Repository navigation
opencode serve: local stdio MCP connection silently dropped mid-session — tools become permanently unavailable #38266
Description
Summary
Local stdio MCP servers (specifically serena-agent) work initially in opencode serve + opencode attach mode, but silently lose their connection after some tool calls. The MCP server process stays alive, no error is logged in the MCP server's logs — the tool execution itself completes in <20ms — but the opencode server-side MCP client has already dropped the connection, causing subsequent tool calls to time out.
Reproduction
- Start opencode in serve mode:
opencode serve --port 4096 - Attach a session:
opencode attach http://127.0.0.1:4096 - Verify serena MCP server is configured and appears connected
- Use
serena_create_text_fileor other serena tools successfully (they work) - After some period or number of tool calls, serena tools become unavailable
- The serena process remains running (
ps auxshows the process alive with same PID) - The user sees:
Model tried to call unavailable tool 'serena_create_text_file'or tool calls time out - The serena MCP logs (
~/.serena/logs/) show the tool completed successfully with zero errors
Evidence
- serena-side: All
create_text_filecalls complete in <20ms. Zero timeout errors in serena logs across all sessions. - Process state: Multiple serena processes remain running (
ps aux | grep serena) — they never crashed. - Tool availability: serena tools ARE available at session start (initial
serena_read_file,serena_get_symbols_overviewcalls succeed), then BECOME unavailable later. - No serena-side error: The disconnect is invisible to serena — it never knows the client dropped the connection.
# serena log showing successful execution:
INFO 2026-07-22 08:44:58,683 [MainThread] mcp.server.lowlevel.server:_handle_request - Processing request of type CallToolRequest
INFO 2026-07-22 08:44:58,724 [SerenaAgentTaskExecutor] serena.task_executor:_process_task_queue - Starting execution of Task-44:CreateTextFileTool
INFO 2026-07-22 08:44:58,728 [Task-44:CreateTextFileTool] serena.tools.tools_base:task - Result: File created: tests/test_doi_routes.py.
INFO 2026-07-22 08:44:58,729 [Task-44:CreateTextFileTool] serena.task_executor:stop - Task-44:CreateTextFileTool completed in 0.004 seconds
Root Cause Analysis
The serena MCP tool execution itself is fast (<20ms) and never errors. The problem is at the opencode server's MCP transport layer in serve mode:
- The
opencode servedaemon spawns a serena process per session and communicates via stdio - The MCP client (in
packages/opencode/src/mcp/index.ts) callsclient.listTools()on every LLM step viaresolveTools()(as documented in Bug: MCP tools permanently lost mid-session after single transient listTools() failure — no retry, no reconnect #17099) - A transient
listTools()failure (e.g., pipe hiccup, GC pause, timing issue) triggers the catch handler which permanently deletes the MCP client fromstate.clients - Once deleted, the client is never recreated — the serena process stays alive but the opencode server has no reference to it
- In
opencode servemode, this eviction affects ALL attached sessions (they share the server's MCP state) - The
timeoutfield inMcpLocalConfigonly covers the initial handshake, not ongoing per-request calls
The --project-from-cwd flag also means each serena process independently auto-detects the project and starts LSP servers, which adds startup time that makes the initial listTools() more likely to hit timeouts.
Related Issues
- Bug: MCP tools permanently lost mid-session after single transient listTools() failure — no retry, no reconnect #17099 (CLOSED): MCP tools permanently lost mid-session after single transient listTools() failure — same root cause (delete on transient failure), but the fix may not cover
servemode where the MCP state is shared - MCP remote client has no transport-level retry on socket/connection errors #25287 (OPEN): MCP remote client has no transport-level retry on socket/connection errors — same missing retry pattern, but focuses on remote HTTP transport, not local stdio in
servemode - Session hangs indefinitely after MCP tool-call — no timeout recovery (deadlock) #35207 (OPEN): Session hangs indefinitely after MCP tool-call — no timeout recovery (deadlock) — related symptom of MCP calls that never return
- MCP transport stays 'failed' after a transient connection close — plugin tools disappear for the rest of the session #38088 (CLOSED): MCP transport stays 'failed' after a transient connection close — plugin tools disappear — same symptom, closed as duplicate of MCP remote client has no transport-level retry on socket/connection errors #25287
- fix(mcp): MCP server loses connection mid-session causing intermittent failures #23997 (CLOSED): fix(mcp): MCP server loses connection mid-session — related fix
Environment
- opencode version: 1.18.4
- Mode:
opencode serveon port 4096 +opencode attach - MCP server: serena-agent 1.2.0 (Python FastMCP, stdio transport)
- OS: Linux (Debian)
Activity
wdz211 commentedon Aug 4, 2026
Additional Windows reproduction evidence (OpenCode Desktop 1.18.13, Windows 11, local stdio MCP):
opencode.json, includingdesktop-touch.desktop-touchthen became unresponsive:server_statusanddesktop_statereturned MCP error-32001: Request timed out; the child process remained alive and loaded the native Windows UIA engine. Diagnostic output showed CPU spikes and a slowdesktop_statecall rather than a clean child-process crash.This appears related to the issue's described class of failures: the MCP child remains alive while the OpenCode-side client/transport becomes unusable and requests time out. The duplicate local-server spawning is an additional Windows Desktop symptom worth investigating. Suggested diagnostics: log MCP server key, client instance identity, spawn/close/reconnect events, and ensure reconnect/disposal is idempotent when the same config is initialized more than once.
github-actions commentedon Oct 5, 2026
To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.