The abstraction tax: MCP versus a plain CLI.

You connect ten MCP servers to an agent and it has spent tens of thousands of tokens before you type a word. A CLI does the same job in eighty. Here is why the simplest interface - a binary you can also run yourself - is quietly winning, and the one place MCP still earns its keep.

Open a fresh agent session, connect the ten MCP servers your team has standardized on, and watch the token counter before you have typed a single instruction. It is already deep into five figures. The servers loaded every tool they expose - names, descriptions, JSON schemas, enum values, field-level docs - straight into the model’s context, and they did it eagerly, all of them, whether or not this particular task will touch a single one. You are paying rent on capability you are not using. That is the abstraction tax, and once you see it you cannot unsee it: the Model Context Protocol buys you a tidy integration story by charging your context window up front, on every request, forever.

The uncomfortable part is that this is not a hot take from a skeptic. It is the position of the people who built the thing.

The context tax is real, and the protocol’s own steward admits it

Anthropic’s engineering post Code execution with MCP says it plainly: “Tool descriptions occupy more context window space, increasing response time and costs,” and “in cases where agents are connected to thousands of tools, they’ll need to process hundreds of thousands of tokens before reading a request” (Anthropic). It gets worse mid-task, because the wire is chatty by design: “every intermediate result must pass through the model.” Pull a document to hand it to another tool and the full payload flows through context twice. Their own worked example - a Google Drive to Salesforce sync - drops from 150,000 tokens to 2,000 once the same work is expressed as code instead of a chain of tool calls, “a time and cost saving of 98.7%.”

Sit with that number for a second. A 98.7% reduction is not an optimization. It is an admission that the default path was spending fifty times what the task required.

Figure - Tokens spent before the first instruction, as you add tools
Connected tools: Tokens / tool schema:
Drag Connected tools and watch the MCP bar climb past 100k while the CLI entrypoint stays flat near the floor. MCP loads every schema up front; a CLI advertises an ~80-token entrypoint and discovers the rest on demand via --help. Switch the per-tool weight to see how fast the tax compounds.

The fix Anthropic shipped tells the same story. The Tool Search Tool marks definitions defer_loading: true so they are not loaded into context until the model asks for them - the agent boots seeing only a lightweight search interface and fetches a schema on demand. This very page was written by an agent running that exact mode: most of its tools arrived as names only, their full schemas deferred until needed. That is the protocol quietly walking back its founding move. Load-everything-upfront was the whole ergonomic promise of MCP, and the newest guidance is: please, do not do that.

Read the fix as a verdict: When the answer to “why is my agent slow and expensive” is stop loading the tool definitions, the tool definitions were the problem.

A CLI is the same capability with fewer layers

Strip the diagram back to what actually happens and MCP is a wrapper around a call you could already make. A curl hits an API in two hops: your process speaks HTTP, the API answers. A CLI adds one - your process runs a binary, the binary speaks HTTP. MCP adds a small stack: the host spins up a client, the client opens a stateful JSON-RPC 2.0 channel over stdio (spawning the server as a child process) or over HTTP, the server translates that into the same API call underneath (modelcontextprotocol.io). Every one of those layers is a place to configure, version, break, and debug. The API at the bottom never changed.

Figure - The same API call, wrapped in three different amounts of machinery
Press Send a call and watch one request travel each path to the same API at the far right. cURL takes two hops; the CLI adds a binary; MCP threads a client, a JSON-RPC transport, and a server in between. Notice which packet arrives last - every extra layer is latency and one more thing to debug.

That extra indirection shows up on the invoice. A benchmark from Apideck found MCP “costing 4 to 32x more tokens than CLI for identical operations” - a simple repository language check ran to 1,365 tokens through a CLI and 44,026 through an equivalent MCP server (Apideck). The mechanism is not mysterious. A CLI discovers itself the way a human does: tool --list costs about twenty tokens, tool accounting --list about two hundred, tool accounting invoices create --help about a hundred and fifty. You pay for the branch you actually walk down. MCP pays for the entire tree before you have decided where to go.

MCP server

  • Loads every tool schema into context up front
  • Needs a host that speaks the protocol
  • Intermediate results round-trip through the model
  • Debug across host, client, transport, and server

Plain CLI

  • Discovers itself on demand via <code>--help</code>
  • Runs anywhere a shell does
  • Pipes data between commands without touching the model
  • Debug one binary you can run by hand

Reach: a binary runs anywhere a shell does

Here is the part that makes the abstraction feel like a cage. An MCP server is only useful inside a host that implements an MCP client. A CLI is useful everywhere. As Apideck put it, “every serious agent framework ships with ‘run shell command’ as a primitive” - which means the same binary works in Claude Code, in Cursor, in Codex, in a bespoke agent you wrote last week, in a CI job, in a cron entry, and in your own terminal at 2am when you are debugging the agent’s mess. You write the capability once and every caller that can spawn a process gets it for free, no protocol adapter required. MCP asks each of those callers to speak a specific dialect first. Tools that only your one favored host can reach are tools you will regret the day you switch hosts.

The honest downside: authentication

None of this makes CLIs a free lunch, and the place they genuinely hurt is credentials. An MCP server, running as a long-lived process you configured once, has a natural home for a secret. A CLI invoked fresh on every call has to find its credential somewhere, and “somewhere” is exactly where secrets management gets awkward.

Local
Keychain
On a workstation this is fine - macOS Keychain, <code>libsecret</code>, a gitignored dotfile with tight permissions. The binary reads it on startup.
Session
Env var
Injected per invocation, never written to disk. Clean until you have twenty tools each wanting a different variable spelled a different way.
Cloud
The hard case
An ephemeral sandbox with no keychain and no persistent home is where a plain CLI has no good answer, and a brokered, short-lived token is the only sane option.

This is the real trade, stated honestly. If your agents run in disposable cloud environments and every tool needs its own long-lived secret, a server that holds credentials and brokers access is doing something a bare binary cannot. It is worth naming, because most of the MCP-versus-CLI debate skips it. Just notice how narrow the win is: it is an authentication convenience, not an argument for shipping your entire tool surface through a protocol that taxes every request.

Distribution is already a solved problem

The other objection to CLIs is shipping. A server you host once; a binary you have to get onto every machine, and machines come in flavors. This was a real cost fifteen years ago. It is close to free now if you pick the right language. Go cross-compiles from a single codebase to a single statically linked binary for Linux, macOS, and Windows across amd64 and arm64 - set GOOS and GOARCH, build, done, no runtime to install and no dependency tree to resolve on the target. You publish a handful of artifacts to a release page and every agent, CI runner, and laptop pulls the one that matches. The distribution “overhead” is a build matrix you write once, and it buys you something MCP never offers: a tool a human can also just download and run.

Security cuts the other way too

The strongest security argument actually favors the binary. In a CLI, the permission logic lives in the code - GET auto-approves, POST asks, DELETE is blocked unless a flag says otherwise - and that logic runs identically no matter what the model was talked into. Apideck makes exactly this point: enforcement in the binary holds “regardless of prompt injection attempts.” Move that gate up into prompt-mediated tool descriptions and you have made your authorization boundary a thing an attacker can argue with in natural language.

And the ambient risk is worse than it sounds. As we wrote in June, MCP crossed thousands of public servers with most shipping no auth story at all - an agent with tool access and a connected server is a privileged process pulling from endpoints nobody is reviewing. A CLI you compiled and pinned has a provenance you control. A server someone stood up and you connected to does not.

Where the authorization boundary belongs: In compiled code that runs the same way every time, not in a tool description the model can be persuaded to reinterpret.

So where does this land

I do not think MCP disappears tomorrow. JSON-RPC over stdio is a perfectly reasonable wire, and as plumbing between a host and a trusted local process it will stick around. What I think is already dying is the ergonomic premise that sold it: connect a server, dump its whole schema into the model, and let the abstraction sort it out. The people who built MCP are the ones shipping the escape hatches - tool search, deferred loading, code execution - and every one of those hatches moves the design back toward “let the model call a program and read only what it asked for.” Which is a CLI. The industry spent eighteen months wrapping APIs in a protocol, and the frontier labs are now spending their engineering posts explaining how to un-wrap them.

If you are choosing today, the boring answer is usually right. Ship the capability as an API. Wrap it in a CLI so an agent - any agent - and a human can both drive it. Reach for an MCP server only when you have a specific reason the protocol earns its tax, and know going in that the reason is almost always authentication, not ergonomics. Build the thing you can also run yourself.

Manual checklist - 10 things to verify yourself

  1. Measure your cold-start token cost. Open an agent with your MCP servers connected and read the token count before you send a message. If it is five figures, that is your daily tax.
  2. Confirm deferred loading is on. If your host supports Tool Search / defer_loading, verify your tools are actually deferred and not loaded eagerly.
  3. Count the hops. For one real capability, trace the call: cURL to API, or agent to client to transport to server to API. Fewer layers is fewer failure points.
  4. Try the CLI portability test. Take one tool and run it from a second agent (or a plain shell). If it only works inside one host, you have coupled yourself to that host.
  5. Locate your credential. For each CLI-style tool, write down exactly where its secret comes from - keychain, env, broker - and whether that source exists in your cloud runtime.
  6. Check the cloud-sandbox path specifically. If agents run in ephemeral environments, confirm secrets arrive as short-lived brokered tokens, not baked-in long-lived keys.
  7. Verify the permission gate is in code. Confirm your destructive operations are blocked by the binary’s own logic, not by a sentence in a tool description a model could reinterpret.
  8. Audit connected MCP servers for auth. List every server your agent can reach and confirm each one actually authenticates. Assume the ones that do not are readable by anyone.
  9. Pin and review tool provenance. For every binary and server, confirm you know who built it and that the version is pinned - the same supply-chain hygiene you would apply to any dependency.
  10. Run the un-wrap thought experiment. For your most-used MCP server, ask what breaks if you replaced it with a CLI over the same API. If the honest answer is “only the auth,” you have your decision.
Work with us

Production AI, with guardrails.

Start with a fixed-scope AI Workflow Audit. We map the opportunity and quote a build.

Start a Discovery Sprint