DEV Community

Cover image for Before I Type a Word, My Agent Burns 8,248 Tokens
MCP Token Saver
MCP Token Saver

Posted on

Before I Type a Word, My Agent Burns 8,248 Tokens

Last Tuesday night I was five messages into a refactor with Claude Code. It had just suggested a helper function, I asked it to wire up the call sites, and by then it had already forgotten the signature it wrote in message two. I opened a fresh session, repeated the prompt, everything worked. An hour later the amnesia came back in a different file.

First suspect: my own config

The project CLAUDE.md had grown into a hedge, so I cut it in half and stripped the style guide down to three lines. Then I checked the context meter of a brand new session, zero messages typed. The idle count sat at 8,248 tokens. An empty conversation burning that much points at something the client sends before I say anything.

Second suspect: the MCP servers

I run a mid-fat local stack: sqlite, git, fetch, memory, search, scheduler, translator, fsops. Eight servers, 48 tools. I disconnected them one by one and watched the idle count after each restart. Every disconnect knocked a few hundred off, and even with everything unplugged the number never went near zero. At that point I was ready to quit MCP entirely and go back to pasting code by hand.

Reading the traffic instead of guessing

I pointed a local proxy at the client and dumped the first request of that empty session. The messages array was empty, literally []. The tools array was not. Every one of those 48 tool definitions arrived wrapped in full JSON Schema: "type": "object", properties, required, plus a friendly paragraph of description for each argument. I ran tiktoken (cl100k_base) over that field alone. 8,248 tokens. Per request. Before the first character I type.

{
  "type": "object",
  "properties": {
    "repo": { "type": "string", "description": "Repository name..." },
    "path": { "type": "string", "description": "File path inside..." }
  },
  "required": ["repo"]
}
Enter fullscreen mode Exit fullscreen mode

The model re-reads that catalog on every call, every turn, every session. The "forgetfulness" finally made sense: a fifth of my working window was spent holding JSON the conversation never touches.

Does a model actually need the braces?

I repacked the same 48 definitions with mcptoon's pipeline: schema simplification plus its compact pipe notation, one line per field, all 48 tools kept, nothing truncated. Same information, 4,192 tokens. 49% of the original bill, and the model still received every tool with every field name it needs to make a call. I re-ran my sessions against the compact manifest: tool choice and arguments still landed right, including the annoying nested-object ones.

measured: 8 servers / 48 tools / tiktoken cl100k_base
raw JSON manifest ....... 8,248 tokens
mcptoon (simplify+slim) . 4,192 tokens  (-49%)
Enter fullscreen mode Exit fullscreen mode

One honest note about the size of the cut: how much you save depends on how bloated your schemas are. Documented, human-readable schemas like mine land around half. Flatter, machine-generated schemas compress much harder. Your number is between those poles, and the only way to know is to measure your own manifest.

The treasure at the end of the search

After fixing my setup I went to GitHub to see who else had hit this. Found mcptoon. Around two hundred stars, zero dependencies, pure stdlib Python, and it does exactly this one job: it re-serves your MCP tool manifest in a compact form any MCP client can consume. For a job this narrow, the polish is ahead of the star count.

Fair limits: if your stack is one or two servers with a dozen tools, this tax is pocket change and not worth an evening. If you run a heavier stack and your empty sessions open heavy, audit the tools field before you blame the model.

Question for the comments: what does your context meter read on an empty session, before you type anything? Drop the number. Curious what a normal idle bill looks like across setups.

Top comments (0)