A failed MCP server attach at startup is terminal for the session — no retry, even for transient network errors

Status Open
Reported on v2.1.221
Maintainer reply None cached
Activity 0 comments · opened Aug 7, 2026

Summary

When Claude Code spawns MCP servers at startup, a failed initialize is treated as terminal for the entire session. The server shows "Could not attach to MCP server <name>" and stays unavailable until the user manually restarts Claude Code.

There appears to be no retry and no reconnection attempt, even when the failure is obviously transient — a DNS hiccup, a laptop that has not finished associating with Wi-Fi, or a remote server mid-restart.

Why this is more than a papercut

The window that decides the outcome is very small. Measured against a remote MCP server over stdio:

  • Healthy: initialize returns in 0.42–0.94s, tools/list (62 tools) under 1.2s
  • Unreachable downstream: the proxy answers initialize with a JSON-RPC error in ~0.2s, and the client gives up

So a network blip lasting a couple of seconds, coinciding with launch, costs MCP for the whole session. Nothing recovers on its own.

I measured how often that actually bites. A 12-hour probe of one remote MCP endpoint, once per minute:

720 samples
507 success (~0.2s)
213 failures, in three CONTIGUOUS blocks (1h42m, 1h50m, and one isolated sample)

The failures were local connectivity drops — a machine tethered to a phone that periodically left the building. Roughly 30% of that window was a hole a startup could land in, and several did. Each cost a session's MCP access, and the symptom ("Could not attach") looks like a server problem, so debugging goes to the wrong place.

Suggested behavior

Retry the attach with backoff rather than failing permanently. Options, roughly in order of value:

  1. Bounded retry at startup — e.g. 3–5 attempts over ~30s before declaring failure. Cheap, and covers the overwhelming majority of these.
  2. Background reconnection — keep retrying at a low rate after startup, so a server that becomes reachable at minute 3 attaches then, rather than requiring a restart.
  3. A user-initiated reattach that does not require restarting the whole session. /mcp currently reports state; being able to retry from there would help even without automatic retry.
  4. Distinguish the failure classes in the message. A connection/DNS error is transient; a missing binary or a config error is not. They currently present identically, which sends users to the wrong diagnosis.

Even (1) alone would eliminate nearly all of what I observed.

Workaround, for anyone hitting this

I patched the wrapper script that launches the server so it probes the endpoint's health URL and blocks until reachable (up to 60s) before exec'ing the MCP proxy. Verified three ways:

| Case | Result |
|---|---|
| Healthy endpoint | initialize 0.67–0.94s — no added latency |
| Unreachable | retries instead of dying in 0.2s |
| Unreachable, then recovers after 7s | waited 8.2s, attached successfully |

That third case is the one that was previously fatal.

This only works if you control the launch command and the server exposes a health endpoint. It cannot help for servers spawned directly, and it has to be repeated per server — which is why the durable fix belongs in the client.

Environment

  • Claude Code 2.1.221, macOS
  • Remote MCP server over a stdio proxy; same behavior observed against two different servers
  • Reproducible by pointing an MCP server at an unreachable host and starting Claude Code

View original on GitHub ↗