MCP is having a moment on DEV this week. The big thread is about how simple the protocol is. The quieter question underneath it is what all those connected servers cost you, both in context window and in money, before the model writes a single line of code.
I build websites and apps for founders, and I test AI coding tools in real projects. This post is the practical version of that question: where MCP tokens come from, how to measure them for your own setup with about 40 lines of Node, and the three settings that cut the bill. Everything below links to the official docs I checked on November 15, 2026.
Where MCP token cost comes from
An MCP server tells the client what it can do through tools/list. According to the MCP tools specification, each tool has a name, a description, an inputSchema (JSON Schema), and optionally a title, outputSchema and annotations.
Your AI client then hands those definitions to the model. On the model API side, that is just input. Anthropic's tool use pricing says tool requests are priced on "the total number of input tokens sent to the model (including in the tools parameter)", and that the extra tokens come from tool names, descriptions and schemas, plus tool_use and tool_result blocks.
There is also a fixed overhead. When any tool is present, the API adds a tool use system prompt. Here is what the docs list for a few current models with tool_choice set to auto:
| Model | Tool use system prompt tokens (auto/none) |
|---|---|
| Claude Opus 5.5 | 286 |
| Claude Sonnet 5 | 354 |
| Claude Sonnet 4.6 | 497 |
| Claude Haiku 4.5 | 496 |
So the token cost of MCP has three parts:
- Definitions: every tool from every connected server, sent with every request unless you defer them.
- Overhead: the tool use system prompt, a few hundred tokens.
- Traffic: the tool calls and the results they return, which can be large. A database query or a page snapshot can easily be bigger than the definitions.
The first part is the one people underestimate, because it is invisible. You never see it in the chat. It just quietly eats context in every turn of an agent loop.
How big is "a lot of MCP tools"?
Anthropic's own tool search docs give a concrete example: a typical multi-server setup (GitHub, Slack, Sentry, Grafana and Splunk) "can consume ~55k tokens in definitions before Claude does any work." The same page says Claude's ability to pick the right tool "degrades once you exceed 30–50 available tools."
That second point matters as much as the money. Bloated tool lists don't only cost more. They make the agent worse at choosing.
To make the money concrete, here is plain arithmetic using Anthropic's published prices for Claude Sonnet 5: $2 per million base input tokens, $0.20 per million for cache hits.
| 55,000 definition tokens on Claude Sonnet 5 | Per request | Per 1,000 requests |
|---|---|---|
| Uncached input ($2 / MTok) | $0.11 | $110 |
| Cache hit ($0.20 / MTok) | $0.011 | $11 |
That is only the definitions, before any prompt, code or output. An agent that takes 20 steps to finish a task sends them 20 times. If you want to run these numbers for your own volume and model, I keep an AI token calculator for exactly this.
One more trap: the pricing FAQ notes that Claude 4.7 and later models use a newer tokenizer that "produces approximately 30 percent more tokens for the same text." A token count you measured on an older model is not valid for a newer one. Recount.
Measure MCP tool definition tokens for your own servers
Guessing is pointless when you can measure. The script below connects to any stdio MCP server with the official TypeScript SDK, pages through tools/list, and prints the JSON size of each tool so you can spot the heavy ones.
// measure.mjs // npm i @modelcontextprotocol/sdk import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js"; const [command, ...args] = process.argv.slice(2); const client = new Client({ name: "tool-budget", version: "0.1.0" }); await client.connect(new StdioClientTransport({ command, args })); const tools = []; let cursor; do { const page = await client.listTools(cursor ? { cursor } : {}); tools.push(...page.tools); cursor = page.nextCursor; // tools/list is paginated } while (cursor); await client.close(); const rows = tools .map((t) => ({ name: t.name, chars: JSON.stringify(t).length })) .sort((a, b) => b.chars - a.chars); console.table(rows); console.log(`${tools.length} tools, ${rows.reduce((s, r) => s + r.chars, 0)} chars of JSON`); Run it against the official filesystem server:
node measure.mjs npx -y @modelcontextprotocol/server-filesystem /tmp With version 2.3.0 of that server, it reports 16 tools and about 19,000 characters of JSON. The largest are edit_file, directory_tree and search_files, each around 1,700–1,800 characters. Your numbers will vary with the server version.
Characters are not tokens, though, and every model tokenizes differently. To get the real number, ask the model provider. Anthropic's token counting endpoint accepts tools, is free to use (with rate limits), and returns input_tokens. Add this after client.close():
// npm i @anthropic-ai/sdk (needs ANTHROPIC_API_KEY) import Anthropic from "@anthropic-ai/sdk"; const anthropic = new Anthropic(); const model = "claude-sonnet-5"; const messages = [{ role: "user", content: "hi" }]; // MCP uses inputSchema; the Messages API expects input_schema const asClaudeTools = tools.map((t) => ({ name: t.name, description: t.description ?? "", input_schema: t.inputSchema, })); const base = await anthropic.messages.countTokens({ model, messages }); const withTools = await anthropic.messages.countTokens({ model, messages, tools: asClaudeTools, }); console.log(`Tool cost on ${model}: ${withTools.input_tokens - base.input_tokens} tokens per request`); The difference includes both the definitions and the tool use system prompt, which is what you actually pay. Two caveats from the docs: the count "is an estimate" and can differ slightly from real usage, and the endpoint rejects server tools and the MCP connector. For those, read the usage object on a real response.
If you mostly work inside Claude Code rather than the API, the Claude Code MCP docs describe tool search as on by default. They also say Claude Code warns when one MCP tool's output exceeds 10,000 tokens and caps it at 25,000 by default (configurable with MAX_MCP_OUTPUT_TOKENS). That covers the "traffic" part of the bill.
How to reduce MCP token usage: three settings that work
1. Import only the tools you need (allowed tools)
Most servers expose far more tools than one task needs. OpenAI's MCP and connectors guide says it directly: exposing many tools "can result in high cost and latency," and the allowed_tools parameter lets you import only a subset:
{ "type": "mcp", "server_label": "openai_docs", "server_url": "https://developers.openai.com/mcp", "require_approval": "never", "allowed_tools": ["search_openai_docs"] } This is also the safer choice. Fewer tools means fewer things an agent can do by mistake. I wrote up the access side of this in MCP servers for web development: choose access first. The token argument and the security argument point the same way.
2. Defer loading with tool search
When you genuinely need a large catalog, don't load it up front. Anthropic's tool search tool lets you send every definition but mark most with defer_loading: true. Claude sees only the search tool and non-deferred tools at first, searches when it needs something, and the API expands the matches (up to 5 by default) into full definitions:
{ "tools": [ { "type": "tool_search_tool_regex_20251119", "name": "tool_search_tool_regex" }, { "name": "search_files", "description": "Search through files in the workspace", "input_schema": { "type": "object", "properties": { "query": { "type": "string" } }, "required": ["query"] }, "defer_loading": true } ] } Anthropic says tool search "typically reduces this by over 85 percent" in the multi-server example above. Two details worth knowing: at least one tool must stay non-deferred, and discovered definitions still count as input tokens once they load. OpenAI offers the same idea for remote MCP servers, with defer_loading: true on the MCP tool entry when you use tool search.
The trade-off is an extra search step and a model that can miss a tool if its description is vague. Good names and descriptions now matter for retrieval, not just for the human reading them.
3. Keep the tool list stable so caching works
The MCP spec says servers SHOULD return tools in a deterministic order, because stable ordering "improves LLM prompt cache hit rates when tools are included in model context." On Claude Sonnet 5, a cache hit is a tenth of the base input price, as the table above shows. If your client reorders tools, or you toggle servers mid-session, you pay full price again. Pin your server set for a session and let the cache do its job.
The honest trade-off
MCP's simplicity is real, and it's why it spread so fast. But "easy to connect" turns into "easy to over-connect." My rule for client projects is boring on purpose:
- Start with zero servers. Add one when you catch yourself pasting the same data into chat.
- Scope it to the tools that task needs.
- Measure the token cost once with the script above, then again after upgrading models.
- Defer anything you use less than every session.
None of this needs a new framework. It is the same discipline as keeping a bundle small: measure, cut, measure again.
If you price these workflows against real API rates, I keep an updated Claude API pricing breakdown on my site. I also take on freelance web and app builds for founders, including AI features that need to stay fast and affordable in production.
How many MCP tools does your daily setup load? Run the script and share the number in the comments. I'm curious how wide the range is.

