fix(mcp): scope list config reads to active profile (#5619)
This commit is contained in:
1 parent
07b9708cde
commit
3c8d9f851e
3 files changed
+32
-10
No files matched your search
+3
-2
@@ -2822,6 +2822,7 @@ from api.config import (
|
||||
_load_yaml_config_file,
|
||||
_save_yaml_config_file,
|
||||
reload_config,
|
||||
get_config_for_profile_home,
|
||||
_cfg_lock,
|
||||
PENDING_BG_TASK_COMPLETIONS,
|
||||
)
|
||||
@@ -24181,7 +24182,7 @@ def _mcp_tools_from_registry(server_summaries):
|
||||
|
||||
def _handle_mcp_tools_list(handler):
|
||||
"""List known MCP tools from already-available runtime inventory only."""
|
||||
cfg = get_config()
|
||||
cfg = get_config_for_profile_home(get_active_hermes_home())
|
||||
servers = cfg.get("mcp_servers", {})
|
||||
if not isinstance(servers, dict):
|
||||
servers = {}
|
||||
@@ -24695,7 +24696,7 @@ def _handle_notes_item(handler, parsed):
|
||||
|
||||
def _handle_mcp_servers_list(handler):
|
||||
"""List configured MCP servers with safe, read-only runtime visibility."""
|
||||
cfg = get_config()
|
||||
cfg = get_config_for_profile_home(get_active_hermes_home())
|
||||
servers = cfg.get("mcp_servers", {})
|
||||
if not isinstance(servers, dict):
|
||||
servers = {}
|
||||
|
||||
@@ -42,17 +42,33 @@ SAMPLE_MCP = {
|
||||
class TestMcpList:
|
||||
"""GET /api/mcp/servers — list with masked secrets."""
|
||||
|
||||
@patch('api.routes.get_config')
|
||||
def test_returns_servers_list(self, mock_cfg):
|
||||
@patch('api.routes.get_config_for_profile_home')
|
||||
@patch('api.routes.get_active_hermes_home')
|
||||
def test_returns_servers_list(self, mock_home, mock_cfg):
|
||||
mock_home.return_value = sentinel_home = object()
|
||||
mock_cfg.return_value = {'mcp_servers': SAMPLE_MCP}
|
||||
h = _make_handler()
|
||||
_handle_mcp_servers_list(h)
|
||||
assert h.send_response.called
|
||||
status = h.send_response.call_args[0][0]
|
||||
assert status == 200
|
||||
mock_cfg.assert_called_once_with(sentinel_home)
|
||||
|
||||
@patch('api.routes.get_config')
|
||||
def test_empty_config(self, mock_cfg):
|
||||
@patch('api.routes.get_config_for_profile_home')
|
||||
@patch('api.routes.get_active_hermes_home')
|
||||
def test_reads_active_profile_home_for_servers(self, mock_home, mock_cfg):
|
||||
mock_home.return_value = sentinel_home = object()
|
||||
mock_cfg.return_value = {'mcp_servers': {'active': SAMPLE_MCP['searxng']}}
|
||||
h = _make_handler()
|
||||
_handle_mcp_servers_list(h)
|
||||
payload = _json_payload(h)
|
||||
assert [srv['name'] for srv in payload['servers']] == ['active']
|
||||
mock_cfg.assert_called_once_with(sentinel_home)
|
||||
|
||||
@patch('api.routes.get_config_for_profile_home')
|
||||
@patch('api.routes.get_active_hermes_home')
|
||||
def test_empty_config(self, mock_home, mock_cfg):
|
||||
mock_home.return_value = object()
|
||||
mock_cfg.return_value = {}
|
||||
h = _make_handler()
|
||||
_handle_mcp_servers_list(h)
|
||||
@@ -65,8 +81,10 @@ class TestMcpList:
|
||||
assert payload['reload_required'] is True
|
||||
|
||||
@patch('api.routes._mcp_runtime_status_by_name')
|
||||
@patch('api.routes.get_config')
|
||||
def test_list_payload_includes_status_tool_counts_and_safe_invalid_config(self, mock_cfg, mock_runtime):
|
||||
@patch('api.routes.get_config_for_profile_home')
|
||||
@patch('api.routes.get_active_hermes_home')
|
||||
def test_list_payload_includes_status_tool_counts_and_safe_invalid_config(self, mock_home, mock_cfg, mock_runtime):
|
||||
mock_home.return_value = object()
|
||||
mock_cfg.return_value = {
|
||||
'mcp_servers': {
|
||||
'searxng': {'command': 'mcp-searxng', 'args': ['--port', '8888']},
|
||||
|
||||
@@ -29,8 +29,10 @@ def _read(relative_path: str) -> str:
|
||||
|
||||
class TestMcpToolInventoryApi:
|
||||
@patch("api.routes._mcp_runtime_status_by_name")
|
||||
@patch("api.routes.get_config")
|
||||
def test_endpoint_returns_sanitized_registered_mcp_tools(self, mock_cfg, mock_runtime):
|
||||
@patch("api.routes.get_config_for_profile_home")
|
||||
@patch("api.routes.get_active_hermes_home")
|
||||
def test_endpoint_returns_sanitized_registered_mcp_tools(self, mock_home, mock_cfg, mock_runtime):
|
||||
mock_home.return_value = sentinel_home = object()
|
||||
mock_cfg.return_value = {
|
||||
"mcp_servers": {
|
||||
"web-reader": {"url": "http://localhost:3001/mcp", "headers": {"Authorization": "Bearer secret-token"}},
|
||||
@@ -72,6 +74,7 @@ class TestMcpToolInventoryApi:
|
||||
{"name": "url", "type": "string", "required": True, "description": "URL to fetch"},
|
||||
{"name": "limit", "type": "integer", "required": False, "description": "Maximum bytes"},
|
||||
]
|
||||
mock_cfg.assert_called_once_with(sentinel_home)
|
||||
raw = json.dumps(payload)
|
||||
assert "secret-token" not in raw
|
||||
assert "default" not in raw
|
||||
|
||||
Reference in new issue
Block a user