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 → 200 in ~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-stream with 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": false in the server config — this only disables the opencode mcp debug OAuth tool; the real connection still sends the server/discover probe (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
protocolVersion 2025-06-18 (i.e., predates server/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 (or opencode 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) and curl 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
Description
opencode 1.18.8 cannot connect to a spec-compliant Streamable HTTP MCP server whose protocol version predates the new
server/discoverdiscovery method. The connection fails during version negotiation and never falls back to the classicinitializehandshake, 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/discoverprobe usingmcp-protocol-version: 2026-07-28:The server does not implement
server/discoverand 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
resultobject and doesn't accept theerrorkey in this position), so version negotiation fails:After the probe fails, the transport does not fall back to classic
initialize. It opens aGETSSE stream and retries, never sendinginitialize, until it hits the 30s timeout: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):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/discoverprobe fails or the server returns any JSON-RPC error (including-32700/-32601), opencode should tolerate the error and fall back to the classicinitializehandshake, 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 Errorfor a well-formed request carrying an unknown method is arguably non-spec;-32601 Method not foundwould 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 (strictAjvJsonSchemaValidatorrejects draft-07 tool schemas), #39315 (local/stdio MCP timeout).Plugins
mcp (remote)
OpenCode version
1.18.8
Steps to reproduce
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.opencode mcp list(oropencode mcp debug demo).Operation timed out after 30000ms/Version negotiation probe failed.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