[BUG] Severe fixed-cost latency in Claude Desktop's tool-calling layer
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
I have tried lots of things. I give up.
Claude code has produced this bug report:
Severe fixed-cost latency in Claude Desktop's tool-calling layer
Summary
Every tool call observed in a Claude Desktop "Code" tab session carried a ~5-10 second fixed latency floor, regardless of what the tool actually did — confirmed for MCP tool calls (both bridged via mcp-remote and via direct Streamable-HTTP transport) and for a built-in tool (Glob) doing zero network I/O. On top of that floor, write operations requiring the model to author content inline show an additional ~5 ms/byte cost that scales with content size.
Net effect measured on a real product surface (Cowork): writing a ~14KB text file took 85.40 seconds end-to-end. The equivalent raw operation against the same backend, bypassing Claude's tool-calling layer, took under 300 milliseconds. That is roughly 250-300x overhead, and it appears unrelated to the specific MCP server, the network, or the user's environment.
Environment
- Claude Desktop, "Code" tab (Claude Agent SDK-based session)
- A custom internal MCP server ("fs-mcp"): Python + FastMCP, exposing filesystem read/write over Streamable HTTP on a home LAN, no auth, no TLS (trusted local network)
- Default config at the time of testing: bridged via
npx -y mcp-remote <url> --allow-http(a stdio-to-HTTP proxy process) perclaude_desktop_config.json - Notably, fs-mcp itself was purpose-built to fix a prior performance problem: per its own module docstring, it replaced an earlier SMB-based file access setup that had proven unreliable ("dropped sessions mid-write, slow whole-file transfers"). The latency documented in this report is unrelated to SMB — it shows up specifically in the MCP tool-calling layer that was introduced to get away from that earlier problem, i.e. this is a second, independent performance issue on top of one that had already been solved once.
Methodology
Every operation was bracketed with date +%s%3N (millisecond-resolution epoch time) immediately before and after, executed via the session's own Bash tool, to measure end-to-end wall-clock time as experienced within the session.
How to reproduce
The MCP-specific numbers below depend on our own NAS/fs-mcp setup, which won't be available to whoever picks this up. The core finding does not — it reproduces with a plain built-in tool and no custom server at all:
- Open a Claude Desktop "Code" tab (or the standalone
claudeCLI) in any project directory. - Ask Claude to time a trivial, zero-I/O built-in tool call: run
date +%s%3Nvia Bash, callGlobwith a simple pattern (e.g.*.json), then rundate +%s%3Nagain, and report the millisecond difference. - Expected-if-healthy: well under a second — it's a local directory pattern match, no network, no disk work of consequence.
- Observed instead: 8.58-11.87 s, repeatably, in both a long-running conversation and a freshly-opened empty one (tests 7 and 8 below).
To reproduce the MCP-specific part, repeat the same bracketing around a call to any Streamable-HTTP-transport MCP server's tool (self-hosted or otherwise) instead of Glob. Expect a similar multi-second floor through Claude, versus well under a second for a raw HTTP request to that same server made directly (bypassing Claude's tool-calling layer) — see tests 3, 4, and 6.
Data
1. Reference data from a separate product surface ("Cowork"), provided by the user before this investigation started
| Nominal size | Actual bytes | Time |
|---|---|---|
| "1KB" | 1,020 | 13.97 s |
| "10KB" | 9,316 | 51.53 s |
| "20KB" | 14,178 | 85.40 s |
Fitting t = overhead + K × bytes to these three points: overhead ≈ 8-9 s, K ≈ 5.4 ms/byte.
2. write_file via mcp-remote-bridged fs-mcp, this session
| Actual bytes written | Time |
|---|---|
| 10 | 10.58 s |
| 920 | 44.36 s |
| 1,032 | 17.70 s |
| 1,654 | 18.94 s |
| 4,900 | 21.29 s |
| 6,950 | 20.69 s |
3. Control — list_dir via the same bridged fs-mcp, pre-whitelisted (zero approval clicks needed)
6.11 s — rules out human click-latency as the explanation for this call.
4. Control — same MCP server, raw curl directly to it (full JSON-RPC handshake by hand, bypassing Claude's tool-calling layer entirely)
| Operation | Time |
|---|---|
| initialize handshake | 576 ms |
| notifications/initialized | 322 ms |
| tools/call → list_dir | 503 ms |
| tools/call → write_file (1,020 bytes, byte-exact) | 260 ms |
5. Control — local file generation, no network at all (head -c via Bash)
| Size | Time |
|---|---|
| 1,020 B | 138 ms |
| 9,316 B | 140 ms |
| 14,178 B | 134 ms |
| 3 files, total | 879 ms |
6. Control — same fs-mcp server, reconfigured with direct Streamable-HTTP transport via a project-level .mcp.json, completely bypassing mcp-remote
| Call | Time |
|---|---|
| list_dir, first call (fresh approval needed) | 8.98 s |
| list_dir, second call (pre-whitelisted, zero clicks) | 5.16 s |
7. Control — built-in tool, zero MCP, zero network (Glob), same session, run immediately after test 6
| Call | Time |
|---|---|
| First | 11.87 s |
| Second | 8.58 s |
8. Control — brand-new conversation (empty context, freshly opened tab), same list_dir call via direct-HTTP fs-mcp
Both the approval-needed first call and the clean second call: 5-6 s each, self-reported by the user running the same test independently.
What we ruled out
- fs-mcp server code itself — reviewed the full source (Python/FastMCP, ~200 lines).
write_fileis a plain synchronousPath.write_text/open(...).write()call. No artificial delay, retry logic, locking, or anything else that could account for multi-second cost. - Network/NAS latency — direct
curlround-trips to the same server, same LAN: 260-576 ms. - Transport mechanism —
mcp-remote(stdio bridge) vs. direct Streamable HTTP: both showed the same ~5-9 s floor for equivalent, fully-whitelisted calls (tests 3 and 6). - Bridge process respawning — confirmed via OS process inspection (
Get-CimInstance Win32_Process) that themcp-remotebridge processes are long-lived and were not respawned between calls. - Conversation/context length — a brand-new, empty conversation showed the same ~5-6 s floor (test 8), ruling out "large accumulated context slows down each turn" as the primary explanation.
- Human approval-click latency — real and additive on a tool's first use in a session, but a clean ~5-10 s floor persists even for fully pre-whitelisted, zero-click calls (tests 3, 6-second-call, 7).
What remains unexplained
After eliminating all of the above, a ~5-10 second fixed latency floor remains on every tool call — MCP or built-in — inside this Claude Desktop Code-tab session, with no cause identifiable from the client side. Since a built-in tool with zero I/O (Glob) shows the same magnitude of delay as an MCP round-trip to a remote server, the floor appears to live somewhere in Claude Desktop's own tool-call dispatch/round-trip mechanism — something we have no visibility into from outside the client.
Separately, for any write operation where content must be authored inline by the model (required by the MCP tool schema — there is no local-path or binary-copy alternative available), there is an additional ~5 ms/byte cost that scales linearly with content size and dominates total time for anything beyond a few KB. As a related side effect, we also observed that model-authored long, homogeneous content cannot be guaranteed byte-exact — repeated attempts to write an exact 1,020-byte payload by hand produced 1,032-1,654 bytes; only content generated by a separate program (Node.js) and sent via raw HTTP was byte-exact on the first try.
Impact
A single ~14KB documentation update took 85 seconds end-to-end for an operation that is, at the infrastructure level, sub-300-milliseconds — roughly 250-300x overhead. This makes routine file-editing workflows (updating notes, docs, config — a common Claude use case) disproportionately slow and disruptive, independent of any specific MCP server's design, the user's network, or file size in isolation.
Suggested follow-up (needs Anthropic-side visibility we don't have)
- Instrument the tool-call dispatch path inside Claude Desktop end-to-end (model decision → client dispatch → local/remote execution → result return) to find where the ~5-10 s is actually spent.
- Check whether this floor is specific to Claude Desktop's "Code" tab, or also present in the standalone
claudeCLI, claude.ai, and Cowork. - Consider whether large inline-content tool calls (e.g., an MCP
write_file-style tool) could support a lower-overhead path that doesn't require the full content to pass through model-generated output tokens — the ~5 ms/byte cost is otherwise unavoidable by design.
What Should Happen?
Thar Claude's tools work with low(er) latency and not spending 85 seconds internally to process/send 14kb of data to a mcp server that takes 0.5 secs when called with curl (exact same service/environ/time
Error Messages/Logs
Steps to Reproduce
see report above
Claude Model
Not sure / Multiple models
Is this a regression?
No, this never worked
Last Working Version
_No response_
Claude Code Version
1.24012.9 (03c61d)
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
PowerShell
Additional Information
_No response_