DEV Community

Vivek Chimman
Vivek Chimman

Posted on

I built an MCP server to clean prompts — then learned MCP can't save your input tokens

I run a small tool that strips filler from LLM prompts — hedging, redundancy, pleasantries — while keeping every actual requirement. Paste a rambly 181-token prompt, get back the same request at 73 tokens. Same output from the model, 60% fewer input tokens.

The obvious next step was: put this inside the coding agents. I use Claude Code daily; MCP is right there. Expose a clean_prompt tool, let the agent clean prompts automatically, save tokens on every turn.

I built it. It works. And then I traced a session transcript and realized it cannot do the one thing I built it for. This post is the three wrong assumptions I burned a week on, so you don't have to.

Wrong assumption #1: an MCP tool can clean MY prompt

Here's the sequence when you type a messy prompt into an agent that has a cleaning MCP tool:

  1. Your raw prompt enters the conversation context. The input meter has already run.
  2. The model reads it, decides to call clean_prompt.
  3. The tool returns the cleaned version — which is appended to the context.
  4. The model proceeds with raw + cleaned + the tool-call overhead + the tool schema in the system prompt.

Net effect: you paid for the raw prompt, then paid again for the cleaned copy, plus overhead. An MCP tool runs inside the agent loop, after your text arrives. It is structurally incapable of reducing what you pay for your own input.

Where MCP cleaning genuinely pays: prompts the agent 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.

Wrong assumption #2: hooks can rewrite the prompt

Fine — intercept the prompt before the model sees it. Claude Code has hooks; there's one called UserPromptSubmit that fires on exactly the right event.

It can do two things: add context or block the prompt. It cannot replace the text. I re-checked Codex's hooks framework too — same story, add-context or block only. No agent I tested exposes a "mutate the user's prompt before the model sees it" hook. (If you know one that does, genuinely, tell me in the comments.)

Wrong 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. I shipped this and it worked — the model's turn visibly ran on the cleaned text.

Then I opened the session's JSONL transcript. The raw text was still there, recorded as <command-args>. And when the command resolved as a skill, the raw text appeared about four times — command-args, tool args, skill-load note, bash output. The context cost went up, not down.

One more trap from that transcript session, as a bonus: my script failed open (missing API key → passes the original text through, by design), and the model then paraphrased my raw prompt into a plausible-looking "Cleaned prompt: …" on its own. It looked identical to a real clean. The only way to tell was record-level transcript forensics. If you build anything that fails open inside an agent loop, make the failure loudly visible — the agent will helpfully paper over it otherwise.

What actually works: replace the text before you hit send

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 I went around them with OS-level text replacement:

  • A global hotkey (Windows for now — Win32 RegisterHotKey): type the messy prompt into any chat box — Claude Code, Codex, a web chat — press Ctrl+Shift+K, the box's content is selected, sent to the cleaning API, and replaced in place. You review the cleaned text and hit send. The raw version never enters any context.



Measured on my own usage with the default cleaner: 181 → 73 tokens (60%) on a hedge-heavy landing-page prompt, 233 → 157 (33%) on a dense product spec — filler-heavy prompts compress hardest. Swapping the cleaner model (Ctrl+Shift+L → Llama 3.3 70B) took that same spec to 106 tokens (55%). Nothing dropped — the cleaner keeps every requirement, constraint, and conditional; it only removes what the model ignores anyway.

The honest architecture summary

Approach Saves your input tokens? Why
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

If you take one thing from this: know where the meter starts. A lot of "token optimization" tooling operates after that point and quietly makes things worse.


This ships as AI Token Cleaner — REST API + MCP server + the hotkey. Free tier is 100 API cleans/day, no card. The playground needs no signup at all if you just want to see what it cuts. Happy to answer anything in the comments — especially if your agent setup has a pre-send mutation point I missed.

Top comments (0)