All posts

The Right Tool for the Loop

For most of computing’s history, software reached the world through two separate doors. Machines talked to machines through APIs — rigid contracts, no improvisation. People drove terminals by hand — forgiving, discoverable, built for someone who could read an error and try again.

An autonomous agent is neither, and it needs both. It has to call a billing API with the precision of a machine and recover from a failed shell command with the patience of a person. Embedding that agent so it can touch cloud services, data systems, external APIs, and the operating system itself — securely, without a human at the keyboard — is now the central problem of integration design.

Two patterns have emerged to solve it. The Model Context Protocol (MCP) wraps tools in a structured, negotiated schema. The command line (CLI) hands the agent a shell and lets it type. The instinct is to ask which one wins.

The question was never which protocol wins. It’s which loop you’re in.

Two answers to the same problem

The old division was clean: APIs for machines, terminals for people. Agents erase the line between them, and the two patterns that fill the gap sit at opposite ends of a spectrum. One negotiates a typed contract before it acts. The other starts typing and learns as it goes.

Two panels. Left, the Model Context Protocol: a Host (LLM app) connects through a Client to a Server exposing Resources, Prompts, and Tools over JSON-RPC. Right, the command-line interface: an Agent exchanges stdin, stdout, and stderr with a shell subprocess.
Two ways an agent reaches the world: structured negotiation, or raw streams.

Structured negotiation versus probabilistic execution

MCP front-loads the work. The host reads a server’s declared capabilities — its resources, prompts, and tools — as a strict schema, and only then lets the model act. Every call is a typed, validated message over JSON-RPC. Nothing happens that the schema did not describe in advance. The result is predictable and machine-checkable, paid for by declaring everything up front.

The CLI does the opposite. The agent starts blind. It reads a --help output or a man page, guesses a command, runs it, reads stdout, and adjusts — the same loop a developer runs, at machine speed. Nothing is declared ahead of time; the interface is discovered by trying it. The result is flexible and forgiving, paid for by being probabilistic.

The context tax

That up-front schema is not free. To act through MCP, the model has to carry the tool definitions in its context window — and reload them, in full, on every call. For a handful of tools this is invisible. For a real toolset it is a standing cost: in browser-automation benchmarks, the same task run through MCP consumed several times the tokens of a lean CLI invocation, most of it schema and state the model re-reads before it can begin to think.

MCP pays a context tax on every call. The CLI pays once, then forgets.

The cost compounds. As an agent works through a long task, accumulated schemas and intermediate state pile up in the window. Within the first few dozen steps the context can saturate — and a saturated model starts to lose the thread, repeat itself, or trap itself in loops. A stateless CLI invocation has nothing to accumulate. Each call runs in isolation and hands the window back clean, which is why CLI-driven agents tend to hold their precision over long, multi-step runs.

Two horizontal bars of equal length. The MCP bar is almost entirely consumed by schema and state reloaded on every call, leaving little room for reasoning. The CLI bar spends only a small slice on the invocation, leaving most of the window for reasoning.
Every MCP call re-loads the schema; the CLI invocation stays lean.

The inner loop and the outer loop

This is where the real distinction lives — not in which protocol is better, but in which kind of work the agent is doing.

The inner loop is the tight cycle of building: write code, run it, read the failure, fix it, repeat. It is fast, local, and unforgiving of latency. Here the CLI dominates. It is stateless and token-cheap, so the loop stays fast. Models already know the standard tools — pytest, cargo, eslint — from training, so there is nothing to declare. And the feedback is immediate: run the command, read raw stdout, correct, go again, without ever dropping context.

The outer loop is the wider cycle of operating: deploying across systems, enforcing compliance, orchestrating work that spans services and teams. Here MCP dominates. It holds credentials at the server level, so authentication is unified across platforms. Its output is structured and typed, which is what cross-system orchestration needs. And in locked-down hosts — environments like Claude Desktop that deliberately expose no raw shell — MCP is often the only sanctioned route to the outside world at all.

Two tangent rings. The left ring, marked CLI, is the inner loop: fast, local, code, debug, and test. The right ring, marked MCP, is the outer loop: distributed, CI/CD, and compliance. A small square marks the bridge where the loops meet.
CLI owns the inner loop; MCP owns the outer loop.

Match the interface to the loop, not the loop to the interface.

Security cuts both ways

The two architectures fail safe in opposite directions.

MCP is safe by construction. The model can only call what the schema declared, with arguments of the types it specified — there is no way to express an action that was not pre-declared. Hosts layer governance on top: allowlists, denylists, and approval modes that range from automatic, to asking the user, to requiring an administrator. The execution paths are narrow and typed, which makes them hard to subvert through a prompt-injection attack.

Raw CLI access is the opposite. Hand a probabilistic agent a shell and you have handed it the whole machine — including the one hallucinated token that turns a cleanup command into rm -rf /. You cannot ship that. Terminal access for an agent demands a layered harness around it: an allowlist of permitted commands, a dry-run pass that simulates before it executes, and a sandbox — a container or VM — so that even a mistake is contained long before it can reach the host.

Exposing a raw shell to a probabilistic agent hands it a loaded rm -rf /.

A five-stage pipeline guarding raw command-line access: raw model output passes through an allowlist, a dry-run, and a sandbox before it is allowed to reach the host operating system.
Raw shell access needs a layered harness before it reaches the host.

The trade-offs line up cleanly once you set them side by side.

Model Context Protocol (MCP)Command line (CLI)
Overhead per callHigh — full schema loaded each requestNear zero — isolated subprocess
StateNative — persistent server sessionsStateless — full isolation
OutputStructured, validated JSONPlain text, or JSON behind a flag
SafetyPre-validated, typed boundariesHigh-risk — needs an external harness
AuditabilityIndirect — JSON-RPC trafficDirect — stdout logs and exit codes

The synthesis: AI-first CLIs

Stated as a binary — efficiency or safety, flexibility or structure — the choice looks forced. It is not. The interesting designs refuse it.

What architects actually want is the token efficiency and discoverability of the CLI together with the structured output and safety of MCP. A new class of “AI-first” command-line tools is built for exactly that. Instead of pre-loading a massive schema, the agent reads a lightweight skill file — a short Markdown description of what the tool can do. It runs a targeted command. The tool discovers its own capabilities at runtime rather than forcing them into the model’s context up front, sanitizes the response, and returns clean, structured JSON. The model gets machine-readable output without ever paying the full schema tax.

Google’s gws — a command-line tool for Google Workspace — is an early example of this direction: a CLI meant to be driven by both people and agents. Treat the specifics as illustrative of a pattern rather than a settled standard; the shape of the idea is what matters. Discover capability at runtime, emit structured data behind a --json flag, and keep the context lean.

A five-stage AI-first CLI flow: a lightweight skill file leads to a targeted command, runtime capability discovery, output sanitization, and finally structured JSON returned to the agent.
AI-first CLIs discover capability at runtime instead of pre-loading a schema.

The strongest systems don’t choose. They wrap command-line efficiency in machine-readable structure.

What to actually do

None of this resolves into a single winner, because there isn’t one. There is a continuum, from pure CLI to pure MCP, and a few rules for placing yourself on it.

Match the interface to the loop. Reach for the CLI in the inner loop, where speed and token economy decide whether the agent is usable at all. Reach for MCP in the outer loop, where state, governance, and structured output decide whether it is safe to operate.

Budget for the context tax. Schema overhead is real and it compounds. When it starts to crowd the window, that is the signal to move toward runtime-discovery tools — not to load more definitions.

Treat shell access as non-negotiable on security. Either lean on MCP’s typed boundaries, or wrap the terminal in a strict harness. There is no responsible third option.

Expect convergence. The strongest agentic systems already use both, wrapping familiar command-line efficiency inside machine-readable, schema-driven output. The future is not MCP or CLI. It is the right tool for the loop.