mcp-bloat
Audit how many tokens your MCP servers eat from your context window — before your agent pays for them.
Every MCP server you connect makes your AI client load that server's tool
schemas into the model's context — on every session, before you've asked a
single question. A handful of servers can quietly consume a noticeable
share of the context window. mcp-bloat measures it: it finds your MCP
configs, connects to each server for real, and prints the token bill.
Install
pip install mcp-bloat
# or, without installing:
uvx mcp-bloat
For exact token counts (tiktoken's cl100k_base instead of a chars/4
estimate), install the accurate extra:
pip install "mcp-bloat[accurate]"
Usage
# Audit every MCP server in your known client configs
mcp-bloat
# See it work without configuring anything: audits three generated demo servers
mcp-bloat --demo
# Machine-readable output
mcp-bloat --json
# Just the per-server totals, without the per-tool breakdown
mcp-bloat --summary
# Fail CI if your servers eat more than 30,000 tokens of context
mcp-bloat --budget 30000
# Audit one specific config file
mcp-bloat --config ./mcp.json
# Audit one remote server directly, by URL — for example a server you
# use through ChatGPT or another hosted client
mcp-bloat --url https://example.com/mcp
# Look up ONE tool by name — which server(s) host it and what it costs
mcp-bloat --tool createPaymentTransaction
# If that server expects an Authorization header, pass it through
# (--header is repeatable, and --name sets the label shown in the report)
mcp-bloat --url https://example.com/mcp --header "Authorization: Bearer <token>"
# Compute the percentages against a specific model's context window —
# looked up live from OpenRouter/LiteLLM (free, no API key; cached 24h)
mcp-bloat --model gpt-5
mcp-bloat --model claude-sonnet-4-5
# …or set the window size yourself (this overrides --model)
mcp-bloat --window 128000
Which window am I using?
Every percentage in the report is relative to a context window. By
default that's 200,000 tokens. Pass --model NAME to measure against
the window of the model you actually use — mcp-bloat resolves the name
against live model data from OpenRouter (with LiteLLM as a fallback and
a small built-in snapshot when you're offline), and the report states
which model and window it used. --window N skips the lookup and uses
exactly N tokens. A server that eats 14% of a 200k window eats about 22%
of a 128k one — same tokens, different pain.
Looking up a single tool
The full audit tells you which server is fat; sometimes you just want
one tool. --tool NAME runs the audit as usual, then reports only
that tool — no URL or config spelunking needed, since the tool names
come from the servers themselves:
mcp-bloat --tool createPaymentTransaction
Matching is exact and case-insensitive first, then falls back to
substring matches. If the same tool name is hosted by several servers,
every match is shown. Each match reports the server and config it came
from, the tool's total tokens, its share of that server's tool bill and
of the context window, and a cost split — how much of the bill is the
name + description text versus the input schema (the two parts plus the
JSON structure roughly add up to the total). If nothing matches, you
get the closest tool names that do exist and exit code 2. --tool
combines with --config and --url to search just that target, and
with --model/--window for the window percentage; with --json it
prints {"tool": ..., "matches": [...]} instead.
From mcp-bloat --demo --tool run_tests:
Tool lookup: run_tests
┏━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Tool ┃ Server ┃ Source ┃ Tokens ┃ % of server ┃ % of 200k ctx ┃ Cost split ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ run_tests │ dev-toolbox │ Demo — mcp-bloat --demo (generated config) │ 208 │ 8.7% │ 0.1% │ description ≈ 39 · schema ≈ 166 │
└───────────┴─────────────┴────────────────────────────────────────────┴────────┴─────────────┴───────────────┴─────────────────────────────────┘
╭─ mcp-bloat tool lookup ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ 1 match for 'run_tests' across 1 server(s). │
│ Cost split: description counts the tool's name + description text; schema counts its inputSchema. The two parts plus the JSON structure roughly add up to │
│ the total. │
│ Counting method: tiktoken cl100k_base │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
Sample output
From mcp-bloat --demo (three generated servers: a tidy one, a medium
one, and a deliberately huge one):
Demo — mcp-bloat --demo (generated config)
┏━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━┓
┃ Server ┃ Transport ┃ Tools ┃ Tokens ┃ % of 200k ctx ┃ Status ┃
┡━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━┩
│ notes-lite │ stdio │ 3 │ 204 │ 0.1% │ ok │
│ dev-toolbox │ stdio │ 15 │ 2,394 │ 1.2% │ ok │
│ mega-api │ stdio │ 50 │ 25,164 │ 12.6% │ ⚠ BLOAT │
└─────────────┴───────────┴───────┴────────┴───────────────┴─────────┘
…
dev-toolbox — tools by cost
┏━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━┓
┃ Tool ┃ Tokens ┃ % of server ┃
┡━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━┩
│ grep │ 254 │ 10.6% │
│ run_tests │ 208 │ 8.7% │
│ list_files │ 199 │ 8.3% │
│ edit_file │ 186 │ 7.8% │
│ run_command │ 174 │ 7.3% │
│ read_file │ 172 │ 7.2% │
│ get_git_diff │ 164 │ 6.9% │
│ fetch_url │ 158 │ 6.6% │
│ create_branch │ 155 │ 6.5% │
│ write_file │ 152 │ 6.3% │
│ search_docs │ 147 │ 6.1% │
│ get_git_status │ 130 │ 5.4% │
│ lint │ 108 │ 4.5% │
│ format_code │ 107 │ 4.5% │
│ package_info │ 80 │ 3.3% │
└────────────────┴────────┴─────────────┘
…
╭─ mcp-bloat summary ───────────────────────────────────────────────────╮
│ Total: 27,762 tokens (13.9% of a 200,000-token context window) │
│ Of your 27,762 tokens, that's: │
│ 2.8% of Claude Sonnet 5.5's 1,000,000 window │
│ 6.9% of GPT-5's 400,000 window │
│ 2.6% of Gemini 2.5 Pro's 1,048,576 window │
│ 16.9% of DeepSeek V3's 163,840 window │
│ Servers audited: 3 │
│ Counting method: tiktoken cl100k_base │
│ Most expensive single tool: list_workflow_run (mega-api) — 690 tokens │
│ ⚠ Over 10,000 tokens on its own: mega-api (25,164) │
╰───────────────────────────────────────────────────────────────────────╯
After each config's server table, the report drills into that server's
tools — every tool's token cost, fattest first, with its share of the
server's tool bill — and the summary names the single most expensive
tool of the whole run. Pass --summary to collapse the report back to
per-server totals only; --json always includes the per-tool data
(each server's tools array — including each tool's description/schema
token split — plus a top-level most_expensive_tool).
In default mode (no --model/--window), the summary also lines your
total up against several current frontier models' context windows at
once — resolved from the same live model data — so you can see the cost
on the models people actually use; pass --model or --window and the
summary sticks to that single window instead.
Any single server over 10,000 tokens is flagged ⚠ BLOAT.
How the counting works
For each configured server, mcp-bloat:
- Connects to the server over MCP (stdio or streamable HTTP) and performs the standard initialize handshake.
- Calls
tools/list(andprompts/list/resources/listwhen the server supports them — prompts and resources are surfaced to the model too). - For every tool, serializes
{name, description, inputSchema}to JSON — the same information a client sends to the model so it can call the tool — and counts the tokens in that string.
Token counting uses tiktoken's cl100k_base encoding when the
accurate extra is installed, and falls back to a chars/4 estimate
otherwise. The report always states which method produced the numbers.
This is a close proxy for what clients actually send, not a byte-exact replica: individual clients wrap tool definitions slightly differently, and models with different tokenizers will count a little differently. Treat the numbers as accurate to a few percent — more than enough to find the server that's eating your context.
Servers that fail to start or don't respond within the timeout
(default 20s, --timeout to change) are reported as errors; they never
abort the rest of the audit. Server stderr is discarded so broken
servers can't corrupt the report.
Config locations searched
- Claude Code —
~/.claude.json,./.mcp.json - Cursor —
~/.cursor/mcp.json,./.cursor/mcp.json - Claude Desktop —
~/.config/Claude/claude_desktop_config.json,~/Library/Application Support/Claude/claude_desktop_config.json - Windsurf —
~/.codeium/windsurf/mcp_config.json - VS Code —
./.vscode/mcp.json(theserverskey) - Gemini CLI —
~/.gemini/settings.json,./.gemini/settings.json(both theurlandhttpUrlspellings for HTTP servers) - Codex CLI —
~/.codex/config.toml(the[mcp_servers.*]tables)
Clients that don't keep MCP servers in a local config file — ChatGPT,
for instance — can still be covered: take the server's URL and pass it
to --url, with --header for any authorization header the server
expects.
Malformed config files produce a warning, not a crash.
License
MIT
Metadata
Release files for mcp-bloat 0.6.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| mcp_bloat-0.6.0.tar.gz | 38.8 kB | With provenance | Details for mcp_bloat-0.6.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| mcp_bloat-0.6.0-py3-none-any.whl | Python 3 | none | any | Details for mcp_bloat-0.6.0-py3-none-any.whl |
Total release size: 71.3 kB
Release files / mcp_bloat-0.6.0.tar.gz
| Download URL | mcp_bloat-0.6.0.tar.gz |
|---|---|
| Size | 38.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3261c18ca5dbe7e5d9154679cc9fb471f5b772ee351b8818e01de329107ba3fd
|
|
BLAKE2b-256 checksum How to use checksums |
b3ffc6b696b47eb2ebbf734d1dd8e847802fe7672d12458f7b6648e9e7b966b9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 1, 2026.
Transparency logRelease files / mcp_bloat-0.6.0-py3-none-any.whl
| Download URL | mcp_bloat-0.6.0-py3-none-any.whl |
|---|---|
| Size | 32.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
aae795c0a115c4ef1af03d73d333b2ea75b0efa847e9cb35ecac934bb7b69fa9
|
|
BLAKE2b-256 checksum How to use checksums |
5687e60bea5f4cb813325dbc48b5523e456173cddbcf0aceacf417db0b01a66a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 1, 2026.
Transparency logSecurity for mcp-bloat 0.6.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for mcp_bloat-0.6.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 1, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.