Repository navigation
Description
Summary
When a local (stdio) MCP server returns a large tools/call result (~11.6 MB on one JSON-RPC line), OpenCode drops the whole MCP connection and the call fails with Connection closed. The server process is healthy and sends a valid response. After that the server's tools are gone from the session until it reconnects. I'd expect only that one call to fail (or be truncated), with the connection left open.
Environment
- opencode version: 2.0.16
- OS: Darwin 27.0.0 arm64 (macOS, Apple silicon)
- Terminal: ghostty (TERM=xterm-ghostty, COLORTERM=truecolor)
- Shell: /bin/zsh
- Install/channel: Homebrew
anomalyco/tap/opencode-v2stable (latest) - Active plugins: two local file:// plugins (skills/tools only; neither touches the MCP transport)
Reproduction
Minimal server (no external dependencies) that returns an N-MB text result:
#!/usr/bin/env python3
# big_mcp.py — usage: big_mcp.py <megabytes>
import json, sys
MB = int(sys.argv[1]) if len(sys.argv) > 1 else 12
for line in sys.stdin:
msg = json.loads(line)
mid, method = msg.get("id"), msg.get("method")
if method == "initialize":
res = {"protocolVersion": msg["params"]["protocolVersion"],
"capabilities": {"tools": {}},
"serverInfo": {"name": "big", "version": "0"}}
elif method == "tools/list":
res = {"tools": [{"name": "big", "description": "returns a large payload",
"inputSchema": {"type": "object", "properties": {}}}]}
elif method == "tools/call":
res = {"content": [{"type": "text", "text": "x" * (MB * 1024 * 1024)}]}
elif mid is None:
continue
else:
res = {}
sys.stdout.write(json.dumps({"jsonrpc": "2.0", "id": mid, "result": res}) + "\n")
sys.stdout.flush()- Add it to
opencode.jsonc:
"mcp": { "big": { "type": "local", "command": ["python3", "/path/to/big_mcp.py", "12"], "enabled": true } } - Start OpenCode and ask the agent to call the
bigtool. - The call fails with
Connection closed, and the session shows "Instructions for the following MCP servers are no longer available: big".
Real-world trigger: ruoqa-mcp list_jobs against openqa.suse.de with limit: 60 returns an 11,628,321-byte line in about 4.6 s. Driving the same binary directly over stdio (same env, same request) gets the full response, and the process exits 0 with nothing on stderr.
Expected Behavior
The oversized result produces an error, or a truncated result, for that single tool call (ideally with the size and the limit in the message). The MCP connection stays up and the other tools keep working.
OR - like opencode v1 - > save response into temporary file and give agent path to that file with size warning
Actual Behavior
The whole stdio connection gets torn down when the response arrives:
level=WARN message="failed to call MCP tool" server=openqa error="Connection closed" role=server
The tool result is just Connection closed. The server's instructions and tools are removed from the session, and it only reconnects later (in my case when I switched directory). No log line says why the connection was closed or mentions size.
Additional Context
- Happened once. It reproduces every time with the same request. Small responses from the same server work (for example, the same call with
summary: trueis 4 KB). - Workaround: keep tool responses small on the server side.
- Possibly related, but not the same: mcp: mcp list reports failed while API reports connected after server reconnect #50725 (mcp list status out of sync after reconnect).
- Requests: (1) turn an oversized message into a per-call error instead of closing the transport, (2) log the reason and the limit, (3) document the maximum MCP message size.
Activity
opencodejr commentedon Oct 28, 2026
Thanks for the detailed report and the minimal server. I could reproduce this.
I ran your
big_mcp.pyas a local MCP serverbigon 2.0.16 and had the agent callbigwith a 12 MB response. The call fails withConnection closedand the TUI shows "MCP server failed: big". The same call with a 1 MB response works. On the server side, the write of the large line fails withBrokenPipeError, so OpenCode closes the pipe while the response is still arriving. The server itself is fine.It still happens on the latest
dev(fa1260d). The error is now more detailed, but it's misleading:Connection closed: MCP server process exited with code 1: … BrokenPipeError, which makes it look like the server crashed.A likely cause, from reading the code (not confirmed with a fix yet): the stdio transport has its own 16 MiB per-message limit, but the MCP SDK's read buffer it uses has a default limit of 10 MiB. A message over 10 MiB, like your ~11.6 MB one, makes it throw. That ends the whole transport instead of failing just the one call, and the error never mentions size.
The recording and screenshots below show it (on
devand on 2.0.16), and the script below reproduces it. Until this is addressed, keeping responses under about 10 MiB avoids it. Possibly related, but a different problem: #50725.recording.mp4
Reproduction script (drive.ts)
Run it with opencode-drive:
opencode-drive run ./drive.ts. It drivesopencodefrom yourPATH; setOC_DEVto the path of an OpenCode checkout to run that from source instead.