# MCP vs CLI: where agent tool tokens go, and how to cut them

URL: https://infro.io/blog/mcp-vs-cli-token-overhead
Author: INFRO Editorial (https://infro.io/blog/editorial)
Publisher: INFRO
Published: 2026-10-19
Last modified: 2026-10-19
Last reviewed: 2026-10-19 (next review due 2026-11-18)
Topic: Agents and multimodal systems
Format: Guide

> MCP vs CLI comes down to when tool descriptions enter the context. An MCP client that loads tools up front sends every tool's name, description and schema with each request, so idle tools cost tokens on every turn; a CLI the agent already knows, or a skill, costs nothing until it is used. Count the overhead with a token-counting call, then cut it with fewer and narrower tools, per-key tool filtering, deferred loading or code execution. Keep MCP where you need remote tools, shared auth, governance and an audit trail.

Key takeaways:
- Tool definitions are input tokens. A client that loads MCP tools up front resends every name, description and schema with each request, whether the agent uses them or not.
- A CLI the model already knows, such as gh or aws, adds no per-tool listing; Anthropic recommends preferring one when it exists.
- Measure before arguing: count a request's input tokens with and without the tool list, using the provider's token-counting endpoint.
- Deferred loading, tool search and code execution keep definitions out of context until needed; fewer, narrower tools and per-key tool filtering shrink the list itself.
- MCP still earns its tokens for remote tools, shared credentials, governance, audit and serving several clients from one definition.

The MCP vs CLI argument is about one mechanism: when a tool's description enters the model's context. A client that loads MCP tools up front sends every tool's name, description and input schema with every request, so a server you connected for one task costs tokens on every turn. A command-line tool the model already knows costs nothing until the agent runs it. Anthropic's own Claude Code guidance says CLIs such as `gh`, `aws`, `gcloud` and `sentry-cli` "are still more context-efficient than MCP servers because they don't add any per-tool listing"[1].

That does not make MCP the wrong choice. It makes the overhead something to measure and manage. This guide explains where the tokens go, how to count them, five patterns that reduce them, and when MCP is still the right answer.

## Why MCP tool definitions cost tokens on every turn

An MCP client discovers a server's tools with a `tools/list` request. Each tool comes back with a `name`, an optional `title`, a `description`, an `inputSchema` in JSON Schema, and optionally an `outputSchema` and `annotations`[2]. To let the model call those tools, the client converts them into the model API's tool format and puts them in the request.

Model APIs are stateless, so the tool list goes in every request, not once per session. Anthropic's pricing page is explicit that the `tools` parameter (tool names, descriptions and schemas) is billed as input tokens, and that any request with tools also carries a tool-use system prompt the API adds automatically; on Claude Opus 5.5 that is 286 tokens[3]. An agent turn is several requests, one per tool call, so the definitions are paid for again on each step.

Two consequences follow:

- **Idle tools cost the same as used ones.** A 40-tool server connected for one lookup is paid for on every request of the session.
- **The cost scales with servers, not with work.** Anthropic's tool search documentation gives a typical five-server setup (GitHub, Slack, Sentry, Grafana and Splunk) as about 55,000 tokens of definitions "before Claude does any work"[4].

Size is not the only problem. The same page says Claude's ability to pick the right tool degrades once more than 30 to 50 tools are available[4]. A long tool list is paid for in tokens and in wrong choices.

OpenAI tells Codex users the same thing from the other side: "Every MCP server adds more context to your messages and uses more of your limit," and advises disabling servers you do not need[5].

## MCP vs CLI: the mechanical difference

|  | MCP tools loaded up front | CLI through a shell tool | Skill or instruction file loaded on demand |
| --- | --- | --- | --- |
| What is in every request | Every tool's name, description and schema | One shell tool definition | A short name and description |
| When details load | At session start | When the agent runs `--help` or reads the output | When the agent invokes it |
| Auth | Server holds or brokers credentials | Whatever is on the developer's machine | Whatever the skill's commands use |
| Works remotely | Yes, over HTTP | Only where the binary is installed | Where the agent runs |
| Central control and audit | Possible at the server or a gateway | Shell history, if anything | None by default |

Table: A CLI is cheap in context because the model already knows it; the price is that control lives on each machine.

The CLI advantage depends on the model already knowing the tool. `git`, `gh`, `kubectl` and the major cloud CLIs are in the training data, so the agent can call them without a schema. An internal CLI the model has never seen needs documentation in context, either a skill or the output of `--help`, and that is a tool definition by another name.

## How to measure the overhead

Do not guess. Count a request's input tokens with and without the tool list, using the provider's token-counting endpoint. Anthropic's `POST /v1/messages/count_tokens` accepts the same inputs as a message, including `tools`, returns the total input tokens, is free to use within its own rate limits, and is documented as an estimate that may differ slightly from the billed count[6].

First, fetch the tool list from your MCP server and convert it into the Messages API's tool shape:

```bash
# tools/list from a Streamable HTTP server, then MCP shape -> Messages API shape
curl -s "$MCP_URL" \
  -H "Authorization: Bearer $MCP_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' \
| jq '[.result.tools[] | {name, description, input_schema: .inputSchema}]' > tools.json
```

Then count the same message twice:

```bash
count() {
  curl -s https://api.anthropic.com/v1/messages/count_tokens \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "content-type: application/json" \
    -d "$1" | jq .input_tokens
}
MSG='[{"role":"user","content":"List open issues assigned to me"}]'
count "{\"model\":\"claude-sonnet-5-5\",\"messages\":$MSG}"
count "{\"model\":\"claude-sonnet-5-5\",\"messages\":$MSG,\"tools\":$(cat tools.json)}"
```

The difference is what that server costs on every request. Some servers paginate `tools/list` with a cursor[2]; follow `nextCursor` until it is empty. Recount when you change models: Anthropic notes that Claude 4.7 and later models use a newer tokenizer that produces roughly 30% more tokens for the same text[6].

In Claude Code, `/context` shows what is consuming the context window, server by server[1].

> **Example: Turning a count into a monthly number**
> Illustrative only. A server's tool list counts at 9,000 tokens. An agent session makes 120 requests. That is 1.08 million input tokens of definitions per session, before any work. With prompt caching most of it bills at the cache-hit rate; without caching, or after the cache expires, it bills at the full input rate. Multiply by sessions per developer per month to see whether the server is worth keeping connected by default.

Prompt caching reduces this cost; it does not remove it. On Anthropic's API a cache hit bills at 0.1x the base input rate, 0.05x on Claude Opus 5.5 and Claude Sonnet 5.5[3], but the definitions still occupy the window and still bill. Tool definitions sit at the front of the prompt, so changing the tool list mid-session invalidates the cache behind it. [Long context in production](https://infro.io/blog/long-context-window-management) covers the window side of the same problem.

## Five patterns that cut tool overhead

### 1. Fewer, narrower tools

The cheapest token is the one you do not send. Many MCP servers expose every endpoint of an API as its own tool. Turn off what the agent never needs. Codex supports `enabled_tools` and `disabled_tools` per MCP server in `config.toml`[7]; Claude Code lets you disable unused servers with `/mcp`[1]. If you write the server, merge near-duplicate tools and keep descriptions short and specific. Claude Code cuts tool descriptions that load up front at 4,096 characters by default[8], which is a hint about how long they should be.

### 2. Toolsets per task

Group tools by job: a read-only toolset for investigation, a write toolset for changes. Connect the one the task needs. A server that exposes toolsets lets each client choose the smallest set that works.

### 3. Deferred loading and tool search

Anthropic's API lets you send tools with `defer_loading: true` alongside a tool search tool. The model sees only the search tool and any non-deferred tools at first, searches when it needs something, and the API expands only the matching definitions[4]. Anthropic reports this typically cuts definition tokens by over 85%, loading the three to five tools a request needs, and that deferred tools are excluded from the system-prompt prefix so prompt caching is preserved[4]. Its own guidance: use tool search with ten or more tools or more than 10,000 tokens of definitions, and stay with standard tool calling below that[4]. Note that you still send every definition in the request; deferral controls what enters the context, not what crosses the wire[4].

Claude Code applies this to MCP by default: only tool names and server instructions load at session start[8].

> **Warning: Tool search and custom base URLs**
> Claude Code turns tool search off when `ANTHROPIC_BASE_URL` points at a non-first-party host, "since most proxies don't forward `tool_reference` blocks," and loads every MCP tool up front instead[8]. `ENABLE_TOOL_SEARCH=true` turns it back on, and requests then fail on a proxy that does not support those blocks[8]. If you route Claude Code through a gateway, test this explicitly, and check `/context` before and after.

### 4. Code execution instead of direct tool calls

Anthropic's engineering team describes a different shape: present MCP servers to the agent as code on a filesystem, let it read only the definitions it needs, and let it write code that calls tools and filters their results before anything returns to the model[9]. This addresses both costs the post names, definitions that overload the context window and intermediate results that pass through it; in its worked example token use fell from 150,000 to 2,000[9]. The post is equally clear about the price: running agent-written code needs a sandbox with resource limits and monitoring, which adds operational overhead and security considerations that direct tool calls avoid[9].

Results matter as much as definitions. Claude Code warns when an MCP tool's output exceeds 10,000 tokens and limits it to 25,000 by default, saving larger results to a file[8]. A tool that returns a whole table when the agent needed three rows costs more than its definition ever will.

### 5. Filter tools per key at a gateway

Client-side settings live on each developer's machine and drift. A gateway between agents and MCP servers can decide which tools each credential sees at all: an agent that only triages issues gets three tools, not the server's forty. That shrinks the list before the client ever builds a request, and it works the same whether or not the client supports deferred loading. [The MCP gateway guide](https://infro.io/blog/mcp-gateway-govern-agent-tools) covers the pattern in full.

## When is MCP still the right answer?

Use a CLI where the model knows it, the agent has a shell, and the credentials on that machine are the right ones. Use MCP where those conditions fail:

- **Remote tools.** A hosted agent, a CI job or a chat assistant has no developer laptop to install a CLI on. MCP over HTTP reaches the service from anywhere.
- **Credentials you do not want on every machine.** An MCP server, or a gateway in front of it, holds the service credential; the agent holds only its own. Rotating one secret beats rotating one per laptop.
- **Governance.** Approve which tools exist, which agents may call write tools, and switch a tool off for everyone at once. The MCP specification itself says clients should show users which tools are exposed and keep a human able to deny invocations[2].
- **Audit.** The specification recommends that clients log tool usage for audit purposes[2]. A central path makes that one log instead of one per machine. [MCP in production](https://infro.io/blog/mcp-tool-calling-production) covers the failure modes worth logging.
- **Many clients, one definition.** The same server serves Claude Code, Codex, an internal agent and an IDE. A CLI wrapper per client is more code to keep in step.

The honest framing is not MCP versus CLI but which tools must be on every turn. Keep that list short, defer the rest, and put control where more than one machine depends on it.

## Governing tool lists with INFRO

INFRO's MCP gateway sits between your agents and the MCP servers you already use. An admin registers each server once with its credential, approves and pins each tool's definition, and grants gateway keys access to a server in `read`, `all` or `selected` mode. A key with no grant sees no tools, and on the aggregated endpoint a key lists only the approved tools its grants allow, so an agent's tool list is as narrow as its job. Every call, refusals included, is recorded on the same trace as the agent's model calls, approvals and blocks are written to the audit log, and blocking a tool or disabling a server takes effect on the next call. INFRO executes no tool and hosts no server: the servers are yours, reached with your credentials. Setup is on [the MCP gateway docs page](https://infro.io/docs/mcp-gateway).

For measurement, agents that call Claude through INFRO's `/v1/messages` can use `POST /v1/messages/count_tokens` on the same base URL; it asks the first Anthropic connection serving the model, costs nothing and leaves no request row. INFRO forwards tool search on an Anthropic connection: the deferred tools, the search tool, the `tool_reference` blocks and the `anthropic-beta` header reach Anthropic as Claude Code sent them, so set `ENABLE_TOOL_SEARCH=true` when Claude Code points at INFRO. A model INFRO has to translate to Chat Completions cannot run the search tool, and such a request is refused before any call. Recipes for pointing Claude Code and Codex at INFRO are on [the coding agents page](https://infro.io/docs/coding-agents).

## Questions

### Is MCP worse than a CLI for AI agents?

Not in general. A CLI is lighter when the model already knows it and the agent has a shell, because nothing is listed until it runs. MCP is the better fit for remote services with their own auth, tools many clients share, and anywhere you need to approve, restrict and log what an agent can call.

### How many tokens do MCP tool definitions use?

It depends on the servers. Anthropic's tool search documentation gives about 55,000 tokens of definitions for a five-server setup (GitHub, Slack, Sentry, Grafana and Splunk) before the agent does any work. Measure your own by counting a request's input tokens with and without the tool list.

### Does prompt caching make MCP tool definitions free?

No. Cached definitions bill at the provider's cache-hit rate rather than the full input rate, which is much lower, but they still occupy the context window on every turn and still cost something. A change to the tool list also invalidates the cached prefix that follows it.

### Why did Claude Code stop deferring MCP tools behind my proxy?

Claude Code turns tool search off by default when ANTHROPIC_BASE_URL points at a host other than Anthropic's, because many proxies do not forward the tool_reference blocks it depends on. Setting ENABLE_TOOL_SEARCH=true turns it back on; test it against your gateway first, since requests fail on a proxy that does not support those blocks. INFRO forwards them on Anthropic connections.

## Sources

1. Manage costs effectively — Anthropic. https://code.claude.com/docs/en/costs (accessed 2026-10-19)
2. Tools — Model Context Protocol specification 2025-11-25 — Model Context Protocol. https://modelcontextprotocol.io/specification/2025-11-25/server/tools (accessed 2026-10-19)
3. Pricing — Anthropic. https://platform.claude.com/docs/en/about-claude/pricing (accessed 2026-10-19)
4. Tool search tool — Anthropic. https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool (accessed 2026-10-19)
5. Codex pricing — OpenAI. https://learn.chatgpt.com/docs/pricing (accessed 2026-10-19)
6. Token counting — Anthropic. https://platform.claude.com/docs/en/build-with-claude/token-counting (accessed 2026-10-19)
7. Codex configuration reference — OpenAI. https://learn.chatgpt.com/docs/config-file/config-reference (accessed 2026-10-19)
8. Connect Claude Code to tools via MCP — Anthropic. https://code.claude.com/docs/en/mcp (accessed 2026-10-19)
9. Code execution with MCP: Building more efficient agents — Anthropic. https://www.anthropic.com/engineering/code-execution-with-mcp (accessed 2026-10-19)
