Repository navigation
Description
Description
When opencode batches multiple MCP tool calls in a single message and the MCP server uses SSE transport (port 4201), the second+ tool calls fail with "JSON Parse error: Unexpected EOF". The first call succeeds, but subsequent calls receive corrupted parameters.
Reproduction
- Configure an MCP server with SSE transport (not stdio)
- Have the LLM produce a response with 2+ tool_use blocks targeting that server
- Opencode dispatches the tool calls
- First call succeeds, second call fails with corrupted parameters
Error Pattern
Invalid input for tool register_update: JSON parsing failed:
Text: {"entry_id": {"tool": "register_update", "error": "Invalid input
for tool register_update: JSON parsing failed: Text: {"entry_id": .
Error message: JSON Parse error: Unexpected EOF
The error shows the first tool call's error response text concatenated into the second tool call's parameters string. The parameters should be a JSON object but arrive as a corrupted string containing both valid JSON and error text from a previous call.
Root Cause Analysis
The streaming parser (Vercel AI SDK Anthropic provider) correctly separates input_json_delta buffers per content block index — there is no cross-block buffer leak at the streaming level.
The corruption happens in the MCP SSE transport layer during concurrent tool call dispatch:
- Opencode sends tool call N as an HTTP POST to the SSE-transport MCP server
- The server returns an error response (e.g., validation failure)
- The error response text is somehow fed back into the shared parameter buffer for the next tool call
- Tool call N+1 is sent with parameters =
valid_json + error_text_from_N - The server receives corrupted JSON and rejects it
This is a client-side routing/buffering issue — the MCP client does not properly isolate request construction from response handling when dispatching concurrent tool calls over SSE transport.
Affected Transport
- SSE transport (port 4201): Bug present
- stdio transport: Not affected (serialized connection)
- Streamable HTTP (port 4200): Possibly affected (same HTTP POST mechanism)
Environment
- opencode: v1.18.15 (Bun-compiled TypeScript)
- MCP server: Python MCP SDK (mcp package)
- Transport: SSE via Starlette
- OS: macOS arm64
Suggested Fix
Ensure each tools/call JSON-RPC request has its own isolated parameter buffer. Error responses from one call must not be concatenated into parameter buffers for subsequent calls. Consider:
- Using separate HTTP connections for concurrent tool calls to the same SSE server
- Implementing strict request/response correlation with unique JSON-RPC IDs
- Ensuring parameter buffers are constructed fresh for each call, not shared
Workaround
Our MCP server now has a server-side sanitizer that detects and repairs corrupted parameters by extracting valid JSON from the corruption. This is a safety net, not a proper fix — the fix needs to be in the opencode client.
Activity
Bohdan-Tym commentedon Sep 10, 2026
Confirmed resolved in v1.18.30. After upgrading from 1.18.29 and restarting, batched calls to a legacy (SSE-transport) MCP server no longer corrupt parameters — 3 concurrent DevMind tool calls returned clean results. Consistent with PR #39373 rolling the client back to MCP SDK 1.29.0. This issue can be closed.
jairomello commentedon Oct 2, 2026
Additional evidence from a duplicate report (v1.18.34, Linux, local stdio MCP server, TypeScript
@modelcontextprotocol/sdk):This bug is not SSE-specific — it reproduces with
type: "local"stdio transport too, and the corruption source is broader than error-response feedback:Built-in tool args leak into MCP tool params. A parallel MCP
list_tasks+ built-inbashcall delivered tolist_tasks:(
fieldsreceived the bash arguments object — no error text involved, pure cross-call argument merge.) →JSON Parse error: Expected '}'Pure truncation (no merge, no error text): parallel MCP + built-in call delivered
{"includeDescriptions":→Unexpected EOF.Serial calls never failed in a ~2h session; parallel MCP+MCP worked. Corruption concentrated on MCP tool + built-in tool in the same assistant message.
Conclusion: the shared-buffer leak exists at the tool-call dispatch/argument-assembly level (cross-tool, including non-MCP tools), not only in the SSE transport response handling. The "stdio: not affected" note in the description should be revised.
rekram1-node commentedon Oct 4, 2026
plz share sessions this happened in? run this command in your terminal:
opencode export > session.jsonand then send the json file that the piped output was written to to me.I dont think this has anything to do w/ opencode? I think its a smaller model just failing to call tools well..
thdxr commentedon Oct 11, 2026
Thanks for the report! OpenCode 2.0 is now out and development is focused on V2, so we're closing issues filed against OpenCode 1. Please upgrade (
opencode upgrade --major, details: https://anoma.ly/notes/opencode-2-0), and if this is still relevant on 2.0, reopen this issue or open a new one with your 2.0 version.— from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊