MCP truncation at 2048 chars is invisible: tool `description` leaves no log, `/mcp` shows the untruncated text
MCP instructions and tool description are silently truncated at 2048 chars
Version: 2.1.220 · Platform: macOS (darwin 25.5.0) · Transport: stdio
Summary
Claude Code truncates two MCP server-provided strings at 2048 characters before
they reach the model:
InitializeResult.instructions- every tool's
description
Neither limit is part of the MCP specification — the spec types instructions as
an unbounded optional string, and reference SDKs impose no length cap. The
truncation is a client-side decision, and the server is never told it happened:
no error, no field in the response, no warning.
Truncation itself is defensible — these strings enter the system prompt of every
request. The bug is that it is invisible, and for tool descriptions it is
invisible everywhere.
Impact observed on one machine
502 truncation events across all MCP logs under~/Library/Caches/claude-cli-nodejs/*/mcp-logs-*/*.jsonl.
Worst single case: 10780 → 2048 chars, an 81% loss.
Most affected servers include Anthropic's own connectors:
87 claude-ai-Figma
78 synapse-bridge (ours)
57 pencil
39 claude-ai-<connector>
23 claude-ai-<connector>
An operator has no reason to suspect this. In our case a 9029-character protocol
description had been silently reduced to 2048 for two months across 16 projects;
we found it only by grepping the client's own debug logs.
The two problems
1. Tool description truncation leaves no trace at all
instructions truncation at least writes a debug line:
{"debug":"Server instructions truncated from 9029 to 2048 chars",
"timestamp":"2026-07-25T13:43:41.185Z","sessionId":"...","cwd":"..."}
Tool description has no equivalent log line. It is truncated at the same 2048
boundary with no record in the MCP log, no notice to the server, and no
indication to the user.
2. /mcp shows the full description; the model receives the truncated one
The value surfaced in the /mcp UI is the untruncated string, while the string
assembled into the API request is the truncated one. An author verifying their
tool description in /mcp sees text the model will never receive.
Reproduction
Minimal stdio MCP server, one tool, description of exactly 3000 characters with
distinct markers at the head and tail:
HEADMARK_DESC_A1S2D3 <2960 chars of filler> TAILMARK_DESC_P0O9I8
Connect it, then ask the model to quote the end of the tool's description.
Expected: the model can quote TAILMARK_DESC_P0O9I8.
Actual: the model quotes HEADMARK_DESC_A1S2D3, never sees the tail, and the
text it received ends mid-word at exactly character 2048. /mcp displays the full
3000 characters. Nothing appears in the MCP log.
The same procedure on InitializeResult.instructions truncates identically, but
does produce the debug line quoted above.
Requests, in order of value
- Log
descriptiontruncation the wayinstructionstruncation is already
logged. This alone would make the problem discoverable.
- Surface truncation in
/mcp— mark a truncated field rather than
displaying the full text the model will not receive.
- Communicate the budget to the server. The cleanest fix: return the
per-field character budget in the initialize response, so a server can adapt
its own text rather than discovering the loss months later from logs.
- Make the limit configurable (env var or setting). Optional if 1–3 land —
with the loss visible, authors can fit the budget deliberately.
Prior art
- #41593 — "MCP tool descriptions truncated at 2KB breaks code execution tools"
(opened 2026-03-31, closed 2026-05-06 as not planned by the stale bot, no
maintainer response). That report asked to raise or configure the limit and
documented a concrete failure mode: a code_executor tool whose description
embedded 60 function signatures had 45 of them cut, after which the model
hallucinated non-existent function names. Its author resorted to binary-patching
the constant (WoH=2048 → WoH=15e3) after every update. In 2.1.220 the same
constant is now D$=2048 — renamed, not removed.
- #31302 — "MCP tool schemas with complex/nested properties are silently
truncated" (closed 2026-03-06).
This report is deliberately not a duplicate of #41593. It does not ask to raise
the limit. Truncating strings that enter every request's system prompt is a
reasonable policy. The ask here is that the truncation be observable — which is
strictly cheaper to implement, and is already half-done: instructions truncation
is logged, description truncation is not. Closing the asymmetry would have let
both #41593's author and us find the problem in minutes instead of months.
Notes
- The limit counts UTF-16 code units (JS
String.length), so the documented
phrasing "2KB each" is imprecise: 2048 Cyrillic characters are ~4096 bytes of
UTF-8, and astral-plane characters count as 2.
notifications/claude/channelparams.contentis not subject to this limit,
which is the workaround we adopted. Worth documenting explicitly, since it is
currently the only automatic path into context without a length cap.
3 Comments
was any solution found ?
Server-side confirmation + the workaround we run, in case it helps before the fixes land.
We operate a Rust MCP server (rmcp) that bridges Claude Code sessions into a peer network — the same "16 projects / months of silent truncation" shape described here. Two things we do:
1. We fit
instructionsand every tooldescriptioninto the 2048 budget ourselves, on the server. We treat 2048 as a hard cap and gate at an 1800-char safe threshold (margin for later wording tweaks). Anything past the safe threshold is logged loudly and trimmed/rejected by us — so we decide what survives instead of an invisible trailing cut. Today this is the only reliable defense, sincedescriptiontruncation has no log at all.2. For content that must arrive whole, we don't use
instructions— we push it throughnotifications/claude/channel. As the issue notes at the end, thatcontentfield is the one path into context with no length cap. Each peer's full profile / protocol doc (multi-KB) is delivered as channel-notification content, never stuffed intoinstructions. It lands complete every time.So the pattern: keep
instructions/descriptionunder 2048 by construction, and route anything larger through the uncapped channel content.Strong +1 on the priority list — even just logging
descriptiontruncation (item 1) would have turned a two-month invisible failure into a one-line grep.Fable suggested me to also include in my MCP server a tool "read-first" that would dynamically return long instructions, with the hope model pays more attention to it
I reported issue in Claude Support chat, hopefully this will speed up resolution...