hubagenticai

Compare & Decide Intermediate · 4/12

MCP servers vs. direct CLI calls: when each wins (with measured token costs)

Agents can reach tools through an MCP server or by running CLI commands directly. A decision framework, real token counts for four MCP servers and their CLI equivalents, and what tool search changes.

updated 2026-10-08

Every agent harness can shell out. So why wrap anything in an MCP server at all? Because the two approaches pay different costs in different places, and the break-even point can be measured rather than argued. This piece gives the framework, then the measurements (taken 2026-10-08), then the decision rule.

The trade-off in one table

DimensionDirect CLIMCP server
Setup costZero: the tool already existsWrite + maintain a server (or install one)
Context cost up frontZero if the model already knows the CLITool schemas, unless the client defers them (tool search)
Context cost to learn the tool--help pages, read on demandSchema, already in context or loaded on first use
Output per callWhatever the CLI prints; the model can pick compact flagsWhatever the server returns; fixed by the server author
Error behaviorParse stderr, guess exit codesStructured errors
Reuse across agentsRe-prompt every harnessRegister once per client
Access controlWhatever the shell allowsChoke point you own
AuditabilityShell history, if thatOne log, structured

The token math (framework)

The comparison that matters is total tokens per successful task:

  • CLI path ≈ (discovery: --help output the model reads, if it doesn’t already know the tool) + (retries: malformed flags, stderr round-trips) + (output the command prints).
  • MCP path ≈ (schemas: loaded at session start, or on first use when the client has tool search) + (one structured call per use) + (output the server returns).

The measurements

We counted the tokens in the real tools/list responses of four public MCP servers and in the help text of the CLIs that do the same jobs. Two tokenizers, because counts differ by model family:

  • o200k_base (via tiktoken 0.14.0), the encoding used by OpenAI’s GPT-4o-era models and gpt-oss. Raw text, no request overhead.
  • Claude, via Anthropic’s free token-counting endpoint (messages.count_tokens, model claude-sonnet-5-5), which counts the tools exactly as the API will see them.

Servers: @modelcontextprotocol/server-filesystem 2026.8.31, mcp-server-git 2026.8.18, mcp-server-fetch 2026.8.18, and GitHub’s github-mcp-server v2.0.2 (default toolsets, and with --toolsets all). CLIs: git 2.43.0, gh 2.45.0, curl, and GNU coreutils/findutils/grep on Ubuntu 24.04 (ARM64).

Cost of having the tools available (paid every session)

MCP serverToolso200k tokensClaude tokens, all loaded up frontClaude tokens, deferred behind tool search
filesystem141,9162,7880 (+344 once for the search tool)
git121,4182,0550 (+344 once)
fetch12903730 (+344 once)
GitHub (default toolsets)4613,38319,1090 (+344 once)
GitHub (--toolsets all)9127,68640,0760 (+344 once)

The Claude columns are marginal over a request that already has at least one tool: a request with any tools carries a fixed overhead of about 327 tokens, which we subtracted because every agent harness pays it anyway. “Deferred” means every tool has defer_loading: true and the tool search tool is present. The search tool itself costs about 344 tokens, once, however many servers sit behind it. A deferred tool costs its full schema only after Claude finds and loads it.

Cost of learning the CLI instead (paid only when the model reads it)

CLI help texto200k tokensClaude tokens
git --help509699
git status/diff/log/add/commit/reset/branch/checkout/show -h (9 pages)5,0796,964
gh --help473764
10 gh subcommand --help pages (issue/pr list, view, create, …)3,8805,574
curl --help221304
ls/cat/find/grep/mkdir/mv/head --help16,29823,355

For tools models already know well (git, grep, ls, curl), the honest CLI discovery cost is usually zero: the model just runs the command. Help text matters for less familiar tools, or for flags the model gets wrong.

Cost per call (paid every use)

Same repository, same operation, o200k tokens of what comes back:

OperationMCP (mcp-server-git)CLI
status9895 (git status)
last 5 commits951904 (git log -5), 88 (git log -5 --oneline)
unstaged diff129125 (git diff)

Per call, the two are close. The CLI’s edge is flexibility: the model can choose a compact format like --oneline, while an MCP tool returns whatever its author decided. A well-designed server earns its keep by filtering more than the CLI would (for example, returning three fields instead of a full API object), and a lazily designed one wastes tokens on every call.

What the numbers say

  1. Without tool search, big servers are expensive. Loading GitHub’s default toolsets up front costs about 19,000 Claude tokens per session, before any work. If your agent opens an issue once a week, that is a bad trade, and gh (which models know well) is cheaper.
  2. Small servers are cheap either way. The git server’s full schema (1,418 o200k tokens) costs less than reading three or four git subcommand help pages.
  3. Tool search removes most of the “schemas every session” cost. With deferred loading, an idle server costs nothing, and you pay the schema only for the tools actually used. Claude Code turns tool search on by default for MCP tools: only tool names load at session start (in o200k, about 3 to 4 tokens per tool name for the servers above). The Claude API has the same mechanism (defer_loading plus a tool search tool). Whether your client and model do this varies, so check before you trust the table’s last column.
  4. The CLI still wins when the model already knows the tool and the output is small. Zero setup, zero schema, compact flags.

So the old rule of thumb (“MCP pays its schema cost every session, so infrequent tools favor the CLI”) now depends on the client. With tool search, token cost mostly stops deciding the question, and the other rows of the trade-off table (reuse, access control, auditability) decide it instead.

Reproduce it

Dump a server’s tools with any MCP client (for example, the Inspector’s CLI mode or a few lines of JSON-RPC over stdio) into tools.json, then:

import json, tiktoken  # pip install tiktoken

enc = tiktoken.get_encoding("o200k_base")
tools = json.load(open("tools.json"))["tools"]
schema = json.dumps([{"name": t["name"], "description": t.get("description", ""),
                      "inputSchema": t["inputSchema"]} for t in tools])
print(len(tools), "tools,", len(enc.encode(schema)), "o200k tokens")

For Claude-exact numbers, pass the same tools to client.messages.count_tokens(...) in the anthropic SDK, once with and once without defer_loading: true, and subtract a no-tools baseline. Counts move with server versions: GitHub’s server alone ranges from about 13,000 to 28,000 o200k tokens depending on which toolsets you enable.

The decision rule

Choose direct CLI when: the task is exploratory or one-off; the tool’s interface is stable and well known to models (git, grep, curl, gh); you’re prototyping and the server would be speculation; or your client loads every MCP schema up front and the tool is used rarely.

Choose MCP when any of these is true:

  1. The same operation happens more than a handful of times per session.
  2. Multiple agents or teammates need the same access: write once, register everywhere.
  3. The tool touches anything that needs auth, redaction, or an audit trail.
  4. The raw CLI output is huge and you want the server to filter before it hits context.
  5. Your client has tool search, so idle servers cost almost nothing.

To build one, start with your first MCP server, then wrap a real REST API with validation and redaction. Where MCP tools sit next to skills and hooks in a coding agent is covered in skills vs. tools vs. hooks vs. subagents.

newsletter

One practical agentic-AI guide in your inbox. No news, no hype.

Tutorials and decision frameworks as they ship. Unsubscribe anytime.

Quick Jump: