Skip to content

Build1 publisher3 min readPublished

Eight MCP servers per session push the p90 connect wait to 35.5 seconds

One developer paired the start and established lines in 35 days of Claude Code logs. Across 27,257 connections the median connect ran under 0.6 seconds while the p90 session spent 35.5 seconds before the first token.

The Engineer · Build desk

Illustration accompanying Eight MCP servers per session push the p90 connect wait to 35.5 seconds

What happened

  • Across 35 days of Claude Code logs on one laptop, 33,599 files yielded 27,257 clean start-to-established connection pairs covering 22 MCP servers and 2,888 sessions.
  • The median connection finished in under six tenths of a second, but 39 percent of connections took longer than a second and the p99 reached fourteen seconds.
  • Of 38,876 attempts, 11,556 never logged an established line, and a single remote connector accounted for 7,422 of those.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • cost Per-session process spawning bills the developer's laptop: two stdio servers across thirteen open sessions duplicated roughly 1.4GB, about 54MB per server per session, and pushed a 16GB machine into swap.
  • decision Picking a transport is picking which quantile to protect, because stdio wins the median by 3x and loses the tail, so anyone shipping MCP tooling to sessions that spawn processes should size for p90.
  • constraint The 30,000ms timeout caps each connection but not the session total, so every server added to a config extends startup and the sum has no ceiling.
  • exposure A client-side log cannot separate a broken connector from a file that rotation cut mid-handshake, so an integration that never establishes stays invisible until someone pairs the lines by hand.

Claude Code leaves the measurement on disk already. It writes a JSONL log per MCP server, per session, under `~/Library/Caches/claude-cli-nodejs/<project>/mcp-logs-<server>/` [3]. Two lines bracket each attempt: `Starting connection with timeout of 30000ms`, then `Connection established with capabilities` [4]. Pair them inside one file and you have a latency sample [4].

The first pass of that pairing reported a maximum of 119 seconds and a p99 of 14.5 seconds [15]. The developer, writing on dev.to, threw the maximum out after re-reading the client's own log line: a connection cannot establish at 119 seconds if the client gives up at 30 [15]. Those samples were a closed laptop, with the wall clock still running [15].

The refresh split puts the delay outside the client code. About 740 of the 27,257 pairs, 2.7 percent, had a token refresh inside the connection window, and they ran 5.8 times slower than the rest on the same servers, network and machine [10][4][8]. The write-up decomposes one of them: 550ms of server start, 2.6 seconds of OAuth round-trip while the server sat there doing nothing [9]. You cannot reproduce that on demand.

Fan-out is where the seconds accumulate. The machine loaded a median of eight servers per session and a maximum of sixteen [12]. Eight connections at the median would total 4.8 seconds; the median session actually spent 5.9 [2]. At the p90 session of 35.5 seconds, each server contributed about 4.4 seconds on average, roughly seven times the median connection [3].

Transport shows up in the tail. stdio is 3x faster at the median because there is no network, and worse at p90 [11]. The author put the ceiling on npm: spawning a process costs roughly nothing at the floor, and at the top it costs whatever npm has decided to do [17]. An HTTP server that is already running is slower on average and far more predictable [11].

So the 35.5-second p90 is a fan-out number, not a stdio number, and the aggregate transport comparison does not tell you about any individual server. The worst server by median in this data was one of the two the author had already removed in July with a 56-line shell script called mcp-optional, at 2,261ms median and 10,413ms at p90 [13][1]. "I removed it in July for the wrong reason and got the right outcome," the author wrote [16].

This is one developer's machine [18]. The per-session figures transfer only if your sessions also load about eight servers and some of them authenticate over OAuth; a workstation running three stdio servers and one session reproduces neither the memory cost nor the tail. The method carries over anywhere, because the log path and both lines belong to the client [3][4].

What to watch

  • Whether the connector missing 7,422 established lines is actually failing, which needs its server-side logs rather than the client's.
  • Whether MCP clients move token refresh out of the connect path, since that is where the 5.8x penalty lands.
  • Whether the same log-pairing method run on a machine with fewer sessions and no OAuth connectors reproduces the per-session tail.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories