Skip to main content

mcp-tax

Audit the context tax of your MCP servers — and turn them off per session.

Claude Code loads every configured MCP server's tool schemas into context at session start, with no UI to temporarily disable a server. Users have measured 41k tokens of pure schema; one blog estimates 6 mid-size servers eat 10–15% of the window before the conversation even starts. As the complaint goes: "Claude Code has no way to temporarily disable a configured server."

mcp-tax measures that tax, then lets you launch Claude Code with the expensive servers you don't need right now switched off.

v2 adds what schema audits can't tell you: who is calling this MCP, using what agent, for what project (who-called), a unified audit of all four always-on context sources (audit --all), and a CI gate (gate) that fails your build when the budget is blown.

Zero dependencies. Python standard library only.

Install

pip install mcp-tax
# or with pipx:
pipx install mcp-tax

Requires Python 3.9+. No other packages.

Usage

See what you have configured (reads ~/.claude.json — including the local project scope projects.<cwd>.mcpServers where claude mcp add stores servers by default — plus ./.mcp.json when present):

$ mcp-tax list
github
    npx -y @modelcontextprotocol/server-github
postgres  [off]
    uvx mcp-server-postgres --db-url ...
2 server(s), 1 disabled

Measure the tax — handshakes each server over stdio (initialize, then tools/list), counts tools, and estimates tokens:

$ mcp-tax audit
server    tools  schema chars  est. tokens
------  -------  ------------  -----------
github       51       118,203        29,551
postgres [off]    9        12,440         3,110
------  -------  ------------  -----------
TOTAL        60       130,643        32,661
~16.3% of a 200k context window (est. tokens = schema chars / 4)

Servers that fail (bad command, timeout, handshake error) get a FAILED row and a warning instead of killing the audit. Per-server timeout is 15s (--timeout to change).

Toggle servers off/on (persisted in ~/.config/mcp-tax/disabled.json):

$ mcp-tax off postgres
postgres disabled (affects `mcp-tax run`)
$ mcp-tax on postgres
postgres enabled (affects `mcp-tax run`)

Launch Claude Code without the disabled servers:

$ mcp-tax run -- -p "summarize this repo"
mcp-tax: 2 server(s), 1 disabled -> ~/.config/mcp-tax/mcp-config.filtered.json

This writes a filtered {"mcpServers": ...} config (disabled servers removed) and execs claude --mcp-config <file> --strict-mcp-config with your args forwarded. The "without the disabled servers" part comes from --strict-mcp-config, which mcp-tax always passes: --mcp-config alone only layers the file onto MCP servers from your other config sources (~/.claude.json, .mcp.json), so a disabled server listed there would still load. Your real ~/.claude.json is never modified.

All commands also accept --json (list, audit, who-called, gate) for scripting.

Who is calling this MCP?

Schemas tell you what a server could cost. Transcripts tell you what it actually costs — and who is spending it. who-called mines your local Claude Code transcripts (~/.claude/projects/*/*.jsonl, read-only, nothing leaves your machine) and attributes every MCP tool call to an agent, a project, and a purpose:

$ mcp-tax who-called --server github
time              project    agent       tool                purpose
----------------  ---------  ----------  ------------------  -------------------
2026-10-10 09:03  proj       explorer    github__search_code  fix the github action workflow
2026-10-10 09:01  proj       main        github__get_workflo fix the github action workflow
2 call(s); attribution is heuristic, see README
  • agent: main for the main agent, or the subagent_type when the call came from a subagent (sidechain records with no announced type show as subagent).
  • project: from the transcript's cwd; falls back to a best-effort decode of the project-dir slug.
  • purpose: the nearest preceding user/assistant text, truncated — a hint, not a ground truth.

Options: --days N (lookback window, default 30), --limit N (default 50), --projects-dir to point at a different transcript root.

One audit for all four context sources

MCP schemas are only one of the things your sessions always pay for. audit --all puts the four always-on sources in one metric frame — counts, tokens, and share:

$ mcp-tax audit --all
source        count  est. tokens   share
----------  -------  -----------  ------
rules             4          320    8.1%
memory            2          410   10.4%
skills            6        1,200   30.5%
mcp calls        38        2,010   51.0%
----------  -------  -----------  ------
TOTAL                       3,940  100%
tokens = chars / 4 everywhere; mcp calls cover the last 30 day(s)
  • rules: directives in ~/.claude/CLAUDE.md (+ ./CLAUDE.md when present); count = non-blank, non-heading lines.
  • memory: MEMORY.md files under ~/.claude; count = files.
  • skills: ~/.claude/skills/*/SKILL.md; count = skills.
  • mcp calls: tool calls mined from transcripts (--days bounds the window); tokens = input JSON chars + matched tool-result chars, / 4.

CI gate

Turn the audit into a budget your CI can enforce:

$ mcp-tax gate --max-tokens 50000 --max-calls 200
...
total: 3,940 tokens, 38 mcp calls (last 30 day(s))
GATE PASS

Exit code 1 when tokens exceed --max-tokens or calls exceed --max-calls, with the breach named (GATE FAIL: tokens 60,120 > max 50000). Drop it in a workflow and your context budget stops drifting silently.

How mcp-tax differs

There are interactive token-audit skills that walk you through your usage in a chat. mcp-tax is the opposite kind of tool: a deterministic CLI — same transcripts, same output, every run — with --json on everything and a CI gate that fails builds. Skills are for conversations; this is for automation.

mcp-tax vs mcp-audit

Sibling tools, complementary axes:

  • mcp-tax (this): call attribution and cost audit — who calls which MCP, from which agent and project, and how much context it costs.
  • mcp-audit (PyPI: mcp-runtime-audit): runtime security — known-CVE checks and one-click fixes for your MCP servers.

Cheap is not the same as safe, and safe is not the same as cheap. Run both.

How the token estimate works

For each server, mcp-tax JSON-encodes the full tools/list result (compact, no whitespace) and counts characters. Estimated tokens = round(chars / 4).

This is deliberately crude: it approximates the Anthropic tokenizer's ~4-chars-per-token rule of thumb on English/JSON text. Real token counts vary with the tokenizer and with how Claude Code wraps schemas, so treat the number as an order-of-magnitude gauge — good enough to answer "which server is eating my window?", not a billing meter.

Limitations

  • stdio servers only. Servers using SSE or streamable HTTP transports are not audited (they'd show a connection failure row).
  • Attribution is heuristic. who-called reads the transcript format as of Oct 2026; sidechain/agent fields are inferred, not contractual, and the purpose snippet is the nearest adjacent text. Treat it as an investigator's lead, not a log line. Nothing is uploaded — parsing is local.
  • The --mcp-config / --strict-mcp-config flags for run come from Claude Code's documented CLI options; they could not be verified on the machine where this was built (no Claude Code CLI installed). --strict-mcp-config matters: --mcp-config alone only adds servers on top of your configured ones, so without the strict flag disabled servers would still load. If the flag names ever change, run prints the filtered config path so you can pass it manually.
  • Audit uses select(2) on the server's stdout pipe: fine on Linux/macOS, not on Windows.
  • The estimate ignores tools' runtime behavior — a server with 2 tools can still be expensive if its tool results are huge. This tool measures schema cost only.
  • mcp-tax run writes the filtered config to ~/.config/mcp-tax/mcp-config.filtered.json (overwritten each run).

Development

python3 -m unittest discover -s tests   # 11 v2 tests (who-called, audit --all, gate)
python3 tests/test_smoke.py             # 9 smoke tests, incl. a fake stdio MCP server

The test fixture tests/fake_mcp_server.py speaks the same newline-delimited JSON-RPC 2.0 framing real MCP stdio servers use, so the audit math is tested against a realistic handshake (including stdout noise and hang/timeout cases).

License

MIT — see LICENSE.

Metadata

Release files for mcp-tax 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mcp-tax 0.2.0
File Size Uploaded
mcp_tax-0.2.0.tar.gz 25.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for mcp-tax 0.2.0
File Interpreter ABI Platform
mcp_tax-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 45.2 kB

Release files / mcp_tax-0.2.0.tar.gz

Download URL mcp_tax-0.2.0.tar.gz
Size 25.3 kB
Tags Source
SHA-256 checksum
How to use checksums
e4c83b368284d77d0f84e2de9d1e5af271dbab396ebdaacfa698aa8158a682a0
BLAKE2b-256 checksum
How to use checksums
39d66a68a3c2fff10037308f14ea03f9af05ec32bc49f89369347a8e7ac4a3c2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / mcp_tax-0.2.0-py3-none-any.whl

Download URL mcp_tax-0.2.0-py3-none-any.whl
Size 19.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8e45846e2bd516e5a1acd9e778fbf86314289189976df1b58b4c80b64beb674d
BLAKE2b-256 checksum
How to use checksums
8820e7fef71e39f8b526fee358a6fd9fc08c9276a3271f697db88dad0d5d8965
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release history Release notifications | RSS feed

0.3.0

2 release files

This release

0.2.0 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page