anomalyco / anomalyco/opencode
[FEATURE] Official MCP warm-up / pre-spawn mechanism (+ reconnect path) — all local MCPs marked failed at session start when many cold-start concurrently
@kitlangton is already working on this.
Since Sep 13, 2026.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
Summary
On the Windows desktop app, when many local stdio MCP servers are configured (we run 14+), every one of them gets marked server unavailable ... status=failed at session start, and the user must manually restart each server in the UI. The servers themselves are healthy — they simply lose a startup race: the sidecar spawns all local MCP processes concurrently (uv venvs, npx, python shims — all cold-start), and once its initialization window is exhausted, the remaining servers are marked failed in the same second, never retried.
Feature request: an official, opt-in MCP warm-up / pre-spawn mechanism (plus a reconnect path), so session-start MCP spawn succeeds without manual restarts. Once official support lands, users can delete their homemade workarounds (ours: a PowerShell warm-up script + Startup-folder .vbs).
Environment
- OpenCode Desktop 1.18.30 (Electron 42.3.3), Windows 11 x64
- Install path:
C:\Users\<user>\AppData\Local\Programs\@opencode-aidesktop - Sidecar mode (desktop spawns the opencode server)
- 19 MCP servers configured in
opencode.json: 13 local stdio (uv toolvenv exes for CAD/CADQuery/FreeCAD/OpenSCAD,npx -ypackages, npm.cmdshims) + 6 remote URLs - One plugin (
oh-my-openagent) which dynamically injects additional local MCPs (e.g.lsp,codegraph)
Observed behavior (log evidence, ~/.local/share/opencode/log/opencode.log)
At session start (2026-09-13T01:33–01:35Z), all local servers failed:
01:33:26 server unavailable key=playwright type=local status=failed
01:33:33 server unavailable key=postgres type=local status=failed
01:33:39 server unavailable key=lsp type=local status=failed
01:34:14 server unavailable key=sci-forge type=local status=failed \
01:34:14 server unavailable key=mysql type=local status=failed \
01:34:14 server unavailable key=sqlite type=local status=failed \
01:34:14 server unavailable key=sequential-thinking type=local status=failed > 12 servers,
01:34:14 server unavailable key=fetch type=local status=failed / same second
01:34:14 server unavailable key=build123d-mcp type=local status=failed /
01:34:14 server unavailable key=cadquery-mcp type=local status=failed /
01:34:14 server unavailable key=freecad-mcp type=local status=failed
01:34:14 server unavailable key=openscad-mcp type=local status=failed
01:34:14 server unavailable key=tradingview-mcp type=local status=failed
01:34:14 server unavailable key=financial-hub-mcp type=local status=failed
Key observations:
- Servers with short per-server timeouts fail first (
playwrighthadtimeout: 1200, fails at +0s;postgreshad12000, fails at +7s), then the remaining 12 fail in the same second (+48s) — that looks like a shared sidecar initialization budget being exhausted, after which everything still pending is marked failed at once. - No retry/reconnect happens afterwards. Manually restarting each server in the UI then succeeds immediately — because by then the interpreter processes and OS file caches are warm. This confirms the servers/config are fine; the failure is purely the cold-start race.
- Every subsequent session repeats this: all local MCPs need manual restart on every app launch.
Root cause
Session start spawns all local MCP stdio processes concurrently. Each local server pays a cold-start cost (uv venv interpreter boot, npx resolution, Python import cadquery ≈ 12 s warm / 95 s cold with OCCT/VTK). With 14+ racing at once, disk I/O contention pushes total init past the sidecar's window, and the one-shot snapshot marks everything failed — matching #44291's finding that "MCP connection state is a one-shot startup snapshot with no reconnect path."
Feature request
- Official warm-up / pre-spawn — an opt-in config knob, e.g.:
Implementation could be as simple as: at app/session start, before opening MCP clients, briefly spawn each configured local interpreter ({ "mcp": { "warmup": true // pre-spawn/warm local MCP interpreters before the session's init window } }command[0] -c passstyle) or touch its entry-point binary to warm OS file caches — the same trick users currently hand-roll. - Reconnect path — a failed server should retry (with backoff) instead of staying a one-shot failed snapshot (this is the reconnect half of #44291).
- Per-server or global init budget surfaced in the UI — when a server is marked failed, show whether it was a timeout vs. spawn failure, so users stop debugging healthy configs.
Current workaround (would happily delete once official support lands)
C:\Users\<user>\.opencode\mcp-warmup.ps1: warms every uv-tool venv interpreter, heavy imports, andnpxresolution cache at logonStartup\mcp-warmup.vbs: silent logon trigger- Plus config-side fixes that each removed one failure mode: raised a
1200ms timeout to120000, removed a duplicate MCP
Related
- #44291 — MCP servers fail to connect when a session starts during self-upgrade (same one-shot-snapshot, no-reconnect behavior)
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.