Files
hermes-agent/tests/tools/test_mcp_enabled_reader.py
Siddharth Balyan 3e00a356a4 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.
2026-09-22 22:00:24 +00:00

42 lines
1.6 KiB
Python

"""Every reader of ``mcp_servers.<name>.enabled`` gives one answer per value.
The MCP client, the toolset resolver, the profile editor, the catalog and the list/status
surfaces used to parse the key four different ways, so ``enabled: 0`` was off for the resolver
and on for the client, and ``enabled: "false"`` was on in the server list. The case table is
shared with the desktop (``apps/desktop/src/lib/mcp-enabled-cases.json``).
"""
from __future__ import annotations
import json
from pathlib import Path
import pytest
CASES = json.loads(
(Path(__file__).resolve().parents[2] / "apps/desktop/src/lib/mcp-enabled-cases.json").read_text(encoding="utf-8"))
def _readers():
from hermes_cli.mcp_catalog import server_enabled
from hermes_cli.tools_config import enabled_mcp_server_names
from tools.mcp_tool_common import mcp_server_enabled
from tui_gateway.mcp_rpc_helpers import summarize_server
from tui_gateway.methods_profiles import _mcp_entry_enabled
return {
"mcp client": mcp_server_enabled,
"toolset resolver": lambda cfg: "s" in enabled_mcp_server_names({"mcp_servers": {"s": cfg}}),
"profile editor": _mcp_entry_enabled,
"catalog": server_enabled,
"server list": lambda cfg: summarize_server("s", cfg)["enabled"],
}
@pytest.mark.parametrize("case", CASES, ids=lambda c: repr(c.get("enabled", "<absent>")))
def test_every_reader_agrees_with_the_shared_table(case):
entry = {k: v for k, v in case.items() if k != "on"}
answers = {name: bool(read({"command": "x", **entry})) for name, read in _readers().items()}
assert answers == dict.fromkeys(answers, case["on"])