fix(mcp): raise ImportError instead of NameError when stdio SDK missing (#31450)

When the 'mcp' Python SDK isn't installed, _run_stdio leaked a bare
'NameError: name StdioServerParameters is not defined' because the
top-level 'from mcp import ...' fails inside try/except ImportError,
leaving the names unbound at module scope.

Mirror the _MCP_HTTP_AVAILABLE gate that _run_http already had: raise
a clear ImportError with install instructions instead.

Fixes #30904
This commit is contained in:
Teknium 2026-05-24 04:44:59 -07:00 committed by GitHub
parent 6cafcf9c77
commit 5acaeba2bb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 30 additions and 0 deletions

View file

@ -1462,6 +1462,27 @@ class TestHTTPConfig:
asyncio.run(_test())
def test_stdio_unavailable_raises_importerror_not_nameerror(self):
"""Regression test for #30904.
When the mcp SDK isn't installed, ``_run_stdio`` previously leaked a
bare ``NameError: name 'StdioServerParameters' is not defined``. The
gate now raises a clear ``ImportError`` with install instructions,
mirroring ``_run_http``'s behaviour when the HTTP transport is
unavailable.
"""
from tools.mcp_tool import MCPServerTask
server = MCPServerTask("local")
config = {"command": "python3", "args": ["/tmp/echo.py"]}
async def _test():
with patch("tools.mcp_tool._MCP_AVAILABLE", False):
with pytest.raises(ImportError, match=r"mcp.*SDK"):
await server._run_stdio(config)
asyncio.run(_test())
def test_http_seeds_initial_protocol_header(self):
from tools.mcp_tool import LATEST_PROTOCOL_VERSION, MCPServerTask

View file

@ -1255,6 +1255,15 @@ class MCPServerTask:
async def _run_stdio(self, config: dict):
"""Run the server using stdio transport."""
if not _MCP_AVAILABLE:
raise ImportError(
f"MCP server '{self.name}' requires the 'mcp' Python SDK, but "
"it is not installed. Install with:\n"
" pip install 'hermes-agent[mcp]'\n"
"or (full install):\n"
" pip install 'hermes-agent[all]'"
)
command = config.get("command")
args = config.get("args", [])
user_env = config.get("env")