[{'Text': 'Edited point-topic-mcp/tests/test_gbs_tools.py:\n\n```diff\n@@ -1,239 +1,123 @@\n-"""Test GBS tools with mocked MongoDB (no real connection required)."""\n+"""Tests for GBS tools (gbs_get_status, gbs_add_statistic, gbs_create_source).\n \n-import os\n-from unittest.mock import MagicMock, patch\n+These mock mongodb_utils to test validation, formatting, and error paths\n+without requiring a real MongoDB connection.\n+"""\n+\n+import json\n+from unittest.mock import patch\n \n import pytest\n \n-\n-@pytest.fixture(autouse=True)\n-def gbs_env(monkeypatch):\n-    """Ensure PT_RESEARCH_DATABASE_URI is set so gbs_tools module loads the functions."""\n-    monkeypatch.setenv("PT_RESEARCH_DATABASE_URI", "mongodb://localhost:27017/test")\n+from bson import ObjectId\n \n \n @pytest.fixture\n-def mock_db():\n-    """Build a mock MongoDB db with Operator, Statistics, Sources, GlobalVariables."""\n-    from bson import ObjectId\n-\n-    db = MagicMock()\n-    op_id = ObjectId()\n-\n-    # Operator collection\n-    mock_operators = MagicMock()\n-    mock_operators.find_one.side_effect = lambda q: (\n-        {\n-            "_id": op_id,\n-            "name": "TestOperator",\n-            "country": "UK",\n-            "technologies": ["FTTP", "FTTC"],\n-        }\n-        if q.get("name") == "TestOperator" and q.get("country") == "UK"\n-        else (\n-            {"_id": op_id}\n-            if q == {"_id": op_id}\n-            else None\n-        )\n-    )\n-    db.__getitem__.side_effect = lambda name: {\n-        "Operator": mock_operators,\n-        "Statistics": MagicMock(),\n-        "Sources": MagicMock(),\n-        "GlobalVariables": MagicMock(),\n-    }.get(name, MagicMock())\n-\n-    # For operator lookup by _id\n-    def operators_find_one(q):\n-        if "_id" in q and q["_id"] == op_id:\n-            return {"_id": op_id, "name": "TestOperator", "technologies": ["FTTP", "FTTC"]}\n-        return None\n-\n-    mock_operators.find_one.side_effect = operators_find_one\n-\n-    # Statistics: return some existing records\n-    mock_stats = MagicMock()\n-    mock_stats.find.return_value = iter([\n-        {"type": "broadband", "tech": "FTTP", "channel": "Infrastructure", "domain": "Residential", "state": 1},\n-    ])\n-    db.__getitem__.side_effect = lambda name: {\n-        "Operator": mock_operators,\n-        "Statistics": mock_stats,\n-        "Sources": MagicMock(),\n-        "GlobalVariables": MagicMock(),\n-    }.get(name, MagicMock())\n-\n-    # GlobalVariables: current stats period\n-    mock_gv = MagicMock()\n-    mock_gv.find_one.return_value = {"isCurrent": True, "currentStatsPeriod": "2025Q1"}\n-    db.__getitem__.side_effect = lambda name: {\n-        "Operator": mock_operators,\n-        "Statistics": mock_stats,\n-        "Sources": MagicMock(),\n-        "GlobalVariables": mock_gv,\n-    }.get(name, MagicMock())\n-\n-    # Sources insert\n-    mock_sources = MagicMock()\n-    mock_sources.insert_one.return_value.inserted_id = ObjectId()\n-    db.__getitem__.side_effect = lambda name: {\n-        "Operator": mock_operators,\n-        "Statistics": MagicMock(),\n-        "Sources": mock_sources,\n-        "GlobalVariables": mock_gv,\n-    }.get(name, MagicMock())\n-\n-    return db\n+def gbs_env():\n+    """Ensure PT_RESEARCH_DATABASE_URI looks set so tools register."""\n+    with patch.dict("os.environ", {"PT_RESEARCH_DATABASE_URI": "mongodb://localhost:27017/t"}, clear=False):\n+        # Reload gbs_tools to trigger conditional import\n+        import importlib\n+        import point_topic_mcp.tools.gbs_tools as gbs\n+        importlib.reload(gbs)\n+        yield gbs\n \n \n-def _get_mock_db_collections(mock_db, op_id):\n-    """Return a consistent mock db with all collections properly set."""\n-    from bson import ObjectId\n-\n-    mock_operators = MagicMock()\n-    mock_operators.find_one.side_effect = lambda q: (\n-        {"_id": op_id, "name": "TestOperator", "country": "UK", "technologies": ["FTTP", "FTTC"]}\n-        if (q.get("name") == "TestOperator" and q.get("country") == "UK") or q.get("_id") == op_id\n-        else None\n-    )\n-\n-    mock_stats = MagicMock()\n-    mock_stats.find.return_value.__iter__ = lambda self: iter([\n-        {"type": "broadband", "tech": "FTTP", "channel": "Infrastructure", "domain": "Residential", "state": 1},\n-    ])\n-\n-    mock_sources = MagicMock()\n-    inserted = ObjectId()\n-    mock_sources.insert_one.return_value.inserted_id = inserted\n-\n-    mock_gv = MagicMock()\n-    mock_gv.find_one.return_value = {"isCurrent": True, "currentStatsPeriod": "2025Q1"}\n-\n-    def getitem(name):\n-        colls = {\n-            "Operator": mock_operators,\n-            "Statistics": mock_stats,\n-            "Sources": mock_sources,\n-            "GlobalVariables": mock_gv,\n-        }\n-        return colls.get(name, MagicMock())\n-\n-    mock_db.__getitem__ = getitem\n-    return mock_db\n-\n-\n-def test_list_operators():\n-    """list_operators returns all operators sorted by name."""\n-    from bson import ObjectId\n-\n-    import point_topic_mcp.tools.gbs_tools as gbs\n-\n-    if not hasattr(gbs, "list_operators"):\n-        pytest.skip("GBS tools not loaded (PT_RESEARCH_DATABASE_URI not set)")\n-\n+def test_gbs_get_status_country_level(gbs_env):\n+    """Country-level: returns coverage rollup with operator lists."""\n+    gbs = gbs_env\n     op_id_a = ObjectId()\n     op_id_b = ObjectId()\n-    op_id_c = ObjectId()\n-    # Intentionally unsorted input to verify sorting is applied\n-    mock_ops = [\n-        {"_id": {"$oid": str(op_id_b)}, "name": "Zebra", "country": "UK", "technologies": ["FTTP"]},\n-        {"_id": {"$oid": str(op_id_a)}, "name": "Alpha", "country": "UK", "technologies": ["FTTP"]},\n-        {"_id": {"$oid": str(op_id_c)}, "name": "Beta", "country": "UK", "technologies": ["FTTP"]},\n+    mock_docs = [\n+        {"_id": {"$oid": str(op_id_a)}, "name": "Alpha", "techs": ["FTTP"], "statCount": 5, "stats": [{"state": 3}] * 5},\n+        {"_id": {"$oid": str(op_id_b)}, "name": "Beta", "techs": ["DSL"], "statCount": 0, "stats": []},\n     ]\n-    \n-    with patch("point_topic_mcp.core.mongodb_utils.find_operators", return_value=mock_ops):\n-        # Test 1: basic call, should be sorted\n-        result = gbs.list_operators()\n-        assert "Operators:" in result\n+    mock_return = json.dumps({"currentPeriod": "2025Q1", "targetPeriod": "2025Q1", "docs": mock_docs})\n+\n+    with patch("point_topic_mcp.core.mongodb_utils._run_mongosh", return_value=mock_return):\n+        result = gbs.gbs_get_status(country="UK")\n+        assert "GBS STATUS: UK" in result\n+        assert "period 2025Q1" in result\n+        assert "2 total" in result\n+        assert "1 with data" in result\n+        assert "1 without data" in result\n         assert "Alpha" in result\n         assert "Beta" in result\n-        assert "Zebra" in result\n-        # Check ordering: Alpha should appear before Beta, Beta before Zebra\n-        alpha_pos = result.find("Alpha")\n-        beta_pos = result.find("Beta")\n-        zebra_pos = result.find("Zebra")\n-        assert alpha_pos < beta_pos < zebra_pos, "Operators should be sorted alphabetically"\n-        \n-        # Test 2: with country filter\n-        result_filtered = gbs.list_operators(country="UK")\n-        assert "(country filter: \'UK\', 3 match(es))" in result_filtered\n+        assert "50.0%" in result  # 1/2 coverage\n \n \n-def test_get_gbs_status_operator_not_found():\n-    """get_gbs_status returns error when operator doesn\'t exist."""\n-    import point_topic_mcp.tools.gbs_tools as gbs\n+def test_gbs_get_status_operator_not_found(gbs_env):\n+    """Operator-level: returns error when operator doesn\'t exist."""\n+    gbs = gbs_env\n+    mock_return = json.dumps({"currentPeriod": "2025Q1", "targetPeriod": "2025Q1", "docs": []})\n \n-    if not hasattr(gbs, "get_gbs_status"):\n-        pytest.skip("GBS tools not loaded (PT_RESEARCH_DATABASE_URI not set)")\n-\n-    with patch("point_topic_mcp.core.mongodb_utils.find_one_operator", return_value=None):\n-        result = gbs.get_gbs_status("UK", "NoSuchOperator", "2025Q1")\n-        assert "Operator not found" in result\n+    with patch("point_topic_mcp.core.mongodb_utils._run_mongosh", return_value=mock_return):\n+        result = gbs.gbs_get_status(country="UK", operator="NoSuchOp")\n+        assert "not found" in result\n+        assert "NoSuchOp" in result\n \n \n-def test_get_gbs_status_success():\n-    """get_gbs_status returns status with operator_id, gaps grouped by type, staleness."""\n-    from bson import ObjectId\n-\n-    import point_topic_mcp.tools.gbs_tools as gbs\n-\n-    if not hasattr(gbs, "get_gbs_status"):\n-        pytest.skip("GBS tools not loaded (PT_RESEARCH_DATABASE_URI not set)")\n-\n+def test_gbs_get_status_operator_level(gbs_env):\n+    """Operator-level: returns records, gaps, state breakdown, admin URL."""\n+    gbs = gbs_env\n     op_id = ObjectId()\n-    mock_op = {"_id": {"$oid": str(op_id)}, "name": "BT", "country": "UK", "technologies": ["FTTP", "FTTC"]}\n-    mock_stats = [{"type": "broadband", "tech": "FTTP", "channel": "Infrastructure", "domain": "Residential", "state": 1}]\n-    mock_gv = {"isCurrent": True, "currentStatsPeriod": "2025Q1"}\n-    with (\n-        patch("point_topic_mcp.core.mongodb_utils.find_one_operator", return_value=mock_op),\n-        patch("point_topic_mcp.core.mongodb_utils.find_statistics", return_value=mock_stats),\n-        patch("point_topic_mcp.core.mongodb_utils.find_global_variables_current", return_value=mock_gv),\n-    ):\n-        result = gbs.get_gbs_status("UK", "BT", "2025Q1")\n-        assert "GBS status: BT (UK)" in result\n-        assert "operator_id: " + str(op_id) in result\n-        assert "technologies: FTTP, FTTC" in result\n-        assert "Existing: 1 records" in result\n-        assert "by type: broadband: 1" in result\n-        assert "by state: pending: 1" in result\n-        assert "Staleness: current" in result\n-        assert "broadband (" in result\n-        assert "mobile (" in result\n-        assert "iptv (" in result\n+    mock_stats = [\n+        {"type": "broadband", "tech": "FTTP", "channel": "Infrastructure",\n+         "domain": "Residential", "subscribers": 100000, "state": 1},\n+    ]\n+    mock_docs = [{\n+        "_id": {"$oid": str(op_id)},\n+        "name": "TestOp",\n+        "techs": ["FTTP", "FTTC"],\n+        "statCount": 1,\n+        "stats": mock_stats,\n+    }]\n+    mock_return = json.dumps({"currentPeriod": "2025Q1", "targetPeriod": "2025Q1", "docs": mock_docs})\n \n-    # Test staleness with older period\n-    mock_gv_ahead = {"isCurrent": True, "currentStatsPeriod": "2025Q3"}\n-    with (\n-        patch("point_topic_mcp.core.mongodb_utils.find_one_operator", return_value=mock_op),\n-        patch("point_topic_mcp.core.mongodb_utils.find_statistics", return_value=[]),\n-        patch("point_topic_mcp.core.mongodb_utils.find_global_variables_current", return_value=mock_gv_ahead),\n-    ):\n-        result2 = gbs.get_gbs_status("UK", "BT", "2025Q1")\n-        assert "2 quarters behind current (2025Q3)" in result2\n+    with patch("point_topic_mcp.core.mongodb_utils._run_mongosh", return_value=mock_return):\n+        result = gbs.gbs_get_status(country="UK", operator="TestOp")\n+        assert "GBS STATUS: TestOp (UK)" in result\n+        assert "ID:       " + str(op_id) in result\n+        assert "Records:   1" in result\n+        assert "Filled: 1 combos" in result\n+        assert "Gaps" in result\n+        assert "pending: 1" in result\n+        assert "broadband: 1" in result\n+        assert "Admin:" in result\n+        assert str(op_id) in result\n+        # Should show the record\n+        assert "100,000" in result\n+        assert "FTTP" in result\n+        assert "Infrastructure" in result\n+        assert "Residential" in result\n \n \n-def test_add_statistic_validation():\n-    """add_statistic returns errors for invalid inputs."""\n-    import point_topic_mcp.tools.gbs_tools as gbs\n+def test_gbs_get_status_operator_staleness(gbs_env):\n+    """Operator-level: works with explicit period; any period is accepted."""\n+    gbs = gbs_env\n+    op_id = ObjectId()\n+    mock_docs = [{\n+        "_id": {"$oid": str(op_id)},\n+        "name": "TestOp",\n+        "techs": ["FTTP"],\n+        "statCount": 0,\n+        "stats": [],\n+    }]\n+    # Period specified → should be used as targetPeriod\n+    mock_return = json.dumps({"currentPeriod": "2025Q3", "targetPeriod": "2025Q1", "docs": mock_docs})\n \n-    if not hasattr(gbs, "add_statistic"):\n-        pytest.skip("GBS tools not loaded")\n+    with patch("point_topic_mcp.core.mongodb_utils._run_mongosh", return_value=mock_return):\n+        result = gbs.gbs_get_status(country="UK", operator="TestOp", period="2025Q1")\n+        assert "2025Q1" in result\n+        assert "Records:   0" in result\n \n-    # Invalid type\n-    result = gbs.add_statistic(\n+\n+def test_gbs_add_statistic_validation(gbs_env):\n+    """gbs_add_statistic returns errors for invalid inputs."""\n+    gbs = gbs_env\n+\n+    result = gbs.gbs_add_statistic(\n         type="invalid",\n-        operator_id="000000000000000000000001",\n-        period="2025Q1",\n-        tech="FTTP",\n-        channel="Infrastructure",\n-        domain="Residential",\n-        subscribers=1000,\n-    )\n-    assert "Invalid type" in result\n-\n-    # Invalid channel\n-    result = gbs.add_statistic(\n-        type="broadband",\n         operator_id="000000000000000000000001",\n         period="2025Q1",\n         tech="FTTP",\n@@ -241,12 +125,11 @@\n         domain="Residential",\n         subscribers=1000,\n     )\n-    assert "Invalid channel" in result\n+    assert "Invalid" in result\n \n-    # Invalid operator_id format\n-    result = gbs.add_statistic(\n+    result = gbs.gbs_add_statistic(\n         type="broadband",\n-        operator_id="not-an-oid",\n+        operator_id="bad",\n         period="2025Q1",\n         tech="FTTP",\n         channel="Infrastructure",\n@@ -255,11 +138,10 @@\n     )\n     assert "Invalid operator_id" in result\n \n-    # Invalid period format\n-    result = gbs.add_statistic(\n+    result = gbs.gbs_add_statistic(\n         type="broadband",\n         operator_id="000000000000000000000001",\n-        period="Q1 2025",\n+        period="bad",\n         tech="FTTP",\n         channel="Infrastructure",\n         domain="Residential",\n@@ -267,221 +149,180 @@\n     )\n     assert "Invalid period" in result\n \n-    # Negative subscribers\n-    result = gbs.add_statistic(\n+    result = gbs.gbs_add_statistic(\n         type="broadband",\n         operator_id="000000000000000000000001",\n         period="2025Q1",\n         tech="FTTP",\n         channel="Infrastructure",\n         domain="Residential",\n-        subscribers=-100,\n+        subscribers=-1,\n     )\n     assert "Invalid subscribers" in result\n \n \n-def test_add_statistic_success():\n-    """add_statistic inserts, returns id, and auto-fills operator name/country from DB."""\n-    from bson import ObjectId\n-\n-    import point_topic_mcp.tools.gbs_tools as gbs\n-\n-    if not hasattr(gbs, "add_statistic"):\n-        pytest.skip("GBS tools not loaded")\n-\n-    op_id = ObjectId()\n-    inserted_id = ObjectId()\n-    mock_op = {"_id": {"$oid": str(op_id)}, "name": "BT Group", "country": "United Kingdom", "technologies": ["FTTP", "FTTC"]}\n+def test_gbs_add_statistic_success(gbs_env):\n+    """gbs_add_statistic inserts a pending record with admin URL."""\n+    gbs = gbs_env\n+    op_id = str(ObjectId())\n+    mock_op = {"_id": {"$oid": op_id}, "name": "TestOp", "country": "UK", "technologies": ["FTTP"]}\n \n     with (\n         patch("point_topic_mcp.core.mongodb_utils.find_one_operator_by_id", return_value=mock_op),\n         patch("point_topic_mcp.core.mongodb_utils.find_statistics", return_value=[]),\n-        patch("point_topic_mcp.core.mongodb_utils.insert_one_statistic", return_value=str(inserted_id)),\n+        patch("point_topic_mcp.core.mongodb_utils.insert_one_statistic", return_value=op_id),\n     ):\n-        result = gbs.add_statistic(\n+        result = gbs.gbs_add_statistic(\n             type="broadband",\n-            operator_id=str(op_id),\n-            period="2025Q1",\n+            operator_id=op_id,\n+            period="2025Q3",\n             tech="FTTP",\n             channel="Infrastructure",\n             domain="Residential",\n             subscribers=50000,\n+            created_by="test-agent",\n         )\n         assert "Created statistic" in result\n-        assert str(inserted_id) in result\n-        assert "pending" in result\n-        assert "BT Group" in result\n-        assert "United Kingdom" in result\n-\n-        from point_topic_mcp.core import mongodb_utils\n-        mongodb_utils.insert_one_statistic.assert_called_once()\n-        doc = mongodb_utils.insert_one_statistic.call_args[0][0]\n-        assert doc["subscribers"] == 50000\n-        assert doc["tech"] == "FTTP"\n-        assert doc["operator"] == "BT Group"\n-        assert doc["country"] == "United Kingdom"\n+        assert "state: pending" in result\n+        assert "TestOp" in result\n+        assert "50,000" in result\n+        assert "Admin:" in result\n+        assert op_id in result\n \n \n-def test_add_statistic_duplicate_rejected():\n-    """add_statistic rejects duplicate (same operator/period/type/tech/channel/domain)."""\n-    from bson import ObjectId\n-\n-    import point_topic_mcp.tools.gbs_tools as gbs\n-\n-    if not hasattr(gbs, "add_statistic"):\n-        pytest.skip("GBS tools not loaded")\n-\n-    op_id = ObjectId()\n-    existing_id = ObjectId()\n-    mock_op = {"_id": {"$oid": str(op_id)}, "name": "BT", "country": "UK", "technologies": ["FTTP"]}\n-    mock_existing = [\n-        {"_id": {"$oid": str(existing_id)}, "type": "broadband", "tech": "FTTP",\n-         "channel": "Infrastructure", "domain": "Residential", "state": 1},\n-    ]\n+def test_gbs_add_statistic_duplicate_rejected(gbs_env):\n+    """gbs_add_statistic rejects duplicate (operator, period, type, tech, channel, domain)."""\n+    gbs = gbs_env\n+    op_id = str(ObjectId())\n+    mock_op = {"_id": {"$oid": op_id}, "name": "TestOp", "country": "UK", "technologies": ["FTTP"]}\n+    existing_id = str(ObjectId())\n+    mock_existing = [{\n+        "_id": {"$oid": existing_id},\n+        "type": "broadband",\n+        "tech": "FTTP",\n+        "channel": "Infrastructure",\n+        "domain": "Residential",\n+        "state": 1,\n+    }]\n \n     with (\n         patch("point_topic_mcp.core.mongodb_utils.find_one_operator_by_id", return_value=mock_op),\n         patch("point_topic_mcp.core.mongodb_utils.find_statistics", return_value=mock_existing),\n     ):\n-        result = gbs.add_statistic(\n+        result = gbs.gbs_add_statistic(\n             type="broadband",\n-            operator_id=str(op_id),\n-            period="2025Q1",\n+            operator_id=op_id,\n+            period="2025Q3",\n             tech="FTTP",\n             channel="Infrastructure",\n             domain="Residential",\n             subscribers=50000,\n         )\n         assert "Duplicate" in result\n-        assert str(existing_id) in result\n+        assert existing_id in result\n \n \n-def test_create_source_validation():\n-    """create_source returns errors for invalid inputs."""\n-    import point_topic_mcp.tools.gbs_tools as gbs\n+def test_gbs_create_source_validation(gbs_env):\n+    """gbs_create_source returns errors for invalid inputs."""\n+    gbs = gbs_env\n \n-    if not hasattr(gbs, "create_source"):\n-        pytest.skip("GBS tools not loaded")\n-\n-    result = gbs.create_source(\n-        operator_id="bad-oid",\n+    result = gbs.gbs_create_source(\n+        operator_id="bad",\n         year=2025,\n         quarter=1,\n         type="report",\n-        url="https://example.com",\n     )\n     assert "Invalid operator_id" in result\n \n-    result = gbs.create_source(\n+    result = gbs.gbs_create_source(\n         operator_id="000000000000000000000001",\n         year=2025,\n         quarter=5,\n         type="report",\n-        url="https://example.com",\n     )\n     assert "Invalid quarter" in result\n \n-    result = gbs.create_source(\n-        operator_id="000000000000000000000001",\n-        year=2025,\n-        quarter=1,\n-        type="report",\n-    )\n-    assert "At least one of url or file_url" in result\n-\n-    result = gbs.create_source(\n-        operator_id="000000000000000000000001",\n-        year=2025,\n-        quarter=1,\n-        type="report",\n-        file_url="ftp://example.com/x.pdf",\n-    )\n-    assert "file_url must be s3://bucket/key" in result\n-\n-    result = gbs.create_source(\n-        operator_id="000000000000000000000001",\n-        year=1800,\n-        quarter=1,\n-        type="report",\n-        url="https://example.com",\n-    )\n-    assert "Invalid year" in result\n-\n-    result = gbs.create_source(\n+    result = gbs.gbs_create_source(\n         operator_id="000000000000000000000001",\n         year=2025,\n         quarter=1,\n         type="",\n-        url="https://example.com",\n     )\n     assert "Invalid type" in result\n \n+    result = gbs.gbs_create_source(\n+        operator_id="000000000000000000000001",\n+        year=2025,\n+        quarter=1,\n+        type="report",\n+        url="",\n+    )\n+    assert "At least one" in result\n \n-def test_create_source_success():\n-    """create_source inserts and returns created id with operator info."""\n-    from bson import ObjectId\n \n-    import point_topic_mcp.tools.gbs_tools as gbs\n-\n-    if not hasattr(gbs, "create_source"):\n-        pytest.skip("GBS tools not loaded")\n-\n-    op_id = ObjectId()\n-    inserted_id = ObjectId()\n-    mock_op = {"_id": {"$oid": str(op_id)}, "name": "BT Group"}\n+def test_gbs_create_source_success(gbs_env):\n+    """gbs_create_source inserts a source record."""\n+    gbs = gbs_env\n+    op_id = str(ObjectId())\n+    mock_op = {"_id": {"$oid": op_id}, "name": "TestOp"}\n+    source_id = str(ObjectId())\n \n     with (\n         patch("point_topic_mcp.core.mongodb_utils.find_one_operator_by_id", return_value=mock_op),\n         patch("point_topic_mcp.core.mongodb_utils.find_sources", return_value=[]),\n-        patch("point_topic_mcp.core.mongodb_utils.insert_one_source", return_value=str(inserted_id)),\n+        patch("point_topic_mcp.core.mongodb_utils.insert_one_source", return_value=source_id),\n     ):\n-        result = gbs.create_source(\n-            operator_id=str(op_id),\n+        result = gbs.gbs_create_source(\n+            operator_id=op_id,\n             year=2025,\n-            quarter=1,\n+            quarter=3,\n             type="report",\n             url="https://example.com/report",\n         )\n         assert "Created source" in result\n-        assert str(inserted_id) in result\n-        assert "BT Group" in result\n-        assert "2025Q1" in result\n-\n-        from point_topic_mcp.core import mongodb_utils\n-        mongodb_utils.insert_one_source.assert_called_once()\n-        doc = mongodb_utils.insert_one_source.call_args[0][0]\n-        assert doc["year"] == 2025\n-        assert doc["quarter"] == 1\n-        assert doc["type"] == "report"\n+        assert source_id in result\n+        assert "TestOp" in result\n+        assert "2025Q3" in result\n \n \n-def test_create_source_duplicate_rejected():\n-    """create_source rejects duplicate (same operator/year/quarter/type/url)."""\n-    from bson import ObjectId\n-\n-    import point_topic_mcp.tools.gbs_tools as gbs\n-\n-    if not hasattr(gbs, "create_source"):\n-        pytest.skip("GBS tools not loaded")\n-\n-    op_id = ObjectId()\n-    existing_id = ObjectId()\n-    mock_op = {"_id": {"$oid": str(op_id)}, "name": "BT"}\n-    mock_existing = [\n-        {"_id": {"$oid": str(existing_id)}, "type": "report",\n-         "url": "https://example.com/report", "fileUrl": None},\n-    ]\n+def test_gbs_create_source_duplicate_rejected(gbs_env):\n+    """gbs_create_source rejects exact duplicates."""\n+    gbs = gbs_env\n+    op_id = str(ObjectId())\n+    mock_op = {"_id": {"$oid": op_id}, "name": "TestOp"}\n+    existing_id = str(ObjectId())\n+    mock_existing = [{\n+        "_id": {"$oid": existing_id},\n+        "type": "report",\n+        "url": "https://example.com/report",\n+        "fileUrl": None,\n+    }]\n \n     with (\n         patch("point_topic_mcp.core.mongodb_utils.find_one_operator_by_id", return_value=mock_op),\n         patch("point_topic_mcp.core.mongodb_utils.find_sources", return_value=mock_existing),\n     ):\n-        result = gbs.create_source(\n-            operator_id=str(op_id),\n+        result = gbs.gbs_create_source(\n+            operator_id=op_id,\n             year=2025,\n-            quarter=1,\n+            quarter=3,\n             type="report",\n             url="https://example.com/report",\n         )\n         assert "Duplicate" in result\n-        assert str(existing_id) in result\n+        assert existing_id in result\n+\n+\n+def test_discovery_uses_prefix(gbs_env):\n+    """Tool auto-discovery prefixes module name."""\n+    import point_topic_mcp.tools as tools\n+    all_tools = tools.get_all_tools()\n+    names = [n for n, _ in all_tools]\n+    assert "gbs_tools_gbs_get_status" in names\n+    assert "gbs_tools_gbs_add_statistic" in names\n+    assert "gbs_tools_gbs_create_source" in names\n+    # Old names should be gone\n+    old_names = ["gbs_tools_list_operators", "gbs_tools_get_gbs_status",\n+                  "gbs_tools_add_statistic", "gbs_tools_create_source"]\n+    for old in old_names:\n+        assert old not in names, f"Old tool \'{old}\' should be removed"\n\n```'}]