Files
odysseus/tests/test_mcp_reconnect_args.py
T
Kenny Van de Maele 5ce2056521 refactor(tools): migrate config/integration admin tools to the registry (#4742)
Part of #3629 (the `admin_tools.py` bullet). Moves the config/integration admin
tools off the legacy elif dispatch chain in tool_implementations.py onto the
agent_tools registry:

  manage_endpoints, manage_mcp, manage_webhooks, manage_tokens, manage_settings

The do_* implementations (and manage_mcp's command-allowlist / RCE guard:
_validate_mcp_command, _mcp_allowed_commands, and the _MCP_* constants) move
verbatim into the new src/agent_tools/admin_tools.py. They register through a
single ADMIN_TOOL_HANDLERS map that TOOL_HANDLERS.update()s, and the five elif
branches plus their imports are dropped from tool_execution.py, so these tools
now flow through _direct_fallback like the other migrated clusters. The names
are re-exported from src.agent_tools for back-compat.

Dedup:
  - _parse_tool_args was duplicated in tool_implementations.py and
    document_tools.py. It now lives once in src.tool_utils (which imports nothing
    from the project beyond src.constants, so this introduces no cycle) and both
    call sites import it from there. The orphaned `import json` in document_tools
    is removed with it.
  - The five tools share one _owner_adapter(fn) factory that threads ctx["owner"]
    into the owner-taking do_* signature, instead of five near-identical wrappers.

Tests: new tests/test_admin_tools_registry.py pins the registration, the
re-export back-compat, the owner-threading adapter, and the single-source
_parse_tool_args (across admin_tools and document_tools). Existing MCP /
settings / webhook suites are repointed at the new module.
2026-06-24 09:29:10 +02:00

47 lines
1.5 KiB
Python

"""Verify that MCP reconnect via the agent tool passes full server metadata."""
import asyncio
import json
from unittest.mock import AsyncMock, MagicMock, patch
from types import SimpleNamespace
def test_reconnect_passes_full_server_config():
"""do_manage_mcp reconnect must pass name/transport/command/args/env/url."""
from src.agent_tools.admin_tools import do_manage_mcp
fake_mcp = MagicMock()
fake_mcp.disconnect_server = AsyncMock()
fake_mcp.connect_server = AsyncMock(return_value=True)
fake_mcp.get_server_status = MagicMock(return_value={"tool_count": 3})
fake_srv = SimpleNamespace(
id="srv-123",
name="test-server",
transport="stdio",
command="/usr/bin/test",
args=json.dumps(["--flag"]),
env=json.dumps({"KEY": "val"}),
url=None,
)
fake_db = MagicMock()
fake_db.query.return_value.filter.return_value.first.return_value = fake_srv
with patch("src.agent_tools.admin_tools.get_mcp_manager", return_value=fake_mcp), \
patch("core.database.SessionLocal", return_value=fake_db):
result = asyncio.run(do_manage_mcp(
json.dumps({"action": "reconnect", "server_id": "srv-123"})
))
assert result["exit_code"] == 0
fake_mcp.connect_server.assert_called_once_with(
server_id="srv-123",
name="test-server",
transport="stdio",
command="/usr/bin/test",
args=["--flag"],
env={"KEY": "val"},
url=None,
)