Token Accounting: The Context Cost of Each Surface

Context window tax is the single largest hidden cost in building MCP servers, often exceeding the compute cost of the inference itself. Most teams treat token usage as a billing line item. It is not. It is a latency constraint and a reliability risk. When you package a capability as a Model Context Protocol server, you are not just exposing a function. You are forcing the host LLM to read the schema, the description, and the parameter definitions for every single tool in your registry, on every single turn. If your server exposes twenty tools, and each description is fifty words, you have just burned one thousand tokens before the model has generated a single character of output. This is the standing cost. It does not disappear when the user asks a simple question. It accumulates. The pipeline we built in the earlier lessons treats the core logic as transport-agnostic. The pack contains the business rules. The loop handles the execution. But the surface area changes the input shape. A plain function call receives a JSON payload. The LLM has already decided to call it. The schema was read once during the planning phase. The token cost is limited to the arguments. A CLI receives a string. The LLM generates the command. The token cost is the length of the command string. An MCP server requires the LLM to maintain the entire tool registry in its context window. The token cost is the registry plus the arguments. To see the difference, we need to measure the actual byte count of the prompts sent to the model. We do not guess. We instrument the client.

Instrumenting the Token Budget

We need a consistent way to count tokens across the three surfaces. The standard approach is to log the input string length at the point where the LLM receives it. For the function surface, this is the JSON body. For the CLI, this is the command string. For MCP, this is the combined prompt containing the system instructions, the tool definitions, and the user query. Use a library like `tiktoken` or the provider’s native counting utility. Do not rely on the provider’s dashboard. Dashboard numbers often aggregate across retries or include system overhead that varies by endpoint. We need the raw input size. Set up a test harness that runs the same task through all three surfaces. The task should be non-trivial. A simple “hello world” will not expose the overhead. Use a task that requires multiple steps. For example, retrieve a resource, transform it, and write it back. This forces the model to plan, call tools, and interpret results. Run the task ten times. Record the input token count for each turn. Sum them. This gives you the session cost. Divide by the number of turns to get the per-call average. The per-call average is misleading for MCP. It hides the standing cost. The session cost reveals it. You will see that the function surface has the lowest session cost. The schema is read once. The arguments are small. The CLI surface is slightly higher. The command string is longer than the JSON arguments. But it is still linear. The MCP surface is disproportionately high. The tool definitions are repeated in every turn. If the conversation lasts ten turns, you have sent the tool definitions ten times.

The Standing Cost of Tool Descriptions

The standing cost is the price of clarity. MCP requires detailed descriptions so the LLM knows when to use each tool. A vague description leads to wrong tool calls. Wrong tool calls lead to retries. Retries lead to more tokens. So we write good descriptions. Good descriptions are long. Long descriptions are expensive. Consider a tool that searches a database. A minimal description might be “Search the database.” This is thirty tokens. A good description might be “Search the PostgreSQL database for records matching the given criteria. Supports filtering by date, status, and owner. Returns a list of JSON objects. Use this when the user asks for specific records.” This is sixty tokens. Double the cost. Now imagine you have twenty such tools. The difference is one thousand tokens per turn. This is where teams start moving MCP surfaces back to CLIs. The CLI does not need descriptions. The LLM learns the command syntax from examples. The command syntax is compact. `search-db –status active –owner john` is shorter than the JSON equivalent and much shorter than the MCP tool definition. The CLI trades explicit schema for implicit learning. This works well for stable APIs. It breaks down when the API changes often. MCP still wins when the tool set is dynamic. If the tools change at runtime, the CLI approach fails. The LLM does not know the new commands. MCP updates the registry. The LLM sees the new tools. The cost is higher, but the flexibility is real. This is the tradeoff. Stability versus adaptability.

Producing the Token Table

We need a single table that captures the session cost for each surface. This is the artifact you will produce. It should have three rows: Function, CLI, MCP. It should have three columns: Tokens per Call, Standing Cost per Turn, Total Session Cost. The tokens per call is the average input size for a single tool invocation. The standing cost per turn is the overhead that is not related to the specific task. For the function, this is zero. For the CLI, this is zero. For MCP, this is the size of the tool registry. The total session cost is the sum of the per-call costs plus the standing cost multiplied by the number of turns.

Token cost comparison across three transport surfaces for a ten-turn session
Surface Tokens per Call Standing Cost per Turn Total Session Cost
Function Measured 0 Measured
CLI Measured 0 Measured
MCP Server Measured Measured Measured

Fill in the measured values. Do not estimate. Run the test harness. Record the numbers. You will likely see the MCP total session cost is two to three times higher than the function cost. This is not a bug. It is the cost of the interface. The limitation of this approach is that it assumes a static tool set. If the tool set grows, the MCP cost grows linearly. The function and CLI costs remain stable. This means MCP is not scalable in the same way. You cannot just add more tools. You have to manage the context window. You have to prune old tools. You have to group related tools. This adds engineering overhead. It is not just a token cost. It is a maintenance cost. Be fair about where MCP still wins. It wins in discoverability. The LLM knows exactly what is available. It wins in type safety. The schema prevents invalid arguments. It wins in composition. Multiple MCP servers can be combined. The CLI approach requires the LLM to learn multiple command sets. The function approach requires the LLM to manage multiple JSON schemas. MCP standardises this. The cost is high, but the benefit is real.You should finish with Measured token table. This table is the evidence. It allows you to make a defensible choice. It moves the discussion from opinion to data. You can now answer the question: should this be an MCP server? The answer depends on the token budget. If the budget is tight, choose the function or CLI. If the budget is flexible and the tool set is dynamic, choose MCP. The next lesson, Choosing: A Decision Table You Can Defend, takes this data and builds a framework for making the final call.

Apply it to your work