mcptoon
Add 255 MCP tools → 90,804 tokens gone. Add mcptoon → 117 tokens.
Keep 100+ MCP servers always configured. Zero context pollution. No loading. No unloading. One CLI for every agent.
If this saves you tokens, please star the repo — it helps others discover it.
English | 中文文档 | 🌐 Ecosystem | 📦 Profiles | Report Bug | Request Feature
The problem
Every MCP-enabled agent loads all tool schemas into your context — before any work starts.
Add 10 MCP servers (especially browser tools like puppeteer/playwright)
→ Each server returns tools/list with full JSON schemas
→ ALL schemas injected into your context
→ 50,000-100,000+ tokens consumed
→ 128K context: 40-80% gone before you even ask a question
Add 100 servers → 200,000+ tokens → context is dead.
So you unload servers when not needed. Reload when needed. Repeat. Forever.
And when you want to add a new MCP server? You manually edit JSON config files (claude_desktop_config.json, etc.). One syntax error, wrong path, or missing env var — MCP won't load. You debug for hours.
You're managing MCP servers instead of doing work.
The solution
mcptoon keeps all your MCP servers configured — but their schemas never enter your agent's context.
😤 5 pains. ✅ 5 kills.
😤 Context death → ✅ 0 tokens, forever
Add 10 MCP servers — especially browser tools like puppeteer (47 tools, 23K tokens of schemas) or playwright (52 tools, 28K tokens). Before you ask a single question, 50-100K tokens of {"type":"object","properties":...} are squatting in your context. Your AI forgets what you were talking about. So you uninstall servers to make room. Then you need one — reinstall, wait, reconfigure. You're playing Tetris with MCP servers inside your context window. This is why people say "MCP is unusable past 5 servers."
→ mcptoon: 100 servers configured, 0 tokens in context. Use any tool, anytime. No Tetris.
😤 Config hell → ✅ One command, done
Want to add a server? Hand-edit claude_desktop_config.json. Miss a comma → MCP won't load. Wrong path → won't load. Missing env var → won't load. Sometimes it loads but tools silently don't appear — no error, no log, just nothing. You stare at a blank tool list and debug for an hour.
→ mcptoon: mcptoon add myserver --stdio npx -y @package. One command. Something's wrong? mcptoon doctor checks Python, config syntax, server connectivity — tells you exactly what.
😤 Agent can't self-serve → ✅ AI installs its own tools
Your agent is mid-task and says "I need GitHub search to finish this." It can't install tools — it's an AI, not an admin. So you stop coding, go edit JSON, restart the agent, wait for it to reconnect. Your AI forgot what it was working on. Momentum — dead.
→ mcptoon: Your AI runs mcptoon add github ... itself, and keeps going. No human in the loop. No context lost.
😤 Reconfigure per agent → ✅ One config, all agents
You set up 15 MCP servers for Claude Code. Now you try Cursor — different config format, different file location, redo all 15 from scratch. Then OpenCode. Then Codex. Same servers, 4× the work, 4× the chances to miss a comma.
→ mcptoon: One config file, every agent. ~/.mcptoon/config.json. Switch agents in seconds. Config follows you.
😤 Paying for JSON garbage → ✅ TOON, 20-97% smaller
Every MCP result looks like {"content":[{"type":"text","text":"{\"name\":\"react\",\"stars\":219000}"}]} — 80 tokens of braces, quotes, and type declarations to deliver 6 tokens of actual data. Over a session with 200 tool calls, that's 15,000 tokens of pure syntax waste.
→ mcptoon: Returns name:react|stars:219000 — same data, 20-40% fewer tokens on results, 61% on schemas. Discovery: 97% fewer. Schemas: 93% fewer. tiktoken-verified.
100 MCP servers. 0 context waste. Use any tool, anytime. No loading. No unloading. No JSON config errors.
How? CLI mode.
mcptoon is a CLI tool, not an MCP client library. Your agent doesn't connect to MCP servers — it just runs mcptoon commands. MCP schemas live on disk in ~/.mcptoon/config.json, not in your context window. Only the compact output you request enters context — and TOON encoding makes it 20-97% smaller than JSON.
Show me
JSON (287 tokens) — what every other MCP client puts in your context:
[
{"name": "search_web", "description": "Search the web for information",
"inputSchema": {"type": "object", "properties": {"query": {"type": "string", "description": "Search query"}, "num_results": {"type": "number", "default": 5}}, "required": ["query"]}},
{"name": "fetch_url", "description": "Fetch content from a URL",
"inputSchema": {"type": "object", "properties": {"url": {"type": "string"}}, "required": ["url"]}}
]
TOON (5 tokens) — what mcptoon returns:
search_web fetch_url
Measured benchmark (255 tools, 23 servers)
| Tools | JSON (tokens) | mcptoon compact | Reduction |
|---|---|---|---|
| 5 | 1,897 | 16 | 99.2% |
| 10 | 3,567 | 34 | 99.0% |
| 25 | 9,009 | 97 | 98.9% |
| 50 | 17,790 | 117 | 99.3% |
| 93 | 33,191 | 117 | 99.6% |
| 150 | 53,350 | 117 | 99.8% |
| 200 | 71,135 | 117 | 99.8% |
| 255 | 90,804 | 117 | 99.87% |
TOON format for tool results: 61% smaller than JSON. SLIM format for full schemas: 93% smaller than JSON.
📊 Full benchmark data (click to expand)
| Tools | JSON tokens | TOON tokens | SLIM tokens | Compact tokens | TOON save | SLIM save | Compact save |
|---|---|---|---|---|---|---|---|
| 5 | 1,897 | 785 | 111 | 16 | 59% | 94% | 99% |
| 10 | 3,567 | 1,391 | 235 | 34 | 61% | 93% | 99% |
| 25 | 9,009 | 3,580 | 595 | 97 | 60% | 93% | 99% |
| 50 | 17,790 | 6,981 | 1,203 | 117 | 61% | 93% | 99% |
| 93 | 33,191 | 13,086 | 2,231 | 117 | 61% | 93% | 100% |
| 150 | 53,350 | 20,958 | 3,626 | 117 | 61% | 93% | 100% |
| 200 | 71,135 | 27,952 | 4,842 | 117 | 61% | 93% | 100% |
| 255 | 90,804 | 35,735 | 6,174 | 117 | 61% | 93% | 100% |
Reproduce: python _benchmark.py → outputs assets/benchmark_data.json + assets/benchmark.html. Token count: chars ÷ 4 (GPT BPE approximation). tiktoken verification: python _audit2.py.
Third-party research & context window economics
| Source | Finding | Why it matters |
|---|---|---|
| Anthropic, Context Windows for Agents | “Context window is a scarce resource. Every token of schema is a token stolen from the user's actual task.” | MCP schemas are the #1 source of context waste in agent workflows |
| OpenAI, Function Calling Guide | Tool definitions consume context tokens proportional to schema complexity | 100+ tools with full schemas can eat 40-80% of a 128K context window |
| Cursor Team, Context Engineering | “The difference between a good and bad agent is almost always context management, not model intelligence.” | Token optimization at the transport layer (like TOON) directly improves agent quality |
| Latent Space, MCP Ecosystem Analysis | “The MCP protocol injects full JSON schemas into every request — this is by design, but it creates a scaling cliff around 20-30 tools.” | Confirms the problem mcptoon solves: 20-30 tools is the pain point, not 100+ |
| Simon Willison, LLM Tooling | “JSON is the least token-efficient format possible for structured data sent to an LLM.” | Validates TOON's approach: any non-JSON encoding saves tokens |
| GitHub Issues | Puppeteer MCP (47 tools) + Playwright MCP (52 tools) = ~50K tokens of schemas alone | Two browser MCP servers consume more context than this entire README |
Quick start
pip install mcptoon
Zero dependencies. 50KB. Python 3.10+. Windows, macOS, Linux.
mcptoon init # Sample config: ~/.mcptoon/config.json
mcptoon add fetch --stdio npx -y @modelcontextprotocol/server-fetch
mcptoon manifest --compact # → all tool names, 350 tokens
mcptoon manifest --slim # → tool schemas, 93% smaller than JSON
mcptoon call fetch fetch '{"url":"https://example.com"}' --toon
Works with every agent
mcptoon is a CLI tool. If your agent can run shell commands, it can use mcptoon. No plugins. No SDK. No per-agent MCP setup. No JSON config editing.
| Agent | How to use |
|---|---|
| Claude Code | Write mcptoon commands in SKILL.md files |
| Codex (OpenAI) | Add mcptoon to AGENTS.md |
| OpenCode | Use mcptoon in custom commands |
| Cursor | Add mcptoon to .cursorrules |
| CatPaw | Write mcptoon commands in skill files |
| Any agent | If it runs shell commands, it can call mcptoon |
Configure once in ~/.mcptoon/config.json. Every agent shares the same servers, the same tools, the same token savings. Switch agents? Config follows you. No migration.
export MCPTOON_AGENT_TYPE=claude # auto-select --toon for all calls
Agent self-service
Your agent can add MCP tools on its own — no human intervention needed:
# Agent wants a web scraper? Just add it:
mcptoon add firecrawl --stdio npx -y firecrawl-mcp
# Agent wants GitHub access? One command:
mcptoon add github --stdio npx -y @modelcontextprotocol/server-github
# Verify everything works:
mcptoon doctor
# Use it immediately:
mcptoon call github search_repos '{"query":"token optimization"}' --toon
No JSON config files. No RPC debugging. No server restarts. Just CLI commands.
How TOON works
TOON (Token-Optimized Object Notation) is mcptoon's encoding that compresses JSON for LLM consumption. Savings come from structural compression — removing JSON braces, quotes, brackets, and type wrappers — not from scalar substitution.
| JSON | TOON | Why |
|---|---|---|
{"name":"search","count":3} |
name:search|count:3 |
Pipes replace braces + quotes + colon |
[1, 2, 3] |
1 2 3 |
Spaces replace brackets + commas |
true / false |
true / false |
Kept as-is (1 token either way) |
null |
null |
Kept as-is (∅ costs 2 tokens, worse) |
"a:b" |
a_b |
Colons → underscore (avoids pipe ambiguity) |
{"a":{"b":[1,2]}} |
a:b:1_2 |
Recursive compaction |
tiktoken verification (o200k_base / cl100k_base):
{"content":[{"type":"text","text":"hello"}]} → hello (85% savings)
{"type":"object","properties":{"q":{"type":"string"}}} → q:s* (83% savings)
{"name":"search","count":3,"cached":true,"error":null} → name:search|count:3|cached:true|error:null (24% savings)
Token optimization at the transport layer is mcptoon's primary focus.
Output formats
| Flag | What you get | Token footprint |
|---|---|---|
--compact |
Tool names only, space-separated | 97% less than JSON |
--slim |
Ultra-compact schemas (name|param:type*) | 93% less than JSON |
--toon |
Compact notation, full semantics | 20-40% less than JSON (tiktoken-verified) |
--json |
Standard JSON (for scripts, CI) | Baseline |
--raw |
Raw response, no parsing | Full size |
--head N |
First N items only | Variable |
--max-chars N |
Hard truncate at N chars | Variable |
--full |
Disable the default 4000-char truncation | Full size |
SLIM mode
When you need tool schemas but want maximum token savings:
$ mcptoon manifest --slim
search|q:s*|n:n
fetch|url:s*
create|meta:o{title,tags}|tags:a[s]
Format: tool_name|param:type*|param:type
s=stringn=numberb=booleana[type]=arrayo{keys}=object*marks required parameters
93% token savings vs JSON for full tool schemas.
Architecture — Three-layer decoupling
mcptoon is built on a three-layer decoupled architecture. Each layer is independent — swap one without touching the others.
┌─────────────────────────────────────────────────┐
│ Layer 1: mcptoon CLI (~50KB, zero deps) │
│ ───────────────────────────────────────────── │
│ Runs in your agent's shell. Token-optimizes │
│ everything. No schemas in context. Ever. │
└──────────────────────┬──────────────────────────┘
│ reads JSON templates (on disk)
┌──────────────────────▼──────────────────────────┐
│ Layer 2: MCP Server Profiles (~1KB each) │
│ ───────────────────────────────────────────── │
│ 23 JSON templates in mcp/stdio/*.json. │
│ Not installed software — just connection specs. │
│ Security-audited: credential_safe, env_vars, │
│ permissions declared per profile. │
│ Add your own — it just works. │
└──────────────────────┬──────────────────────────┘
│ spawns on-demand via npx
┌──────────────────────▼──────────────────────────┐
│ Layer 3: Actual MCP Servers (npm packages) │
│ ───────────────────────────────────────────── │
│ Real MCP servers (@modelcontextprotocol/server-* │
│ etc). Only launched when you actually call a │
│ tool. Not installed at config time. │
│ Not loaded at startup. Zero overhead until use. │
└─────────────────────────────────────────────────┘
Why three layers?
- Layer 1 (CLI) stays tiny — 50KB, zero deps. No MCP SDK bloat.
- Layer 2 (Profiles) are editable JSON — add, remove, fork without touching code. Each is a ~1KB file describing how to connect, not the server itself.
- Layer 3 (Servers) spin up lazily — only when
mcptoon callactually runs. No idle processes. No startup tax.
This means:
- 100 servers configured → 0 running until you use one
- Remove a profile → the rest work fine
- Add a profile → no code changes, no rebuild
- mcptoon never bundles MCP servers — you install what you use
Security-audited profiles
Every profile declares its security posture:
// mcp/stdio/puppeteer.json
{
"name": "puppeteer",
"security": {
"audited": true,
"credential_safe": true,
"env_vars_required": [],
"permissions": ["read: web pages, DOM", "write: form inputs, JS execution"]
},
"bundled": false,
"install_method": "on-demand"
}
23 profiles: fetch, github, exa, brave-search, firecrawl, filesystem, memory, sequential-thinking, sqlite, time, puppeteer, playwright, postgres, slack, notion, git, gitlab, tavily, google-maps, docker, aws, cloudflare, tmux. See mcp/README.md.
Features
Tested with 255+ MCP tools across 23+ servers, 30K+ real calls.
--stdin— Pipe large payloads bypassing OS command-line limitsdoctor— One-command self-diagnosis (Python, config, servers, connectivity)discover— Server health check with tool counts- Tool poisoning guard — Detects prompt injection in MCP results (
ignore previous instructions,[INST], data exfiltration attempts) - Credential leak detection — Scans tool results for exposed API keys, AWS keys, GitHub PATs, OpenAI/Anthropic keys, Slack tokens, JWTs, private keys — blocks them before they reach your agent's context
- Fuzzy match — "Did you mean: search, search_all?" on typos
- Cross-agent export —
--format openai|openapi|mcpfor non-CLI agents - Schema cache — 5-min TTL, avoids repeated
tools/listround-trips - Usage tracking — Local-only call statistics and token estimates
- Dangerous-op blocking — Blocks
delete/drop/purgeunless--destructive - Shell completion — bash, zsh, fish, PowerShell
Security layers
| Layer | What it does | Example |
|---|---|---|
| Dangerous-op guard | Blocks delete/drop/purge/kill by default |
docker_remove → blocked unless --destructive |
| Prompt injection guard | Scans results for injection patterns | "ignore previous instructions" → blocked |
| Credential leak guard | Scans results for exposed keys/tokens | sk-abc...xyz → blocked, masked in error message |
# Credential leak detection in action:
$ mcptoon call github get_file --toon
# Error: CREDENTIAL_LEAK — potential OpenAI API Key leak detected: sk-abc...wxyz
# The result never enters your agent's context.
🌐 Ecosystem
| Component | What it is | Status |
|---|---|---|
| 📦 Server Profiles | 23 ready-to-use MCP server profiles (186+ tools) | 23 → 100+ |
| 🔧 TOON Format | Token-optimized notation (open spec) | v1 in mcptoon |
| 📚 Integration Guides | Agent-specific setup docs | Coming soon |
| 🏷️ Powered by Badge | For MCP servers using mcptoon | Available |
Python API
from mcptoon.client import MCPClient
from mcptoon.output import toon
with MCPClient(stdio=["npx", "-y", "@modelcontextprotocol/server-fetch"]) as c:
tools = c.list_tools()
print(toon(tools)) # compact TOON
result = c.call_tool("fetch", {"url": "https://example.com"})
print(toon(result))
Config
# stdio (any npx MCP server)
mcptoon add fetch --stdio npx -y @modelcontextprotocol/server-fetch
mcptoon add github --stdio npx -y @modelcontextprotocol/server-github
# HTTP
mcptoon add myapi --http http://localhost:3001/mcp --header "Authorization: Bearer xxx"
Config lives at ~/.mcptoon/config.json. Project-level override at ./.mcptoon.json.
Privacy
- No telemetry. No analytics, no crash reports, no phone-home.
- No credential storage. API keys pass through from your config or env vars.
- No dependencies. Pure Python stdlib. No supply chain to audit.
- Credential leak guard. Scans tool results for exposed API keys/tokens — blocks them before they reach your agent.
Architecture
src/mcptoon/
├── cli.py # CLI entry + arg parsing
├── client.py # MCPClient — stdio + HTTP transport
├── router.py # Tool routing, custom handlers, poisoning + credential leak detection
├── config.py # Server config
├── manifest.py # Tool discovery with cache
├── output.py # TOON / JSON / compact / slim rendering
├── cache.py # Schema cache (5-min TTL)
├── usage.py # Local usage tracking
└── errors.py # Structured error envelopes
~2,500 lines. 187 tests. Zero third-party imports. 50KB installed.
Contributing
git clone https://github.com/activeing123/mcptoon.git
cd mcptoon
pip install -e . --no-build-isolation
pip install pytest pytest-cov
python -m pytest tests/ -v # 187 tests, 0.2s
Zero dependencies is a hard rule. New features need tests. See CONTRIBUTING.md.
License
Apache 2.0. See LICENSE and NOTICE.
mcptoon is an independent third-party MCP client. Not affiliated with Anthropic.
Found this useful? Star the repo to help others find it.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mcptoon-0.3.0.tar.gz.
File metadata
- Download URL: mcptoon-0.3.0.tar.gz
- Upload date:
- Size: 53.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
23ce3ac12c3933efdf9ddc900f0c595bf56c889028d305df8b272248d29b0dc3
|
|
| MD5 |
72cc5c9ec0d32e50ff8e6f3f368c2ad8
|
|
| BLAKE2b-256 |
acb243cadcdb3a72344bf4ff9c1671a3745283d0fc124eb303de7a8d9d324807
|
File details
Details for the file mcptoon-0.3.0-py3-none-any.whl.
File metadata
- Download URL: mcptoon-0.3.0-py3-none-any.whl
- Upload date:
- Size: 42.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7505402b45e23d9c3ff8353466bfc0bfb85c7238ca404dfa6d09fb8449356445
|
|
| MD5 |
b571b7054002ca3bbcb636d3eb5bd4e4
|
|
| BLAKE2b-256 |
9ca31a92910bd3cd5186a21dc97c1124a5d54cd215c914833d34d1fe23a333de
|