Skip to content

mcp: remote MCP servers that fail once are never retried until service restart #52237

Open

Description

@duanhongyi

Summary

When a remote (HTTP) MCP server connection fails — e.g. after macOS sleep/wake kills long-lived connections — the background service keeps it in failed state indefinitely. Creating new sessions or restarting the TUI does not help, because MCP state lives in the background service (opencode serve --service), and there is neither a periodic retry nor a manual reconnect command. Only opencode service restart recovers.

Environment

  • opencode version: v2.0.20
  • OS: Darwin 27.0.0 arm64 (macOS, MacBook Air)
  • Terminal: ghostty (TERM=xterm-256color, COLORTERM=truecolor)
  • Shell: /bin/zsh
  • Install/channel: latest (npm global)
  • Active plugins: @omagents/omagents

Reproduction

  1. Configure a remote MCP server (e.g. { "type": "remote", "url": "https://mcp.context7.com/mcp" }) and start the TUI. Verify opencode mcp list shows it connected.
  2. Put the Mac to sleep for ~30+ minutes (close the lid). macOS runs DarkWake maintenance cycles every few minutes, which freeze user processes and kill/stall TCP connections.
  3. Wake the Mac. opencode mcp list now shows the remote servers as failed: Request timed out (or ECONNRESET), and their tools are gone from sessions.
  4. Create a new session, or quit and restart the TUI → servers stay failed.
  5. Run opencode service restart → all servers connect within seconds.

Expected Behavior

Failed MCP connections should recover without restarting the background service. Any of these would work:

  • periodic reconnect with backoff for servers in failed state,
  • retry on new session creation (per project/directory),
  • retry on system wake / network-change events,
  • a manual trigger, e.g. an opencode mcp reconnect [name] CLI subcommand or a TUI action.

Actual Behavior

Once marked failed, a remote server is never retried while the service keeps running. Observed: two remote servers (context7, websearch) failed at 13:05 local time and were still failed ~1 hour later, even though the network had fully recovered — both endpoints answered curl in <5s, and a different project directory initialized at 14:05 connected all 5 MCP servers within 6 seconds.

The failures correlate to the second with macOS DarkWake events from pmset -g log:

opencode log (UTC) pmset (local, UTC+8)
05:05:41 mcp connect failed DarkWake 13:05:41
05:10:54 mcp connect failed DarkWake 13:10:54
05:27:07 event stream stalled DarkWake 13:27:07
05:40:18 DarkWake 13:40:18
05:45:30 DarkWake 13:45:30
05:50:42 DarkWake 13:50:43
05:55:55 DarkWake 13:55:56

Additional Context

Typical log entries:

level=WARN message="mcp connect failed" server=context7 status.status=failed status.error="Request timed out" http.span=313211
level=WARN message="mcp http request failed" errors="[{... \"code\":\"ECONNRESET\" ...}]" durationMs=1252864 server=websearch

What seems to happen: an MCP request/reconnect attempt starts during a 10–60s DarkWake window, the machine goes back to sleep mid-request, the socket hangs across several sleep cycles, and ~313s later it fails with Request timed out or ECONNRESET. During sleep this repeats at every DarkWake (each stall triggers a retry that lands in the next DarkWake). After a real wake, the system is stable, so no retry is ever triggered again and the failed state sticks forever.

Local (stdio) MCP servers recover fine; only remote HTTP servers get stuck.

opencode mcp --help currently lists only list / add / auth / logout — there is no way to force a reconnect.

Workaround: opencode service restart (drops all attached TUI clients).

Activity

  1. github-actions commented on Sep 30, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    • #25287: Remote MCP transport errors can leave the client failed with no retry or reconnect.
    • #29190: Remote HTTP/SSE MCP connections that drop after idle periods have no automatic reconnection.
    • #15209: Remote MCP idle-timeout disconnections require manual recovery.
  2. zhzjm commented on Oct 3, 2026

    @zhzjm

    Additional data point from Windows 11 / v2.0.21→2.0.22: this is not limited to remote (HTTP) servers — a local stdio MCP that fails during service startup gets stuck in failed the same way.

    After upgrading to 2.0.22 and the service restart that followed, both of my servers came up as failed during that startup's initialization (network was briefly unavailable at that moment):

    • exa (remote HTTP): failed: getaddrinfo ENOTFOUND mcp.exa.ai
    • context7 (local stdio via context7-mcp): failed: Request timed out

    Network was verifiably healthy immediately afterwards (direct curl to both endpoints succeeded), but the state never recovered on its own — the MCP tools disappeared from the Code Mode tool catalog too, so this wasn't just the lister probe issue from #52563. opencode service restart re-initialized both and they connected immediately, matching this issue's report.

    Confirmed still reproducible on 2.0.22. I see #52614 ("retry transient MCP connect failures") was merged on 2026-10-02 but is not contained in the v2.0.22 tag (it is 44 commits ahead of it) — so the retry fix should land in the next release, which presumably closes this.

  3. phoriah commented on Oct 3, 2026

    @phoriah

    Adding data points from a Windows / opencode 1.18.31 reproduction that differ from the sleep/wake trigger in the original report.

    Different trigger — no sleep or network event involved. In my case the remote server's app was simply not running when the connection was established, so the connect attempt was refused outright:

    level=WARN message="mcp http request failed" errors="[{\"type\":\"TypeError\",\"message\":\"Unable to connect. Is the computer able to access the url?\",\"code\":\"ConnectionRefused\",\"errno\":0}]" durationMs=13 server=<remote>
    level=WARN message="mcp transport error" server=<remote> error="Unable to connect. Is the computer able to access the url?..."
    

    Refusal is immediate (13–21 ms), not a timeout. Once the app was started again, the endpoint answered normally and there were still zero further connect attempts for that directory over the next 3h42m.

    Connections appear to be per project directory, which makes this look intermittent and project-specific rather than global. Every log line carries directory=, and only the directories whose first connect attempt was refused stayed dropped:

    T+0:00  mcp connected     server=<remote> tools=3 directory=<project-a>
    T+1:08  mcp connect failed server=<remote> errors="[{...\"ConnectionRefused\"...}]" directory=<project-a>
    T+1:43  mcp connect failed server=<remote> errors="[{...\"ConnectionRefused\"...}]" directory=<project-a>
            # no further attempts for 3h42m; a local stdio server in the same
            # config kept connecting throughout this window
    T+5:26  mcp connected     server=<remote> tools=3 directory=<project-a>
    

    The impact is that the tools silently vanish from the agent's catalog. The session reported the MCP as unavailable even though it was reachable, with no user-visible notification. A type: "local" server in the same config was unaffected — its tools stay listed and individual calls fail with Request timeout instead — so the two failure modes differ enough that the remote case is easy to miss.

    Version note: this is 1.18.31, where the HTTP API's POST /api/experimental/mcp/{server}/connect isn't reachable from the CLI (opencode mcp offers only add, list, auth, logout, debug, and there is no opencode api / opencode service subcommand), so on this version there's no shell-side recovery at all.

    A workaround that doesn't drop attached clients. Editing the server entry in the config forces a reconnect, and the second write restores it — each write makes opencode re-resolve mcp.servers and reconnect every loaded directory ~200 ms later, with no restart and nothing disconnected:

    // ~/.config/opencode/opencode.json — set, then restore
    "mcp": { "servers": { "<remote>": { "type": "remote", "url": "...", "disabled": true } } }

    This suggests the reconnect path already exists and is fast; it's just only triggered by config changes, not by a server becoming reachable again. If retry/backoff, or a CLI equivalent of the existing connect route, would surface that path, this case would self-heal.

  4. phoriah commented on Oct 3, 2026

    @phoriah

    Follow-up to my comment above: two corrections and a confirmation on a newer version.

    Correction — version. I reported this against 1.18.31, which is no longer the build I have. I'm now on the v2.0.22 desktop app and reproduced it there, so the version reference in my comment is stale. The signature is otherwise identical:

    WARN mcp http request failed errors="[{\"type\":\"TypeError\",\"message\":\"Unable to connect. Is the computer able to access the url?\",\"code\":\"ConnectionRefused\",\"errno\":0}]" durationMs=32 server=<remote>
    WARN mcp transport error   server=<remote> error="Unable to connect. Is the computer able to access the url? (ConnectionRefused)"
    INFO mcp connect failed    server=<remote> status.status=failed status.error="Unable to connect. Is the computer able to access the url? (ConnectionRefused)"
    

    Refused again in 32 ms, then no further attempts — a type: "local" stdio server in the same config connected normally a few ms later. So this is not fixed in 2.0.22 either, consistent with @zhzjm's note that #52614 merged but isn't in this tag.

    Correction — local stdio. My comment claimed local servers are unaffected and stay listed with per-call timeouts. That was too strong. @zhzjm reproduced this with a local stdio MCP stuck in failed, and my own run doesn't disprove it either — the stdio server simply connected cleanly while the remote one was refused. My observation only covers the remote case; the local case is @zhzjm's.

    A caveat for anyone verifying this by hand. opencode mcp list reported <remote> as connected while the server was in fact refused, because it reads the already-running background service rather than the config you point it at. To test this you need an isolated server (--standalone) or you will get a false pass — this looks like the same lister-probe issue as #52563.

  5. zhzjm commented on Oct 4, 2026

    @zhzjm

    Confirming the local stdio case from my side as well, on the CLI/npm build of v2.0.22 (Windows):

    • Remote: identical signature — ConnectionRefused in 28 ms, http request failed / transport error / connect failed triple, then nothing.
    • Local stdio: MCP server process exited with code 1 → status.status=failed. I then repointed the same entry at a working stdio server and waited 10+ minutes — zero reconnect attempts.

    A correction to the workaround, at least on this build — enabled: true → false → true does not reconnect. The config watcher clearly fires on each write (watcher stopped / re-subscribe / started in the log) but no MCP events follow. Measured:

    config write MCP events
    enabled toggle, global config 0 — watcher fires, nothing reconnects
    any write, project-level opencode.json 0
    add a new server name connects it in ~1 s, once per loaded directory
    add a new server while another is stuck failed only the new one connects
    remove the entry, then re-add it reconnects — mcp connected within seconds

    So the effective trigger is "the config diff introduces a server name", not "any write" — on the CLI build the manual recovery is delete-and-re-add, not the disabled round-trip. Either way your core point stands: the connect path exists and is fast, it's just wired far too narrowly. A startup retry/backoff, or exposing the connect route to the CLI, would make this self-heal.

    Also +1 on the list false-pass, with a worse variant: in a directory whose config defines 4 servers (2 failed, 2 connected), opencode mcp list printed No MCP servers configured. And --standalone is listed in opencode --help but rejected: opencode --standalone mcp list → Unrecognized flag: --standalone in command opencode mcp, so that isolation path isn't reachable from the CLI on 2.0.22 either.

  6. Rachdevop commented on Oct 4, 2026

    @Rachdevop

    Another data point, Windows 11 / Desktop + CLI v2.0.22, laptop with Modern Standby. It shows a trigger not covered by #52614.

    What happens (log timestamps correlate to the second):

    Local time Source Event
    01:44:32 Kernel-Power 105 power source change (AC → battery) wakes the machine briefly
    01:44:33–36 opencode location services evicted then location services booted for all 3 loaded directories
    01:44:43 Kernel-Power 172 Connectivity state in standby: Disconnected, Reason: Adaptive Connected Standby
    01:44:44 opencode mcp connect failed for the 4 remote servers: getaddrinfo ENOTFOUND

    Why it happens:

    1. location-activity.ts evicts a location's services after 60 min without session activity. During standby, that TTL elapses for every location. So any brief wake runs the sweep and reconnects every MCP server at once.
    2. On Windows, with "network connectivity in standby" managed by Windows (the default on battery), the network is down for the whole standby period, not just for a few seconds.
    3. Once failed, nothing retries.

    Why #52614 won't cover this: its retries span about 1.25 s (250 ms, then 1 s). Here the network stays down for minutes to hours.

    What the user sees: the next morning, the directory in active use stays failed indefinitely, because its TTL keeps being refreshed and it is never re-booted. Idle directories recover on their own at the next eviction/boot cycle, once the network is back. mcp.list shows the mismatch: the home directory has 6/6 connected, the workspace 1/6.

    Possible fixes:

    • retry failed remote servers when a session uses the location (prompt or tool catalog access);
    • retry on resume or network-availability change;
    • or a bounded backoff that lasts minutes, not milliseconds.

    Recovery that works on Desktop without a service restart: /mcps, then toggle each server. This calls mcp.connect for that location.

  7. sunmaxim commented on Oct 10, 2026

    @sunmaxim

    Additional data point — v2.0.26, macOS (arm64), 4 remote HTTP servers: failed state persists 25+ minutes, recovery only when a new client connects

    Environment:

    • opencode v2.0.26 (npm), macOS on arm64
    • 4 remote MCP servers in the global config (~/.config/opencode/opencode.json), all type: "remote" with a static Authorization: Bearer header, no OAuth

    Trigger: brief network/VPN unavailability while the background service was running.

    Timeline (UTC, role=server log; hostnames redacted):

    17:20:43Z  WARN  mcp connect failed  server=crm        status.status=failed status.error="getaddrinfo ENOTFOUND <internal-host>"
    18:04:09Z  WARN  mcp connect failed  server=<remote-a> status.status=failed status.error="Request timed out"
    18:04:09Z  WARN  mcp connect failed  server=<remote-b> status.status=failed status.error="Request timed out"
    18:04:10Z  WARN  mcp transport error server=<remote-b> error="Failed to send cancellation: AbortError: The operation was aborted."
    18:04:10Z  WARN  mcp connect failed  server=<remote-c> status.status=failed status.error="Request timed out"
    18:04:10Z  WARN  mcp transport error server=<remote-c> error="Failed to send cancellation: AbortError: The operation was aborted."
                  # ... no further connect attempts for these connectionIDs for ~25 minutes ...
    18:25:15Z  WARN  mcp transport error server=crm        error="Error POSTing to endpoint: {…} (HTTP 404)"
    18:30:15Z  INFO  mcp connected       server=<remote-b> tools=33
    18:30:18Z  INFO  mcp connected       server=<remote-a> tools=33
    18:30:42Z  INFO  mcp connected       server=crm        tools=11
    

    Observations:

    1. After the 18:04 failure batch (3 of 4 servers, Request timed out + AbortError), none of the stuck connectionIDs made another attempt for ~25 minutes, even though the endpoints answered new connections in under a second from 18:30 on. All the 18:30 mcp connected lines belong to new runs/clients (new connectionIDs) — i.e. recovery happened on client (re)connect, not on a retry of the stuck connections.
    2. The 404 on crm at 18:25/18:30 shows a connect attempt can land while the remote side is mid-restart; the following attempt succeeded.
    3. Separately, at 18:35:16-17 three servers logged mcp transport error … "SSE stream disconnected: TypeError: The socket connection was closed unexpectedly" (connection span ~10 min) exactly when the background service restarted; the affected TUI session lost its MCP tool catalog until the service came back.
    4. Lister side note (matches cli: mcp list reports "Request timed out" for healthy, connected servers #52563): while 4 servers were defined in the global config and the service-side log showed them connected, opencode mcp list from the project directory printed No MCP servers configured. After opencode service restart the same command lists all 4 as connected.

    Wishlist (same as the issue): retry failed remote servers on network-availability change / on next session or tool-catalog activity, or a manual opencode mcp reconnect <name> CLI/TUI trigger.

  8. yashikaagarwal-creator commented on Oct 11, 2026

    @yashikaagarwal-creator

    Additional data: this reproduces on opencode v2.0.24, and the failure is DNS-specific

    Adding evidence from another affected machine (macOS 27.0.1, Apple M1, opencode v2.0.24, Darwin 22.6.0 arm64). I think this is the same root cause already described here and in #43444, but with three findings that pin the mechanism down more precisely.

    1. The failures are DNS resolver rejections, not socket errors

    The log shows TypeError/getaddrinfo ENOTFOUND, not ECONNRESET or a timeout:

    message="mcp transport error" server=context7 error="getaddrinfo ENOTFOUND mcp.context7.com"
    message="mcp http request failed" errors="[{\"type\":\"TypeError\",\"message\":\"getaddrinfo ENOTFOUND api.githubcopilot.com\",\"code\":\"ENOTFOUND\",\"errno\":4}]"
    

    Counts across the whole log — 174 events total, spanning 10 distinct session runs:

    host ENOTFOUND events
    mcp.context7.com 72
    opencode.ai 55
    api.githubcopilot.com 33
    mcp.sentry.dev 18
    models.opencode.ai 14

    2. It is not limited to remote MCP servers

    opencode.ai, models.opencode.ai and models.dev fail the same way, so OpenCode's own provider-config and model-list fetches degrade too. This is why the problem looks intermittent — every call retries and eventually succeeds, but the service is permanently burning retries:

    message="failed to load OpenCode provider config" cause="HttpClientError: Transport error (GET https://opencode.ai/console/api/v2/config) (cause: TypeError: getaddrinfo ENOTFOUND opencode.ai)"
    message="Failed to fetch models.dev"
    

    3. Child processes spawned by the service resolve fine — this isolates the fault

    Run inside a shell spawned by the failing service (spawning process command=/bin/zsh, same run id), 15 rounds each across 3 hosts:

    node  ok=45 fail=0
    bun   ok=45 fail=0
    

    System resolvers also answer normally during a burst:

    dig +time=3 +tries=1 @fe80::3215:77ff:fedc:9108%en0 github.com A   → 16ms, status NOERROR
    scutil --dns resolver #1 → reach: 0x00020002 (Reachable, Directly Reachable Address)
    

    So system DNS is healthy and the resolver works in-process for node and bun children, yet the long-lived service process cannot resolve. The failure is isolated to the service process's own HTTP transport state.

    DarkWake correlation (this is the part that seems decisive)

    Local time is IST (UTC+05:30). Matching pmset -g log wake events against opencode log timestamps:

    DarkWake / Wake (IST) UTC opencode.log
    00:49:32 19:19:32 mcp connect failed server=sentry at 19:19:32
    02:12:00 20:42:00 mcp connect failed server=playwright,openviking at 20:42:03
    02:13:06 20:43:06 all 8 servers fail at 20:43:06–20:43:08
    06:10:16 00:40:16 29 ENOTFOUND events inside 00:40

    Dark Wake Count in this sleep cycle: 22.

    Two more bursts land on wake boundaries — 11 events at 00:52, 19+23 at 00:56/00:57, and 38 at 01:35 — with wake/display-wake activity at 06:47 and 07:03 IST in the same window.

    Recovery is always opencode service restart. Nothing else clears it: dscacheutil -flushcache did not help, and a brand-new project directory does not help, because DNS state lives in the shared service process rather than the session.

    What would help

    Anything that resets or revalidates the resolver for the service process on wake. The suggestions already in this issue seem right — the notable addition is that it likely needs to cover the provider/model fetch path, not just MCP, since opencode.ai and models.dev degrade through the same resolver.

    Environment

    • opencode version: v2.0.24
    • OS: macOS 27.0.1 (26A434), Darwin 22.6.0 arm64, MacBook Air M1
    • Terminal: TERM=xterm-256color (no TERM_PROGRAM)
    • Shell: /bin/zsh
    • Install/channel: latest
    • Active plugins: opencode-pty, opencode-auto-resume, @tarquinen/opencode-dcp, opencode-subagent-statusline, @openviking/opencode-plugin
    • Local plugin files: none (no .opencode/plugin/ or .opencode/plugins/ directory)
  9. JosXa commented on Oct 19, 2026

    @JosXa
    Contributor

    Another data point: offline location boot after sleep (2.0.29)

    On laptops that sleep and use a corporate VPN, the V2 background service regularly ends up with failed MCP servers (and plugin-provided state) that never recover. opencode service restart is the only fix our users have found. We see this across macOS and Windows users on 2.0.2x.

    The trigger is a location boot while the network is unavailable:

    1. A location's services are evicted after 60 minutes without session activity (location-activity.ts).
    2. After wake, the next request boots the location again. At that moment the VPN is still reconnecting, so DNS fails (ENOTFOUND) or the connection times out.
    3. MCP.startServer sets the server to failed and logs mcp connect failed. Nothing schedules another attempt (packages/core/src/mcp/index.ts, startServer around L427-481 in v2.0.29).
    4. A connection that closes later (connection.onClose, around L404) is also marked failed and stopped without a reconnect.
    5. reconcile (around L537-575) only restarts servers whose config changed (isDeepStrictEqual), so config reloads do not retry a failed server. The only paths that restart one are MCP.connect (L640, the /mcps toggle), Credential.Event.Switched, and HTTP session expiry.
    6. The same applies to package plugins: plugin/supervisor.ts keeps an install or load failure as failed until a source, config, or policy change, the 24-hour update check, or a restart.

    The location in active use is the one that never recovers, because its activity TTL keeps refreshing and it is never evicted and re-booted.

    Reproduction (macOS, 2.0.29)

    1. Configure a remote MCP server that is only reachable on VPN, for example {"mcp": {"internal": {"type": "remote", "url": "https://mcp.internal.example/mcp"}}}.
    2. Disconnect the VPN (or block the host with /etc/hosts to 127.0.0.1:9), then run opencode service restart and open a session in a project.
    3. /mcps shows internal as failed.
    4. Reconnect the VPN (or remove the block) and wait several minutes. /mcps still shows failed, and tool calls return "Reconnect it from /mcps".
    5. Toggle the server in /mcps or run opencode service restart; it connects at once.

    Expected

    Failed MCP servers (remote and local) retry with backoff while they are failed, and the service retries connections and failed plugin installs when the network changes or the machine wakes.

    Suggestions

    • Keep a per-server retry loop with capped exponential backoff (for example 15 s → 5 min) for every server whose status is failed, including timeouts and stdio servers whose command failed with network errors.
    • Retry failed servers when the service detects wake (a large wall-clock jump) or a network interface change.
    • Expose mcp.connect(name) (or "retry failed") on the plugin MCPDomain, so plugins can trigger recovery after they refresh credentials.
    • Retry failed package plugin installs on the same backoff.
  10. JarvisMaxDev commented on Oct 23, 2026

    @JarvisMaxDev

    Another data point: v2.0.32, Linux (WSL2), remote Streamable HTTP server with OAuth

    Environment: opencode 2.0.32 (npm, latest), WSL2 on Windows (kernel 6.18 microsoft-standard-WSL2), background service shared by several open directories. The affected server is the remote Figma MCP endpoint (https://mcp.figma.com/mcp, OAuth). No sleep/wake or network change was identified as the trigger.

    What we see:

    • Each loaded directory holds its own connection, so the same server ends up failed in some directories and connected in others at the same time.
    • Over four days the log shows 111 mcp connect failed for this server. Most failures are either ECONNRESET (median ~15 s after the request started) or The operation timed out (300–360 s).
    • Once a directory's connection is failed, it stays that way. A manual POST /api/experimental/mcp/figma/connect for that directory restores it immediately, and the endpoint answers normally when probed directly at the same time.
    • In 2.1.4, onClose in packages/core/src/mcp/index.ts still sets failed and stops the server without scheduling a reconnect, so upgrading alone would not change this. Only SessionExpiredError goes through recover.

    Separately, the 300–360 s failures are far longer than the 30 s startup timeout. A minimal repro without OpenCode shows that the MCP client SDK does not bound the notifications/initialized POST with the connect timeout or signal (2.0.0 and 2.3.1): modelcontextprotocol/typescript-sdk#3078. We could not confirm from logs that this is the request that hangs here, but it would explain why a connection attempt can stay pending for minutes before failing.

  11. enioclimacosalesjunior commented on Oct 25, 2026

    @enioclimacosalesjunior

    Additional data point — bare-metal Arch Linux (NetworkManager + Wi-Fi laptop), v2.1.2: instant EAI_AGAIN bursts, per-directory failed state, and a working reconnect-at-runtime mitigation

    Environment

    • opencode 2.1.2 (distro package, pacman)
    • Arch Linux x86_64, bare-metal (kernel 7.2.11-zen1-1-zen), NetworkManager + systemd-resolved
    • Wi-Fi laptop (wlan0-class iface); DNS = single on-link resolver from DHCP/RA on the router
    • 4 remote HTTP MCP servers in the global config (static headers, no OAuth): an agent/cloud imaging service, context7, pollinations, tavily

    What happens

    1. Bursts where all four remote servers fail at the same second with instant DNS rejections, not timeouts:
    level=WARN message="mcp http request failed" errors="[...\"getaddrinfo EAI_AGAIN mcp.tavily.com\"...]" durationMs=6
    level=WARN message="retrying MCP connect" server=tavily error="getaddrinfo EAI_AGAIN mcp.tavily.com"
    level=WARN message="mcp connect failed" server=context7 status.error="getaddrinfo EAI_AGAIN mcp.context7.com"
    
    1. Frequency: 163 EAI_AGAIN events across 3 active days (Oct 16: 37, Oct 23: 38, Oct 24: 86). The surviving state is per directory — directories whose connection was marked failed stay red indefinitely, while fresh runs in other directories connect all servers fine.

    2. The failures are instant (durationMs=1–6 ms) — the resolver answers "fail fast", there is no network timeout involved. During the same windows, child processes from the same service resolve normally (getent hosts, node dns.lookup for the same hosts: 12/12 and 45/45 OK). This matches phoriah's macOS finding above: the fault isolates to the long-lived service process's own resolver/transport state.

    3. Trigger pattern here is the laptop's Wi-Fi layer — NetworkManager connectivity-change bursts (suspend/resume, roam, DHCP renew). fix(core): retry transient MCP connect failures #52614's 1.25 s connect-retry window is very often shorter than the Wi-Fi outage, so the server ends up failed and nothing schedules another attempt.

    Manual recovery that works (v2.1.2)

    • POST /api/experimental/mcp/{server}/connect supports ?location[directory]=..., and it heals one directory at a time. The un-parametrized POST only fixed the config-owner directory; enumerating the canonical dirs from GET /api/project and POSTing per directory is what fully recovers every loaded location. This confirms the "connections are per project directory" observation and that the runtime connect route is already sufficient for a self-heal — it's just not triggered by anything.

    Runtime mitigation built (works, as a userspace workaround — or a feature)

    • A NetworkManager dispatcher hook on connectivity-change + a systemd --user watcher on the service log (tail -F … | grep --line-buffered "mcp connect failed") + a small recover script that (a) lists loaded directories from GET /api/project, (b) for each directory GET /api/mcp?location[directory]=…, (c) for every server in failed/disconnected state POSTs the tracked connect route. Debounce via flock + 10 s window; logs to journald.
    • Verified live: forced a genuine mcp connect failed (dead URL, ECONNREFUSED) → watcher fired, script POSTed connect for all four configured directories within seconds (logged reconectado: <server> @ <dir> ×4), and after restoring the URL everything returned to connected in all directories without touching the service. After fixing host DNS robustness (cache + fallback), no further bursts.

    What would help here (echoing the thread's wishlist)

    • Retry failed remote servers with bounded backoff, per directory (a fresh run elsewhere does not unfail this directory's state)
    • Retry on network-availability change / resume — same category as the Windows Modern-Standby data point above; on Linux, NM event → retry would cover it
    • Exposing the existing ?location[directory] connect route as opencode mcp reconnect would collapse this whole workaround to one command
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions