writing/claude-code-context-bloat-is-mcp
AIJul 16, 2026·6 min read

Claude Code context bloat is MCP, not your prompt

A logging proxy reported 93,780 input tokens on one Claude Code request. The API said 2. Measured properly, MCP was 43k of my 99.1k context, not the prompt.

Adrian Szabłowski
Adrian SzabłowskiAI web developer at Tidio
A dense band of amber schema blocks streaming from the left and filling most of the frame, cut by a thin luminous vertical line, with a single small teal token glowing alone in the dark space beyond it

Every Claude Code request carries a payload you never typed: MCP tool schemas, a skills catalogue, instructions for features you may never touch. The advice going around is to cut it, and the tool people reach for is Matt Pocock's logging proxy, which records every request between the CLI and the API.

I ran it. Its first log said:

**93,780 input tokens** billed for this request (from the response usage).

The raw usage in the same file said:

{"input_tokens": 2, "cache_creation_input_tokens": 340,
 "cache_read_input_tokens": 93438,
 "cache_creation": {"ephemeral_5m_input_tokens": 0,
                    "ephemeral_1h_input_tokens": 340},
 "output_tokens": 178}

Two tokens at the base rate.

Why is the headline number wrong?

The sum is legitimate. Anthropic's prompt caching docs define total_input_tokens as exactly that addition. The prices are not equal: a 5-minute cache write costs 1.25x base, a 1-hour write 2x, a cache read 0.1x. Mine was a 1-hour write.

fieldtokensrateequivalent
input_tokens21x2
cache_creation_input_tokens (1 hour)3402x680
cache_read_input_tokens93,4380.1x9,344
proxy headline93,78010,026

Nine point four times, from summing three prices as one.

Why did everything land in cache_read? The docs define input_tokens as the tokens after the last cache breakpoint, and mine was 2. The schemas and system prompt sat ahead of it and don't change between turns: a large stable prefix, a small variable suffix, the ideal shape for caching. The payload everyone panics about is the part that caches best.

Cache reads are 10% of base, not 0%, and every fresh session pays a 1-hour write at 2x to lay the prefix down again. A ninth as expensive is not the same as cheap.

The scarce thing is your context window

Tool definitions consume space and attention. The model reads past all of them before reaching your question, and picks from a longer list. /context shows where they go. Mine, copied as printed:

99.1k/1m tokens (10%)
  System prompt:   3.1k
  System tools:    6.1k
  MCP tools:      43k     ← 127 tools
  Custom agents:   1.1k
  Memory files:    8.6k
  Skills:          9.8k   ← 494 skills
  Messages:       28.5k

43k of MCP. Not the system prompt at 3.1k, which no setting of mine can shrink. Not the skills catalogue, which sounds enormous at 494 entries and costs 9.8k.

MCP tool definitions, by plugin
apple-numbers
33.1 KBmongodb
19.4 KBplaywright
16.7 KBaws-knowledge
7.4 KBcloudflare
7.2 KBprisma
5.0 KBcontext7
4.6 KBdak
3.5 KB
Bytes of JSON schema shipped on every request, grouped by the plugin that owns the server.

A spreadsheet server was my largest line item. 26 tools, 33 KB, on every request I had ever sent. I have never once asked Claude to open a spreadsheet.

Check what your projects import

The obvious move is to delete anything you don't recognise. I nearly did, and would have broken two of my own apps. So I grepped every package.json on the machine for the packages behind each server instead.

Ten repositories, and the answer contradicted my instinct. expo was in two, including my training app. @supabase/supabase-js in two more. prisma and stripe live in a third. All four were on my cut list only because the project I happened to be sitting in didn't use them, which is the wrong question when the setting is global. mongodb, playwright, and @auth0/* came back empty across all ten.

That test only works for servers backed by an npm dependency. My 33 KB spreadsheet server has no package to grep for, so nothing in that output justified cutting it. I cut it on the sentence above, which is a judgement, and I'd rather label it as one than dress it up as a measurement.

The result: 43k of MCP down to zero

19 plugins removed, 16 kept. Then /context again:

25.9k/1m tokens (3%)
  System prompt:   3.2k
  Custom agents:   1k
  Memory files:    8.6k
  Skills:          9.9k   ← 254 skills
  Messages:        3.1k
 
MCP tools · /mcp (loaded on-demand)
  16 tools · 0 tokens

111 of 127 tool schemas gone. Three things I won't claim from that.

I can't tell you why the line reads 0. The second reading carries a label the first didn't: loaded on-demand. Whether my cut triggered that mode, or whether it would have fired anyway with all 35 plugins installed, I couldn't determine. I went looking in the binary, found the deferral machinery, and couldn't isolate the condition. An earlier session had tools deferred with every plugin still enabled, which points against my instinct.

99.1k to 25.9k isn't mine either. Messages fell 28.5k to 3.1k because the second reading was a fresh session.

I'm not counting the 6.1k of system tools that vanished between readings. Removing MCP plugins shouldn't remove Claude Code's built-ins, and a number without a mechanism is what this post is complaining about. Attributable: 43k.

The half that did nothing: 240 skills, no change

Those 19 plugins took their skills with them, 494 entries down to 254. The skills line went from 9.8k to 9.9k.

It went up. Make that a fourth thing I can't explain: at roughly 16 bytes per bare entry, losing 240 of them should have taken about 1k off, and instead the line gained 0.1k. Rounding moves 0.1k, not 1k, and it doesn't move a number the wrong way.

What I can measure is the shape. The catalogue is one line per skill, and most lines are a bare name worth about 16 bytes. Of the 173 skills in my home directory, the set I can open and count, 147 were bare and cost 2.3 KB between them, while 26 carried 12 KB. I'm assuming the 240 plugin entries that vanished skewed the same way, which I can't verify now that they're gone.

Either way the count was never the cost, so cutting the long tail is theatre. Whether the expensive minority can be trimmed is a question I haven't answered, and after watching this line move the wrong way I'd want to measure it before believing anyone who says it can. Including me. That instinct is the whole of why AI builds the plausible feature, not yours: the confident answer and the correct one are different things.

What to do

Run /context before touching a setting. If it's the system prompt at 3.1k, there's nothing to win. If it's MCP, list what your projects import rather than what you remember installing.

And read the proxy's request body, which is what it's genuinely good at. Its per-tool ranking found the 33 KB server I'd been shipping for months. Just don't let the headline send you looking for a bill that was never there.

For the version of this argument where the numbers do carry a dollar sign, see what an eval harness caught that a bigger model couldn't, or the rest of the levers in production LLM cost optimization.

Questions about this post.

How much context do MCP tools use in Claude Code?
In my setup, MCP tool definitions were 43k of a 99.1k context window, covering 127 tools across 35 plugins. That is four times my skills catalogue at 9.8k and fourteen times my system prompt at 3.1k. The split varies by what you have installed, so run /context to get your own number rather than borrowing mine.
Does MCP context bloat increase your Claude Code bill?
Far less than the token count suggests. Tool schemas sit ahead of the last cache breakpoint, so they arrive as cache reads billed at 0.1x the base rate. One of my requests logged 93,780 input tokens, but only 2 billed at the base rate: the rest was 93,438 cache reads plus a 340 token one-hour cache write. Trim for the context window, not the invoice.
Why did the logging proxy report 93,780 input tokens?
Because it sums input_tokens, cache_creation_input_tokens and cache_read_input_tokens into a single figure. Anthropic defines that sum as total_input_tokens, but the three parts bill at different rates: 1x for base input, 1.25x or 2x for a cache write depending on lifetime, and 0.1x for a cache read. Treating them as one price overstated my request by 9.4x.
Do Claude Code skills use a lot of context?
Count is not cost. Cutting my catalogue from 494 skills to 254 moved the skills line from 9.8k to 9.9k, so it went up rather than down, which I could not explain. Most entries are a bare name worth roughly 16 bytes. Of the 173 skills in my home directory, 147 bare ones cost 2.3 KB between them while 26 carried 12 KB.
How do you reduce MCP context in Claude Code?
Run /context before changing any setting. If MCP dominates, grep every package.json in your projects for the packages behind each server instead of deleting what you do not recognise. I nearly cut the Expo and Supabase servers that two of my own apps depend on. After I removed 19 unused plugins the MCP line read 0, though it also gained a loaded on-demand label, and I could not establish that my cut caused the 0.
// KEEP READING

Command palette

Search pages, posts, and actions