From 05884c300d1ab6de362a12b76f24db52b83fd746 Mon Sep 17 00:00:00 2001 From: Michael Lam Date: Mon, 4 May 2026 17:04:13 -0700 Subject: [PATCH 1/2] feat: add MCP server visibility panel --- api/routes.py | 88 ++++++++++++++- .../pr-media/696/mcp-servers-system-panel.png | Bin 0 -> 72771 bytes static/i18n.js | 82 +++++++++++++- static/index.html | 37 +----- static/panels.js | 105 ++++++------------ static/style.css | 16 ++- tests/test_issue538_mcp_management.py | 47 ++++++++ tests/test_issue696_mcp_visibility_panel.py | 46 ++++++++ 8 files changed, 301 insertions(+), 120 deletions(-) create mode 100644 docs/pr-media/696/mcp-servers-system-panel.png create mode 100644 tests/test_issue696_mcp_visibility_panel.py diff --git a/api/routes.py b/api/routes.py index 92109eecff..0de35c0094 100644 --- a/api/routes.py +++ b/api/routes.py @@ -7133,33 +7133,111 @@ def _mask_secrets(obj): return masked -def _server_summary(name, cfg): +def _parse_mcp_enabled(value) -> bool: + """Parse Hermes MCP ``enabled`` values without raising on bad config.""" + if value is None: + return True + if isinstance(value, bool): + return value + if isinstance(value, (int, float)): + return value != 0 + if isinstance(value, str): + normalized = value.strip().lower() + if normalized in {"true", "1", "yes", "on"}: + return True + if normalized in {"false", "0", "no", "off"}: + return False + return True + + +def _mcp_runtime_status_by_name() -> dict[str, dict]: + """Return already-known MCP runtime status without starting servers. + + ``tools.mcp_tool.get_mcp_status()`` only reads the existing MCP registry and + configuration; it does not probe or spawn MCP subprocesses. If Hermes Agent + is unavailable, fall back to an empty map so the API remains safe. + """ + try: + from tools.mcp_tool import get_mcp_status + statuses = get_mcp_status() + except Exception: + return {} + if not isinstance(statuses, list): + return {} + return { + str(entry.get("name")): entry + for entry in statuses + if isinstance(entry, dict) and entry.get("name") + } + + +def _server_summary(name, cfg, runtime_status=None): """Return a safe summary of an MCP server config.""" + runtime_status = runtime_status if isinstance(runtime_status, dict) else {} out = {"name": name} + if not isinstance(cfg, dict): + out.update({ + "transport": "invalid", + "timeout": 120, + "connect_timeout": 60, + "enabled": False, + "active": False, + "status": "invalid_config", + "tool_count": None, + }) + return out + + enabled = _parse_mcp_enabled(cfg.get("enabled", True)) + connected = bool(runtime_status.get("connected")) if enabled else False if "url" in cfg: out["transport"] = "http" # Mask auth headers if "headers" in cfg: out["headers"] = _mask_secrets(cfg["headers"]) out["url"] = cfg["url"] - else: + elif "command" in cfg: out["transport"] = "stdio" out["command"] = cfg.get("command", "") out["args"] = cfg.get("args", []) if "env" in cfg: out["env"] = _mask_secrets(cfg["env"]) + else: + out["transport"] = "invalid" + enabled = False + connected = False + out["timeout"] = cfg.get("timeout", 120) + out["connect_timeout"] = cfg.get("connect_timeout", 60) + out["enabled"] = enabled + out["active"] = connected + if out["transport"] == "invalid": + out["status"] = "invalid_config" + elif not enabled: + out["status"] = "disabled" + elif connected: + out["status"] = "active" + else: + out["status"] = "configured" + out["tool_count"] = runtime_status.get("tools") if runtime_status else None return out def _handle_mcp_servers_list(handler): - """List all configured MCP servers.""" + """List configured MCP servers with safe, read-only runtime visibility.""" cfg = get_config() servers = cfg.get("mcp_servers", {}) if not isinstance(servers, dict): servers = {} - result = [_server_summary(name, scfg) for name, scfg in servers.items()] - return j(handler, {"servers": result}) + runtime = _mcp_runtime_status_by_name() + result = [ + _server_summary(name, scfg, runtime.get(str(name))) + for name, scfg in servers.items() + ] + return j(handler, { + "servers": result, + "toggle_supported": False, + "reload_required": True, + }) def _handle_mcp_server_delete(handler, name): diff --git a/docs/pr-media/696/mcp-servers-system-panel.png b/docs/pr-media/696/mcp-servers-system-panel.png new file mode 100644 index 0000000000000000000000000000000000000000..32c8789ad5bf3a4c066d645c2a11b8630999c855 GIT binary patch literal 72771 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 SugbMg3eHFm$NJO%O8yW2%mbnT literal 0 HcmV?d00001 diff --git a/static/i18n.js b/static/i18n.js index a13f7f6351..ea1b745c76 100644 --- a/static/i18n.js +++ b/static/i18n.js @@ -46,7 +46,7 @@ const LOCALES = { parse_failed_note: 'parse failed', you: 'You', mcp_servers_title: 'MCP Servers', - mcp_servers_desc: 'Manage MCP servers configured in config.yaml.', + mcp_servers_desc: 'View MCP servers configured in config.yaml.', mcp_no_servers: 'No MCP servers configured.', mcp_add_server: '+ Add Server', mcp_field_name: 'Server Name', @@ -67,6 +67,16 @@ const LOCALES = { mcp_deleted: 'MCP server deleted.', mcp_delete_failed: 'Failed to delete MCP server.', mcp_load_failed: 'Failed to load MCP servers.', + mcp_restart_hint: 'Server changes are read-only here for now. Edit config.yaml and restart Hermes for changes to take effect.', + mcp_toggle_followup: 'Enable/disable controls are intentionally deferred until MCP reload semantics are explicit.', + mcp_status_active: 'Active', + mcp_status_configured: 'Configured', + mcp_status_disabled: 'Disabled', + mcp_status_invalid_config: 'Invalid config', + mcp_status_unknown: 'Unknown', + mcp_tool_count: '{0} tools', + mcp_enabled_yes: 'Enabled', + mcp_enabled_no: 'Disabled', // PDF preview (#480) pdf_loading: 'Loading PDF {0}…', pdf_too_large: 'PDF too large for inline preview', @@ -969,6 +979,16 @@ const LOCALES = { mcp_deleted: 'MCPサーバーを削除しました。', mcp_delete_failed: 'MCPサーバーの削除に失敗しました。', mcp_load_failed: 'MCPサーバーの読み込みに失敗しました。', + mcp_restart_hint: 'Server changes are read-only here for now. Edit config.yaml and restart Hermes for changes to take effect.', + mcp_toggle_followup: 'Enable/disable controls are intentionally deferred until MCP reload semantics are explicit.', + mcp_status_active: 'Active', + mcp_status_configured: 'Configured', + mcp_status_disabled: 'Disabled', + mcp_status_invalid_config: 'Invalid config', + mcp_status_unknown: 'Unknown', + mcp_tool_count: '{0} tools', + mcp_enabled_yes: 'Enabled', + mcp_enabled_no: 'Disabled', // PDF preview (#480) pdf_loading: 'PDF {0} を読み込み中…', pdf_too_large: 'PDF が大きすぎてインラインプレビューできません', @@ -1868,6 +1888,16 @@ const LOCALES = { mcp_deleted: 'MCP 伺服器已刪除。', mcp_delete_failed: '刪除 MCP 伺服器失敗。', mcp_load_failed: '載入 MCP 伺服器失敗。', + mcp_restart_hint: 'Server changes are read-only here for now. Edit config.yaml and restart Hermes for changes to take effect.', + mcp_toggle_followup: 'Enable/disable controls are intentionally deferred until MCP reload semantics are explicit.', + mcp_status_active: 'Active', + mcp_status_configured: 'Configured', + mcp_status_disabled: 'Disabled', + mcp_status_invalid_config: 'Invalid config', + mcp_status_unknown: 'Unknown', + mcp_tool_count: '{0} tools', + mcp_enabled_yes: 'Enabled', + mcp_enabled_no: 'Disabled', thinking: 'Думаю', expand_all: 'Развернуть всё', collapse_all: 'Свернуть всё', @@ -2701,6 +2731,16 @@ const LOCALES = { mcp_deleted: 'MCP 服务器已删除。', mcp_delete_failed: '删除 MCP 服务器失败。', mcp_load_failed: '加载 MCP 服务器失败。', + mcp_restart_hint: 'Server changes are read-only here for now. Edit config.yaml and restart Hermes for changes to take effect.', + mcp_toggle_followup: 'Enable/disable controls are intentionally deferred until MCP reload semantics are explicit.', + mcp_status_active: 'Active', + mcp_status_configured: 'Configured', + mcp_status_disabled: 'Disabled', + mcp_status_invalid_config: 'Invalid config', + mcp_status_unknown: 'Unknown', + mcp_tool_count: '{0} tools', + mcp_enabled_yes: 'Enabled', + mcp_enabled_no: 'Disabled', thinking: 'Pensando', expand_all: 'Expandir todo', collapse_all: 'Contraer todo', @@ -3537,6 +3577,16 @@ const LOCALES = { mcp_deleted: 'MCP-Server gelöscht.', mcp_delete_failed: 'Fehler beim Löschen.', mcp_load_failed: 'Fehler beim Laden.', + mcp_restart_hint: 'Server changes are read-only here for now. Edit config.yaml and restart Hermes for changes to take effect.', + mcp_toggle_followup: 'Enable/disable controls are intentionally deferred until MCP reload semantics are explicit.', + mcp_status_active: 'Active', + mcp_status_configured: 'Configured', + mcp_status_disabled: 'Disabled', + mcp_status_invalid_config: 'Invalid config', + mcp_status_unknown: 'Unknown', + mcp_tool_count: '{0} tools', + mcp_enabled_yes: 'Enabled', + mcp_enabled_no: 'Disabled', thinking: 'Nachdenken', expand_all: 'Alle ausklappen', collapse_all: 'Alle einklappen', @@ -4377,6 +4427,16 @@ const LOCALES = { mcp_deleted: 'MCP 服务器已删除。', mcp_delete_failed: 'MCP 服务器删除失败。', mcp_load_failed: 'MCP 服务器加载失败。', + mcp_restart_hint: 'Server changes are read-only here for now. Edit config.yaml and restart Hermes for changes to take effect.', + mcp_toggle_followup: 'Enable/disable controls are intentionally deferred until MCP reload semantics are explicit.', + mcp_status_active: 'Active', + mcp_status_configured: 'Configured', + mcp_status_disabled: 'Disabled', + mcp_status_invalid_config: 'Invalid config', + mcp_status_unknown: 'Unknown', + mcp_tool_count: '{0} tools', + mcp_enabled_yes: 'Enabled', + mcp_enabled_no: 'Disabled', thinking: '\u601d\u8003\u8fc7\u7a0b', expand_all: '\u5168\u90e8\u5c55\u5f00', collapse_all: '\u5168\u90e8\u6298\u53e0', @@ -5212,6 +5272,16 @@ const LOCALES = { mcp_deleted: 'MCP 伺服器已刪除。', mcp_delete_failed: '刪除 MCP 伺服器失敗。', mcp_load_failed: '載入 MCP 伺服器失敗。', + mcp_restart_hint: 'Server changes are read-only here for now. Edit config.yaml and restart Hermes for changes to take effect.', + mcp_toggle_followup: 'Enable/disable controls are intentionally deferred until MCP reload semantics are explicit.', + mcp_status_active: 'Active', + mcp_status_configured: 'Configured', + mcp_status_disabled: 'Disabled', + mcp_status_invalid_config: 'Invalid config', + mcp_status_unknown: 'Unknown', + mcp_tool_count: '{0} tools', + mcp_enabled_yes: 'Enabled', + mcp_enabled_no: 'Disabled', thinking: '\u601d\u8003\u904e\u7a0b', expand_all: '\u5168\u90e8\u5c55\u958b', collapse_all: '\u5168\u90e8\u6298\u758a', @@ -6909,6 +6979,16 @@ const LOCALES = { mcp_deleted: 'MCP server deleted.', mcp_delete_failed: 'Failed to delete MCP server.', mcp_load_failed: 'Failed to load MCP servers.', + mcp_restart_hint: 'Server changes are read-only here for now. Edit config.yaml and restart Hermes for changes to take effect.', + mcp_toggle_followup: 'Enable/disable controls are intentionally deferred until MCP reload semantics are explicit.', + mcp_status_active: 'Active', + mcp_status_configured: 'Configured', + mcp_status_disabled: 'Disabled', + mcp_status_invalid_config: 'Invalid config', + mcp_status_unknown: 'Unknown', + mcp_tool_count: '{0} tools', + mcp_enabled_yes: 'Enabled', + mcp_enabled_no: 'Disabled', thinking: '생각 중', expand_all: '모두 펼치기', collapse_all: '모두 접기', diff --git a/static/index.html b/static/index.html index 2906184421..3816b75119 100644 --- a/static/index.html +++ b/static/index.html @@ -950,42 +950,9 @@

What can I help with?

-
Manage Model Context Protocol servers configured in config.yaml.
+
View Model Context Protocol servers configured in config.yaml.
- -
- diff --git a/static/panels.js b/static/panels.js index a4f19bb51c..0faf82d275 100644 --- a/static/panels.js +++ b/static/panels.js @@ -3875,93 +3875,50 @@ function dismissErrorBanner(){ // ── MCP Server Management ── +function _mcpStatusLabel(status){ + const key={ + active:'mcp_status_active', + configured:'mcp_status_configured', + disabled:'mcp_status_disabled', + invalid_config:'mcp_status_invalid_config', + }[status]||'mcp_status_unknown'; + return t(key); +} function loadMcpServers(){ const list=$('mcpServerList'); if(!list) return; + list.innerHTML=`
${esc(t('loading'))}
`; api('/api/mcp/servers').then(r=>{ - if(!r||!r.servers) return; + if(!r||!Array.isArray(r.servers)) return; if(!r.servers.length){ - list.innerHTML=`
${t('mcp_no_servers')}
`; + list.innerHTML=`
${esc(t('mcp_no_servers'))}
`; return; } + const toggleNote=r.toggle_supported?'':'
'+esc(t('mcp_toggle_followup'))+'
'; list.innerHTML=r.servers.map(s=>{ - const transportLabel=s.transport==='http'?'HTTP':s.transport==='stdio'?'stdio':(''+s.transport); + const transportLabel=s.transport==='http'?'HTTP':s.transport==='stdio'?'stdio':(''+(s.transport||'unknown')); const transportClass=s.transport==='http'?'mcp-http':s.transport==='stdio'?'mcp-stdio':'mcp-unknown'; - const badge=`${esc(transportLabel)}`; - const detail=s.transport==='http'?s.url:`${s.command} ${s.args?s.args.join(' '):''}`; + const transportBadge=`${esc(transportLabel)}`; + const status=s.status||'configured'; + const statusBadge=`${esc(_mcpStatusLabel(status))}`; + const toolCount=s.tool_count===null||typeof s.tool_count==='undefined'?'—':String(s.tool_count); + const detail=s.transport==='http' + ? (s.url||'') + : (s.transport==='stdio'?`${s.command||''} ${Array.isArray(s.args)?s.args.join(' '):''}`:t('mcp_status_invalid_config')); const envInfo=s.env?Object.entries(s.env).map(([k,v])=>`${k}=${v}`).join(', '):''; + const headersInfo=s.headers?Object.entries(s.headers).map(([k,v])=>`${k}=${v}`).join(', '):''; + const secretInfo=[envInfo,headersInfo].filter(Boolean).join(' | '); return `
-
- ${esc(s.name)}${badge} +
+ ${esc(s.name)} + ${transportBadge} + ${statusBadge}
-
${esc(detail)}${envInfo?' | '+esc(envInfo):''}
- +
${esc(detail)}${secretInfo?' | '+esc(secretInfo):''}
+
${esc(t('mcp_tool_count',toolCount))}${esc(t(s.enabled===false?'mcp_enabled_no':'mcp_enabled_yes'))}
`; - }).join(''); - }).catch(()=>{list.innerHTML=`
${t('mcp_load_failed')}
`}); - // Delegate delete-button clicks — uses data-mcp-name to avoid inline onclick XSS - if(list&&!list._mcpDeleteBound){ - list._mcpDeleteBound=true; - list.addEventListener('click',function(e){ - const btn=e.target.closest('.mcp-delete-btn'); - if(!btn) return; - const name=btn.getAttribute('data-mcp-name'); - if(name) deleteMcpServer(name); - }); - } -} - -function showMcpAddForm(){ - const wrap=$('mcpAddFormWrap'); - if(wrap) wrap.style.display='block'; -} -function hideMcpAddForm(){ - const wrap=$('mcpAddFormWrap'); - if(wrap) wrap.style.display='none'; - ['mcpName','mcpCommand','mcpArgs','mcpUrl','mcpTimeout'].forEach(id=>{ - const el=$(id);if(el)el.value=id==='mcpTimeout'?'120':''; - }); - const tr=$('mcpTransport');if(tr)tr.value='stdio'; - mcpTransportChanged(); -} -function mcpTransportChanged(){ - const tr=$('mcpTransport'); - const isHttp=tr&&tr.value==='http'; - const cmdF=$('mcpCommandField');if(cmdF)cmdF.style.display=isHttp?'none':''; - const argsF=$('mcpArgsField');if(argsF)argsF.style.display=isHttp?'none':''; - const urlF=$('mcpUrlField');if(urlF)urlF.style.display=isHttp?'block':'none'; -} -function saveMcpServer(){ - const name=($('mcpName')||{}).value||''; - if(!name.trim()){showToast(t('mcp_name_required'));return;} - const tr=($('mcpTransport')||{}).value||'stdio'; - const timeout=parseInt(($('mcpTimeout')||{}).value)||120; - const body={timeout}; - if(tr==='http'){ - body.url=($('mcpUrl')||{}).value||''; - if(!body.url.trim()){showToast(t('mcp_url_required'));return;} - }else{ - body.command=($('mcpCommand')||{}).value||''; - if(!body.command.trim()){showToast(t('mcp_command_required'));return;} - const argsStr=($('mcpArgs')||{}).value||''; - if(argsStr.trim()) body.args=argsStr.split(',').map(a=>a.trim()).filter(Boolean); - } - const encName=encodeURIComponent(name.trim()); - api(`/api/mcp/servers/${encName}`,{method:'PUT',body:JSON.stringify(body)}) - .then(r=>{ - if(r&&r.ok){showToast(t('mcp_saved'));hideMcpAddForm();loadMcpServers();} - else{showToast((r&&r.error)||t('mcp_save_failed'));} - }).catch(()=>{showToast(t('mcp_save_failed'));}); -} -async function deleteMcpServer(name){ - const _ok=await showConfirmDialog({title:t('mcp_delete_confirm_title'),message:t('mcp_delete_confirm_message',name),confirmLabel:t('delete_title'),danger:true,focusCancel:true}); - if(!_ok) return; - const encName=encodeURIComponent(name); - api(`/api/mcp/servers/${encName}`,{method:'DELETE'}) - .then(r=>{ - if(r&&r.ok){showToast(t('mcp_deleted'));loadMcpServers();} - else{showToast((r&&r.error)||t('mcp_delete_failed'));} - }).catch(()=>{showToast(t('mcp_delete_failed'));}); + }).join('')+toggleNote; + }).catch(()=>{list.innerHTML=`
${esc(t('mcp_load_failed'))}
`}); } function loadGatewayStatus(){ const card=$('gatewayStatusCard'); diff --git a/static/style.css b/static/style.css index e428982e90..a192a1ba3d 100644 --- a/static/style.css +++ b/static/style.css @@ -2271,16 +2271,22 @@ main.main.showing-profiles > #mainProfiles{display:flex;} #mainSettings #btnSignOut:hover{color:var(--accent-text)!important;border-color:var(--accent-bg-strong)!important;} /* MCP Server Management */ -.mcp-server-row{display:flex;align-items:center;gap:8px;padding:6px 8px;border:1px solid var(--border);border-radius:6px;margin-bottom:4px;position:relative;font-size:12px;} +.mcp-server-row{display:flex;flex-direction:column;gap:4px;padding:8px 10px;border:1px solid var(--border);border-radius:8px;margin-bottom:6px;position:relative;font-size:12px;background:var(--surface);} .mcp-server-row:hover{background:var(--code-bg);} +.mcp-server-row-head{display:flex;align-items:center;gap:8px;min-width:0;flex-wrap:wrap;} .mcp-server-name{font-weight:600;color:var(--text);} -.mcp-server-detail{flex:1;color:var(--muted);font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;} -.mcp-transport-badge{font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;padding:2px 6px;border-radius:4px;flex-shrink:0;} +.mcp-server-detail{color:var(--muted);font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%;} +.mcp-server-meta{display:flex;gap:10px;color:var(--muted);font-size:11px;} +.mcp-transport-badge,.mcp-status-badge{font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;padding:2px 6px;border-radius:999px;flex-shrink:0;} .mcp-stdio{background:rgba(99,102,241,.12);color:#818cf8;} .mcp-unknown{background:rgba(161,161,170,.12);color:#a1a1aa;} .mcp-http{background:rgba(34,197,94,.12);color:#4ade80;} -.mcp-delete-btn{background:none;border:none;color:var(--muted);font-size:16px;cursor:pointer;padding:2px 4px;border-radius:4px;flex-shrink:0;} -.mcp-delete-btn:hover{color:#ef4444;background:rgba(239,68,68,.1);} +.mcp-status-active{background:rgba(34,197,94,.12);color:#4ade80;} +.mcp-status-configured{background:rgba(245,158,11,.12);color:#f59e0b;} +.mcp-status-disabled{background:rgba(161,161,170,.12);color:#a1a1aa;} +.mcp-status-invalid_config,.mcp-status-unknown{background:rgba(239,68,68,.12);color:#f87171;} +.mcp-tool-count{color:var(--text);} +.mcp-readonly-note,.mcp-restart-hint{margin-top:8px;color:var(--muted);font-size:11px;line-height:1.45;background:var(--code-bg);border:1px solid var(--border2);border-radius:6px;padding:8px 10px;} /* Picker grids (theme / skin / font-size): make the card chrome use tokens so all skins flip correctly. */ diff --git a/tests/test_issue538_mcp_management.py b/tests/test_issue538_mcp_management.py index 0a1c735cd0..758eff1a80 100644 --- a/tests/test_issue538_mcp_management.py +++ b/tests/test_issue538_mcp_management.py @@ -6,6 +6,7 @@ _handle_mcp_server_update, _handle_mcp_server_delete, _mask_secrets, + _parse_mcp_enabled, _server_summary, _strip_masked_values, ) @@ -18,6 +19,11 @@ def _make_handler(): return h +def _json_payload(handler): + body = handler.wfile.write.call_args[0][0] + return json.loads(body.decode('utf-8')) + + SAMPLE_MCP = { "searxng": { "command": "mcp-searxng", @@ -52,6 +58,43 @@ def test_empty_config(self, mock_cfg): assert h.send_response.called status = h.send_response.call_args[0][0] assert status == 200 + payload = _json_payload(h) + assert payload['servers'] == [] + assert payload['toggle_supported'] is False + 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): + mock_cfg.return_value = { + 'mcp_servers': { + 'searxng': {'command': 'mcp-searxng', 'args': ['--port', '8888']}, + 'web-reader': { + 'url': 'http://localhost:3001/mcp', + 'headers': {'Authorization': 'Bearer secret123'}, + }, + 'disabled': {'command': 'disabled-cmd', 'enabled': 0}, + 'broken': 'not-a-dict', + } + } + mock_runtime.return_value = { + 'searxng': {'connected': True, 'tools': 3}, + 'web-reader': {'connected': False, 'tools': 0}, + } + h = _make_handler() + _handle_mcp_servers_list(h) + payload = _json_payload(h) + by_name = {s['name']: s for s in payload['servers']} + assert by_name['searxng']['status'] == 'active' + assert by_name['searxng']['active'] is True + assert by_name['searxng']['tool_count'] == 3 + assert by_name['web-reader']['status'] == 'configured' + assert '••••' in by_name['web-reader']['headers']['Authorization'] + assert by_name['disabled']['enabled'] is False + assert by_name['disabled']['active'] is False + assert by_name['disabled']['status'] == 'disabled' + assert by_name['broken']['transport'] == 'invalid' + assert by_name['broken']['status'] == 'invalid_config' def test_secrets_are_masked(self): """_mask_secrets hides API keys in headers and env.""" @@ -75,6 +118,10 @@ def test_server_summary_default_timeout(self): summary = _server_summary('minimal', {'command': 'x'}) assert summary['timeout'] == 120 + def test_numeric_zero_enabled_flag_is_disabled(self): + """YAML numeric false-y values should not show a disabled server as enabled.""" + assert _parse_mcp_enabled(0) is False + class TestMcpSave: """PUT /api/mcp/servers/ — add or update.""" diff --git a/tests/test_issue696_mcp_visibility_panel.py b/tests/test_issue696_mcp_visibility_panel.py new file mode 100644 index 0000000000..999192e5be --- /dev/null +++ b/tests/test_issue696_mcp_visibility_panel.py @@ -0,0 +1,46 @@ +"""Regression tests for issue #696 — MCP server visibility panel MVP.""" +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] + + +def read(relpath: str) -> str: + return (ROOT / relpath).read_text(encoding="utf-8") + + +def test_settings_system_panel_contains_readonly_mcp_visibility_section(): + html = read("static/index.html") + assert 'data-i18n="mcp_servers_title"' in html + assert 'id="mcpServerList"' in html + assert 'class="mcp-restart-hint"' in html + assert 'id="mcpAddFormWrap"' not in html + assert 'onclick="showMcpAddForm()"' not in html + + +def test_mcp_panel_renders_status_badges_tool_counts_and_empty_error_states(): + js = read("static/panels.js") + assert "function _mcpStatusLabel" in js + assert "mcp-status-badge" in js + assert "mcp-tool-count" in js + assert "mcp-empty-state" in js + assert "mcp-error-state" in js + assert "mcp_toggle_followup" in js + assert "api('/api/mcp/servers')" in js + assert "mcp-delete-btn" not in js + assert "showMcpAddForm" not in js + assert "saveMcpServer" not in js + + +def test_mcp_i18n_includes_visibility_status_labels(): + i18n = read("static/i18n.js") + for key in [ + "mcp_status_active", + "mcp_status_configured", + "mcp_status_disabled", + "mcp_status_invalid_config", + "mcp_tool_count", + "mcp_enabled_yes", + "mcp_enabled_no", + "mcp_toggle_followup", + ]: + assert key in i18n From 423e5d5be81cd395984194e94ed67a5ee4c3fbae Mon Sep 17 00:00:00 2001 From: Michael Lam Date: Mon, 4 May 2026 17:42:47 -0700 Subject: [PATCH 2/2] feat: add searchable MCP tool inventory --- api/routes.py | 184 ++++++++++++++++++ docs/pr-media/697/mcp-tools-search-filter.png | Bin 0 -> 65004 bytes static/i18n.js | 64 ++++++ static/index.html | 8 + static/panels.js | 56 +++++- static/style.css | 6 + tests/test_issue697_mcp_tool_inventory.py | 136 +++++++++++++ 7 files changed, 453 insertions(+), 1 deletion(-) create mode 100644 docs/pr-media/697/mcp-tools-search-filter.png create mode 100644 tests/test_issue697_mcp_tool_inventory.py diff --git a/api/routes.py b/api/routes.py index 0de35c0094..a95c04744c 100644 --- a/api/routes.py +++ b/api/routes.py @@ -2570,6 +2570,10 @@ def handle_get(handler, parsed) -> bool: if parsed.path == "/api/mcp/servers": return _handle_mcp_servers_list(handler) + # ── MCP Tools (GET) ── + if parsed.path == "/api/mcp/tools": + return _handle_mcp_tools_list(handler) + # ── Checkpoints / Rollback (GET) ── if parsed.path == "/api/rollback/list": qs = parse_qs(parsed.query) @@ -7222,6 +7226,186 @@ def _server_summary(name, cfg, runtime_status=None): return out +def _mcp_safe_display_text(value, *, limit: int) -> str: + """Return redacted, bounded MCP text safe for WebUI inventory rows.""" + if not isinstance(value, str): + value = "" if value is None else str(value) + value = _redact_text(value).strip() + value = re.sub(r"Authorization:\s*Bearer\s+\S+", "[REDACTED CREDENTIAL]", value, flags=re.I) + if len(value) > limit: + value = value[: max(0, limit - 1)].rstrip() + "…" + return value + + +def _mcp_schema_type(schema) -> str: + """Return a compact, non-sensitive display type for a JSON schema node.""" + if not isinstance(schema, dict): + return "unknown" + typ = schema.get("type") + if isinstance(typ, list): + typ = "/".join(str(t) for t in typ if t) + if isinstance(typ, str) and typ: + return typ + for composite in ("anyOf", "oneOf", "allOf"): + if isinstance(schema.get(composite), list) and schema[composite]: + return composite + if "enum" in schema: + return "enum" + return "unknown" + + +def _mcp_schema_summary(schema, *, limit: int = 12) -> list[dict]: + """Summarize an MCP input schema without exposing raw defaults/examples. + + The WebUI only needs searchable/displayable argument hints. Returning raw + JSON Schema can overexpose server-provided defaults, examples, enums, or + vendor extensions, so this strips each parameter down to name/type/required + and a redacted description. + """ + if not isinstance(schema, dict): + return [] + properties = schema.get("properties") + if not isinstance(properties, dict): + return [] + required = schema.get("required") + required_names = set(required) if isinstance(required, list) else set() + out = [] + for name, prop in properties.items(): + if len(out) >= limit: + break + if not isinstance(name, str): + continue + prop = prop if isinstance(prop, dict) else {} + desc = prop.get("description", "") + if not isinstance(desc, str): + desc = "" + desc = _mcp_safe_display_text(desc, limit=180) + out.append({ + "name": name, + "type": _mcp_schema_type(prop), + "required": name in required_names, + "description": desc, + }) + return out + + +def _mcp_tool_schema_from_payload(tool): + if not isinstance(tool, dict): + return {} + for key in ("parameters", "inputSchema", "input_schema", "schema"): + value = tool.get(key) + if isinstance(value, dict): + if key == "schema" and isinstance(value.get("parameters"), dict): + return value["parameters"] + return value + return {} + + +def _mcp_tool_summary(name, tool, server_summary): + """Return a safe global inventory row for one MCP tool.""" + server_summary = server_summary if isinstance(server_summary, dict) else {} + if isinstance(tool, str): + tool = {"name": tool} + elif not isinstance(tool, dict): + tool = {} + tool_name = str(tool.get("name") or name or "") + description = tool.get("description") or "" + if not isinstance(description, str): + description = str(description) + description = _mcp_safe_display_text(description, limit=360) + return { + "name": tool_name, + "server": str(server_summary.get("name") or ""), + "description": description, + "active": bool(server_summary.get("active")), + "enabled": bool(server_summary.get("enabled")), + "status": server_summary.get("status") or "unknown", + "schema_summary": _mcp_schema_summary(_mcp_tool_schema_from_payload(tool)), + } + + +def _mcp_tools_from_runtime_status(runtime_by_name, server_summaries): + """Read detailed MCP tool payloads from runtime status when available.""" + tools = [] + if not isinstance(runtime_by_name, dict): + return tools + for server_name, runtime in runtime_by_name.items(): + if not isinstance(runtime, dict): + continue + raw_tools = runtime.get("tools") + if not isinstance(raw_tools, list): + raw_tools = runtime.get("tool_schemas") + if not isinstance(raw_tools, list): + continue + server_summary = server_summaries.get(str(server_name), {"name": str(server_name)}) + for index, tool in enumerate(raw_tools): + fallback_name = f"{server_name}:{index}" + summary = _mcp_tool_summary(fallback_name, tool, server_summary) + if summary["name"]: + tools.append(summary) + return tools + + +def _mcp_tools_from_registry(server_summaries): + """Read already-registered MCP tool schemas without probing MCP servers.""" + try: + from tools.registry import registry + except Exception: + return [] + tools = [] + try: + names = registry.get_all_tool_names() + except Exception: + return [] + for tool_name in names: + try: + toolset = registry.get_toolset_for_tool(tool_name) + except Exception: + continue + if not isinstance(toolset, str) or not toolset.startswith("mcp-"): + continue + server_name = toolset[len("mcp-"):] + schema = registry.get_schema(tool_name) or {} + server_summary = server_summaries.get(server_name, { + "name": server_name, + "enabled": True, + "active": False, + "status": "configured", + }) + tools.append(_mcp_tool_summary(tool_name, schema, server_summary)) + return tools + + +def _handle_mcp_tools_list(handler): + """List known MCP tools from already-available runtime inventory only.""" + cfg = get_config() + servers = cfg.get("mcp_servers", {}) + if not isinstance(servers, dict): + servers = {} + runtime = _mcp_runtime_status_by_name() + server_summaries = { + str(name): _server_summary(str(name), scfg, runtime.get(str(name))) + for name, scfg in servers.items() + } + tools = _mcp_tools_from_runtime_status(runtime, server_summaries) + source = "mcp_runtime_status" + if not tools: + tools = _mcp_tools_from_registry(server_summaries) + source = "tool_registry" if tools else "none" + tools.sort(key=lambda row: (row.get("server", ""), row.get("name", ""))) + unavailable_servers = [ + summary["name"] for summary in server_summaries.values() + if summary.get("enabled") and not summary.get("active") + ] + return j(handler, { + "tools": tools, + "total": len(tools), + "source": source, + "inventory_scope": "already_known_runtime_only", + "unavailable_servers": unavailable_servers, + }) + + def _handle_mcp_servers_list(handler): """List configured MCP servers with safe, read-only runtime visibility.""" cfg = get_config() diff --git a/docs/pr-media/697/mcp-tools-search-filter.png b/docs/pr-media/697/mcp-tools-search-filter.png new file mode 100644 index 0000000000000000000000000000000000000000..3d681893f994e62f460fd0506da4135f7e504793 GIT binary patch literal 65004 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�UaM0CN5+VV`YlPEBed~q9*^vxveEaa#7npcZyXyL)1DJPC8XK3LgOL& zqCpbUw9<_=8-K|k7m6HhQOOFQQj7|kTw0BLS-zH%>cZ`1Hkp*SZAf+0ldg<4JaUD5 z)z~msgQ=z#P?e+C6TdKSl-Jc4f~8I+LUf)nkKGz7VQzS|{!%}ciS|GtC=MAi)=>~# z6^id-_sG4OQ^Qb_S4(nEIlndBZX@5glTDryS}>y)Pa3NUfp+EO5*HS%@a^eO42(pJ z9hM4|VI66x#X-olQv9;6SWH7=Q<}qyYHL<3otsjz#ic(eK_IJjVdk(++|Mh4CSP4@ zK%P12=Gqv*5u`@-gW^OcD#@PCbnX*jToqW1kX}G-F6Y1!Wxu+@aMFl;JA&U$f~-3? zR*@^ua;T9ly}iF;zovSz*wDOj-i+?J)nF*vI3-AIpKVC7<6|Cqfqx^%9Hk~r)o3cQ z=2EgnV3JtEFGaVc6@Vp=lgI10R2_h=Z%`8YY$q9u09)@n+M^f|@JgbUUupiP#WiK0 z=dxiUk1K8!ACLUl2r}x4J>5;@E*a~t2hGTFxHqXeP7OFjVqnFbkS3)@7c4KCdv564=X9R2=9;n*G~Uxd%fVU&_ZV75b<1xx zs{6&K^ z!BH#kqK?50!ebUz7PyFW&{lO&j_3yGeB$xR|EvV96CR+s&HcQp&!@E+N9o)dx;)Tz z;tt#U6TX~b`>}s+(j2Ab(R1fQ>7t-oK&T~oQXF}(x=-RtZZS-YKkqp^OyQR#15S)0 zL-U3SJyj*`!SV|RYFxPcw#!_PqZ{vx%J;du)grtY9yJQB)}dZrdo8A+ObyDCLN^7= z)2HN1XCk(ESZp9VPwSDZ%Ejsf0p@N~rf*AAsiu6#b2TJM4oQsU5xN7r#j{E;HEM>- z52zH1Eru7~)xRmSbRZad(CQCmXdn8(hWME}Tm=My-^2zT1SySqkDHhIFc$ujhxem| z;qeH-ODdOFk{EKNPmz9_UNz59u$#WM3RMSvsrf4UV}8M!u-H;$4!n7AYN_N)6MDUW zG%cSk6(&tq%H!sWaP+2EueDG2&{h}hrNbzpE)s#}fhVCx)MfrhQpW4*;NLwi+<7V2WW0xn^ zqa3~VWZ{FN@hCuC|C>|Lpf^u@uD;&>cz$;{g7@TbcKjo4fe=2NHBv~;?9{nXOm7{w zI>#a$?R#pYfwDWqDgXwY!sX-;)TTJ&+*I3Gk{vs7aco9d(?cn?wk7@gMBLA)M1+Ut zU`RWTM>|y^+xYsG5CABV_0swP807I*19x`24CC0L)v=UuQE2H|6^U=9sYg3;TOCf9KbA#Q!h}~`mEPGn@3Kbw`&SJqIELEA{eG-tkR@r zo>e=YL8^?XsZsPRd6*01e${C;_35TfsMEl=@X8=3J3P%M!=0^7`H0!nu)pFSXCiB) za0%w;(li5uD$;8!!bY=D6_6;^H$&h3evXdRR-XM6@^a9H9nn4|01bo7yL%%8e`SI;O4?#SKD#)Ml1=>j2n`~|PqD_tk{e}uKEX1lHRk2Q?q(-;+p+jSSJHW$V zhT>LQIwm}hss=LV4f?Iyp)waJexGBYYDKg;m2>EQ&p@Gf)@>VSsv)<{k{0_)ZIVK1MZrn?y@I;y* z;)t7*aS>TS8q_V;OUhHgKcUHJ?tOG`^~mUr2FX+%uPGHPZ_$m6_-q{wRg?HLrI5AT z(h}C#yoNvdX%*y0b+#^%6>Y+KvGTZHI*$9aCuqYlKubh5^D;9R#E#oW6YIlCtJUX* z3%Zc2=giC`@P1kfnkPJAHXE4WeN!|tU8tz0Kf}!C_~d$?pI$)Z`GzD{*#V_Va8e!4 zlXY_Rb4p5TmO_s2sl*?8Y8K5)^Z{;P!ICo7)I=u9*jcSiprgf3Gc0ie zT%d}r)HmijIJHJ(K~j8m`e~MDJ`rVuoD1-)Hb0FN3GSEhZ9-qyuU6gn5J- z;)AomD?wT`{77CZlNF8304>6sG4F*4e2fI<-)viU+KNN1udap^;>W&UPH&cp;7<;i zogn|@yzvL7#MA*uh)xM=wK>%;R8l|W#GUfg%t(^XQ|i7&Fu9S_^2p=_EGg$am6+9N z4*pg*g{2}SYsw;KI(qM0XbUN?({uEXk|jEoBuT29wk31_Ry#lN`AD6Lx9eHUA296hW^KsLtoU)i4yW(92-(m|5r9dMHoI;ZjNC@Y&eO|n;!Eo zKcNr{hCr$wRwFwi^l?AI+Mz7ZVqm4E>7$m-vMOIM;E=>wb9&bG;}Ie zC7b=Ouz+0->76;}&_w(xk@#w_gg3LpQj!p^!vAI^SkHJV?TLu>Hp*n0rbwEzg0L<4 z1v3{AXV?yNn{vTG^oPBQzne`ZiQkiyx*>}b&*Oz-%KrDc{dUP-;)pg(bHs_h>c zEEqtWy4;=-;f6ZSS3br3LXSf}zc{#Cag*nLII9A}*#5P0KlT6wd3)}Y#+9`$IN#aY zc1Ik}$}5*?Jv@RZnHURqi%rkmuMa}Ewtj7F=>4;eBy*#Bnc2L4EQ|Zy_I-i;>eZQZ z#X@{;ZZ4oXKRvp2h2iu4!)i6kw8^LxPcVaFVyuj#xvQKxhkNU8czc%dPY&C390tp& zxf;KL>#tPPGc&P(5_zEW37d-Z3-H(XUAPvg^tcx<6R9-PUI0OQoGD?0hJOP4jO#V% zTHbsBqSWuTwsYHus;82b&CKM?j6O$%yvP?7ho__?>&_wLOcA#cCrR{am(P+bC@wAz z4nlv{I#bE@DnvXz34nP2JJ>|`OH|n+RD!x+x4%;7u091Q@1*KEGA_iW~u zzs|6o%$z+mWK8h&6)93Gp`jJIl6Vfy=a(?}8*aJOPfJ1ZVXT@Z36XIV(!V4J4HfQB zAj;`Mi8?6tRp5_64kg83)i58|OU?4ThNoRWt2dGZP_LdNXrZR^04WwVG04oI{R=sf z4D>J+8k95YkmNV!|9oAfY}nfBfs-rnf)&5S>#4QBpK?q5Q>W$tl+5d}X8{uG`#lR? z(R%{VqZSa^)72yh>HX74$^)R(N09$UFDZMG`i|T1nX3bp?iq?0L$58J%3W|`GCbKT#~6hIh_KD9pVKijQMe{Yu` zpEz0INz(D;jg%osDBnAFx^y+CiFMyw413s>YVwfmUAnaOCb)A`f;N>h`Iv^~{k=PU;u=2jG!!EjN^#x(H6;2-xd2771wd?J>j{{#Aozj;-MVr6Z-5BiP z>rA*;0$c#iO-`5DatxjES+mc5+F5Qd$G4yW$1@m6gd`1PVHvqko$C8ux*&nF;BfSo zef~a8v)k75PCF?=dwA*LGL~+bvyuyPCb!+^Na|xalKN@af$lc$*E=Gvay#(@%1euq zf-v*j*>A)AiEOcmvF^G!viq?{i2lTUa8&_mu*#~LaY;|uzpFu%X4V#cmYMaG^&iPy zk?h1rWHrz<AN)VN3VR6jgbUaZYoQSMha{dimjL&o?`Ryj7iIM`%YN<=69rB_sQG+Q+{i z6IACy*CEaccFH60syet=eg~ZxPD-dd8}NstPvP2;Xgf7}mc{mHZIVeU44dzJw8Vl% zubiapue@l+_XD-GZyKA2G@zkq`AtpxOVlYX7wi=Zw)$wFqv$t*9D}&ztBnq!S~~B5 z!xYOuvM3vkwR=2eD^mKoF(H>p$y{VU6r!G7YkB3cTxvl?dvU1YdhYo&-7u@>apzsS zsNum?6vfBn;!l@EcRl`gXzapDEtR^dp#DSjQ|HqyUqn>gV+?4zm}`>0?r!I?*xo5& z>AmNi?INL-lJqj37Ae%&1u#Y$8*4|4B?kq=I-Tx3)11Edm`@KZ421~MQ@tbS^PmM> z)>?uB%IeD*h6hA#RY3g#`$b2Yg29aR^sGe`v9e1;a)5<>reC(USuQhDQ6b$l}Wv zYa<+?iD+ZOi}>6r$)2w45pWEmRghro2f~n%)#}Y!A?nP*-PBMNe;TaRNo>AhDa&i) zT-VI82hd~w{NtbjnO zR+)&`>}bS)nWUA>gck#(eVL|v@8oPeNr;OrQx$4l?a@P-MSqs=T)J68S1E!yD*90DCHffTVw*u zd_#FoybP3T9ojtn59XhEzR3wc5_M#fnpdt?Z>Qc0+z$@NI(oDHsRX4kV z%twuTNy@ZHPXt9P0B@B5_xydna+P=lZV<3CgTnsjWe#;P3)J60MT3Ttf&TZfnDn(l z%vcU!Caf`xZwB~&MJfMhEr3Ak`O*MWoabgH^+q1$t*;`Rsi%ye-k6DVY5(GA~ii2W&$3wy$Yf54}a%m$deDLMH(sw zYT4A=mtTM>35U_>6}%jjl$Lm4McZK%YINml{MZTZ^M29=61DRs2Ts&yFxN8)pFaV{ z5)_#a3OnD}Ef>W0gO84qH}ts6G5&s)Sl5dbqwP6ww=)z7Oh>M28aS*W_s3okjDH); zN&w#fVr>n;iP=ZQ@{Ej%`m);CSgT!olob(?0}v?wnUr2$sif#R93R+R?yPRxFp6kr z=NLM>IuieF2uKg0Z}{xw)9}m#$n;7S=zlH*)9ij25rC5yO*~ zfJrUj$p`=%R3szIMGcJp-HwUAMD%>%NMGgTBrp4~${tF-nvli>ZC@}8eu3xK1Z-&l zWQEl-n^?BUtaJLHX?~sq$j=H)Xj}~SIx4E{WDB-vivGM2!iBT?jj`?Az*tpPhB-MV zEno#6z5EA&^uc5-4bVCU`ehZs05Vt4YDB%w6RhpEo@)r@Ofc>aWVf=jV|t!Qw{Pms z6T8al8t*2?IAAnv=j{VY9Rcdds+ZS&hp)B*w`>D00QMh@^*~3hWaa|10+XZ>v5(Ts zX_C(;k^0WnlqiOCaGMRDn>PHSJRcaityUhIO4$=K33L9rzoQ9CCB;auFpo=ttF;E7 z*|5E#2h%e2;jEhbOTLArr3=K>46-?fqE-iJecyM33n+V+mISl~oIA zKSlBX6%zYrYlR=r(@?YWtN80{IdA96B#>V&1F4RDQUR4S;u`JdZQ*LwbemdeobStQxbMT}0E>Wz=-@%Uim zmiZ}M%lln{D&B;nct;aZUT>*E#fBrnaP=)Yzzyxf@=((-CkO^$CFR^qn~}A35R1}|Fp$ocp&0(xUy`K8NNyuOYgc^ zM4uaBwT+`I4niSWq<#xIEz)GG=>ho$j*Fs(GJF!X^)gekf!wABtSoOJOSI^MKZ@epL?}My)q8eT7tYbx0CurQ4_Vy`@?HJjyYoWll7?HK40~{RP9Ld;7=avdjR`7O1xxZR~8GWeoyyjob^hGb&w) z*k6XB+?9@S`xno0@fhBO9 z9vh2`k64Yu$l?p@PbcC-M&dW6%LEeSZf*ft^hyZ|CX}d*)$s?_zg(+kp3j;V_8FK< z#-HFyXF1n5`w(E*Lmx=ha@g{_`17ExB@K>iX({O&x;Evz%vu2n9Uo$e%+^v0!o~Do zMJk*=)E{D@S)alxxkF1DqH~B^XkjJ04UUeZxsaQrPuM`<4;ec%4Ls^?9QIYZh|lL~ z(lZ8y2N;*fiqNvG)oxBK6C8O(?$(ra3>UhYA&4t2_^?|x6}UA~XUDXIyIm+^-EZ(S zXQ^1!dJ3;w)>P&ew8VaWvD{9Itf54C0z02~!3W1a+4j0fj_DXb^dLN+5aFK_5=g>+ z?DkUjsyI}ON&11I{8nV8mXPTXV$-5Q>h8DB1;XX@kfVne!j($E^+-9#UK$RQHox1@ zS;a!f8Z|UUQXLOOXlnK55$6w&@niech4q2}!~yJ93U|9FI*+ny~Gv zcMZtUfB|;>qNJlcnHkQ~@4cDsnKh~QM^2-mr2I490UHhrZweYx1Kh!0&6ayE z-;K8()REPXkKhM5gvIM~x5nhqBKgs6QopYWvd2yK7L`hTTzMqm{+T|+0!vV~va+%!dp$%#_X!CJ<8`lu z&Yyz|VD`=by&qbktW!l^H`dh0>Gxq)Eq~idH*^NbtHmX>mlwZYF1tPt^}t9jajvrL zibSwvz1cJE-pcX!Qz#Qk+!V#f*|vLO(KLEW%Jb`EE|2@$;Uq6A8X91Vb0&t}q_s(g ze0)q}^#76e-ce12?b{$WP!SQNS3!^t(xofCSLs!H?+|)a6a)mMHvuUD5du<@&{64x zUIL*??+GpRvV-sMJ!f~%_wAlN`}~=i%slhVJa@V7a@F3vw4aLj8ai8e0PCXE;>qMvHn)z055are5mzDm6E z1mZjCrGnCn9abkM)UeGGyJuMN=T9%pFM;}#n|O{wfbcuknO$lFU(qKNvEFQm+g4U1 zwx)XLauwFUb+Wd_b`bNj`ibuW{q*MaM;{K8TW@>{5bjOiMiZ4%)8ie5vk(oC~QI7T8m7S6Tzo@4xL*<$bZuZOGB55Ou1qU`r*2 zyNWuR4Q?_p)2y=dGN6C%tHV>V{O%|)z67ZhlC%80%Ij#iMmE#s!ggIdu?U{LlQJYB zYUV2FJU!@scry?3lKN!3*wl%;XX1$Q>Li_#n@0temp#W&TV4ix09%xOZSnY3@l0f9xG|hp>&;Ecc>Bhz5O@EFa z9U>UPl+g7TPH&!|aV@vr@8-r+7I&W<>PE0vV9}2ZINtSE?$ZlTz+xdYk(Tk=xl=GN zL*@~e-edk*zPsy&9k}mqQ<^NCL}Qecp$)@W0_OPfj<{XFWTQ!=#8LCBi@CfSf&BVT7?7Nq4kK%RYQH zxiUQaPR(g`KC%0>kIrwD(T8cT!Q;1=II*fq>&a28xez|X-GFGNj zGX1sJwk+!B?|$ZIrw>gXLKFA?ND$sD?S27wTg{V){T!dl)uJfoI3|7dW-sAbY!&fKXfL{yC0cS*Wy zQ6NN<6^ud1&#g0tNgeweEPPyB+aHP&iXic$6%2d+xN@Ua5Z&fA80^s^x`)~`r#5B- zh1IOW6PG1gL{2WcFNO{1RhT|-ktMY;N=qf@33r$jNDljlowh67Awe5g(OApr)yiI+ zEHmaBDxWsX@a@3b#u{{gw6onrx)*fBf^{la8~7Zpx?dQmC-w~vivAMa1rtS z$|#eDS0i(bBT~EIRcz#1#8%fur$ylJ6DkeYVdb2syV=rp2>{+{ENAcS+w zmxDt_?z)|^&f+TLxL>-z47v%bg%N6*HK(%GN%7~UHWfal&B7v294rE$uBvuDC-U~m zAf>Q{cG*`FSa=g-3ZFosvJKhOO7xTtN&380Dp z$qU$+{`Y+i0;G7MXYluz0OS;4hTndY&1n7rgh9FN{B2H3J0-qc1|z{tGm?`Ngc1Fw z{K-_b+*8j#7ksHJnHPVUBU#oUs6i6L`XJ%{J)#s`&*vCQcWToq)hQ5}{rTY(`A7Z- zx(*{rLUM~Q^e0bTI$o+JWPYdH;3WT&%-NT7r~hI$H|)%InYPe)47aE9DRaeeo#nyi zL|m5FmeG$?sv63t{T#D6Pl_D%ZmVFBH=MH8+k-)ZBdC4xPVh<0&GwU;s+SsBemtl3 zUJhMy-~UO{AA0qPa;l~eTKQr(uk8$?XFqLwp{Sm- zl$nx16?z$B0;ArOXr>TqwvmW}ymVGs(p|}4jv-YTZECCmNbTW`CN&&GcAM;u+w zSg~BiNEbf3`WL?SorFtfIEA}QB_<_vOY3gcYe5PY$|d!8aKiAI;kpi4Rv5HNKv+CM zeJ^ZCfPZWZL9a3$YR<8@hO)5M>HuWYZ0&YCX?_)@qOGCR11qcb4^9{OM_9<#cPRu8 z-jO4D+i=k9d?B~vap>h7CGqyOKjziuW+slq3p1*-;3#v^I@>Wot#)sd$&NI3N@#bw zZ!cRun<`t}-WD78{y`wZVmq1gVIjFmkc{n*NH>6D`t7q-FGdQ$e2b6KFV2pi2$0^G z_!KX_i*W-V&<(9BV$Js5mNB*5Quci`9duK5Z?t|4SIspZN$?-Bp(K?DD_vu4vn?#K ziB5N+fxint!72+13JOA|p`0poUAb5GZ)VHSQ?Zp9>az6jf8PNH3Gs9dtI@KtkB^}yStQDpa zXuBwSHY^mkm>P$$P2WS0f4^mLWo1m9>cNetx5*qAayn1#5U)8C64~4`YO`59#aXrF z+n`?V)-Vbm%)IZR$X12L?RnY^3z=MswX8EasrSLHgFdKnc&g{_)nZZfl8I z(_#tHO%YLOsi!7&23lXP{lGyTz$tbY`k8j$67eTX^=0kY-RFY zg@~e>Vqf;Gny!+(+G>a%_Qga)_FGTxhLb?G(I_X*{9ff=Qrw|iMN3Xzm#V&zKkb&Q zazoD47tL;=AZD`U&Vk9Awy8g}VNL6q_vxAlT9k*&XHFa7?fO>7H;c3rymyat!aK>{ z`}Z#pKw2vjg$w2GG&WjnNJEs3g?uuls$@z&&NT`We}ET=@-F+DZ6+azi`#qOD(QKKRfq(7m7yJ)etcvtf_M3LEr?5Q%ty*cO%D$&UNeTcHq8J|C56{a&8l zSk?Sm|6HH```oP?Ks&xahGclZ1lyGBPqe^b@gc`LUD{`xf66`jZL2?`B@h^D#utI> z0udxe-aZAQVW5lYlR45e&8rZ!@-ls3s)6x-#Ov)oOA!V#O$OLO!>(+e(c_ElPFh+N zvT|?bT?IVxh;1OdKLjRRkV;ZBe&i}C8M?P59F9CiPr~-oE9IVT_q9nBipub_rj0rC z*^*ek>1Z#*pMKl3Vj<~YdDPXNON_FZhWQyDV4#PKo!sUkU{;OmvzsKnUwxg8H7_n?;u3qh=Lko{)i$6I6EmGx? ztDM`nQx2u56^QhMPbcau&(i!hVZk;B^c{h(#}t-Kf(A_Z3mzw2Wka-)S`mzD!CxNQ zk;7cmOekmqw~xEsZHoAI>^&Haz*V|#)8ZgZe|q<}9^9gr)AVtB-OQXx9KC4hZ>xyP z!i1|zs3ps6Icsb0tTcG-)2;%L3+ULF zcR5@mr!{1xT<|2dyy|RTobtxj0Hj6!(_JCAe^^%26Y$t0Ec5ud_;u2NW7JywU$y~S zFu~ku=~ASYhj*{)5yNAkDE!MQ0bW3dqjcaW(ER6tuh$@-B*Co3q`T48ACg<6w=ufC5?VsnMF6kxcYlOTOdsoN18dIyYp8yGfMSqy3pFfOq2!WDJNl zKX)(#vK#ILtM;pUwADN<^B%A@`O5@t>ZXu?j`Pcy&QC1dRtanJ#I#q*o*R^sI@Z!j?l)|#!1XpI9`50D(W^l*DCj%*C>{LHt~Ld*KVLMYe- z#Ke@@b~W`JjP(1M<3)9F+KD|lO1>M#ySa2qq;_bx&i%C*nj=-(pbhOxEcqzuhyLvP zwOBvffM@s8eTv;%4vWra1*S9@fWqAR2$h&P>+d>WJR43Vjl2{*hSF<9tGO#-pA7b1 zJT7Ja-|yZ(kl`(W2fCF&JIsjTKx^9)Acd=Lz*+H0P@~&iMd{Pp`7#cfy~b= zIp1KRb5Z^li@l~QgdXNC^p6$4owPOqsImrK*2#ExLAMFBH^XFh8&-ne^5v*XG04m+ z=z%j^kA@jQJ^gn%>b_J~hOb^0dJMGO3M zS*JWFqCql8o7rov#UHr?JCfF+uO{=Nj{Lotb{YI~?xF1B6WpE5R}@j7e!K)24uO76 z)$;PSFfAl0eW~uh3>rH8CW8v$u)Hd9Hx3TgL1szo@2(D!renZ&&Y7)Q(A8LX5u-q; z>BNP`#m) zl_ypFqK|1+>Bon;cF2iIT5W`@SYnr!XBk93j5nX{q#-f-(6 zSRj}y=}Ox&es~t((OArs@MRi2zj!JIKy1H~iVYbqtg{#MsZAfovVLI7V3RSg=+(`g zE=WgsUriE|^|XCYQX;o;;9=aulAkR`hVJa=$}MFW#+lWYtat^&G)k`nA3H|AdrJ$t z;Y_P0fi%X!Pa|y3^5->a-mMS=oBCxE+-XlDi*t6V$nEs#y@tMY%jLGIUJEn;af;Zx z%H4}9mo6|Vk`nbB6uXuQ@x9+fr&Y@inn%C*q`ZvT`IP7FPLQmtVII%Oq zgQKH0?>zo(OaRDCPd<{L*xn5^Hj2wm%@2_#<9DkBg<@GN)g1Rmu zt8vu-6*tLW{%kJkDg#IUijAOQ&*wA6{(H!mDQdjm;u^*S4)r&)i$p1XEBVu!4_pLt zwOykrl~}+0_5*PE*S_tp1Y#S%_L1Wcpy54UK;5t_F2I(LQmgapBU-M+}L*5M$KoBC1((kxD5shaF zxojmA73k$F-XTAEaJ>yuWu5!{{drum+BJ?HZkbw&U#AbQuj)wp@cfO}+UrvEB1ZiI z``U1&@??EFFayAm^6BKBuMgZJFQ37qtZ8tkxYlJt}}bCSFAX60g$t-}9F2^iD`!cMdgf|{C@OZ7<{AO4%cJz#sXIGY;-#6rTC*GPo;~=dV(fHLnEJQ>j>(nk z$F!5))c8lh=b-ZB5z}?Mi-3ntusb2m=`Zy@0)ef+#@1B(iKGXA0Z(XWnuCXD#k=pG zkp4g2$r>>aB-mX~TGCU>Lh5E@^Js_^#Zifxi%ek8VhtPA&{;=`TB3(Bxn|M zu@A1{PE*I{>C82F(~yh&2Lv}g5RNerq-3zI$j)Tx4~?POnEofF@WAhl-a zvAZ`!p7jXG0Kn7wXV|=5%>+PZD70;KbP2^H7W+j7sZg+xFYtkEC%`PKtz&vxl1*vo z`+;n5t=@mJ0B??gwnFmAbjkKFDT<4}?^Zt42=MT*iwva!DE9H{Jkaa~(EOCGo|82R z6y)myf*!D~7j-n*nzZmXW&cmK{Hj$j%_| z$X_mK6Y<m2sAjI2= zm%Cop0kNXipOsAEQz}vCy}t{B;~YvhyP$j17R1H#zI)Ne?phb1ci;#k*Eja|sks#_ z1N`-;bPwf9^Dl=~1D}0x5-`*-)3XT#wt4P{VBoF(4P=8OgxKV9cnpYyi z!sIau2oEk*HSEk;&x;cta~dnQDTI~&>+*@<+2~4)de6$8Ii;m&{QfM7F)6-~-TKfn zQTon0<~QXkCM{MM98hHPz{)W?g=na>+Kz+ma9b?V%*gK@UDmr119d;jRITDJ^*FJ{ z(79zZc#r4e1KmHA+%jGQDwer@%=YWGG)OYO_>Tdj{D z;C?dV-Va9q6kU$~x%56x>ht33KbL{h%Z{6e$f+y_F`o-7uGNbAoeHyBIJ4dWX*DL> z@_e*zsVjrF*mCV>W7A0!M>N)5#?R(zrss&A7TH>Lo7j#3@3`{`U?C1B-wR2Dio#be zcx?BZaiVK6i~B_X~Hn@i#j;oL&QMM zdBW222&+v}tWpndgoX%)!fmy;HQF}OiuvvpSgGI&e0MW5+ROG$i^HSR%6xoyGh+WW z9+-nSh}RiwPTmh&Sz`- z>^4E*^`u^=_&?88gq_MfcITGz5#&bX(^l%%Nn(R4(J_b6LSGWPFh-6vvhSLuJ#tne zmpy$DaCd4>pE#7q&8h_0p!a^OP~d%|e$>z+P}2a}Rfv>UL-1S%{7kk;&yw&3dkiUS z5z=_!E;owp7>V84#_V#U>K_%ueG~3tBVC7^FScUbr+WwQnd57nIP18HE^I9CQZ60* znS*FaM1@zU@lQSuI;c!jo(vqU^veMFK!(2UHo!HgG5yn@#Dn+ncd10|R`D0}u}O!F zC=8QYiBTG+;sK~jtI<&5$<=WU$1xKCWJ znk7SqW}6tVoHry@RY66@)&so$pP%tCsi9USFkVe#2%i?n@BV;40mPJFt*mEwl&2BpfIW5Cd=gJu z3s2@Y6fe$4*eMBU`tHBxYmxpCp&mUVsPr+yfx4B9fUxD6W7-L_wlLf`=34=qKsR*sBOn$QO?9uH|q zUqt$QYR|klIjKs@$alAdmP1}kp&~I8H1yB6+8J2(*TzkoHHwyxj-9Dy=uT_-R^lyl z71fZ{R?0UP13jXOul85!3-ZUommCvv3tRKQy-SaIXOD(f?oed^3$CVDV|(e?Gf!cu5bO!%MfOpW;X zH&UTrx3b9&eVOXkGk!!1|J=WDO{&;c@LyVJKeIbpS(BVc4&Li91mzzp^wjv3@#b;3 zAQ;M-^R?7;B#+l+hdow`!t8`8aTo82x=sFgZLF{Kj#)&1l3ZTdnnhHnjm$4?#MTpz z*z`XmsP#{okcd+8m$DP2&{|qpel|~PXOfw(h+eC}hnn2m;HU?!u>>$$&wV^o@8CJ&zZT_X;j9sdMLfIFCs@(R;xtAI=}9NC4QLETOp>;1 zWaPWLO1V6k!f0gjA%!#{UCATF?aXQ%@y|wobhBza-DhMwWK)M4!iqHnfSc$ z4?>(tY^*)^Kje@uW*5eJa5o<-w#ysD34ucSUZZT;4}3YC6{O8;YT_W%rfG#fyBQtv z0nB-ARBQLoDrUdbpI&w{M-_Y`@uT{AkbRkh*`~uHm{wFA-zO)ienvYBn^Q^+aa0Mc zai+xndTdN{Wr-3xT|Dz4Romk7ZX_oR{T`&MZ=;T^;up@y=-GR#W%!cv_q650oqGA~ z@Q(B+%U%jNzhQHv$by*fS7FfTAco$Y<>>JNGuJ(A7!iB2P&BH9+`HbYTh94gxi%Vb zHG>Q?sK_|PR2QsPXX{Go3!kH~vSn+wJzFmeh^VY^X%NJHd4!*hW()g?| zsr>x-%@Gxn?36JX31_LQCV z;xqjtyK_Hr3!N#+gOiS_lm?0PePzYrls1+(`9WRUBpfX|#>Ea#kFryV7*_VYudHBp z`R|3(d=IwEAA|~uM@(Dx?AZn1+K0?omU(cDEm_R@?3n!OrId= zrIF?B(wAS`^9DJM_7rrg6pZQr2&aq^pQEBxvjD)@RwfSqkPEaFLB;LfttA1wSpku32Gp*vUADv)rQXq~dy>hd7HmY!DarC8^7f|WI!^!zW z@{7J*k9Sl9eXDRshcl0gp5rN17THn}q?D6Yq@DN1Z=25sG%@D* zlYwUvX*gl%8(5Y3RhY~8h0}}WBNrF)D!nsJTf(i?Gu+*S_~x3Y+q2x}XLq#L)mPi> zEv4xatkENV89$xa{IM}SR@BW6SLt{lQ9jBr@4y)6^3lycFLO7u2Jx7l$zUaiYTUJi zs2n1x#BUhrs3$(aQp46qp`3vxCge4;%GoLUsy}Kt|L$C|E|VHG@xAi;$ZGa(Y?K$p zH%VBC?%8&zKuT>X)xplvsLjXEvDl@ANI|pi=2EAp6cm*AMEFJiiv?VA@clU0yuXMp zF*gps%nt`!OqFp%jX41zpz}JV*zwS}WOX+8z<6Q$uhYfp1MJJspocQb8}^q$+L*l# zJmLgJf7hdPyHx=fkGRq%P=mlwSHC@nK;5qBfn0-+$_nn7w!@es4oi1bw6IuLarTg5 zFx+t|ByleDmQie9IYE#@i`f0@_JJ?;SOKGD*2q~WX9&6pg_v5j_6oj zluVh-Htd`{UbKk2){ALRwi$WhD7HV5dX(m62&D8egj;qWZ%$LUbA=*De%vw6TIo%@ z3hp6jm5gW^YEtGI=xwA1>&$i~J2ye{ab>kX7yk;+aqx*ZOIpc-)?-79MMImseL3l? z5yh1zcQtNqG6;ow)Y43?@rs?|Fi9A_QxGG(rnN5#Y_2EPXmnYd*EM-cfvsaN`OqbX;3H{Cf;U}yzWSQ3@}X=zvz`i?b2;Eoq1shz)x|FUG+V4g$E z9!qeMz~NR?2!G|asGlx+y8~q1`p3qddc#b_G(F^4K5^U##3)noc#1cLXmPR*5SfKZ z@7r?5{e|JpnlVwI;?+b&hWp`LQiC&1E?N%n%0lKSY7YzbHItpZgd#&&(CK{+8(gMn zYmfHG&g1&CI)Y<~PWO`G)GUKL&@c5prah^d>4pqewGAQ*3zGy`!v3PGP%K0<___45 z6;6ywv(rNQ;;-9oN?YkuQpUzKhdH`5^T6|sr=$9u0Qz)A_P@^uRkG2tuIW$dq1z+= z3&XbfTx~VyXU#Q=f!opeGev}2=mOWLyieyz6kehGW&sa)Mg~Hl)$E|yb=JukM(iO> zK_SZ!pO!WCrOW}zmQYjFLPJJ2I>bmxqynWLF1)Fisnc(BZ?6Zh?<)kd{nSkCuk&_y z6&yZ*EQJW_{sZPRiE;|hhI8!$rfVNnJbB31G90cH%}Y14ZwSzCsTK^Gm_&=w#r?K= zG9YSlPm%%AY)Pc5vOZ(|m{4%oHkpD-9VpGkJ5RcnrIMB`6_N7LPzAFk|%R`59 ziT0z+jgR|PhLy!(lG0K10s(IcnG~D@r+?4MwjA>my_I~Qn5YY@f5{2!2AI)vJgx?2 zFWxHnJqu_CCx}~-%Q6|f;#Q{w)vu|b>DNkYoH`f|sJnQlLv4MQ(VuK=s+=o=Jd)O# znqIM~OsQ|^SJ<4A7;BubLd@*C#lKCV4Q%`u@T<~e}{=@d|fHkJY!7u0S zl%Nay-=BrSVO7J00I92#D5HK<_rAj~n+a9LOIeD8FrpBS9lS&JU%*V>{=DIF#s-q2 zB=Ylz`$lId9iIOdOX;sGwj8_)ZqVzMl#-%UFRDpTPj7DKYYTVy{hkaeGP|8Kxy{L% zZSh5E(Z+hEJv#j?Aw4Am8`H`!SHpJeSJO*C1pfUkEFdsEHkOoXZ&uT_v};C1lR4W- zXkT9Evl!cPr?qush3n&U+`W`SadDPTWuFgZ1?Qiglg}Q2_(izZUpy1yw8c5RW{Ao# z4vo3-D~(!*8t*N^vmAib2!dt;nRfX{n+abua`9Uh()sXPGge$%xsOk_%71X5RSVUhl=Q~;!n z_f|q4cvxUOxe3hh`iHyM=K_QI(KXnOhxh4vHGuKIJi$s)up$W4bTr$zS8XGgD$=7| ze=z;Wj$($T`pd9k)4};s+Oz23fuCjG1F4eX=}`}moQKJ)e50SJ6nRE!>S83vC; z3-hHEva%6^TIVxu9?rF$2-Tm9`-C~^exZ;x;u@ynYixag3wc+esf$iC0Sz3%$4N<`ywp&CPzVZH!E6n!B6@ zo>3ooPyOE5SZN#X5!N-wy$XKmh6kQ^(hD7v4(|CuDYAT8Zzq>I#6BIX6c?11OlC_3 zdA9<3IL4_~2VWB^C?7DG`rE_FZt}H=wq{(P(S75-3SpXCn7k?^MDq+@XcB z3s32U^}2ryS<`gjR=CX4W${2Vz|nP!Ttzm)>r-7`kE(CU)@E| z>|MT#sBT&~9dqAk2*NT?R+YO|1dgHlijo?RvL737T9p5+G1T97d8{Vt!Q=OAq-9!q8{vV9#LLo&ZhSi>bNbP_ZUas^S|1GtqO|QlN%9P8frBqAU^0FYB zmO*qftn#8(&7#&;?j%!pU^X1r(t|V`K0m$eDF2f9Rt*_L*^nHu=F`ONl_$MK$ss%Z z?6#@@w&S`mHy0RQ+jVK5EzuP4CnWBfWR8cVVbh{-TA7YDe2cM#rs`~Tej6txZS2Bp zW@rJQ*7y69cUx423&A*PJjRhl$SF!@w8i-1GZLvfyd~V=vTf~z7Fvl?6sfgQj?X>x#nb(DL zJXa<=vYy6WjzOvTtBvqF-QEHjnqGicb4aYvRj+Gol&u#zUeV`C|NTc5fv<5pxm{^+ z>8zWfh(<0&S?Q!ZVY(W^AXy4C5!i-_XV0*$TTY>81gTIg^R`Z!Ir!;awKXjY@bGbI zRvTi={miCFbZb~A9Zd-EtZwED;PrZv5L>COkVA^dY=%IVyxLbKf-FJ3Dv4*46N&t- ziJr}QZ_3{Id@D7iF8ok;V;mjFYo}aMJ#$vu{yk;s!RCjPF8|`WT7X*B7cuq5#o0%` zJc16v-crUsRVJjtM$PhO^q$>qG`P7AX4>Z!9(s8@Mnz`a2F_AD@Ku{e)@}$D(2?R6 zl^)wt(aM8LEt~o>v+XQnBO&qRS#Y~}WB-Oh03C09T?;j zjG*h!XR!P>mM5}bFH!$dSjyOWx0_k4;oA$gR#$b^LAHmPdMu{#UzTU%D1wu1zw<9i z*YOu$IpPwkn1T2iPdb z)3LH3$0KvCJn!$5WJ@4&`Awn5fp?bqOy&ZYXR4dIz(b};5lWTVNa9h6&~7AG57dyc zEazw0ms%0|)CzDt=f6b$*$!ls z(2~1&V>OCos4Q&8nQ^mGpkNJI52vzp$TH2!tsbq|6dQ7)m$^eKg+|=q{+f09i z8#ttCQB|jA;*y|NU8?{)B}zS9(d`G!KBK}z2({)*15R6XwP_tfz4W%vv|#W&V=3U* zF(%387;(-_4X#ZbDkQ4k@;A)2OiO5Z!HU5zph-=3Gg>H-dF?^`fq6{Z*beV@gFuQzq|DlJ8yG7 zD?@|x1zH#1dX|=LC?ow=)?`Q+f9-KenkX+t&c3@=%j)aadxn2E*1SE`BZO z>lOB%yq^>0A-+XG7wZs0o^@z@6qrnYctF5L?^6y57>j-YEwn;IE>H&lV@MhsvMknbLz-Qi#>nIXrJmu>dG1J!J* zi8L8-uOFDSH09M#F6+>qpOM~2&ao$b7)NWLah>@=c#eXTQJdoi&(x|KP9|=c=32_5 zCC2@MC_1i38f>MFrf$+nT@$oVDIciPZ$d9GsJPROwJ6#^hczFu7XiFA23Tn9XTwz}GPoL7<`H3G^O^M#HIAIJ+JYsS`ck<`4nIFz6 zrvcD_tYTu@BF+y-QALKTszH{Pt8Mc&z{cLOV}UHWmrNu=c2DKPK&BV(1ea{_@QUKD zZNDuh5X01NQb{a&{54KC39!r%;r~-i_Wx+AUE6T~JptjSqWxbi;D2e?{X6*^!1aNC z!t|YTVqzL2b_!xH>)YGWn|67gwd=PKAshdnwnZiy6uiV55uqj zy;b|)rFzRJ8q0LlO?kK#usIkx5DX0`MRe5_Mhc~5B(>b&mD zbF?CqI=njj-N;@WJZ>T?*|K^TzX2K5=W7aEgVG1jPV9E%L}Mu<41pFzKOH&&(^%84 zC}?x<98!{4%cI*fJj_#p3A`NZ(MNS7UkMoP@AI6}^2(*bFk@*3#_m16_kxd&g?c}ySHqtHdRD7O0g^YV5xU}63XW-|tl#}q z)c`rP%IajpAi|U`W@kFj4(eRsDdel@Imwlb(;6C^Lz|OR=_z#16uU_Gj-!sj-w7_6 z%9)>!SVjs?0&k@C%{R1~1NOH&{q=%!Kq?P1i0UJ<3AV!^Vl`Dpn+;a0%S{jCui%~cKmTPzjKd`uG6NIc{F8wJSwza2KZ{;+f zI1J;07LgUaTKrLJFkBQkR!_twpk7qC<(6_M{G!h@pprD-2Vt2V45X-6a(>^?sJ*s%PvkH0}{t@=K^%+j6oMuli{ znS^Ea{;dYfY5Kfb{|3|k=bTW4UQAEo8x?eFzN=5Bj>(a?z13h~mHpg0uW|KrM1W0q zfocg7jSFZXQ@^N5ex?GjDs9WgpdfWVxUX z1gPxA&;iTa?8;)EI9-3F)G2Wx`&32e)|64{9=d479Sx*2j+r^>qt>|Nmno6%Q$+by zDBagqI6AcP^3J9%#m1=}i8tNUm7#`Ovt`}1PSa7qcrB|cO{n+PS;Iq)I-NwJD!L75 zY30;?PSIkevN#sR__oZ7DtFnr#n8gYAu4%cIAyp50cXTkyO*9&k|;pd$#YA1UwVoT_gYLhkOTvghezs_Dzz;bgDf zm0cz-FcW<@FNVi9edKTrVb+@(Ju^Q`$_jlz(1P7neRvt0CHp

Cj%UKxz&#yUqKg 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 literal 0 HcmV?d00001 diff --git a/static/i18n.js b/static/i18n.js index ea1b745c76..d39b4e48e0 100644 --- a/static/i18n.js +++ b/static/i18n.js @@ -77,6 +77,14 @@ const LOCALES = { mcp_tool_count: '{0} tools', mcp_enabled_yes: 'Enabled', mcp_enabled_no: 'Disabled', + mcp_tools_title: 'MCP Tools', + mcp_tools_desc: 'Search known tools across active MCP servers.', + mcp_tools_search_placeholder: 'Search tools by name, server, or description…', + mcp_tools_no_tools: 'No MCP tools are available from the active runtime inventory.', + mcp_tools_no_matches: 'No MCP tools match your search.', + mcp_tools_load_failed: 'Failed to load MCP tools.', + mcp_tools_schema_empty: 'No schema parameters.', + mcp_tools_runtime_note: 'Tool inventory only uses already-known active MCP runtime data; the WebUI does not start or probe servers.', // PDF preview (#480) pdf_loading: 'Loading PDF {0}…', pdf_too_large: 'PDF too large for inline preview', @@ -989,6 +997,14 @@ const LOCALES = { mcp_tool_count: '{0} tools', mcp_enabled_yes: 'Enabled', mcp_enabled_no: 'Disabled', + mcp_tools_title: 'MCP Tools', + mcp_tools_desc: 'Search known tools across active MCP servers.', + mcp_tools_search_placeholder: 'Search tools by name, server, or description…', + mcp_tools_no_tools: 'No MCP tools are available from the active runtime inventory.', + mcp_tools_no_matches: 'No MCP tools match your search.', + mcp_tools_load_failed: 'Failed to load MCP tools.', + mcp_tools_schema_empty: 'No schema parameters.', + mcp_tools_runtime_note: 'Tool inventory only uses already-known active MCP runtime data; the WebUI does not start or probe servers.', // PDF preview (#480) pdf_loading: 'PDF {0} を読み込み中…', pdf_too_large: 'PDF が大きすぎてインラインプレビューできません', @@ -1898,6 +1914,14 @@ const LOCALES = { mcp_tool_count: '{0} tools', mcp_enabled_yes: 'Enabled', mcp_enabled_no: 'Disabled', + mcp_tools_title: 'MCP Tools', + mcp_tools_desc: 'Search known tools across active MCP servers.', + mcp_tools_search_placeholder: 'Search tools by name, server, or description…', + mcp_tools_no_tools: 'No MCP tools are available from the active runtime inventory.', + mcp_tools_no_matches: 'No MCP tools match your search.', + mcp_tools_load_failed: 'Failed to load MCP tools.', + mcp_tools_schema_empty: 'No schema parameters.', + mcp_tools_runtime_note: 'Tool inventory only uses already-known active MCP runtime data; the WebUI does not start or probe servers.', thinking: 'Думаю', expand_all: 'Развернуть всё', collapse_all: 'Свернуть всё', @@ -2741,6 +2765,14 @@ const LOCALES = { mcp_tool_count: '{0} tools', mcp_enabled_yes: 'Enabled', mcp_enabled_no: 'Disabled', + mcp_tools_title: 'MCP Tools', + mcp_tools_desc: 'Search known tools across active MCP servers.', + mcp_tools_search_placeholder: 'Search tools by name, server, or description…', + mcp_tools_no_tools: 'No MCP tools are available from the active runtime inventory.', + mcp_tools_no_matches: 'No MCP tools match your search.', + mcp_tools_load_failed: 'Failed to load MCP tools.', + mcp_tools_schema_empty: 'No schema parameters.', + mcp_tools_runtime_note: 'Tool inventory only uses already-known active MCP runtime data; the WebUI does not start or probe servers.', thinking: 'Pensando', expand_all: 'Expandir todo', collapse_all: 'Contraer todo', @@ -3587,6 +3619,14 @@ const LOCALES = { mcp_tool_count: '{0} tools', mcp_enabled_yes: 'Enabled', mcp_enabled_no: 'Disabled', + mcp_tools_title: 'MCP Tools', + mcp_tools_desc: 'Search known tools across active MCP servers.', + mcp_tools_search_placeholder: 'Search tools by name, server, or description…', + mcp_tools_no_tools: 'No MCP tools are available from the active runtime inventory.', + mcp_tools_no_matches: 'No MCP tools match your search.', + mcp_tools_load_failed: 'Failed to load MCP tools.', + mcp_tools_schema_empty: 'No schema parameters.', + mcp_tools_runtime_note: 'Tool inventory only uses already-known active MCP runtime data; the WebUI does not start or probe servers.', thinking: 'Nachdenken', expand_all: 'Alle ausklappen', collapse_all: 'Alle einklappen', @@ -4437,6 +4477,14 @@ const LOCALES = { mcp_tool_count: '{0} tools', mcp_enabled_yes: 'Enabled', mcp_enabled_no: 'Disabled', + mcp_tools_title: 'MCP Tools', + mcp_tools_desc: 'Search known tools across active MCP servers.', + mcp_tools_search_placeholder: 'Search tools by name, server, or description…', + mcp_tools_no_tools: 'No MCP tools are available from the active runtime inventory.', + mcp_tools_no_matches: 'No MCP tools match your search.', + mcp_tools_load_failed: 'Failed to load MCP tools.', + mcp_tools_schema_empty: 'No schema parameters.', + mcp_tools_runtime_note: 'Tool inventory only uses already-known active MCP runtime data; the WebUI does not start or probe servers.', thinking: '\u601d\u8003\u8fc7\u7a0b', expand_all: '\u5168\u90e8\u5c55\u5f00', collapse_all: '\u5168\u90e8\u6298\u53e0', @@ -5282,6 +5330,14 @@ const LOCALES = { mcp_tool_count: '{0} tools', mcp_enabled_yes: 'Enabled', mcp_enabled_no: 'Disabled', + mcp_tools_title: 'MCP Tools', + mcp_tools_desc: 'Search known tools across active MCP servers.', + mcp_tools_search_placeholder: 'Search tools by name, server, or description…', + mcp_tools_no_tools: 'No MCP tools are available from the active runtime inventory.', + mcp_tools_no_matches: 'No MCP tools match your search.', + mcp_tools_load_failed: 'Failed to load MCP tools.', + mcp_tools_schema_empty: 'No schema parameters.', + mcp_tools_runtime_note: 'Tool inventory only uses already-known active MCP runtime data; the WebUI does not start or probe servers.', thinking: '\u601d\u8003\u904e\u7a0b', expand_all: '\u5168\u90e8\u5c55\u958b', collapse_all: '\u5168\u90e8\u6298\u758a', @@ -6989,6 +7045,14 @@ const LOCALES = { mcp_tool_count: '{0} tools', mcp_enabled_yes: 'Enabled', mcp_enabled_no: 'Disabled', + mcp_tools_title: 'MCP Tools', + mcp_tools_desc: 'Search known tools across active MCP servers.', + mcp_tools_search_placeholder: 'Search tools by name, server, or description…', + mcp_tools_no_tools: 'No MCP tools are available from the active runtime inventory.', + mcp_tools_no_matches: 'No MCP tools match your search.', + mcp_tools_load_failed: 'Failed to load MCP tools.', + mcp_tools_schema_empty: 'No schema parameters.', + mcp_tools_runtime_note: 'Tool inventory only uses already-known active MCP runtime data; the WebUI does not start or probe servers.', thinking: '생각 중', expand_all: '모두 펼치기', collapse_all: '모두 접기', diff --git a/static/index.html b/static/index.html index 3816b75119..6c0c7cea13 100644 --- a/static/index.html +++ b/static/index.html @@ -954,6 +954,14 @@

What can I help with?

Server changes are read-only here for now. Edit config.yaml and restart Hermes for changes to take effect.
+ +
+ +
Search known tools across active MCP servers.
+ +
+
Tool inventory only uses already-known active MCP runtime data; the WebUI does not start or probe servers.
+
diff --git a/static/panels.js b/static/panels.js index 0faf82d275..7adfb454f8 100644 --- a/static/panels.js +++ b/static/panels.js @@ -3920,6 +3920,60 @@ function loadMcpServers(){ }).join('')+toggleNote; }).catch(()=>{list.innerHTML=`
${esc(t('mcp_load_failed'))}
`}); } +let _mcpToolsCache=[]; +function _filterMcpToolsForSearch(tools, query){ + const q=(query||'').trim().toLowerCase(); + if(!q) return Array.isArray(tools)?tools:[]; + return (Array.isArray(tools)?tools:[]).filter(tool=>{ + const hay=[tool.name,tool.server,tool.description].map(v=>String(v||'').toLowerCase()).join(' '); + return hay.includes(q); + }); +} +function _mcpToolSchemaText(schemaSummary){ + if(!Array.isArray(schemaSummary)||!schemaSummary.length) return t('mcp_tools_schema_empty'); + return schemaSummary.map(p=>{ + const req=p.required?'*':''; + const desc=p.description?` — ${p.description}`:''; + return `${p.name}${req}: ${p.type||'unknown'}${desc}`; + }).join('\n'); +} +function _renderMcpTools(tools, query){ + const list=$('mcpToolList'); + if(!list) return; + const filtered=_filterMcpToolsForSearch(tools, query); + if(!filtered.length){ + const key=query?'mcp_tools_no_matches':'mcp_tools_no_tools'; + list.innerHTML=`
${esc(t(key))}
`; + return; + } + list.innerHTML=filtered.map(tool=>{ + const status=tool.status||'unknown'; + const statusBadge=`${esc(_mcpStatusLabel(status))}`; + const schemaText=_mcpToolSchemaText(tool.schema_summary); + return `
+
+ ${esc(tool.name)} + ${esc(tool.server||'unknown')} + ${statusBadge} +
+
${esc(tool.description||'')}
+
${esc(schemaText)}
+
`; + }).join(''); +} +function filterMcpTools(){ + const input=$('mcpToolSearch'); + _renderMcpTools(_mcpToolsCache,input?input.value:''); +} +function loadMcpTools(){ + const list=$('mcpToolList'); + if(!list) return; + list.innerHTML=`
${esc(t('loading'))}
`; + api('/api/mcp/tools').then(r=>{ + _mcpToolsCache=(r&&Array.isArray(r.tools))?r.tools:[]; + filterMcpTools(); + }).catch(()=>{list.innerHTML=`
${esc(t('mcp_tools_load_failed'))}
`}); +} function loadGatewayStatus(){ const card=$('gatewayStatusCard'); if(!card) return; @@ -3946,7 +4000,7 @@ function loadGatewayStatus(){ const _origSwitchSettings=switchSettingsSection; switchSettingsSection=function(name){ _origSwitchSettings(name); - if(name==='system'){loadMcpServers();loadGatewayStatus();} + if(name==='system'){loadMcpServers();loadMcpTools();loadGatewayStatus();} }; // ── Checkpoints / Rollback ────────────────────────────────────────────────── diff --git a/static/style.css b/static/style.css index a192a1ba3d..9b2fe3b837 100644 --- a/static/style.css +++ b/static/style.css @@ -2287,6 +2287,12 @@ main.main.showing-profiles > #mainProfiles{display:flex;} .mcp-status-invalid_config,.mcp-status-unknown{background:rgba(239,68,68,.12);color:#f87171;} .mcp-tool-count{color:var(--text);} .mcp-readonly-note,.mcp-restart-hint{margin-top:8px;color:var(--muted);font-size:11px;line-height:1.45;background:var(--code-bg);border:1px solid var(--border2);border-radius:6px;padding:8px 10px;} +.mcp-tool-search{width:100%;margin:0 0 8px 0;padding:8px 10px;background:var(--code-bg);color:var(--text);border:1px solid var(--border2);border-radius:8px;font-size:12px;outline:none;} +.mcp-tool-search:focus{border-color:var(--accent);box-shadow:0 0 0 2px var(--accent-bg-soft);} +.mcp-tool-row{display:flex;flex-direction:column;gap:5px;padding:9px 10px;border:1px solid var(--border);border-radius:8px;margin-bottom:6px;font-size:12px;background:var(--surface);} +.mcp-tool-name{font-weight:600;color:var(--text);overflow-wrap:anywhere;} +.mcp-tool-server{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);background:var(--code-bg);border:1px solid var(--border2);border-radius:999px;padding:2px 6px;} +.mcp-tool-schema{margin:2px 0 0 0;padding:7px 8px;white-space:pre-wrap;max-height:140px;overflow:auto;background:var(--code-bg);border:1px solid var(--border2);border-radius:6px;color:var(--muted);font-size:11px;line-height:1.45;} /* Picker grids (theme / skin / font-size): make the card chrome use tokens so all skins flip correctly. */ diff --git a/tests/test_issue697_mcp_tool_inventory.py b/tests/test_issue697_mcp_tool_inventory.py new file mode 100644 index 0000000000..4dfd4ba127 --- /dev/null +++ b/tests/test_issue697_mcp_tool_inventory.py @@ -0,0 +1,136 @@ +"""Regression tests for issue #697 — searchable global MCP tool inventory.""" +import json +from unittest.mock import MagicMock, patch + +from api.routes import ( + _handle_mcp_tools_list, + _mcp_schema_summary, + _mcp_tool_summary, +) + + +def _make_handler(): + h = MagicMock() + h.path = "/api/mcp/tools" + h.command = "GET" + return h + + +def _json_payload(handler): + body = handler.wfile.write.call_args[0][0] + return json.loads(body.decode("utf-8")) + + +def _read(relative_path: str) -> str: + from pathlib import Path + + return (Path(__file__).resolve().parents[1] / relative_path).read_text(encoding="utf-8") + + +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): + mock_cfg.return_value = { + "mcp_servers": { + "web-reader": {"url": "http://localhost:3001/mcp", "headers": {"Authorization": "Bearer secret-token"}}, + "disabled": {"command": "disabled-cmd", "enabled": False}, + } + } + mock_runtime.return_value = { + "web-reader": { + "connected": True, + "tools": [ + { + "name": "mcp_web_reader_fetch_page", + "description": "Fetch a page without leaking Authorization: Bearer secret-token", + "parameters": { + "type": "object", + "properties": { + "url": {"type": "string", "description": "URL to fetch", "default": "https://token.example/?key=secret-token"}, + "limit": {"type": "integer", "description": "Maximum bytes"}, + }, + "required": ["url"], + }, + } + ], + }, + "disabled": {"connected": False, "tools": 0}, + } + h = _make_handler() + _handle_mcp_tools_list(h) + payload = _json_payload(h) + + assert payload["source"] == "mcp_runtime_status" + assert payload["total"] == 1 + assert payload["tools"][0]["name"] == "mcp_web_reader_fetch_page" + assert payload["tools"][0]["server"] == "web-reader" + assert payload["tools"][0]["status"] == "active" + assert payload["tools"][0]["active"] is True + assert payload["tools"][0]["enabled"] is True + assert payload["tools"][0]["schema_summary"] == [ + {"name": "url", "type": "string", "required": True, "description": "URL to fetch"}, + {"name": "limit", "type": "integer", "required": False, "description": "Maximum bytes"}, + ] + raw = json.dumps(payload) + assert "secret-token" not in raw + assert "default" not in raw + assert "Authorization" not in raw + + def test_schema_summary_uses_parameter_names_types_required_and_descriptions_only(self): + schema = { + "type": "object", + "properties": { + "query": {"type": "string", "description": "Search text", "examples": ["secret"]}, + "tags": {"type": "array", "items": {"type": "string"}, "description": "Tag filters"}, + }, + "required": ["query"], + } + assert _mcp_schema_summary(schema) == [ + {"name": "query", "type": "string", "required": True, "description": "Search text"}, + {"name": "tags", "type": "array", "required": False, "description": "Tag filters"}, + ] + + def test_tool_summary_rejects_non_dict_schema_and_redacts_description(self): + summary = _mcp_tool_summary( + "search", + {"description": "use API_KEY=super-secret", "parameters": "not-a-dict"}, + {"name": "search", "status": "configured", "enabled": True, "active": False}, + ) + assert summary["description"] != "use API_KEY=super-secret" + assert "super-secret" not in summary["description"] + assert summary["schema_summary"] == [] + + +class TestMcpToolInventoryUi: + def test_system_settings_contains_searchable_global_mcp_tool_section(self): + html = _read("static/index.html") + assert 'data-i18n="mcp_tools_title"' in html + assert 'id="mcpToolSearch"' in html + assert 'id="mcpToolList"' in html + assert 'oninput="filterMcpTools()"' in html + + def test_panels_js_loads_tools_and_filters_name_server_description(self): + js = _read("static/panels.js") + assert "function loadMcpTools" in js + assert "api('/api/mcp/tools')" in js + assert "function filterMcpTools" in js + assert "_filterMcpToolsForSearch" in js + assert "tool.name" in js + assert "tool.server" in js + assert "tool.description" in js + assert "mcp-tool-empty-state" in js + assert "mcp-tool-error-state" in js + + def test_mcp_tool_i18n_keys_are_present(self): + i18n = _read("static/i18n.js") + for key in [ + "mcp_tools_title", + "mcp_tools_desc", + "mcp_tools_search_placeholder", + "mcp_tools_no_tools", + "mcp_tools_no_matches", + "mcp_tools_load_failed", + "mcp_tools_schema_empty", + ]: + assert key in i18n