Architecture diagram comparing CLI-first tools versus MCP protocol abstraction layers
Engineering

CLI-First vs MCP: Choosing Your AI Agent Architecture

By Agents Squads · · 7 min

TL;DR — MCP won the standards war (97M downloads, 10K+ servers), but that doesn’t mean every tool belongs behind the protocol. After migrating most of our tooling, we landed on 80% CLI / 20% MCP. Use CLI for stateless, auditable operations; reserve MCP for stateful integrations, cross-platform distribution, and complex OAuth flows.

MCP Won. The Question Is Whether You Need It.

Model Context Protocol won the standards war. 97 million monthly downloads, 10,000+ available servers, Linux Foundation governance, and every major cloud provider signed on as a platinum member. When your competitors join your standards body, the debate is over. MCP is infrastructure now — the “HTTP of agentic AI.”

So why are we writing a comparison piece?

Because winning the standards war doesn’t mean every tool belongs behind the protocol. We migrated most of our agent tooling away from MCP over the past year, and the experience taught us something the ecosystem doesn’t talk about enough: the right architecture depends on what each tool actually does, not on which protocol is trending. This article is a decision framework for teams making that choice. We’ve written separately about CLI-first architecture patterns and why we lean toward CLI — here, we’re focused on helping you decide which approach fits each tool in your stack.

What MCP Costs You

MCP adds a layer between your agent and its tools. Without it, the path is simple: the agent issues a shell command, the shell executes it, and the result comes back. With MCP, the agent talks to an MCP client, which speaks the protocol to an MCP server, which invokes the underlying tool, then the result travels the whole chain in reverse. That indirection is the price of abstraction, and it buys you real things — but you should know what you’re paying.

The first cost is transparency. A shell command like curl -s "https://api.example.com/data" -H "Authorization: Bearer $TOKEN" tells you exactly what’s happening. You can read it, copy it, run it manually, pipe it into other tools. An MCP tool invocation like {"tool": "fetch_data", "params": {"endpoint": "data"}} hides the HTTP method, the headers, the error handling, and the retry logic inside a server you’d need to read the source code to understand.

The second cost is operational overhead. MCP servers are processes. They need starting, stopping, health monitoring, credential management, version updates, and security audits. For teams already stretched thin on ops, each additional server is friction. For teams without dedicated ops, it can be a blocker.

The third cost is context window consumption. Every MCP tool registers itself with a name, a description, and a full JSON input schema. Multiply that across dozens of tools and you’re burning thousands of tokens on tool descriptions before any actual work begins. A bash command, by contrast, costs only the tokens in the command string itself.

None of these costs are deal-breakers. They’re tradeoffs. The question is whether what you get back justifies them for a given tool.

Key Takeaway — MCP’s three hidden costs are transparency (you can’t read tool calls without source-diving), operational overhead (servers need monitoring, credentials, updates), and context window consumption (tool schemas burn thousands of tokens before work begins).

What CLI-First Gives You

CLI-first architecture means your agents invoke shell commands directly — gh issue list, supabase db execute, curl, playwright screenshot — rather than routing through protocol servers. The advantages flow naturally from the directness.

Every command is readable. You can grep shell history to see every API call your agent made last Tuesday. When something fails, the error is a shell error with an exit code, not a protocol mystery buried three layers deep. There are no servers to manage — tools invoke on demand and exit when done. And the tooling is already familiar: developers know bash, curl, and jq. There’s no new abstraction to learn.

When a CLI tool doesn’t exist for something you need, the pattern is straightforward — write a wrapper script:

#!/bin/bash
# .agents/tools/api-query.sh
API_KEY="${API_KEY:?API_KEY required}"
API_HOST="${API_HOST:-https://api.example.com}"

curl -s -X GET "${API_HOST}/$1" \
  -H "Authorization: Bearer ${API_KEY}" \
  -H "Content-Type: application/json"

The agent calls ./.agents/tools/api-query.sh "users/123" and gets back JSON. Readable, auditable, no server required.

Where MCP Earns Its Keep

We’re not absolutists. MCP is genuinely better for certain categories of tools, and pretending otherwise would make this a worse decision framework.

Stateful integrations are the clearest win for MCP. Some tools require persistent connections — WebSocket subscriptions for real-time data, OAuth flows with automatic token refresh, or long-running database transactions. Shell commands are inherently stateless: they start, execute, and exit. If your tool needs to hold a connection open or remember something between invocations, MCP servers handle that naturally in a way that’s awkward to bolt onto shell scripts.

Cross-platform portability matters if you’re building tools for others. A single MCP server works identically across Claude Code, Cursor, Cline, and VS Code extensions. CLI scripts may need platform-specific variants for Windows versus Unix, or may depend on tools that aren’t installed everywhere. If your audience is diverse, MCP’s abstraction pays for itself.

Ecosystem leverage is a practical argument. With 10,000+ MCP servers available, someone has likely already built the integration you need for Slack, GitHub, or your database. Using an existing server is often faster than writing and maintaining a CLI wrapper, especially for complex APIs.

Enterprise governance is the final case. Some organizations need centralized tool governance, rate limiting, usage analytics, or approval workflows around what agents can do. MCP servers can implement these controls at the protocol level. Bare CLI tools leave that responsibility to the calling environment.

The Decision Framework

Rather than a rigid matrix, we’ve found it more useful to ask three questions about each tool:

Does this tool need persistent state? If the answer is yes — it holds connections, manages sessions, or caches data between calls — MCP is the natural fit. If the tool is stateless (most are), CLI is simpler.

Does a good CLI already exist? Tools like git, gh, psql, aws, gcloud, kubectl, and supabase already have excellent command-line interfaces. Wrapping them in MCP adds a layer without adding capability. On the other hand, if the only way to interact with a service is through a complex REST API with pagination and auth token juggling, an MCP server might genuinely simplify things.

Who needs to consume this tool? If it’s your own agents, CLI is fine — you control the environment. If you’re distributing tools to other teams or to the open-source ecosystem, MCP’s standardized interface makes consumption easier across different agent frameworks.

Most tools fall clearly on one side. For the edge cases, we default to CLI and upgrade to MCP only when we hit a concrete limitation — not a theoretical one.

Important — Default to CLI and upgrade to MCP only when you hit a concrete limitation. The three deciding questions: Does it need persistent state? Does a good CLI already exist? Who needs to consume this tool?

Migrating Without Breaking Things

If you’re currently running MCP servers and want to simplify, the migration doesn’t need to be dramatic. Start by auditing your MCP servers. For each one, note whether it needs persistent state, whether a CLI equivalent exists, and how frequently your agents call it. Low-frequency, stateless tools with CLI equivalents are your first candidates.

Then replace them one at a time. Write a shell script or identify the existing CLI tool that does the same thing. Test for parity — the output should match what the MCP server was producing. Once you’re confident, remove the MCP server registration from your agent configuration and add the CLI tool to its available commands.

# Before: MCP server handles database queries
# After: direct CLI call
supabase db execute --project-ref "$PROJECT" "$SQL"

After each replacement, monitor for changes in latency, error rates, and developer experience. CLI should be faster for simple operations — if it’s not, that’s a signal worth investigating.

Once you’ve migrated the easy targets, you’ll have a clear picture of which MCP servers genuinely earn their keep and which were adding complexity without adding value. Keep the ones that matter. For most teams, that’s a small number.

The Deeper Choice

The CLI-vs-MCP decision reflects a philosophical split in how you think about agent architecture.

MCP’s thesis is that abstraction enables reuse. Standardize the interface, and you can swap implementations, share tools across frameworks, and build an ecosystem. This is a powerful idea, and it’s why MCP won the standards war.

CLI-first’s thesis is that transparency enables trust. See exactly what your agent does, debug without layers, and use the same tools your developers already know. This matters most when you’re running agents in production and need to understand — quickly — what went wrong.

We’ve landed on a hybrid. Our critical-path tools are CLI scripts, where we need maximum transparency and minimal overhead. Complex integrations that genuinely benefit from abstraction run through MCP. And for commodity integrations where someone’s already built a solid MCP server, we use the ecosystem rather than reinventing.

Our Data — After migrating, our tooling split landed at roughly 80% CLI and 20% MCP. The MCP servers that survived are stateful integrations (OAuth, WebSockets) and commodity ecosystem servers where someone else maintains the code.

The distribution, in our experience, works out to roughly 80% CLI and 20% MCP. Your ratio will depend on your team’s ops capacity, your audit requirements, and how much of your tooling is stateful. But if you’re running MCP servers for simple, stateless operations like git commands, file searches, or straightforward API calls, you’re probably paying the abstraction tax without getting much in return.

MCP won the standards war. That doesn’t mean every tool needs to be an MCP server. Use the right abstraction for the right job.


Note: This represents one team’s architectural choices. MCP is excellent infrastructure. The question isn’t whether MCP is good — it’s whether you need it for a specific tool.

Related Reading

Back to Engineering