[BUG] Claude Desktop: hardcoded 60s initialize timeout drops stdio MCP servers whose package-runner cold start exceeds it

Status Open
Maintainer reply None cached
Activity 2 comments · opened Aug 5, 2026

Summary

Claude Desktop cancels the MCP initialize request after exactly 60 seconds and there is no way to raise that limit. For stdio servers launched through a package runner (uvx, npx, pipx run), the download+install of dependencies happens inside that 60s window, before the server process exists. Any dependency refresh that pushes cold start past 60s therefore drops the server permanently for that session.

This is not a hypothetical: a routine upstream release of a transitive dependency (botocore, which ships a new version every business day) is enough to take a working configuration to a fully broken one overnight, with no change on the user's side.

Environment

  • Claude Desktop 1.25927.0 (macOS 26.5.2, arm64)
  • 3 × stdio MCP servers, identical launcher: uvx --with 'mcp[cli]<2' opensearch-mcp-server-py
  • uv 0.8.3

What happens

From ~/Library/Logs/Claude/mcp-server-<name>.log, identical in all three servers:

10:42:46.158Z [info] Initializing server...
10:42:46.170Z [info] Server started and connected successfully
10:42:46.194Z [info] Message from client: method="initialize" id=0
              Downloading botocore (14.8MiB)
10:43:46.215Z [info] Message from client: method="notifications/cancelled"   <-- +60.000s
10:43:46.216Z [info] Client transport closed
10:43:48.229Z [info] Server transport closed

The cancellation lands 60.000s after initialize — a fixed deadline, not a network failure. The servers' tools are then absent from the session entirely.

Measured by hand, same command, same env:

| Condition | Time to initialize response |
|---|---|
| Cold (dependency resolution + download of 68 packages) | 110 s |
| Warm (uv cache populated) | 7–26 s |

Warm start succeeds and the servers work perfectly. So the only thing standing between "works" and "silently gone" is whether an upstream package published a release since the last launch.

Root cause chain

  1. The MCP server package declares boto3>=1.39.0 — an open upper bound.
  2. botocore releases daily (24 releases in July 2026 alone).
  3. uvx resolves to the newest match on each launch; a new botocore invalidates the cached environment and triggers a fresh 14.8 MB download (occasionally numpy/scipy/scikit-learn too, ~50 MB total, 68 packages).
  4. Cold install takes ~110 s > 60 s deadline → notifications/cancelled.
  5. All three servers race for the same uplink simultaneously, making each slower.

Evidence that step 3 happens routinely: the local uv cache holds 42 separate environments spanning 15 botocore versions (1.43.46 … 1.43.64), and has grown to 11 GB. botocore 1.43.64 was published at 20:12 the previous day; the failure above is from the next morning's first launch.

Why notifications/progress cannot solve this

The usual answer to a slow initialize is for the server to emit progress notifications and let the client extend its deadline. That is structurally impossible here. During the download there is no server process yet — uvx is still assembling the environment that will contain the server. Nothing exists that could send a notification. A client-side configurable deadline is the only thing that can help.

Why existing issues don't cover this

  • #43791, #22542, #16837, #3033, #20335 — all about tool call / request timeouts, not the initialize handshake.
  • #60224 — closest, but Claude Code CLI on Windows and a session-init probe; closed as not planned.
  • #26666 — lazy init to unblock the prompt; closed as duplicate. Related but orthogonal: lazy init alone would still cancel this handshake.
  • #64671 — Windows UtilityProcess spawn timeout (5 s, OS-level), a different stage.

What is specific here: Claude Desktop, the initialize stage, and a server that has not started yet because its package manager is still installing it.

Steps to reproduce

  1. Configure a stdio MCP server launched via uvx with a package whose dependency tree is large and unpinned (any package depending on boto3 works).
  2. Run uv cache clean to simulate the state after an upstream dependency release.
  3. Start Claude Desktop.
  4. Observe Downloading … in the server log, then notifications/cancelled at exactly +60 s, and the server's tools missing from the session.

Expected behaviour

Any one of these would resolve it:

  1. A configurable initialization timeout — honour a timeout (or initTimeout) field per server in claude_desktop_config.json, or an MCP_TIMEOUT env var, for the initialize phase.
  2. Treat stderr activity as liveness — the child process is demonstrably alive and writing Downloading botocore (14.8MiB) to stderr throughout. Resetting the deadline on output would fix the common package-runner case with no config.
  3. Retry / late attach — if a server completes initialize after cancellation, register its tools rather than discarding them. The install finishes ~50 s later and the server sits there fully functional but unreachable.
  4. At minimum, surface the cause in the UI. The server currently shows as failed with no hint that a download was cut short; a user reasonably concludes their backend is down and investigates in the wrong place.

Current workaround

Pin the package version so resolution stops picking up new transitive releases, and pre-warm the cache manually before starting the app. Both require knowing about the 60 s deadline in the first place, which is only discoverable by reading the logs closely enough to notice the timestamps are exactly 60.000 s apart.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗