What is lazy MCP loading?
Lazy MCP loading is deferring an MCP server's tool manifest — every tool name, description, and parameter schema — until the moment the agent actually wants to call one of its tools, instead of injecting the whole manifest into the context window on every single turn. Early agents were eager: the instant you connected a server, its full manifest rode along with every message you sent, whether you touched those tools or not. Lazy loading flips that. The agent sees a thin index up front and pulls the full schema for a tool only when it decides to use it.
For a while this was a real fight. I spend most of my day inside Claude Code with a handful of servers connected, and once I started actually counting tokens, what bothered me was how much I paid for tools that just sat there. You connected GitHub because you reviewed PRs twice a week, and then paid for its manifest on every prompt. That fight is now mostly won: Anthropic built tool search into Claude Code and turned it on by default for Claude 4.5 and later models, and the other major agents moved the same way. Modern agents defer tool loading by default.
So this piece does two things. It explains how lazy loading works and where you still have to set it up yourself, and then it moves to the MCP cost that has not gone away: what the tools return. It is a spoke off the broader question of how to reduce AI coding agent token usage; start there for the full menu of levers.
Why did eager MCP loading cost so much?
Eager loading cost so much because the manifest is fixed overhead paid on every turn, and turns add up fast. A coding session isn't one big request — it's dozens or hundreds of round-trips as the agent reads files, runs commands, and reacts to output. Every one of those round-trips re-sends the system prompt and the full tool manifest for each connected server.
Here's the part that surprises people: the manifest for a big server can be large. The GitHub MCP server's README documents around 82 tools across 20 toolsets, five of them enabled by default. GitHub has never published a token cost for that manifest, and the third-party estimates in circulation disagree badly — 42,000, 55,000 and 64,600 tokens all appear in blog posts and issue threads about the same server — so treat any single figure with suspicion. What is not in dispute is the direction: a server that size is a large block of text the model mostly ignores, paid before you've typed a word. Connect two or three like it and the overhead adds up fast.
Now multiply by turns and by price. Take an illustrative 40,000-token manifest — a round number, not a measurement. With Claude Opus 5.5 at $4 per million input tokens (Anthropic pricing, as of October 2026), that's $0.16 of input — once. But if it rides along on 150 turns in a session, that's $24 of input just for the privilege of having a tool connected that you may never call. Prompt caching helps a lot here: cache hits on Opus 5.5 bill at $0.20 per million (5% of input), which drops that to about $1.20 — but caching only works while the prefix is stable and the cache is warm, and a manifest you never use is still tokens you never needed to send. On Sonnet 5.5 ($2 / $10 per MTok) or Haiku 4.5 ($1 / $5) the absolute numbers shrink, but the ratio doesn't: on an agent that loads everything upfront, you pay continuously for capability you use intermittently. That is the arithmetic that made deferred loading the default. The numbers behind this are collected in our AI coding agent token costs breakdown.
How does lazy loading actually work?
Lazy loading works by splitting the manifest into a cheap index and an expensive body, and only sending the body on demand. The mechanics are simple once you see them:
- At connect time, the agent receives a minimal descriptor per server — enough to know the server exists and roughly what it covers — rather than the full schema for all its tools.
- When the model decides it needs a tool, the loader resolves the full schema for that specific tool (or that tool's group) and injects it for the turns where it's relevant.
- When the work is done, the schema can drop back out of the active context, so it isn't re-sent on the next two hundred unrelated turns.
The result is that the per-turn floor — the cost you pay before you've said anything useful — collapses toward zero for servers you aren't currently using. You keep the capability; you stop pre-paying for it. This is the same family of move as output filtering (compacting noisy tool results before they hit context) and semantic code search (retrieving the right code by meaning instead of dumping whole files) — different lever, same principle: only the bytes that earn their place should reach the model.
It pairs naturally with prompt caching rather than competing with it. Caching makes the bytes you do send cheaper to re-send; lazy loading makes sure you weren't going to send most of them in the first place. Stack both and the savings compound.
Does Claude Code already load MCP tools lazily?
Yes, by default, since it shipped MCP tool search, and that is the biggest change to this topic since we first wrote about it. For most Claude Code users on a current model, the manifest problem is solved without any setup. As of October 2026, Claude Code's MCP docs say tool search is on by default for Claude Opus 4.5, Sonnet 4.5, Haiku 4.5 and later: MCP tool definitions are deferred, only tool names and server instructions enter context, and Claude loads a tool's full schema through a search step when it needs it. The same mechanism exists on the API as the tool search tool, where you mark tools defer_loading: true.
It is not universal, and the exceptions are exactly where people get caught:
- Third-party proxies. When
ANTHROPIC_BASE_URLpoints to a non-first-party host, Claude Code turns tool search off, because most proxies don't forward the blocks it relies on. Every schema loads upfront again unless you setENABLE_TOOL_SEARCHexplicitly and your proxy supports it. alwaysLoadservers. A server (or a single tool) markedalwaysLoad: trueloads in full at session start, whatever the setting.- Some hosted deployments. Microsoft Foundry on Azure and Agent Platform models older than the Claude 4.5 generation load all MCP tools upfront.
- Threshold mode.
ENABLE_TOOL_SEARCH=autokeeps tools upfront while their definitions total under 10% of the context window, and defers them past that;auto:Nsets your own percentage.
Deferral also isn't zero. Every connected tool still contributes its name, and each server its instructions, on every turn. Anthropic's own cost guide still recommends disabling unused servers with /mcp and preferring CLIs like gh or aws, which add no per-tool listing at all. Run /context to see what your servers actually occupy. Other agents vary: most current ones defer tool schemas too, but check yours before assuming it does.
When you still need to manage it yourself
If you sit in one of the exceptions above, or use an agent without tool search, the old discipline still applies. In rough order of effort:
- Check what actually loads. Run
/contextin Claude Code, or your agent's equivalent, and look at how many input tokens land before your first real instruction. If tool manifests you never touch make up a big share, you are in an eager setup. - Turn tool search back on where you can. Behind a proxy that forwards the needed blocks, set
ENABLE_TOOL_SEARCHexplicitly. DropalwaysLoad: truefrom servers that don't fire on most turns. - Prune what you don't use. A server you call once a week is better connected on demand than left on permanently. Our best MCP servers for Claude Code ranking covers which servers earn their place.
- Prefer a CLI when one exists.
gh,awsorpsqladd no tool listing at all, and the agent already knows how to call them.
You can sanity-check rough numbers with the token counter and the LLM token cost calculator.
The MCP cost that remains: what the tools return
Deferred loading fixes what the agent knows about. It does nothing about what a tool sends back once it's called, and that is where MCP sessions now spend their tokens. A GitHub MCP list_issues or get_pull_request returns pages of JSON full of URLs, IDs, avatars and nested user objects. A Playwright or Puppeteer snapshot can run to thousands of lines of accessibility tree. A database query returns every row and column you asked for, and a few you didn't. All of it lands in context, and then rides along in history on every later turn.
That is the part Tokenade handles. Its MCP proxy sits between your agent and each MCP server (tokenade mcp-wrap install wraps the servers you have configured, and tokenade install does it for you) and compacts what the tools return before it reaches the model:
- Dedicated compactors for GitHub and GitLab, browser automation (Playwright, Puppeteer, Chrome), filesystem, Git, memory servers and databases (Postgres, SQLite, MySQL, Supabase, DuckDB).
- A generic, shape-aware compactor for every other server, which folds repetitive JSON structure instead of cutting it blindly.
- Screenshots and images pass untouched, so visual work isn't degraded.
- The full result stays recoverable: the agent can pull back the original whenever it needs a detail.
Tokenade doesn't defer tool loading itself; that is your agent's job, and current agents do it well. It works on the bytes that loading can't touch, alongside the same compaction for shell output and file reads, and you can see what each tool saved with tokenade dashboard.
What goes wrong (anti-patterns)
The failure modes here are mostly about confusing "connected" with "free." A few to watch for:
- Assuming every setup defers. A third-party proxy, an
alwaysLoadflag or an older model quietly brings back eager loading. Check/contextonce rather than trusting the default. - Assuming caching makes it free. Prompt caching cuts re-send cost to 10% of input on Sonnet 5.5 (5% on Opus 5.5, 2.5% on Fable 5.1), which is excellent, but it doesn't help on a cold cache and never beats simply not sending the bytes.
- Deferring the wrong tools. If a tool genuinely fires on most turns, deferring it just adds a search step each time. Marking that one
alwaysLoadcan make sense; deferral is for the long tail. - Watching the manifest and ignoring the output. Once loading is deferred, a single large tool result can outweigh every schema you connected. Measure what tools return, not just what they declare.
The honest summary: lazy loading was the right fix, and it is now built into the agents most people use. Keep the how-to above for the setups where it isn't. The MCP spend that's left is tool output, and that is a smaller, more practical piece of context engineering that a tool can handle for you.
See also:
Cut your AI agent's token bill.
Ranked #1 on the Token-Harness Optimizer Leaderboard. Zero config.
Tokenade cuts the token bill of AI agents: one install, zero config, and it trims what your agent sends to the model.