fix(mcp): one reader for mcp_servers.<name>.enabled (#119567)

The `enabled` key had four parsers. The MCP client (`_parse_boolish`) read
`enabled: 0` as on; the toolset resolver and editor (`_parse_enabled_flag`)
read it as off. The server list (`summarize_server`, `/api/mcp/servers`) read
any non-`False` value as on, so `enabled: "false"` showed on while the agent
skipped it. The catalog and `hermes mcp list` accepted only true/1/yes, so
`enabled: on` showed off while the server ran.

`tools/mcp_tool_common.py::mcp_server_enabled` is now the only reader, and
every surface calls it. `_parse_boolish` treats YAML numbers by truthiness
(0 off, other numbers on). Everything else keeps the client's semantics:
the off words are off, absent / null / junk stay on, with the existing
warning for junk.

The desktop MCP page mirrors the rule in `serverEnabled`
(`apps/desktop/src/lib/mcp-servers.ts`). One case table
(`mcp-enabled-cases.json`) drives the Python invariant test and the vitest
test, so the page and the runtime cannot drift apart again.
This commit is contained in:
Siddharth Balyan
2026-09-23 03:30:24 +05:30
committed by GitHub
parent ec21bd7674
commit 3e00a356a4
20 changed files with 132 additions and 52 deletions

View File

@@ -281,11 +281,11 @@ def _enabled_mcp_servers(config: Optional[dict[str, Any]]) -> list[str]:
"""Names of MCP servers the user has enabled — kept in the coding posture."""
try:
from hermes_cli.config import read_raw_config
from hermes_cli.tools_config import _parse_enabled_flag
from tools.mcp_tool_common import mcp_server_enabled
servers = read_raw_config().get("mcp_servers") or {}
return [
str(name) for name, cfg in servers.items()
if isinstance(cfg, dict) and _parse_enabled_flag(cfg.get("enabled", True), default=True)
if isinstance(cfg, dict) and mcp_server_enabled(cfg)
]
except Exception:
return []