This repository implements a TypeScript CLI (mcpusage) that reproduces the workflow described in
Measuring Token Cost of MCP Tool Advertisements in TypeScript. It fetches every tool definition
from an MCP server, serializes the resulting “tool surface”, and measures how many tokens that block
would occupy for one or more OpenAI and Anthropic models (starting with GPT-5 / GPT-5.1 families,
Codex variants, and Claude Sonnet).
- Connects to any MCP server via stdio (launching a local process) or HTTP/SSE endpoints.
- Automatically paginates
list_toolsresponses so the entire tool surface is counted. - Serializes tool metadata deterministically (sorted by tool name, optional
_metastripping). - Uses
@dqbd/tiktoken(OpenAI models) and@anthropic-ai/tokenizer(Claude family) for token accounting with model-aware or custom encoding fallbacks; Anthropic API mode reports official counts and includes the local tokenizer total alongside for comparison. - Supports multiple models per run and highlights when tokenizers are assumed vs. officially published.
- Prints a Claude-style per-tool breakdown so you can see which MCP schema objects are most expensive.
- Can export the captured tool advertisement JSON for offline diffing or audits.
npm install
npm run build # compiles the CLI to dist/cli.jsOr install from npm (Node.js 20+):
# quick, no global install
npx mcpusage --help
# or install globally
npm install -g mcpusage
mcpusage --helpFor rapid iteration you can run the CLI directly from TypeScript:
npm run dev -- --helpAfter building, invoke the binary via:
node dist/cli.js --help
# or install globally / link if desired:
npm link
mcpusage --helpmcpusage \
--stdio npx -y @modelcontextprotocol/server-filesystem ./sample_files \
--model gpt-5 --model gpt-5.1-codexmcpusage \
--url https://mcp.example.com/mcp \
--header Authorization:"Bearer <token>" \
--transport streamable \
--dump-tools ./snapshots/server-a.jsonmcpusage --stdio-shell "poetry run python ./scripts/server.py" --format json--stdio <cmd...>/--stdio-shell <string>: launch a server via stdio; combine with--stdio-cwd,--stdio-env, and--stdio-echo-stderr(stdout is always silent, stderr is suppressed unless you opt in).--url <url>: connect to a remote MCP server via Streamable HTTP (default) or SSE (--transport).--model <name>: repeatable; defaults togpt-5,gpt-5.1,gpt-5-codex,gpt-5.1-codex, andclaude-sonnet-4-5-20250929. When you omit this flag the CLI shows totals only; specify one or more models to focus on and the output will include detailed per-tool breakdowns for those models.--anthropic-mode local|apiplus--anthropic-key(orANTHROPIC_API_KEY) lets you switch Claude measurements from local approximation to Anthropic’s officialcount_tokensendpoint so you can mirror Claude Code exactly (API mode issues one request per tool and the summary shows the local tokenizer total alongside the API count for comparison). Use--anthropic-tool-prefix <id>to optionally mirror Claude Code’smcp__<id>__toolrenaming in the request payload (defaults to the MCP server name when available).--dump-tools <file>/--print-schema: write the tool advertisement out (to a file or stdout). When paired with--format json,--print-schemaembeds the schema directly in the JSON payload.--include-meta: keep_metafragments in the snapshot (off by default to reduce noise).--format table|json: human-friendly table or machine-readable JSON output.--timeout <ms>/--max-retries <n>: fine-tunelist_toolsand HTTP retry behaviour.
Run mcpusage --help to view the full set of switches.
To inspect Claude’s accounting without other noise, we ship a deterministic MCP server under fixtures/minimal-mcp:
cd fixtures/minimal-mcp
npm install
npm run build # optional; npm run dev works tooYou can point the CLI at it:
# Local tokenizer baseline
node dist/cli.js \
--stdio-shell "cd fixtures/minimal-mcp && node dist/server.js" \
--model claude-sonnet-4-5-20250929 --anthropic-mode local
# Anthropic `count_tokens` (mirrors Claude Code exactly; requires API key)
ANTHROPIC_API_KEY=sk-your-key node dist/cli.js \
--stdio-shell "cd fixtures/minimal-mcp && node dist/server.js" \
--model claude-sonnet-4-5-20250929 --anthropic-mode apiBecause the server exposes only one tool, you can register it inside Claude Code, run /context, and compare the “MCP tools” usage to these known totals. Any extra tokens Claude attributes to the tool demonstrate the constant prompt overhead being bundled into their measurements.
- Connect to the MCP server and issue
list_tools, following pagination untilnextCursoris empty. - Sort the resulting tool definitions by name and convert them to JSON via
JSON.stringify. - Select the tokenizer for each requested model. GPT-5 has native
@dqbd/tiktokensupport; GPT-5.1 and Codex variants currently map too200k_baseuntil OpenAI publishes official tokenizers. - Encode the serialized JSON and report the token length per model, alongside byte/character counts.
This mirrors the PDF’s guidance for pre-computing an agent’s “tool surface” cost so you can budget prompt tokens before invoking the actual model.
- Requires Node.js 20+ (ESM with top-level await).
- No destructive actions are taken; the tool only reads schemas and optional output paths you specify.
- Warnings and connection diagnostics are printed to stderr so
--format jsonremains clean on stdout.