anomalyco / anomalyco/opencode
Bug: Batched MCP tool calls corrupt parameters when using SSE transport
@neriousy is already working on this.
Since Aug 18, 2026.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- Avg merge
- 7h 2m
- Merged PRs (30d)
- 384
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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.