Skip to main content

MCP vs CLI Is the Wrong Debate — Here's What Actually Matters

· 12 min read
MCPBundles

There's a war happening on Reddit right now, and it's getting heated.

On one side: developers who believe the Model Context Protocol is overengineered middleware — that AI agents should just call gh issue create and curl like any terminal user. On the other: engineers running MCP in production who say the skeptics will inevitably reinvent every feature MCP provides, just worse.

Both sides are partially right. But the debate itself is framed wrong.

I spent the last day using our MCPBundles CLI to search Reddit via MCP tools — browsing posts, pulling comment threads, analyzing arguments — all through authenticated MCP tool calls executed from the command line. The irony was not lost on me: I was using CLI to call MCP to read arguments about whether we need MCP or CLI.

The answer, as it turns out, is both. But not in the way most people think.

The case for CLI (it's stronger than you think)

The most popular post in this debate is a 1,900-upvote manifesto from a former backend lead at Manus titled "I stopped using function calling entirely." His thesis is elegant:

Unix made a design decision 50 years ago: everything is a text stream. LLMs made an almost identical decision 50 years later: everything is tokens. These two decisions, made half a century apart from completely different starting points, converge on the same interface model.

His approach: one run(command="...") tool, all capabilities exposed as shell commands. Instead of choosing between 15 tools with different schemas, the LLM composes a single string it already knows how to write:

cat /var/log/app.log | grep ERROR | wc -l

One tool call replaces three. Not because of special optimization — because Unix pipes natively support composition.

The training data argument is hard to dismiss. LLMs have seen billions of lines of shell commands in their training data — README install instructions, CI/CD scripts, Stack Overflow answers. They're remarkably good at writing CLI invocations. As the top comment put it: "The most powerful agent framework might end up looking exactly like the shell."

Over on r/LocalLLaMA, another post asks the question directly: "Please explain: why bothering with MCPs if I can call almost anything via CLI?" The poster had just discovered MCPorter — a tool that wraps MCP servers back into CLI commands — and was genuinely confused about why anyone would add a protocol layer between the agent and gh issue create.

Fair question. And the Cloudflare team published CodeMode making the same case from a different angle: let the LLM write code that calls tools, rather than using function calling one round-trip at a time. Perplexity's CTO announced they were dropping MCP internally for the same reason.

The CLI crowd has real points. Let's acknowledge them honestly:

  • Training data density. LLMs are trained on shell commands. They're not trained on MCP tool-calling schemas.
  • Composition via pipes. |, &&, || give you workflow composition for free.
  • Progressive discovery. --help is a pattern the model already knows.
  • Context efficiency. One run() tool description vs. fifteen tool schemas burns fewer tokens.
  • Simplicity. For a single developer on a single machine, gh is faster than a GitHub MCP server.

A 693-upvote post titled "I spent 3 weeks building my dream MCP setup and honestly, most of it was useless" backs this up with hard numbers. The author set up 15 MCP servers and ended up using four. Monthly API costs went from $40 to $120 before they trimmed. The top comment: "I stopped using the GitHub MCP and just use gh cli. My agent is much better with the cli vs the mcp."

These aren't uninformed takes. They're experience reports from people who tried MCP maximalism and found diminishing returns.

Where the CLI argument falls apart

But there's a 157-upvote comment on the "eulogy for MCP" post that captures what the CLI crowd consistently misses:

People who claim that there's no need for MCP will, if they build projects of growing complexity, sooner or later reinvent everything MCP provides, but in a non-standardized fashion bespoke to their project.

Another commenter puts it bluntly: "People saying MCP is dead are not software engineers. You want: 1) Auth, ideally via standardized OAuth. 2) Servers to declare their capabilities dynamically. If you need neither of these, then sure use a CLI."

The highest-voted comment on the "I genuinely don't understand the value of MCPs" thread (125 upvotes) lays out the actual production requirements that CLI can't solve:

MCP solves for structured discovery — what's available and what params are needed. It guarantees execution the same way every time. It controls the shape and size of data returned to the AI. It provides authentication layers without exposing database credentials. For my clients, they need a centralized set of tools for all of their AI systems to call so they can authenticate and access internal APIs, databases, etc.

Let's break down where CLI genuinely can't compete:

Authentication at scale

This is the killer feature and it's not close. gh issue create works because you've already run gh auth login on your machine. But what about Stripe? HubSpot? Salesforce? PostHog?

Each service has its own auth mechanism — OAuth 2.0 with different flows, API keys with different header formats, refresh token rotation, PKCE, client credentials grants. A CLI approach means the agent needs access to raw credentials, or you need to build and maintain auth wrappers for every service.

MCP centralizes this. One protocol, one auth layer, one place to manage credentials for 500 services. The agent never sees an API key.

Schema enforcement

When an LLM writes curl -X POST https://api.stripe.com/v1/charges -d amount=2000, it's composing a string. If it hallucinates a parameter name, you get a runtime error. If it forgets a required field, you get a runtime error. If it sends the wrong type, you get a runtime error.

MCP provides JSON Schema for every tool input. Modern LLM runtimes use constrained decoding — they convert the schema into a grammar that forces the model to generate only valid tool calls. The model literally cannot produce a syntactically invalid invocation. As one commenter noted: "CLI tools return unstructured text that the model has to parse. MCP gives you structured inputs and outputs. Less ambiguity means fewer hallucinated interpretations."

Controlled response shape

APIs return whatever they return. A Jira API response is 200 lines of nested JSON. Most of it is irrelevant to the agent's task, but it all burns context tokens.

A well-designed MCP tool transforms the response before returning it — extracting the fields that matter, formatting them for the model, trimming the noise. As the top-voted comment on the CLI question put it: "API provides 'get last 10 tickets' to verbose JSON. MCP should provide a markdown processed version of important keys in a digestible way."

Enterprise distribution

"A major MCP advantage in enterprise is that MCP can be created once as a remote server with auth support and control," wrote one commenter. "No package installs. No custom CLI instructions. No necessary CLI configuration. Just copy paste the MCP config to your mcpServers.yaml with your API key and you are all set."

Distributing CLI tools to a team of 50 means 50 install scripts, 50 auth configurations, 50 environment-specific setups. An MCP server is one URL.

Security boundaries

The most darkly funny comment in the entire debate (138 upvotes): "OP's post is a psyop to give your LLM agent full rights to your terminal."

It's a joke, but it identifies a real problem. Giving an agent run(command="...") means giving it a shell. A shell that can rm -rf /, curl your credentials to a remote server, or DROP TABLE users. The Manus post acknowledges this — their solution is sandbox isolation, API budgets, and user cancellation buttons.

MCP provides a narrower interface by design. The agent can call stripe_list_charges but it can't execute arbitrary code on your machine. The tool boundary is the security boundary.

The real answer: composable tools with coordinated execution

Here's what both sides miss. The debate is framed as MCP or CLI, as if you have to pick one interface for everything. But the actual breakthrough is using MCP for what it's good at — authenticated, schema-enforced access to external services — and giving the agent CLI-like composition for orchestrating those tools.

This is exactly what code_execution does on MCPBundles. Every bundle includes a code_execution tool that lets the agent write Python code calling any authenticated MCP tool in the bundle — with in-memory variables, conditional logic, error handling, and multi-step sequencing. The MCP tools handle auth and schema. The code handles composition.

Here's what that looks like in practice. You tell the AI — in ChatGPT, Claude, Cursor, Claude Code, wherever you've connected MCPBundles:

"Check if tony@example.com has any failed Stripe charges. If they do, create a Linear ticket with the details."

The AI writes and executes this in a single code_execution call:

customers = await stripe_search_customers(bundle="stripe", query="email:'tony@example.com'")
customer_id = customers["data"][0]["id"]

charges = await stripe_list_charges(bundle="stripe", customer=customer_id, limit=10)
failed = [c for c in charges["data"] if c["status"] == "failed"]

if failed:
await linear_create_issue(
bundle="linear",
title=f"Customer {customer_id} has {len(failed)} failed charges",
description=f"Failed charge IDs: {', '.join(c['id'] for c in failed)}"
)

Or if you're in a terminal — Cursor, Claude Code, Codex, any agent with shell access — the same prompt produces the same coordinated execution via the MCPBundles CLI:

mcpbundles exec -f /tmp/check_failed_charges.py

Same code_execution under the hood. Same authenticated MCP tools. Same in-memory variables and conditional logic. The interface is different — MCP tool call vs. shell command — but the execution model is identical.

One natural language prompt. Three services. Five API calls. Conditional logic. In-memory variable passing. One LLM round-trip. The user never writes code — the AI does, and the MCP tools handle auth for each service transparently.

This is the exact pattern Cloudflare's CodeMode promotes — let the LLM write code, not individual function calls — but with MCP providing the authenticated tool layer underneath. You get Unix-pipe-style composition without giving the agent a raw shell. You get structured tool schemas without the round-trip overhead of one-tool-at-a-time function calling.

The Manus post's best insight was that "N commands x 4 operators — the composition space grows dramatically." Code execution gives you the same composition space — variables, conditionals, loops, error handling — without the security footgun of a raw shell.

What "I stopped using MCP" actually means

When Perplexity's CTO says they dropped MCP internally, or when someone writes "I just use gh cli," they're describing a specific scenario: a single developer, on their own machine, with tools they've already installed and authenticated, building something for themselves.

In that scenario, CLI is genuinely better. Less overhead, more familiar, better model performance on known commands. Nobody should set up an MCP server to check the weather.

But the posts with the most nuanced takes consistently identify the inflection point. From the r/mcp thread:

CLI works fine when YOU are the orchestrator. You know what tools exist, you write the glue. But MCP lets an agent discover available tools at runtime, call them through a standard interface, and chain them without you hardcoding every integration.

Or more concisely:

For a single script running locally? CLI is simpler. For a system of agents? MCP removes a huge maintenance burden.

The debate isn't about which protocol is theoretically superior. It's about what you're building and who it's for.

How this blog post was researched

This isn't hypothetical. I researched this entire article using MCPBundles' Reddit tools via the CLI:

mcpbundles call search-posts-2e1 --bundle reddit -- \
query="MCP vs CLI tools AI agents" limit:=10 sort="relevance"

mcpbundles call get-post-details-2e1 --bundle reddit -- \
post_id="1rw7z6l" sort="top" limit:=15

mcpbundles call get-post-details-2e1 --bundle reddit -- \
post_id="1s41ltp" sort="top" limit:=15

CLI syntax, calling MCP tools, authenticated via OAuth to Reddit's API, with structured JSON responses I could analyze across posts. The MCP server handled Reddit's OAuth token refresh and rate limiting. The CLI gave my AI agent a familiar interface to compose searches and drill into threads.

That's the point. It was never MCP or CLI. The question is how they compose.

The posts that shaped this article

If you want to read the source material yourself:

PostSubredditScoreComments
I stopped using function calling entirelyr/LocalLLaMA1,927400
I spent 3 weeks building my dream MCP setupr/mcp693116
A eulogy for MCP (RIP)r/mcp311202
I don't understand the value of MCPsr/mcp257126
Perplexity drops MCP, Cloudflare explains whyr/mcp23946
Why bother with MCPs if I can call anything via CLI?r/LocalLLaMA9890

The combined engagement across these six posts: 3,525 upvotes and 980 comments. This isn't a niche disagreement. It's the central question of how AI agents should interact with the world.

The answer is that MCP and CLI aren't competing interfaces — they're complementary layers. MCP solves auth, schema, discovery, and governance. CLI solves familiarity, composition, and developer ergonomics. Code execution bridges them, giving you structured tool access with programmatic composition in a single round-trip.

The developers who are most productive aren't the ones who picked a side. They're the ones who use both.