๐ฉบ A health check for your MCP setup โ measure the context tax and hygiene of your MCP servers
Project description
๐ฉบ mcp-checkup
A health check for your MCP setup.
One command that tells you what your MCP servers cost you โ in context-window tokens and dollars โ and whether they follow basic security hygiene.
The problem
Every MCP server you connect injects its full tool schemas into your model's context window โ on every single request โ before you type a word.
- GitHub's official MCP server alone consumes ~17,600 tokens per request in tool definitions (autopsy).
- Teams have burned 72% of a 200k context window on tool definitions before doing any actual work (MCP spec issue #2808).
- A security audit of publicly exposed MCP servers found 119 out of 119 sampled allowed unauthenticated access to internal tool listings.
You are paying a context tax on every request, and you probably have no idea
how big it is. mcp-checkup measures it.
What it looks like
Real output of a bare uvx mcp-checkup on a developer laptop (v0.2.0):
$ uvx mcp-checkup
๐ฉบ MCP Checkup โ 5 server(s), 128 tools
โโโโโโโโโโโโโโโโโณโโโโโโโโโโโโโโโโโณโโโโโโโโณโโโโโโโโโโโโณโโโโโโโโโณโโโโโโโโโ
โ Server โ Clients โ Tools โ anthropic โ openai โ gemini โ
โกโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฉ
โ alpaca โ claude-code โ 69 โ 18,611 โ 19,025 โ 18,542 โ
โ edgartools โ claude-code โ 13 โ 3,725 โ 3,803 โ 3,712 โ
โ playwright โ claude-desktop โ 23 โ 3,198 โ 3,336 โ 3,175 โ
โ filesystem โ claude-desktop โ 14 โ 1,640 โ 1,723 โ 1,626 โ
โ yahoo-finance โ claude-code โ 9 โ 1,396 โ 1,450 โ 1,387 โ
โโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโผโโโโโโโโผโโโโโโโโโโโโผโโโโโโโโโผโโโโโโโโโค
โ Total โ โ 128 โ 28,570 โ 29,337 โ 28,442 โ
โโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโดโโโโโโโโดโโโโโโโโโโโโดโโโโโโโโโดโโโโโโโโโ
Context tax: ~28,916 tokens on Anthropic models (incl. 346 tool-use
system overhead), before your first message.
That's 14% of a 200k context window, spent before the first user message.
Supported clients (auto-discovery)
| Client | Config discovered |
|---|---|
| Claude Desktop | claude_desktop_config.json (macOS/Windows/Linux) |
| Claude Code | project .mcp.json + ~/.claude.json user/local scopes |
| Cursor | ~/.cursor/mcp.json + project .cursor/mcp.json |
| Windsurf | ~/.codeium/windsurf/mcp_config.json |
| VS Code | .vscode/mcp.json + user-profile mcp.json (servers key) |
Hygiene checks
Every scan also runs read-only hygiene checks over what your servers advertise โ sample real findings:
Hygiene findings (10)
W01 medium alpaca > get_portfolio_history: tool is 8.7x its minimal schema (1443 vs 166 tokens)
W01 medium alpaca > replace_order_by_id: tool is 3.3x its minimal schema (1501 vs 451 tokens)
W04 low alpaca: server exposes 69 tools; models degrade with large tool lists
W05 low get_option_chain is advertised by 2 servers: alpaca, yahoo-finance
| ID | Checks for |
|---|---|
| W01โW05 | Schema bloat vs minimal equivalent, oversized descriptions, enum explosions, tool-count explosion, cross-server duplicate tools |
| H01 | Remote HTTP servers configured without client credentials |
| H02 | Tool-poisoning language in descriptions (hidden instructions, concealment, sensitive-path exfiltration) |
| H03 | Cross-server tool shadowing ("instead of X, alwaysโฆ") |
| H04 | Write/exec tools alongside network-fetch tools (exfiltration-chain heuristic) |
All checks are heuristics โ disable any with --disable-check ID; see details
with --verbose. For deep security-only scanning also consider
invariantlabs' mcp-scan; mcp-checkup's focus is the combined
cost + hygiene physical.
Quickstart
uvx mcp-checkup # or: pip install mcp-checkup
Point it at your client config (.mcp.json, Claude Desktop, Cursor, โฆ) or a
running server. That's the whole interface โ one command, one report.
Roadmap
Full detail per milestone in ROADMAP.md.
| Version | Theme | One line |
|---|---|---|
| v0.1.0 | Weigh one server | weigh <target> prints a per-tool token table for one server |
| v0.2.0 | Auto-discovery | Zero-flag scan of Claude Desktop/Code, Cursor, Windsurf, VS Code |
| v0.3.0 | Dollars & context tax | $/request, $/session, and context-tax % per model |
| v0.4.0 | Hygiene | Weight (W01โW05) and security (H01โH04) checks, two-pillar report |
| v0.5.0 | CI gate | Budget/severity gates, stable exit codes, GitHub Action |
| v0.6.0 | --fix emit |
Semantic-safe schema compression with before/after report |
| v0.7.0 | Trim proxy + rug-pull pins | serve --wrap --trim proxy, changed-since-pin detection |
| v0.8.0 | Shareable reports | Self-contained HTML report, badge endpoint, diff command |
| v0.9.0 | Hardening + SDK v2 | MCP SDK v2 transport, Windows CI, perf budget |
| v1.0.0 | Stable | Frozen CLI/exit codes/schema with a deprecation policy |
Put your schemas on a diet
mcp-checkup fix <server> builds compressed versions of every tool schema โ
semantic-safe: tool names, types, and required fields never change; only
prose (descriptions, titles, examples) and over-restrictive sugar are trimmed.
Measured on real servers with the default policy (keep first sentence):
$ mcp-checkup fix "npx -y @modelcontextprotocol/server-everything"
Total: 1,084 -> 735 tokens % saved: 32.2%
$ mcp-checkup fix "python toy_bloated_server.py"
search: 1,243 -> 336 tokens (73% saved)
--emit DIRwrites drop-in sidecar schema files + aTOOLS.mdfor the server's author--emit-pr-text FILEgenerates a polite, data-driven issue body to file upstream
Honest limit: your client still fetches the original schemas from the server โ permanent fixes belong server-side, or use the trim proxy below.
Trim proxy โ enforce the diet permanently
mcp-checkup serve --wrap "<server command>" is itself a stdio MCP server:
it re-serves the wrapped server's tools/list compressed while passing tool
calls, resources, and prompts through unchanged (~2 ms overhead per call).
Measured live: the bloated fixture server drops from 1,342 to 412 tokens
(-69%) when weighed through the proxy.
// your client config โ before // after
"toy": { "toy": {
"command": "python", "command": "mcp-checkup",
"args": ["toy_server.py"] "args": ["serve", "--wrap",
} "python toy_server.py", "--trim"]
}
mcp-checkup fix --config <file> --emit-proxy-config <out> generates that
rewrite for every stdio server in a config copy โ never in place. The proxy is
read-only-by-default glue: --allow-tools a,b additionally hides tools you
never want exposed.
Rug-pull pinning (H05)
--write-baseline pins a sha256 of every tool's name+description+schema.
If a later scan sees a pinned tool's definition change โ the classic
approve-once-then-swap attack โ it raises a high-severity H05 finding, which
--fail-on-severity high turns into a failing exit code in CI.
Gate your context budget in CI
Treat context bloat like coverage: gate it. Exit codes are a stable contract โ
0 ok, 1 token budget exceeded, 2 hygiene findings at/above threshold,
3 no server reachable.
# .github/workflows/mcp-checkup.yml
- uses: mohitgurnani1/mcp-checkup@v0
with:
fail-over-total: "20000"
fail-on-severity: high
Or directly: uvx mcp-checkup scan --fail-over-total 20000 --fail-on-severity high.
--format markdown emits a PR-comment-ready report; --write-baseline records
a snapshot and later runs print per-server token drift against it.
Share it
--format htmlโ self-contained report (no external assets), CI-artifact and Slack friendly--badge FILEโ shields.io endpoint JSON: put a live "context tax: N tokens" badge on your repomcp-checkup diff old.json new.jsonโ drift between two baselines- docs/GALLERY.md โ measured context tax of popular MCP servers (github: 3,546 tokens, playwright: 3,198, โฆ)
How counting works (and its error bars)
Each tool schema is serialized into every provider's actual wire format
(Anthropic tools, OpenAI functions, Gemini functionDeclarations) and
counted with tiktoken's o200k_base encoding โ exact for the GPT-4o/GPT-5
family, a close proxy (ยฑ~10%) for Anthropic and Gemini. Anthropic totals add
the documented tool-use system-prompt overhead. For billing-exact Anthropic
numbers, install mcp-checkup[precise], set ANTHROPIC_API_KEY, and pass
--precise โ it queries the free count_tokens API with your real schemas.
Prices and context windows come from a vendored snapshot of LiteLLM's
community-maintained pricing table; --refresh-pricing fetches the latest at
runtime (with silent fallback). $ per session assumes schemas are resent
every turn โ with prompt caching you pay full price on turn one and on every
cache invalidation.
Status
Stable (1.0). CLI flags, exit codes, and document schemas are frozen under the stability contract. If the context tax bothers you too: โญ star the repo, open an issue with your worst MCP token bill, or see CONTRIBUTING.md โ mutation testing and MCP SDK v2 migration are open contributor-friendly tasks.
License
Project details
Release history Release notifications | RSS feed
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 mcp_checkup-1.0.0.tar.gz.
File metadata
- Download URL: mcp_checkup-1.0.0.tar.gz
- Upload date:
- Size: 208.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c4fff322cc395933026014306435d9ac72bdcd67eed4239238705025bf49995b
|
|
| MD5 |
b393c5316b969f64a5f4eb3022bf23a5
|
|
| BLAKE2b-256 |
8767387f77e85b7472d4218a5a80884ea5b7c790e8aa40c0ef0513aaa434c1cf
|
File details
Details for the file mcp_checkup-1.0.0-py3-none-any.whl.
File metadata
- Download URL: mcp_checkup-1.0.0-py3-none-any.whl
- Upload date:
- Size: 64.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8d67c1180a87b29d24f606ab0697e72a9cc94daea79c8db4c6ac772627259168
|
|
| MD5 |
000776eab79a89874de7214521e60b30
|
|
| BLAKE2b-256 |
7a9ed1fcc1dc059ed406f6489a163412518c4e847cf436f2e89f9b39aaa9ca37
|