Remote MCP servers declaring completions/logging capabilities fail to connect despite valid initialize handshake
Remote MCP servers declaring completions/logging capabilities fail to connect, despite a valid initialize handshake
Claude Code version: 2.1.216
Summary
claude mcp list / /mcp report Failed to connect for remote HTTP/SSE MCP servers built on the official MCP SDKs (MongoDB MCP, SonarQube MCP, ClickHouse MCP), while other remote servers on the identical transport, same host/ALB, and same auth posture connect successfully. A raw curl of the initialize handshake against the failing servers returns a fully valid 200 OK JSON-RPC response, proving the server and network path are healthy — the failure is client-side.
Environment
- 3 remote servers behind one internal ALB, config identical in shape (
~/.claude.json, user scope):
``json``
"mcp-mongodb": { "type": "streamable-http", "url": "https://.../mongo/mcp" },
"mcp-clickhouse": { "type": "sse", "url": "https://.../clickhouse/sse" },
"mcp-sonarqube": { "type": "streamable-http", "url": "https://.../sonarqube/mcp" },
"mcp-graphify-*": { "type": "streamable-http", "url": "https://.../graph/{service}/mcp" } // 15 of these, all connect fine
- All backend pods confirmed
2/2 Running, Vault-injected credentials confirmed present in logs, no restarts.
Steps to reproduce
- Configure a remote MCP server (HTTP or SSE transport) whose
initializeresponse declarescapabilities.completionsand/orcapabilities.logging, and/or includes a top-levelinstructionsstring — this is the case for any server built on the official MCP Python/TS SDKs that enables those capabilities. - Run
claude mcp listor open/mcp. - Observe
✘ Failed to connect, with no further diagnostic detail (claude mcp get <name>also gives no extra reason beyond the same status line).
Expected behavior
The client completes the initialize → notifications/initialized → tools/list sequence and reports the server as connected, matching what a raw JSON-RPC client observes.
Actual behavior
The server is reported as failed to connect. Verified independently via curl:
Failing server (mcp-mongodb) — direct curl -X POST .../mongo/mcp with a standard initialize request returns:
{"result":{"protocolVersion":"2024-11-05","capabilities":{"resources":{"listChanged":true,"subscribe":true},"completions":{},"logging":{},"tools":{"listChanged":true}},"serverInfo":{"name":"MongoDB MCP Server","version":"1.13.0"},"instructions":"..."},"jsonrpc":"2.0","id":1}
HTTP/2 200, valid mcp-session-id header, correct SSE framing (content-type: text/event-stream).
Working server (mcp-graphify-*, custom minimal MCP server, same transport/host) — identical request returns:
{"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2024-11-05","capabilities":{"experimental":{},"resources":{"subscribe":false,"listChanged":false},"tools":{"listChanged":false}},"serverInfo":{"name":"graphify","version":"1.28.1"}}}
The only structural differences in the response bodies: the failing server's capabilities object additionally declares completions: {} and logging: {}, and it includes a top-level instructions field. Both are valid, optional fields per the MCP spec (2025-03-26 lifecycle spec). This is the only observable difference between the group that connects and the group that doesn't — all three failing servers share this trait; all fifteen working servers lack it.
What we ruled out
- Backend health: pods
2/2 Running, no crash loops, Vault secrets injected correctly (confirmed viakubectl logs -c vault-agent-init). - Network/ALB/TLS:
curlhandshake succeeds end-to-end with correct headers and session ID. - Client-side auth cache:
~/.claude/mcp-needs-auth-cache.jsonhas no entries for these servers. - Config drift: verified via direct JSON comparison that the failing and working entries are structurally identical except for
url/type(sse vs streamable-http) and connect status. claude --debug mcp listproduced no additional per-server diagnostic output in this scenario (18 lines of unrelated output, no mention of the failing servers).
Request
- A way to get an actual client-side error/reason for
Failed to connect(currently there is none —claude mcp get <name>repeats the same one-line status). - Confirmation on whether declaring
completions/loggingcapabilities in a server'sinitializeresponse is expected to work with the CLI's remote HTTP/SSE client, since three independently-built official-SDK servers all fail the same way while custom minimal servers on identical infra succeed.