You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
server: stdio MCP child processes not terminated on service restart / config reload #50758
When the background server restarts — or when an MCP config change triggers a reload — the processes of local (stdio) MCP servers are not terminated. Old generations linger as orphans while a new generation starts, leaking processes/memory. Under CPU contention this cascades: the client↔server event stream stalls, the server restarts, and another full set of MCP processes is spawned.
Active plugins: local plugins loaded from ~/.config/opencode/plugins/
Reproduction
Configure several local MCP servers (mcp.servers, type: "local") in opencode.json.
Start the background service and let the MCP servers connect.
Run opencode service restart (or change one MCP entry to trigger a reload).
Inspect the process table: the previous MCP child processes remain alive; a new set is started.
Expected Behavior
The server should terminate its MCP child processes on restart/shutdown (preferably via a process group / cgroup kill) and reconnect cleanly, leaving a single set.
Actual Behavior
Old stdio MCP processes survive as orphans. After switching one MCP in the config, several local servers reported failed: Connection closeduntil a full restart — with their processes still alive. Under CPU contention we observed 7 overlapping MCP generations within ~86 s (~120 orphan processes) and 7 Event stream stalled entries; the server restarted repeatedly.
Additional Context
opencode mcp list right after the reload: one server connected, the rest failed: Connection closed, with the processes still present in ps.
Log: Event stream stalled followed by All fibers interrupted at ServerProcess.start (~/.local/share/opencode/log/opencode.log).
Aggravating architecture: runs using --standalone start a private server per execution, each with its own copy of the local MCPs — multiplication by design (the MCP spec states stdio serves one client, HTTP serves many).
Workaround adopted: (a) automated runs use the shared service instead of --standalone; (b) heavy MCPs run as long-lived services behind an HTTP proxy (Streamable HTTP).
Host: 4 vCPU, 8 GB; load reached 11. The systemd-managed service itself stayed up (NRestarts=0).
This issue might be a duplicate of existing issues. Please check:
service: restart leaves stale daemon and duplicated MCP servers running #42270: "service: restart leaves stale daemon and duplicated MCP servers running" — very closely related: service restart also fails to terminate the old daemon's MCP child processes, leaving stale processes running alongside the new generation.
If this covers a distinct scenario (specifically config-reload-triggered restarts cascading under CPU contention), it may still warrant its own tracking, but please review the above issues first to see if your report fits better there or can be consolidated.
Adding a data point that suggests a second trigger beyond restart/config-reload, and it may be the more important one.
In my case none of the triggers in the original report happened: no opencode service restart, no config change, no MCP entry edited. The app was simply left open, and the server reconnected the same MCP server on its own every 3–5 minutes.
Reconnect timestamps, last 12, all from a single server instance (run=4482db38):
~66 reconnects per disconnect. I searched the log for mcp disconnected, mcp closed, dispose, and cleanup — there is no per-connection teardown path, so each reconnect leaves a full 4-process tree (cmd.exe → node → node --liftoff-only → watchdog node) behind with its parent still alive.
Measured growth over 8 minutes with no user action: 1.478 GB / 16 processes → 2.811 GB / 30 processes, roughly 370 MB per reconnect.
Possible causal chain — the reconnect may not be the root cause but a symptom. The codegraph CLI ships a self-watchdog whose command line contains:
functionkill(extra){/* "Main thread unresponsive for ~Ns" */process.kill(parentPid,'SIGKILL');}
with timeoutMs=60000 and capMs=600000. So the main codegraph thread is being detected as wedged, the watchdog kills it, and opencode reconnects — then fails to dispose the dead tree.
If that holds, the missing dispose is still the thing to fix here, but there may be a companion fix needed so the watchdog death is handled as a clean shutdown rather than triggering a reconnect that stacks a new tree.
Related: #46174 (Windows, multi-GB, same shape) — I have the fuller process census and the 132-vs-2 connect/disconnect accounting there.
Activity
github-actions commentedon Sep 22, 2026
This issue might be a duplicate of existing issues. Please check:
service restartalso fails to terminate the old daemon's MCP child processes, leaving stale processes running alongside the new generation.If this covers a distinct scenario (specifically config-reload-triggered restarts cascading under CPU contention), it may still warrant its own tracking, but please review the above issues first to see if your report fits better there or can be consolidated.
Tyxiel commentedon Sep 29, 2026
Adding a data point that suggests a second trigger beyond restart/config-reload, and it may be the more important one.
In my case none of the triggers in the original report happened: no
opencode service restart, no config change, no MCP entry edited. The app was simply left open, and the server reconnected the same MCP server on its own every 3–5 minutes.Reconnect timestamps, last 12, all from a single server instance (
run=4482db38):And the accounting over the whole log:
~66 reconnects per disconnect. I searched the log for
mcp disconnected,mcp closed,dispose, andcleanup— there is no per-connection teardown path, so each reconnect leaves a full 4-process tree (cmd.exe→node→node --liftoff-only→ watchdognode) behind with its parent still alive.Measured growth over 8 minutes with no user action: 1.478 GB / 16 processes → 2.811 GB / 30 processes, roughly 370 MB per reconnect.
Possible causal chain — the reconnect may not be the root cause but a symptom. The codegraph CLI ships a self-watchdog whose command line contains:
with
timeoutMs=60000andcapMs=600000. So the main codegraph thread is being detected as wedged, the watchdog kills it, and opencode reconnects — then fails to dispose the dead tree.If that holds, the missing dispose is still the thing to fix here, but there may be a companion fix needed so the watchdog death is handled as a clean shutdown rather than triggering a reconnect that stacks a new tree.
Related: #46174 (Windows, multi-GB, same shape) — I have the fuller process census and the 132-vs-2 connect/disconnect accounting there.