mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 19:01:54 +00:00
Over streamable_http the contract probe judged initialize, tools/list and the read call by HTTP status alone. A server that answers 200 with a JSON-RPC `error` object therefore passed initialize and the read call, and failed tools/list only as "server serves []", which names the wrong cause. The SSE path checked initialize and the read call, but not tools/list. mcp-adapter, which fronts WordPress, maps invalid params to 200, and Moodle's webservice_mcp answers a failing tool call with 200 and code -32603, so a read that returned nothing could turn the check green. rpc_error() extracts the error object of a JSON-RPC body, refused() is built on it, and reject_error() fails initialize, tools/list and the read call on both transports with the server's own message. A 200 whose body is not JSON still carries no error object, so a provider that has not started keeps the caller retrying as before. The streamable_http initialize, and the one in the negative probes, sent no clientInfo, which the MCP SDK requires. Home Assistant (mcp 1.26.0, stateless) answers such an initialize with 200 and -32602 and serves the rest anyway, so only the old status check let it pass. All three initialize calls now share one INITIALIZE with clientInfo, as the SSE path already sent. Against a Home Assistant-shaped endpoint on mcp 1.26.0 the SDK logs "InitializeRequest.params. clientInfo Field required" for the old probe, and the fixed one prints OK. Against HEAD, an error-on-200 at initialize and at the read call printed OK; now all three steps print REJECTED naming the error. The MCP adapter in front of sixteen of the nineteen streamable_http providers answers 200 only with a result (svc-ai-mcp-adapter/files/python/server.py), so none of them changes outcome. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>