· via dev.to (home feed)
27,257 MCP connections measured: p90 session startup wait hits 35.5 seconds
A dev.to analysis of 27,257 MCP connections from 35 days of Claude Code logs found session-level p90 connect times of 35.5 seconds, with OAuth token refreshes making single connections 5.8x slower.

A single machine, 35 days of logs
An engineer has turned connection logs left behind by Claude Code into one of the few empirical datasets on Model Context Protocol (MCP) latency. In a dev.to post published on September 16, Achiya Cohen describes parsing 33,599 log files spanning August 13 to September 16, 2026, which held 38,876 connection attempts, 27,257 completed connections across 22 servers, and 2,888 sessions.
The method required no new instrumentation. Claude Code writes one line when a connection to an MCP server begins, including its 30,000ms timeout, and another when the connection is established. Pairing the two lines inside a single log file yields a genuine connection latency. Cohen frames the single-machine setup as the point: it captures the distribution a developer actually experiences rather than a synthetic benchmark.
Per-connection latency looks fine until the tail
Individually, connections appear healthy: a median of 582ms, p75 of 1,650ms, p90 of 3,678ms, p95 of 6,428ms and p99 of 14,049ms. But 39% of connections took longer than a second, and the p99 approaches half of the client's 30-second timeout, which Cohen argues makes the tail impossible to write off.
OAuth refreshes, not server code
The most consequential finding is that slow connections usually are not the server's fault. Splitting the data by whether an OAuth token refresh occurred inside the same connection window shows 748 refresh-path connections with a median of 3,170ms and p90 of 9,619ms, against 26,509 non-refresh connections with a median of 550ms and p90 of 3,400ms. That is a 5.8x gap on the same servers, network and machine. Only 2.7% of connections hit a refresh, but because token expiry looks random from the user's chair, that small slice produces much of the erratic, unreproducible slowness that gets blamed on server implementations.
stdio wins the median, HTTP wins the tail
Transport choice repeats the pattern of good averages and bad tails. stdio connections (7,363) had a median of 222ms but a p90 of 4,693ms; HTTP connections (19,894) had a median of 676ms and a p90 of 3,395ms. Local stdio servers are roughly three times faster at the median since no network is involved, but process spawning has an unpredictable ceiling, with npm behavior named as a frequent culprit, while an HTTP server that is already running behaves far more consistently.
Fan-out produces the 35-second p90
The headline numbers are session-level. Sessions on this machine connected to a median of 8 servers, up to 16, and total connect time across them had a median of 5.9 seconds, a p90 of 35.5 seconds and a p99 of 81.8 seconds. A third of sessions (33.7%) spent more than 10 seconds merely connecting. The slowest server by median, at 2,261ms with a p90 of 10,413ms, was one Cohen had already disabled in July using a 56-line script called mcp-optional, after stdio servers spawning a Node process per session consumed roughly 1.4GB of memory across about 13 open sessions on a 16GB M4 machine.
A 29.7% no-show rate
Of the 38,876 attempts, 11,556 (29.7%) never logged an established line. Cohen treats this as an upper bound on failure, since log rotation can cut a file mid-handshake, but the distribution is not uniform: a single remote connector accounts for 7,422 of the missing connections, suggesting one integration failing repeatedly while nothing surfaces the error.
A measurement trap worth copying
An initial pass produced a maximum of 119 seconds and a p99 of 14.5 seconds, figures that cannot represent live connections given the client's declared 30-second timeout. They were artifacts of the laptop sleeping while wall-clock time kept counting. Cohen capped all measurements at 30 seconds, discarding 24 of 27,281 samples (0.09%), and notes the uncapped figures would have been more striking but wrong.
What Cohen recommends
- Count servers before tuning any of them; with a median of eight per session, dropping one mediocre server saves more than optimizing a good one.
- Make heavy servers opt-in, which is all mcp-optional does: remove them from the config by default and re-add them on demand.
- Suspect the OAuth refresh path when slowness is erratic rather than uniform.
- Prefer an already-running HTTP server for heavy integrations, accepting a worse median for a better tail.
- Mine the logs clients already write before building new instrumentation.
Why it matters
MCP is becoming the default way coding agents attach external capabilities, and every configured server adds a per-session startup tax that users pay repeatedly without ever seeing it itemized. Cohen's data suggests the intuitive diagnosis, that a given server is simply slow, is usually wrong: the pain concentrates in OAuth refresh tails, process-spawn variance and silent connection failures, all of which compound under fan-out. The post also shows this kind of distribution data sits for free in cache directories on any machine running Claude Code, making independent verification cheap at a moment when such numbers are scarce. Cohen, who runs agent tooling against client infrastructure at Achiya Automation, explicitly invites others to publish their own refresh-versus-no-refresh splits and server counts.
- #mcp
- #model-context-protocol
- #claude-code
- #performance
- #developer-tools
- #observability