Measuring what a tool server costs
In this lesson we measure what a Model Context Protocol (MCP) server costs. We count what the tool definitions of a stand-in issue tracker with twenty tools take from the context window. Then we run one query through the server, and the same query through a command-line tool (CLI). The numbers show what to keep connected. The exercise repeats the measurement with a real server in your own agent and ends in a short table.
The previous lesson connected the reference file-system server to a copy of a small directory and read every call in the transcript. Here the question is what that connection costs on each turn, before the agent uses it and after. The lesson on what a token costs showed that a model reads its whole input again on every call. A tool definition is part of that input.
What the tool list costs
Section titled “What the tool list costs”When a client connects a server, it asks for tools/list, and each tool
comes back with a name, a description and a parameter schema [1].
Each definition takes tokens of context before any work begins [2].
Without on-demand loading, the client passes the definitions to the
model with each request. The model reads them on every turn, whether
the turn uses a tool or not.
The fixture for this lesson is at
site/examples/customizing-agents/mcp-tool-cost/. tracker_server.py is
a stand-in issue-tracker server over stdio with twenty tools, from
search_issues and get_issue to create_milestone and
subscribe_to_issue. Each has a description of two or three sentences
and a schema with one to seven parameters, and each parameter has its own
one-line description. The definitions of a real tracker server are
about this size.
Before you run the measurement, estimate it.
How big is the tool list?
Section titled “How big is the tool list?”The lesson's stand-in issue-tracker MCP server has twenty tools. Each has a description of two or three sentences and a parameter schema with one to seven parameters, and each parameter has a one-line description of its own.
Before the task starts, how many tokens do the twenty tool definitions of the tracker server take?
How many characters does one tool's description and schema take, how many characters make a token, and how many tools are there?
definitions.py asks the stand-in for tools/list and counts the
result with the rule of thumb from the lesson on
what the model can see,
about four characters per token. It counts the names alone too, in the
mcp__<server>__<tool> form that Claude Code uses for MCP tools in
permission rules [3].
Measure the definitions
Section titled “Measure the definitions”Run definitions.py in the fixture directory, and compare with the
output below.
tools = measure.list_tools()definitions = measure.definitions_text(tools)names = measure.names_text(tools)print(f"tools: {len(tools)}")size = f"{len(definitions):,} characters, about {measure.tokens(definitions):,} tokens"print(f"definitions: {size}")print(f"names only: {len(names):,} characters, about {measure.tokens(names):,} tokens")tools: 20 definitions: 13,788 characters, about 3,447 tokens names only: 553 characters, about 138 tokens
Output verified in CI from site/examples/customizing-agents/mcp-tool-cost/definitions.py.
The count is an estimate. A client counts with the model’s own
tokenizer, and in Claude Code the /context command shows what fills
the window, by category [4]. The size is what
matters here: about 3,447 tokens for the full definitions and about 138
for the names.
Claude Code doesn’t send the full definitions by default. Its tool
search holds them back, and the model searches for a tool’s definition
when it needs that tool [5]. Until then, only the tool
names and each server’s instructions enter the context
[6]. The mcp page lists the cases where Claude Code
loads every definition upfront instead: ENABLE_TOOL_SEARCH=false, an
ANTHROPIC_BASE_URL that points to a third-party host such as a proxy,
models before the Claude 4.5 generation on Google Cloud’s Agent
Platform, and a Microsoft Foundry deployment hosted on Azure
[5]. In the Claude API, a definition that search loads
stays in the conversation for later turns, and it counts as input tokens
like any other definition [7].
One query, two ways
Section titled “One query, two ways”Now the query. We want the open bugs about login. The server has
search_issues, and the tracker also has a CLI, which the agent would
run in its shell. one_query.py runs the same search both ways and
counts both sides of each: the call the model writes and the result it
reads back.
One query, two ways
Section titled “One query, two ways”Run one_query.py in the fixture directory, and compare with the output
below. The CLI’s listing comes first.
call, result = measure.server_query({"state": "open", "labels": ["bug", "login"]})command, output = measure.cli_query(["list", "--label", "bug", "--label", "login"])print(output, end="")print()print(f"server: call {measure.tokens(call)} tokens, result {measure.tokens(result)} tokens")print(f"cli: call {measure.tokens(command)} tokens, result {measure.tokens(output)} tokens")#104 Session cookie is not cleared on logout (rivera) #101 Login page times out behind the office proxy (rivera) #106 Single sign-on button missing on mobile (-) #102 Password reset email arrives twice (-) server: call 24 tokens, result 535 tokens cli: call 13 tokens, result 54 tokens
Output verified in CI from site/examples/customizing-agents/mcp-tool-cost/one_query.py.
The calls are about the same size. The results differ, and the
difference comes from how each one was written. search_issues returns
the full record of each issue as JSON (JavaScript Object Notation), with the body, the timestamps, the
reporter and the URL. The CLI prints one line per issue, which is what a
tracker’s CLI does by default. The result has to fit the task. The one-line
list answers “which login bugs are open”, and the model reads the 535
tokens of full records without needing them. A server with a
fields parameter, or a CLI asked for JSON output, moves those numbers.
So measure the server you have, and don’t go by what servers in general
return.
The same query over a session
Section titled “The same query over a session”One query happens once, and the context it adds stays. The call and its
result remain in the conversation, and the definitions arrive with every
request. The model reads both again on every later turn.
session.py adds that up over a ten-turn session with the query on the
first turn, for four setups. The first is the server with all twenty
definitions loaded. The second is tool search: the names on every turn,
plus the one definition that search loads for search_issues. This row
leaves two parts out, because the fixture has no size for them: the
definition of the search tool itself, which the API keeps in the context
on every turn, and the search call with its result, which stay in the
conversation [7]. The real number for this
row is higher. The third
loads only three definitions, the tools the task uses. The last is the
CLI. It runs through the agent’s shell tool. That tool is in every setup
anyway, and the CLI doesn’t bring a definition of its own.
Ten turns
Section titled “Ten turns”Run session.py in the fixture directory, and compare with the output
below.
for label, per_turn, query in setups: print(f"{label:<28} {TURNS * (per_turn + query):>7,}")tokens read over 10 turns server, all 20 tools loaded 40,060 server, tool search 10,150 server, 3 tools loaded 11,650 cli 670
Output verified in CI from site/examples/customizing-agents/mcp-tool-cost/session.py.
Read the table from the top. With the full list the model reads 40,060 tokens over the session. Tool search brings the server down to 10,150, and most of what’s left is the 535-token result, read again on every turn. Keeping three tools, without tool search, reads 11,650, which is in the same range. Which of the two is lower in your client depends on the parts the tool-search row leaves out. The CLI reads 670, because it has no definitions and a short result.
Prompt caching makes a repeated part of the input cheaper to read again [6]. It doesn’t make that part smaller. The definitions still take the same share of the window, and the window is where the rest of the task has to fit.
A second cost doesn’t show in any count. Every tool in the list is
something the model can call, and so is every tool that search can find.
An instruction injected into a web page or an issue body can ask for
delete_comment as easily as the task asks for search_issues. A tool
the task never uses costs tokens and adds a way to do damage. A deny
rule that names a whole tool, such as mcp__tracker__delete_comment,
removes it from what Claude sees [3].
What to keep
Section titled “What to keep”From the measurement:
- Keep only the tools the task uses. A server with twenty tools and a task that needs three is seventeen tools of cost and risk. Deny the rest by name, or pick a server with fewer tools.
- Use the CLI for occasional queries. When the system has a good CLI
and the agent needs it a few times in a session, the CLI costs no
definitions and returns what you asked for. Claude Code’s page on costs
recommends CLIs such as
ghandawsfor the same reason: running a command doesn’t put tool descriptions in the context [6]. - Use the server for constant, structured calls. When the agent calls the system on most turns and needs typed inputs and structured results, the definitions are paid once per turn and used on most of them, and typed inputs and structured results are more reliable than text the model has to parse [2].
- Disable the servers the project doesn’t use. Tool search lowers the
per-turn cost of a connected server. It doesn’t remove it: the names
still load on every turn, some setups load every definition upfront, and
any search can reach every tool, including a search that an injected
instruction asks for. In
Claude Code,
/mcplets you turn a server off without removing its configuration [5], and the cost page names disabling unused servers as one of its controls [6].
What do you connect?
Section titled “What do you connect?”The lesson measured an issue-tracker MCP server with twenty tools against the tracker's CLI, and ended with decisions about when to use the CLI, when to use a trimmed server, and when no tool is needed.
Match each need to what you connect for it. The tracker has an MCP server and a CLI, and the CLI can list and show issues but can’t change them.
How often does the agent call the system, does the task need typed input, and could the agent read the information from a file instead?
Tool search is on
Section titled “Tool search is on”Claude Code's tool search is on by default. The model sees the tool names and the server instructions, and it loads a tool's definition when it searches for that tool.
A project has six MCP servers connected and uses one. A colleague says: “Tool search is on, so the other five are free. There’s no reason to disable them.” What do you answer?
What does tool search still load on every turn, and which tools can the model still reach?
Exercise
Measure a real server in your own agent, on a copy. Copy the handbook
directory from site/examples/customizing-agents/mcp-first-server/ to a
place you can delete, change into the copy, and add the reference
file-system server there as in the previous lesson. It has thirteen
tools, and four of them write [8]. Claude Code gives
the server the directory it was started in as its root, so start the
agent inside the copy every time [5]. Roots are deprecated
in MCP revision 2026-07-28 [9], and the command
below also gives the copy as the argument, so a client that stops sending
roots still leaves the server on the copy. With your own measurement you
can price any server before you keep it connected. The
commands use a new copy, so a changed copy from the previous lesson
doesn’t show up in your listings.
cp -r site/examples/customizing-agents/mcp-first-server/handbook /tmp/handbook-costcd /tmp/handbook-costclaude mcp add handbook -- npx -y @modelcontextprotocol/server-filesystem@2026.8.31 /tmp/handbook-cost- Start Claude Code with every definition loaded,
ENABLE_TOOL_SEARCH=false claude[5], run/context, and write down the tokens it shows for the MCP tools. Quit, startclaudewithout the variable, and write down the same number with tool search on. - In the second session, run
/contextand note the tokens in use. Ask: “Use the handbook server to list this directory. Answer with the listing only.” Run/contextagain. - Run
/clear[10], run/context, and ask: “Runlsin your shell to list this directory. Answer with the listing only.” Claude Code runslswithout asking, becauselsis on its list of read-only commands [3]. Run/contextagain.
Put the four numbers in a short table: the definitions with and without
tool search, and the tokens each query added. A good result has all four
from your own /context output, and says in one line which connection
you would keep for a task that lists a directory twice a week. Remove the
server with claude mcp remove handbook when you are done
[5]. Then ask yourself: at how many calls a session would
the server be the better choice?
Stretch: Deny every write tool of the server by name in your settings, then run /context again and see how the count for MCP tools changes.
A forty-tool server
Section titled “A forty-tool server”A team is about to add a monitoring system's MCP server to a coding agent. The system also has a CLI that the developers already use.
The agent needs to look up an alert about twice a week. The monitoring server has forty tools. What do you set up?
How often will the agent use the system, and what does it cost on the turns it doesn't?
What does the model read again?
Section titled “What does the model read again?”An agent client with tool search on connects one MCP server. The agent ran one query through that server on the first turn of a ten-turn session, and one CLI command on the second turn.
Place each item by when the model reads it.
Which of these are in the conversation or the request once they have appeared, and which exist only when the model asks for them?
Read the session table
Section titled “Read the session table”A ten-turn session table from the lesson: a server with all twenty tools loaded read 40,060 tokens, the same server with tool search 10,150, with three tools loaded 11,650, and the CLI 670. The server's one query returned a 535-token result.
With tool search on, the server still reads 10,150 tokens over ten turns. Which part of that is the largest?
With tool search on, what is left in each turn, and which part of it came from the query?
Recap
- A connected server’s tool definitions are part of the model’s input. Without on-demand loading, the model reads all of them on every turn, and twenty tools of a normal size come to a few thousand tokens.
- A query costs its call and its result, and both stay in the conversation. A verbose result is read again on every later turn, so measure what your server returns and not only what it lists.
- Claude Code’s tool search is on by default [5], and until the model searches, only the names and server instructions are in the context [6]. It lowers the per-turn cost, and the names, the upfront fallbacks and the reach of every tool remain.
- Keep only the tools a task uses, use the CLI for occasional queries and the server for constant structured calls, and turn off the servers the project doesn’t use [6].
You can now
- Explains the token and risk cost of a tool before adding it
References
Section titled “References”- Anthropic and the MCP contributors. Model Context Protocol specification 2026-07-28. modelcontextprotocol.io. Reference.
MCP specification - Addy Osmani, Ivar Soares Urdalen, Leo Simons. MCP deep dive: MCP versus CLI, security failure modes, token cost. Agent Engineer Course. Course.
AEC-16 - Anthropic. Configure permissions. Claude Code documentation. Reference.
Claude Code permissions - Anthropic. Explore the context window. Claude Code documentation. Reference.
Claude Code context window - Anthropic. Connect Claude Code to tools via MCP. Claude Code documentation. Reference.
Claude Code mcp - Anthropic. Manage costs effectively. Claude Code documentation. Reference.
Claude Code costs - Anthropic. Tool search tool. Claude Platform documentation. Reference.
Claude docs tool-search-tool - Anthropic and the MCP contributors. Filesystem MCP Server. GitHub, modelcontextprotocol/servers README. Reference.
MCP filesystem server - Anthropic and the MCP contributors. Deprecated Features, Model Context Protocol specification 2026-07-28. modelcontextprotocol.io. Reference.
MCP deprecated features - Anthropic. Commands. Claude Code documentation. Reference.
Claude Code commands