PR #32088 (closes #25137) added MCP Streamable HTTP session recovery, but it only reinitializes when a POST receives HTTP 404. Some MCP servers return HTTP 400 for an expired/missing session, so recovery never fires and every tool call fails until opencode is restarted.
Reopening as a separate issue because #25137 is closed and may not be re-triaged.
Description
When the remote MCP server invalidates a Streamable HTTP session via idle timeout, the Atlassian/Jira MCP server (uvicorn, Atlassian MCP 1.12.4) responds to the stale mcp-session-id with HTTP 400, not 404. The recovery logic from #32088 only handles 404, so the session is never reinitialized and all subsequent tool calls fail with Bad Request: No valid session ID provided until a full restart. Reproducible every ~15-30 min of inactivity.
The PR description for #32088 explicitly scopes the fix to the 404 POST failure, so this is a known gap rather than a regression.
Steps to reproduce
- Configure a remote Streamable HTTP MCP server that returns 400 for an unknown/expired session id (e.g. Atlassian MCP 1.12.4).
- Use it normally; a few tool calls succeed.
- Wait for the server-side idle timeout (~15-30 min).
- Call any tool again → fails permanently with
Bad Request: No valid session ID provided. Only a restart fixes it.
Reproduced directly against the live server with a stale session id:
$ curl -si <server>/mcp/ -X POST \
-H "Authorization: Token ***" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "mcp-session-id: 00000000000000000000000000000000" \
-d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/list\",\"params\":{}}"
HTTP/1.1 400 Bad Request
server: uvicorn
content-length: 41
Bad Request: No valid session ID provided
Handshake without a session also returns a structured JSON-RPC error (code -32600):
{"jsonrpc":"2.0","id":"server-error","error":{"code":-32600,"message":"Bad Request: Missing session ID"}}
Suggested fix
Extend the recovery trigger (currently 404-only, see #32088) to also cover a 400 that indicates a missing/expired session — e.g. body matching No valid session ID / Missing session ID, or JSON-RPC error code -32600 with session in the message. Keep the same bounded single-retry behavior already implemented.
OpenCode version
1.17.8 (desktop)
Operating System
macOS
Related: #25137, #28567
PR #32088 (closes #25137) added MCP Streamable HTTP session recovery, but it only reinitializes when a POST receives HTTP 404. Some MCP servers return HTTP 400 for an expired/missing session, so recovery never fires and every tool call fails until opencode is restarted.
Reopening as a separate issue because #25137 is closed and may not be re-triaged.
Description
When the remote MCP server invalidates a Streamable HTTP session via idle timeout, the Atlassian/Jira MCP server (uvicorn, Atlassian MCP 1.12.4) responds to the stale
mcp-session-idwith HTTP 400, not 404. The recovery logic from #32088 only handles 404, so the session is never reinitialized and all subsequent tool calls fail withBad Request: No valid session ID provideduntil a full restart. Reproducible every ~15-30 min of inactivity.The PR description for #32088 explicitly scopes the fix to the 404 POST failure, so this is a known gap rather than a regression.
Steps to reproduce
Bad Request: No valid session ID provided. Only a restart fixes it.Reproduced directly against the live server with a stale session id:
Handshake without a session also returns a structured JSON-RPC error (code -32600):
{"jsonrpc":"2.0","id":"server-error","error":{"code":-32600,"message":"Bad Request: Missing session ID"}}Suggested fix
Extend the recovery trigger (currently 404-only, see #32088) to also cover a 400 that indicates a missing/expired session — e.g. body matching
No valid session ID/Missing session ID, or JSON-RPC error code-32600withsessionin the message. Keep the same bounded single-retry behavior already implemented.OpenCode version
1.17.8 (desktop)
Operating System
macOS
Related: #25137, #28567