fix(mcp): hint on stdio protocol pollution

This commit is contained in:
haosenwang1018 2026-04-13 01:07:08 +00:00 committed by Xubin Ren
parent 3573109408
commit 92ef594b6a
2 changed files with 44 additions and 1 deletions

View File

@ -454,7 +454,23 @@ async def connect_mcp_servers(
return name, server_stack
except Exception as e:
logger.error("MCP server '{}': failed to connect: {}", name, e)
hint = ""
text = str(e).lower()
if any(
marker in text
for marker in (
"parse error",
"invalid json",
"unexpected token",
"jsonrpc",
"content-length",
)
):
hint = (
" Hint: this looks like stdio protocol pollution. Make sure the MCP server writes "
"only JSON-RPC to stdout and sends logs/debug output to stderr instead."
)
logger.error("MCP server '{}': failed to connect: {}{}", name, e, hint)
try:
await server_stack.aclose()
except Exception:

View File

@ -356,6 +356,33 @@ async def test_connect_mcp_servers_enabled_tools_warns_on_unknown_entries(
assert "Available wrapped names: mcp_test_demo" in warnings[-1]
@pytest.mark.asyncio
async def test_connect_mcp_servers_logs_stdio_pollution_hint(
monkeypatch: pytest.MonkeyPatch,
) -> None:
messages: list[str] = []
def _error(message: str, *args: object) -> None:
messages.append(message.format(*args))
@asynccontextmanager
async def _broken_stdio_client(_params: object):
raise RuntimeError("Parse error: Unexpected token 'INFO' before JSON-RPC headers")
yield # pragma: no cover
monkeypatch.setattr(sys.modules["mcp.client.stdio"], "stdio_client", _broken_stdio_client)
monkeypatch.setattr("nanobot.agent.tools.mcp.logger.error", _error)
registry = ToolRegistry()
stacks = await connect_mcp_servers({"gh": MCPServerConfig(command="github-mcp")}, registry)
assert stacks == {}
assert messages
assert "stdio protocol pollution" in messages[-1]
assert "stdout" in messages[-1]
assert "stderr" in messages[-1]
@pytest.mark.asyncio
async def test_connect_mcp_servers_one_failure_does_not_block_others(
monkeypatch: pytest.MonkeyPatch,