Key Takeaways
- MCP tools can't reduce your Claude Code input tokens since they run after context entry.
- Use a pre-send hotkey or CLI pipe to clean prompts before they enter the token meter.
What Changed — The Token Optimization Trap You Need to Know
You built a prompt cleaner. You exposed it as an MCP tool for Claude Code. You expected token savings. And then you checked the transcript and realized you'd been paying more, not less.
This is the reality: MCP tools cannot reduce your input tokens. They run inside the agent loop, after your text is already in the context window. Every MCP-based token optimization for your own prompts is a net loss.
What It Means For You — The Three Broken Assumptions
Assumption 1: MCP cleans MY prompt
Here's what actually happens when Claude Code has a clean_prompt MCP tool:
- Your raw prompt enters the conversation context. The token meter has already run.
- The model reads it, decides to call
clean_prompt. - The tool returns the cleaned version — which is appended to the context.
- The model proceeds with raw + cleaned + tool-call overhead + tool schema in the system prompt.
Net effect: you paid for the raw prompt, then paid again for the cleaned copy, plus overhead.
Where MCP cleaning actually works: prompts Claude Code sends downstream — RAG queries, sub-agent instructions, pipeline calls. Those calls never see the raw version, so the savings are real there. That's a legitimate use case; it just isn't the "clean my typing" use case.
Assumption 2: Hooks can rewrite the prompt
Claude Code has a UserPromptSubmit hook that fires before the model sees your prompt. But it can only do two things: add context or block the prompt. It cannot replace the text. Same story with Codex's hooks framework — add-context or block only.
Assumption 3: Slash-command bash injection replaces the prompt
Claude Code slash commands support !command`` injection — the bash runs before the model sees the command body, and its output replaces it. So /clean <messy text> → bash pipes the text through the cleaning API → the model receives only the cleaned version.
This looks like it works. But check the session's JSONL transcript. The raw text is still there, recorded as <command-args>. And when the command resolves as a skill, the raw text appears about four times — command-args, tool args, skill-load note, bash output. The context cost goes up, not down.
Bonus trap: fail-open behavior
If your cleaning script fails open (missing API key → passes original text through), the model will paraphrase your raw prompt into a plausible-looking "Cleaned prompt: …" on its own. It looks identical to a real clean. The only way to tell is record-level transcript forensics.
Try It Now — What Actually Works
The token meter starts when your text enters the context. So the only place cleaning can save input tokens is in the text box, before send. Agent platforms give you no API for that moment — so go around them:

Option 1: Global hotkey (best for interactive use)
Set up a system-level hotkey (Windows Win32 RegisterHotKey, or AutoHotkey/Automator on Mac) that:
- Selects the content of your current text box
- Sends it to a cleaning API
- Replaces the text in place
You review the cleaned text and hit send. The raw version never enters any context.
Option 2: CLI pipe (best for one-shots)
Pipe your prompt through a cleaner before starting Claude Code:
cat messy_prompt.txt | clean_prompt | claude code
This works because the cleaning happens before the Claude Code process starts.
Option 3: MCP for downstream calls only
Use MCP cleaning for prompts Claude Code generates — RAG queries, sub-agent instructions, pipeline calls. Those never see the raw version, so savings are real.
The Honest Architecture Summary
MCP tool ❌ (adds tokens) Runs after raw text is in context Hooks ❌ Add-context / block only, no mutation Slash command + bash injection ❌ Raw persists in command-args; ~4× as a skill CLI pipe ✅ one-shots only Cleans before the process starts In-place hotkey before send ✅ Raw never enters any context MCP for downstream calls ✅ for those calls Sub-calls never see the raw
The one takeaway: know where the meter starts. A lot of "token optimization" tooling operates after that point and quietly makes things worse.
Source: dev.to









