Repository navigation
v1.18.8 remote MCP fails: server/discover probe rejected by server (-32700), no fallback to classic initialize #39354
Description
Description
opencode 1.18.8 cannot connect to a spec-compliant Streamable HTTP MCP server whose protocol version predates the new server/discover discovery method. The connection fails during version negotiation and never falls back to the classic initialize handshake, ultimately timing out after 30000ms.
Root cause (confirmed via a transparent capture proxy):
opencode 1.18.8's remote transport opens the handshake with a server/discover probe using mcp-protocol-version: 2026-07-28:
POST /mcp
Accept: application/json, text/event-stream
Content-Type: application/json
mcp-method: server/discover
mcp-protocol-version: 2026-07-28
{"jsonrpc":"2.0","id":"server-discover-probe-1","method":"server/discover","params":{"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientInfo":{"name":"opencode","version":"1.18.8"},"io.modelcontextprotocol/clientCapabilities":{"roots":{}}}}}The server does not implement server/discover and responds with a JSON-RPC error:
{"error":{"code":-32700,"message":"Parse Error"},"id":null,"jsonrpc":"2.0"}opencode's strict message validator rejects this error response (it expects a result object and doesn't accept the error key in this position), so version negotiation fails:
■ Error: Version negotiation probe failed: [
{ "code": "unrecognized_keys", "keys": ["error"], ... },
{ "expected": "object", "code": "invalid_type", "path": ["result"], "received": "undefined" },
...
]
After the probe fails, the transport does not fall back to classic initialize. It opens a GET SSE stream and retries, never sending initialize, until it hits the 30s timeout:
● ✗ <server> failed
Operation timed out after 30000ms
http://127.0.0.1:63080/mcp
The server itself is healthy and spec-compliant. Verified directly (outside opencode), using the same Basic-auth header:
POST initialize→200in ~35ms with a valid result:{"id":1,"jsonrpc":"2.0","result":{"capabilities":{"prompts":{},"resources":{"listChanged":false},"tools":{"listChanged":true}},"protocolVersion":"2025-06-18","serverInfo":{"name":"<vendor server>","version":"<redacted>"}}}GET /mcp→text/event-streamwith a welcome notification (long-lived stream):event: message data: {"jsonrpc":"2.0","method":"notifications/message","params":{"data":"...","level":"info"}}
So this is a client-side regression, not a server problem.
Workarounds attempted that did NOT help:
"oauth": falsein the server config — this only disables theopencode mcp debugOAuth tool; the real connection still sends theserver/discoverprobe (re-confirmed via capture).
Expected behavior:
When the server/discover probe fails or the server returns any JSON-RPC error (including -32700 / -32601), opencode should tolerate the error and fall back to the classic initialize handshake, which the server supports. A robust client should not hard-fail or stall just because a server doesn't yet implement the brand-new discovery method.
Secondary note (server-side, for awareness): returning -32700 Parse Error for a well-formed request carrying an unknown method is arguably non-spec; -32601 Method not found would be more correct. That said, a graceful client-side fallback should not depend on the exact error code.
Related 1.18.8 MCP-v2 regressions (same release, different code paths): #39343 (OAuth discoveryState), #39333 (strict AjvJsonSchemaValidator rejects draft-07 tool schemas), #39315 (local/stdio MCP timeout).
Plugins
mcp (remote)
OpenCode version
1.18.8
Steps to reproduce
- Run any Streamable HTTP MCP server that advertises
protocolVersion2025-06-18(i.e., predatesserver/discover) and returns a JSON-RPC error for unknown methods. Listen on e.g.http://127.0.0.1:63080/mcp. - Configure it as a remote server (Basic auth via headers):
"mcp": { "demo": { "type": "remote", "url": "http://127.0.0.1:63080/mcp", "headers": { "Authorization": "Basic ***" } } }
- Run
opencode mcp list(oropencode mcp debug demo). - Observe:
Operation timed out after 30000ms/Version negotiation probe failed. - Confirm the server works via direct
curl POST initialize(returns 200 + valid result) andcurl GET(SSE stream).
Screenshot and/or share link
(capture-proxy transcripts available on request — the request/response bytes are quoted above)
Operating System
macOS (Apple Silicon), Darwin 26.x
Terminal
zsh
Activity
rekram1-node commentedon Jul 28, 2026
investigating
felixweinberger commentedon Jul 28, 2026
@rekram1-node FYI saw this report and think there might be a case for being slightly more lenient in which cases we fallback to initialize in the SDK: modelcontextprotocol/typescript-sdk#2571 if you want to weigh in