anomalyco / anomalyco/opencode

Bug: Batched MCP tool calls corrupt parameters when using SSE transport

Open
#43,311 1 comment 0 reactions 1 assignee View on GitHub

@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

  1. Configure an MCP server with SSE transport (not stdio)
  2. Have the LLM produce a response with 2+ tool_use blocks targeting that server
  3. Opencode dispatches the tool calls
  4. 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:

  1. Opencode sends tool call N as an HTTP POST to the SSE-transport MCP server
  2. The server returns an error response (e.g., validation failure)
  3. The error response text is somehow fed back into the shared parameter buffer for the next tool call
  4. Tool call N+1 is sent with parameters = valid_json + error_text_from_N
  5. 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:

  1. Using separate HTTP connections for concurrent tool calls to the same SSE server
  2. Implementing strict request/response correlation with unique JSON-RPC IDs
  3. 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.