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 | 中文文档 | 📦 Server Profiles | 🌐 Ecosystem | Report Bug | Request Feature
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.
mcptoon keeps all your MCP servers configured — but their schemas never enter your agent's context.
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.
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.
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.
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.
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\nstars: 219000 — same data, 30-60% fewer tokens on results (standard TOON), 97% fewer on discovery, 93% fewer on schemas. tiktoken-verified.
100 MCP servers. 0 context waste. Use any tool, anytime. No loading. No unloading. No JSON config errors.
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 30-97% smaller than JSON.
Independent research confirms mcptoon's CLI approach is superior to MCP protocol injection:
| Source | Finding |
|---|---|
| CLI vs MCP benchmark (75 tasks) | CLI agents outperform MCP agents on all metrics: 10-32x lower token cost, ~100% reliability vs MCP's 72% |
| Perplexity | Removed MCP support from their agent architecture entirely — token overhead too high |
| Anthropic internal research | Shell scripts consume 98.7% fewer tokens than equivalent MCP tool calls |
| Latent Space | "MCP protocol creates a scaling cliff around 20-30 tools" — mcptoon has no such limit |
The industry is moving from MCP injection → CLI execution. mcptoon was CLI-first from day one.
mcptoon has a dual-track architecture — the public GitHub repo is clean and self-contained, while your local installation can have private extensions:
GitHub repo (public) Your machine (local)
┌────────────────────────────┐ ┌────────────────────────────┐
│ src/mcptoon/ │ │ src/mcptoon/ │
│ ├─ cli.py │ │ ├─ cli.py │ ← same code
│ ├─ client.py │ │ ├─ client.py │
│ ├─ installer.py │ │ ├─ installer.py │
│ ├─ router.py │ │ ├─ router.py │
│ └─ output.py (TOON) │ │ └─ output.py (TOON) │
│ │ │ │
│ mcp/ (23 profiles) │ │ mcp/ (23 profiles) │ ← same profiles
│ tests/ (429 tests) │ │ ~/.mcptoon/config.json │ ← your servers
│ docs/, README, etc. │ │ local/ (private layer) │ ← your extensions
│ │ │ ├─ handlers/ (30+) │
│ NO private handlers │ │ ├─ router.py (bridge) │
│ NO local credentials │ │ └─ cli_pro.py │
└────────────────────────────┘ └────────────────────────────┘
What goes to GitHub: the clean, zero-dependency CLI core — 13 Python files, ~4,500 lines, 429 tests, 23 server profiles. No private handlers, no credentials, no local config.
What stays local: your personal ~/.mcptoon/config.json, your installed MCP servers, and optionally a local/ directory with private handlers for custom tools. The .gitignore excludes all of it.
Yes — that's the whole point. mcptoon is a tool manager, not a bundle of tools. Here's how a GitHub user gets started:
# 1. Install mcptoon (the CLI core, zero deps)
pip install mcptoon
# 2. Add ANY MCP server you want — one command:
mcptoon add fetch --stdio npx -y @modelcontextprotocol/server-fetch
mcptoon add github --stdio npx -y @modelcontextprotocol/server-github
# 3. Or auto-discover servers already on your machine:
mcptoon init --auto
# 4. Or install from npm/pip/HTTP with auto-handler generation:
mcptoon install brave-search --npm @anthropic/mcp-server-brave-search
mcptoon install my-tool --pip mcp-my-tool
mcptoon install remote-api --url https://example.com/mcp
# 5. See your tools (117 tokens for 255 tools):
mcptoon manifest --compact
# 6. Call any tool:
mcptoon call fetch fetch '{"url":"https://example.com"}' --toonmcptoon never bundles MCP servers. Users install only what they need, from npm, pip, or HTTP endpoints. The 23 pre-configured profiles in mcp/stdio/*.json are just ~1KB JSON templates describing how to connect — not the servers themselves. Servers are launched on-demand via npx only when a tool is actually called.
| What mcptoon ships | What it doesn't ship |
|---|---|
| CLI core (13 files, ~200KB) | MCP server binaries |
| 23 server profile templates (~1KB each) | API keys or credentials |
| 429 tests + benchmark suite | User's private config |
| Integration guides + ecosystem docs | Third-party dependencies |
pip install mcptoonZero dependencies. Python 3.10+. ~200KB source. Windows, macOS, Linux.
# ─── 30-second onboarding ───
mcptoon quickstart # discover + configure + show tools
mcptoon init --auto # auto-discover MCP servers on your machine
mcptoon add fetch --stdio npx -y @modelcontextprotocol/server-fetch
# ─── See your tools ───
mcptoon manifest --compact # → all tool names, 117 tokens for 255 tools
mcptoon manifest --slim # → tool schemas, 93% smaller than JSON
mcptoon manifest --toon # → standard TOON format
# ─── Call a tool ───
mcptoon call fetch fetch '{"url":"https://example.com"}' --toon
mcptoon call --auto search '{"query":"AI"}' --toon # auto-find server
# ─── Self-diagnosis ───
mcptoon doctorFound a new MCP server on GitHub? Install it with one command — mcptoon auto-connects, discovers tools, generates a handler, and registers it. No restart needed.
# From npm
mcptoon install brave-search --npm @anthropic/mcp-server-brave-search
# From pip
mcptoon install my-tool --pip mcp-my-tool
# HTTP/SSE server
mcptoon install remote-api --url https://example.com/mcp
# List installed servers
mcptoon install --list
# Remove
mcptoon install --remove brave-search23 battle-tested server profiles are included in mcp/stdio/*.json. Each is a ~1KB JSON file describing how to connect — security-audited with credential_safe, env_vars_required, and permissions declared.
# Browse profiles:
cat mcp/stdio/github.json
# Use any profile — just add the server:
mcptoon add github --stdio npx -y @modelcontextprotocol/server-github
# Set your API key:
export GITHUB_PERSONAL_ACCESS_TOKEN=ghp_xxx
# Use it:
mcptoon call github search_repos '{"query":"mcp"}' --toonDon't see your server? mcptoon works with any MCP server, profile or not:
mcptoon add my-server --stdio npx -y @any/mcp-server
mcptoon manifest --toon # works immediatelySee all 23 profiles: mcp/README.md
mcptoon is zero-dependency, so the image is small. Build it and run any subcommand. The entrypoint is mcptoon, so args pass through exactly as on the host:
docker build -t mcptoon .
docker run --rm mcptoon help
docker run --rm mcptoon manifest --toonServer config lives at ~/.mcptoon/config.json on the host. Mount it so the container shares your servers:
docker run --rm -v ~/.mcptoon:/root/.mcptoon mcptoon manifest --toonmanifest, list, inspect, and doctor are config-only and work out of the box. call and add --stdio spawn a server process (for example npx), so they need that runtime available inside the image: extend the Dockerfile with the toolchain your servers require.
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 callsYour 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"}' --toonNo JSON config files. No RPC debugging. No server restarts. Just CLI commands.
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
SLIM (with schemas, 14 tokens) — when you need parameter details:
search_web|query:s*|num_results:n
fetch_url|url:s*
| Tools | JSON | Std TOON | mcptoon | SLIM | Compact |
|---|---|---|---|---|---|
| 5 | 1,897 | 981 (-48%) | 785 (-59%) | 111 (-94%) | 16 (-99%) |
| 10 | 3,567 | 1,757 (-51%) | 1,391 (-61%) | 235 (-93%) | 34 (-99%) |
| 25 | 9,009 | 4,491 (-50%) | 3,580 (-60%) | 595 (-93%) | 97 (-99%) |
| 50 | 17,790 | 8,776 (-51%) | 6,981 (-61%) | 1,203 (-93%) | 117 (-99%) |
| 93 | 33,191 | 16,426 (-51%) | 13,086 (-61%) | 2,231 (-93%) | 117 (-100%) |
| 150 | 53,350 | 26,326 (-51%) | 20,958 (-61%) | 3,626 (-93%) | 117 (-100%) |
| 200 | 71,135 | 35,106 (-51%) | 27,952 (-61%) | 4,842 (-93%) | 117 (-100%) |
| 255 | 90,804 | 44,863 (-51%) | 35,735 (-61%) | 6,174 (-93%) | 117 (-100%) |
Standard TOON (--toon): 51% smaller than JSON (round-trip safe).
mcptoon format (--mcptoon): 61% smaller (round-trip safe).
SLIM format (--slim): 93% smaller for full schemas.
Compact (--compact): 100% smaller for tool names only.
Reproduce: python _benchmark.py → outputs assets/benchmark_data.json. Token count: chars ÷ 4 (GPT BPE approximation).
| 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 |
mcptoon supports two token-efficient formats:
Implements the TOON (Token-Oriented Object Notation) spec — an open-source format for token-efficient LLM data exchange. Uses YAML-style indentation for objects and CSV-style tabular layout for uniform arrays.
| JSON | Standard TOON | Why |
|---|---|---|
{"name":"search","count":3} |
name: search\ncount: 3 |
Newlines replace braces + quotes |
[{"id":1,"name":"Alice"}] |
[1]{id,name}:\n 1,Alice |
Field declaration once + CSV rows |
[1, 2, 3] |
[3]:\n 1\n 2\n 3 |
Bracket notation for arrays |
true / false / null |
true / false / null |
Kept as-is (1 token each) |
Round-trip safe: decode(encode(x)) == x. URLs, timestamps, and special characters are preserved.
mcptoon's original pipe-separated format. Simpler but less structured than standard TOON.
| JSON | mcptoon | Why |
|---|---|---|
{"name":"search","count":3} |
name:search|count:3 |
Pipes replace braces + quotes |
[1, 2, 3] |
1 2 3 |
Spaces replace brackets + commas |
"https://example.com" |
https\c//example.com |
Colons escaped as \c (round-trip safe) |
Round-trip safe with mcptoon_decode(). Escape sequences: \c=colon, \p=pipe, \\=backslash.
mcptoon-specific ultra-compact tool schema encoding. No external equivalent.
search|q:s*|n:n
fetch|url:s*
tiktoken verification (o200k_base / cl100k_base):
{"content":[{"type":"text","text":"hello"}]} → hello (85% savings)
{"type":"object","properties":{"q":{"type":"string"}}} → q:s* (83% savings)
Token optimization at the transport layer is mcptoon's primary focus.
| 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 |
Standard TOON (toon-format/toon spec) | 30-60% less than JSON (round-trip safe) |
--mcptoon |
Legacy mcptoon pipe format | 20-40% less than JSON (round-trip safe) |
--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 |
mcptoon is built on a three-layer decoupled architecture. Each layer is independent — swap one without touching the others.
┌─────────────────────────────────────────────────┐
│ Layer 1: mcptoon CLI (~200KB, 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 — ~200KB, 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
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.
Tested with 255+ MCP tools across 55+ servers, 30K+ real calls. 429 tests passing. 10/10 E2E tests passing.
mcptoon install— One-command MCP server installation from npm/pip/HTTP with auto-handler generationmcptoon quickstart— One-command onboarding: discover + configure + show toolsmcptoon doctor— Self-diagnosis (Python, config, servers, connectivity)mcptoon discover— Zero-config auto-discovery (config scan + env detection + network probe)mcptoon search— Cross-server tool search with multi-factor scoringmcptoon call --auto— Auto-route tool calls to the right server--stdin— Pipe large payloads bypassing OS command-line limits- Tool poisoning guard — Detects prompt injection in MCP results
- Credential leak detection — Scans tool results for exposed API keys, AWS keys, GitHub PATs, OpenAI/Anthropic keys, Slack tokens, JWTs, private keys
- 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
- TOML config —
~/.mcptoon/config.tomlsupport
| 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.from mcptoon.client import MCPClient
from mcptoon.output import toon_encode, toon_decode, mcptoon_encode
with MCPClient(stdio=["npx", "-y", "@modelcontextprotocol/server-fetch"]) as c:
tools = c.list_tools()
print(toon_encode(tools)) # Standard TOON output
result = c.call_tool("fetch", {"url": "https://example.com"})
print(toon_encode(result)) # Standard TOON output
# Round-trip: decode back to Python dict
decoded = toon_decode(toon_encode(result))
assert decoded == result # ✅ Round-trip safe# 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. TOML support at ~/.mcptoon/config.toml.
{
"servers": {
"fetch": {
"transport": "stdio",
"command": ["npx", "-y"],
"args": ["@modelcontextprotocol/server-fetch"]
},
"github": {
"transport": "stdio",
"command": ["npx", "-y"],
"args": ["@modelcontextprotocol/server-github"],
"env": {"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxx"}
}
}
}- 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.
src/mcptoon/
├── cli.py # CLI entry + arg parsing
├── client.py # MCPClient — stdio + HTTP transport
├── installer.py # One-command MCP server installation + auto-handler generation
├── router.py # Tool routing, custom handlers, poisoning + credential leak detection
├── config.py # Server config (JSON + TOML)
├── manifest.py # Tool discovery with cache + cross-server search
├── discover.py # Zero-config auto-discovery (5-layer)
├── output.py # Standard TOON + legacy mcptoon + JSON / compact / slim rendering
├── cache.py # Schema cache (5-min TTL)
├── usage.py # Local usage tracking
└── errors.py # Structured error envelopes + fix suggestions
~4,500 lines. 429 tests + 10/10 E2E. Zero third-party imports. ~200KB source.
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 # 429 tests, 0.5sZero dependencies is a hard rule. New features need tests. See CONTRIBUTING.md.
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.
