Skip to content

MCPContentTooLargeError: MCP tool "read_file" response (30206 tokens) exceeds maximum allowed tokens (25000). Please use pagination, filtering, or limit parameters to reduce the response size

Everything worked. The server was connected, the call was dispatched, the tool ran, and a complete result came back — and then your client refused to put it into the conversation. This is not a transport failure, not a crashed server, not a timeout, and not a rejection from the model provider: nothing was sent upstream, so there is no request ID, no billing, and no point checking your API key or your quota. The left number is what your server produced. The right number is a ceiling your client enforces locally, before the content can reach the context window.

Data as of 2026-09. Vendor limits and defaults change; check the official docs for current values before acting on any number below.

A tool result is not something you glance at

The reason this ceiling exists is the thing most people never form a model of, and it is what makes the fix obvious once you have it.

An MCP tool response is pasted into the conversation and then re-sent with every subsequent request for as long as the session lasts. It is not read, consumed and discarded. It becomes message history. So a result of the size in this message does not cost you its size once — it costs that on the turn it arrives and again on every turn after it, as part of the input of each new request. Ten more turns of work after an oversized read means paying for it ten more times.

The end state of that is a session that stops accepting any prompt at all, because the window is full of a file nobody is reading any more. That failure has its own page — prompt is too long, where tool content and definitions crowd out the chat — and it is a much worse place to be, because by then the oversized content is already in the history and the only cures are compaction or starting over.

Seen from there, this error is not an obstacle. It is a circuit breaker that converts a session-ending problem into a recoverable one, before the tokens are spent. The clue is in the message itself: it names the fix (pagination, filtering, limit parameters) rather than just the size.

Two related budget facts are worth holding at the same time. Compaction does not rescue you here: MCP tool definitions are re-injected after a compact, but a tool result is ordinary message history and is summarized away like everything else — you pay full price for it right up until it disappears entirely. And this ceiling is not the same thing as the transport limit underneath it; the Messages API has its own 32 MB request cap, which is measured in bytes rather than tokens and which compaction cannot fix either.

Why it refuses instead of truncating

Because a truncated result that looks complete is more dangerous than no result.

If the client silently handed over the first portion of a file, the model would have no way to know it was reading a fragment. It would reason about a config file whose last section is missing, a JSON document that was cut mid-object, a log whose relevant line is past the cut. The failure mode of that is not an error message; it is a confident wrong answer, produced minutes later, with no trace back to the truncation.

So do not go looking for a “just truncate it” switch as the fix. The truncation has to happen where the meaning is known — inside the tool call — which is precisely why the message asks you for a limit parameter rather than offering to cut it for you.

Is retrying useful?

No. A deterministic call produces a deterministic size, and the same call will be refused again.

Reading the same file returns the same bytes. If the tool you called is a plain read of something stable, every attempt hits the identical ceiling, and the retry costs you the tool’s execution time for a result that is discarded again.

The one case that looks like a successful retry is not a retry: a search, listing, or query tool whose result size depends on its arguments can succeed with a narrower query. That is changing the call, and it belongs in the fix section below. The distinction matters because it tells you which branch you are on — run the same call twice with the same arguments and compare the token counts in the two error messages. Identical numbers mean a fixed-size response and a fix that must change the call shape. Different numbers mean a size-varies-with-input tool, where constraining the input is enough.

There is a consolation in the verdict: this failure is nearly free. Nothing was sent to the model, so you are out a tool execution, not a large block of input tokens.

Fix by the shape of your call

  • You asked for a whole file and the tool has offset and limit parameters — use them. Two bounded reads beat one refused read, and they let you stop as soon as you have what you came for.
  • You asked for a whole file and the tool has no such parameters — use the client’s own file-reading tool instead, which does. A generic MCP read_file is rarely better at reading local files than the built-in path, and it charges the same tokens.
  • You wanted a specific value from a large document — ask the server for the value, not the document. A search or query tool on the same server almost always exists and returns a fraction of the size.
  • The response is only slightly over the ceiling — a limit parameter or one filter will clear it, and it is worth doing even if you could raise the cap, because the content still has to live in the window afterward.
  • The response is many times the ceiling — the tool is the wrong instrument for this data. Something that returns that much content per call will refill the window even when individual calls squeak through.
  • You own the server — make the tool paginate by default and return a cursor, and report sizes in its schema description so the model can choose sensible arguments without discovering the limit by hitting it.
  • Your client exposes a configurable ceiling — raising it is the last resort, not the first move, and check your client’s official docs for the current setting and default rather than assuming the number in your message is universal. Raising the cap does not create context; it relocates the failure to a later turn and a worse error.

Confirming you fixed the budget, not just this call

One success is not the confirmation you want, because a single narrowed call proves only that one call fits. Re-run the same workflow end to end and check two things: the tool calls return, and the conversation is not being dominated by tool output afterward. Inspect what is occupying the context window by category — the client’s /context view breaks it down — and look at whether MCP results are a line item you can live with for the rest of the session.

If you are near the ceiling of a session you intend to keep working in, the honest confirmation is a second full pass through the same task in a fresh session, watching whether the window fills at the same rate. A fix that merely moved you from failing on turn three to failing on turn nine is not a fix.

The other half of the MCP budget problem is the part that costs you tokens before you type anything: a tool name rejected because the server prefix ate its length budget is a page about the same assembled tool list, seen from the definition side rather than the result side. If the failure happens before any result comes back, you are in transport territory instead — MCP error -32000 means the connection died, and nothing about response size applies. And if this error appeared inside a batch of parallel tool calls, expect the other calls in that batch to report a sibling failure that names nothing useful; the size error is the real one and the siblings are collateral. For sorting a message into “my client refused it” versus “the API refused it”, which is the first fork on this page, the AI coding error triage tool asks that question first.