One key aspect that is missed here, is mobile users.
iOS don't have a CLI, Android phones... kinda have a CLI, but it's not really usable by all apps / universal like it is on desktop.
I've been putting together a MCP client for mobile recently [1] since to me it seems apparent that Remote MCP is a great utility but none of the major players offer it without a paid subscription.
As other commenters have mentioned, the use case here is really not for software developers, it's for everyone else. It's bringing that agentic loop to do all those "personal assistant" type things in a connected way with all of your services. We're not there yet, but maybe some day.
MCPs (especially remote MCPs) are like a black box API -- you don't have to install anything, provision any resources, etc. You just call it and get an answer. There's a place for that, but an MCP is ultimately a blunt instrument.
CLI tools on the other hand are like precision instruments. Yes, you have to install them locally once, but after that, they have access to your local environment and can discover things on their own. There are two CLIs are particularly powerful for working with large structured data: `jq` and `duckdb` cli. I tell the agent to never load large JSON, CSV or Parquet files into context -- instead, introspect them intelligently by sampling the data with said CLI tools. And Opus 4.6 is amazing at this! It figures out the shape of the data on its own within seconds by writing "probing" queries in DuckDB and jq. When it hits a bottleneck, Opus 4.6 figures out what's wrong, and tries other query strategies. It's amazing to watch it go down rabbit holes and then recovering automatically. This is especially useful for doing exploratory data analysis in ML work. The agent uses these tools to quickly check data edge cases, and does a way more thorough job than me.
CLIs also feel "snappier" than MCPs. MCPs often have latency, whereas you can see CLIs do things in real time. There's a certain ergonomic niceness to this.
p.s. other CLIs I use often in conjunction with agents:
`showboat` (Simon Willison) to do linear walkthroughts of code.
`br` (Rust port of Beads) to create epics/stories/tasks to direct Opus in implementing a plan.
`psql` to probe Postgres databases.
`roborev` (Wes McKinney) to do automatic code reviews and fixes.
It seems that the author thinks that AI use is limited to developers, I don't understand how short slighted is the debate between CLI and MCP. Sure, CLI are more convenient, but currently most AI users consume LLM through online tools like ChatGPT
A basic example: a company using ChatGPT or Claude, and wanting to connect their business tools (ex: marketing, sales, project management...). in that case MCP is perfect from an enterprise point of view, and the integration can be managed at the company level.
There is nothing wrong with MCP, it's just that stdio MCP was overengineered.
MCP's Streamable HTTP with OAuth discovery is the best way to ship AI integration with your product nowadays. CLIs require sandboxing, doesn't handle auth in a standard way and it doesn't integrate to ChatGPT or Claude.
Look at Sentry, they just ship a single URL https://mcp.sentry.dev/mcp and you don't need anything else. All agents that supports MCP lets you click a link to login to Sentry and they make calls to Sentry to fetch authentificated data.
The main problem with MCP is the implementation. Instead of using bash to call MCP, agents are designed to make single MCP tool calling which doesn't allow composability. We solve this problem with exposing MCP tools as HTTP endpoints and it works like charm.
Very good points, but, I think this blog is pretty focussed on the developer use case for LLMs. It makes a lot more sense in chat style interfaces for connecting to non-dev tools or services with non technical users, if anything just from a UX perspective.
Agree. MCP isn't really required. Skills/CLI/API is good enough.
At the AI startup I work on, we never bothered building MCP's - it just never made sense.
And we were using skills before Claude started calling them skills, so they are kind of supported by default. Skills, CLI, Curl API requests - thats pretty much all you need.
This is like comparing OpenAPI and strings (that may be JSON). That is, weird, and possibly even meaningless.
MCP is formally defined in the general sense (including transport protocols), CLI is not. I mean, only specific CLIs can be defined, but a general CLI is only `(String, List String, Map Int Stream) -> PID` with no finer semantics attached (save for what the command name may imply), and transport is “whatever you can bring to make streams and PIDs work”. One has to use `("cli-tool", ["--help"], {1: stdout})` (hoping that “--help” is recognized) to know more. Or use man/info (if the CLI ships a standardized documentation), or some other document.
But in the they’re both just APIs. If the sufficient semantics is provided they both do the trick.
If immediate (first-prompt) context size is a concern, just throw in a RAG that can answer what tools (MCPs or CLIs or whatever) exist out there that could be useful for a given task, rather than pushing all the documentation (MCP or CLI docs) proactively. Or, well, fine tune so the model “knows” the right tools and how to use them “innately”.
Point is, what matters is not MCP or CLI but “to achieve X must use F [more details follow]”. MCP is just a way to write this in a structured way, CLIs don’t magically avoid this.
Running both MCP and CLI-based agents in production, my take is that this isn't an either/or question.
MCP shines for stateful integrations where auth and session management would be painful to handle in CLI scripts. Think Notion databases, Stripe dashboards, calendar APIs - things where the agent needs to maintain context across multiple operations. The tool descriptions in MCP also let you embed domain knowledge that's hard to capture in --help output.
But for anything involving file manipulation, git, build systems, or standard dev tooling? CLI wins hands down. The composability point is real - being able to pipe output through jq or redirect to a file gives you flexibility that MCP can't match. And as noted, LLMs have been trained on mountains of CLI usage patterns.
The hybrid approach that's worked best for us: MCP for external service integrations, CLI for everything else. Let the agent write and execute shell scripts when it needs to chain operations - that's when you get the best of both worlds.
> This is where the gap gets wide. CLIs compose. I can pipe through jq, chain with grep, redirect to files. This isn’t just convenient; it’s often the only practical approach.
Unix style composability is a beautiful thing. But when was the last time you installed a set of tools that actually worked together like this? It only works for simple tools. And you can already connect all the simple ones you want (grep, awk, etc) through the file system.
For teams that have tried both, where does MCP clearly outperform just giving the model a CLI?
Imagine asking to your favorite LLM the following: "get the document attached to the most recent email from Joe and then upload it into my document management system in a new folder within archive 'Important', make sure to name the folder based the topic of the document following the naming convention already in place for folders in the same archive"
This could be possible for the average user after activating the appropriate "email" and "document management" MCP servers in their chat interface - maybe following an activation process similar to that of Alexa skills.
How could a regular user achieve the same via CLI? Where would the CLI process be running?
One underrated reason that CLIs are often better than MCP is that Unix tools seem to have close to information theoretically optimal layout to enabled reasoning. They are concise, in the Solomonoff/Kolmogorov sense.
This means that the related parts in the inputs and outputs are recursively as close together as possible.
There's a reason humans don't type and read http/json on the command line. It's hard to read and reason over that type of syntax. json is made to be easy to parse for simple algorithms, not meant to organise info in an easy to reason about layout.
AIs benefit from the easy to reason about layout. It's not just about being able to fit in the context window but about the contents of that context window being organized such that the attention mechanism doesn't have to stretch itself out trying to connect far apart related pieces. It doesn't have to try to match brackets to disambiguate information. CLIs tend to use formats that are obvious at a glance for humans and LLMs alike.
It's about the entropy of the formats. https://benoitessiambre.com/entropy.html
I can't believe everyone is talking about MCP vs CLI and which is superior; both are a method of tool calling, it does not matter which format the LLM uses for tool calling as long as it provides the same capabilities. CLIs might be marginably better (LLMs might have been trained on common CLIs), but MCPs have their uses (complex auth, connecting users to data sources) and in my experience if you're using any of the frontier models, it doesn't really matter which tool calling format you're using; a bespoke format also works.
The difference that should be talked about, should be how skills allow much more efficient context management. Skills are frequently connected to CLI usage, but I don't see any reason why. For example, Amp allows skills to attach MCP servers to them – the MCP server is automatically launched when the Agent loads that skill[0]. I belive that both for MCP servers and CLIs, having them in skills is the way for efficent context, and hoping that other agents also adopt this same feature.
As far as I'm aware, all of the benefits of MCP over CLI go away if you just bother to run your agents as OS users with locked down permissions such that they only have access to secrets for similarly locked down users on remote systems.
We've had decades to come up with systems for restricting what users can do, there's no reason to reinvent the wheel just because this user happens to be an AI.
There's been an anti-MCP pro-CLI train going for a while since ~May of last year (I've been personally beating this drum since then) but I think MCP has a very real use case.
Specifically, MCP is a great unit of encapsulation. I have a secure agent framework (https://github.com/sibyllinesoft/smith-core) where I convert MCPs to microservices via sidecar and plug them into a service mesh, it makes securing agent capabilities really easy by leveraging existing policy and management tools. Then agents can just curl everything in bash rather than needing CLIs for everything. CLIs are still slightly more token efficient but overall the simplicity and the power of the scheme is a huge win.
I don't doubt that CLIs + skills are a good alternative to MCP in some contexts, but if you're building an app for non-developers and you need to let users connect it to arbitrary data sources there's really no sensible, safe path to using CLIs instead. MCP is going to be around for a long time, and we can expect it to get much better than it is today.
You actually answered your own question: "If a tool genuinely has no CLI equivalent, MCP might be the right call."
I built an MCP server this week for a structured database of founder decisions extracted from podcasts (https://github.com/echomindr/echomindr). There's no CLI equivalent because the value is in the agent discovering the tool and calling it contextually, when someone asks a startup question, Claude searches real founder experiences before answering.
The key distinction: MCP makes sense for discovery and contextual tool selection. CLIs make sense when the human already knows which tool to use. For `gh pr view 123`, of course the CLI wins. But for "search my specialized dataset when relevant", that's exactly what MCP was designed for.
The token budget angle is what makes this a real architectural decision rather than a philosophical one.
I've been using both approaches in projects and the pattern I've landed on: MCP for anything stateful (db connections, authenticated sessions, browser automation) and CLI for stateless operations where the output is predictable. The reason is simple - MCP tool definitions sit in context permanently, so you're paying tokens whether you use them or not. A CLI you can invoke on demand and forget.
The discovery aspect is underrated though. With MCP the model knows what tools exist and what arguments they take without you writing elaborate system prompts. With CLI the model either needs to already know the tool (grep, git, curl) or you end up describing it anyway, which is basically reinventing tool definitions.
Honestly the whole debate feels like REST vs GraphQL circa 2017. Both work, the answer depends on your constraints, and in two years we'll probably have something that obsoletes both.
I understand the argument, and there are some really good points.
My biggest concern would be that adopting the CLI method would require LLM to have permission to execute binaries on the filesystem. This is a non-issue in an openclaw-type scenario where permission is there by design, but it would be more difficult to adopt in an enterprise setting. There are ways to limit LLMs to a directory tree where only allowed CLIs live, but there will still be hacks to break out of it. Not to mention, LLM would use an MCP or another local tool to execute CLI commands, making it a two-step process.
I am a supporter of human tools for humans and AI tools for AI. The best example is something like WebMCP vs the current method of screenshotting webpages and trying to find buttons inputboxes etc.
If we keep them separate, we can allow them to evolve to fully support each use case. Otherwise, the CLIs would soon start to include LLM-specific switches and arguments, e.g., to provide information in JSON.
Tools like awscli are good examples of there LLM can use a CLI. But then we need to remember that these are partly, if not mostly, intended for machine use, so CI/CD pipelines can do things.
AI Agent's like Claude Code are an arms race to the bottom. Just like frontier model quality, they all converge on feature sets over time (plan mode, skills, remote execution, sandboxing, etc.,) and opencode is holding its own, preferred even, in a lot of cases.
The real differentiated value comes from the environment the AI Agent operates in, the runtime.
The runtime is agent agnostic but provides a stable interface to your domain. People tried this with MCP, but MCP is a dead end. Local tool calling is so much better. Being able to extend integrations autonomously is the way, instead of being forced in to a bloated bag of tools.
This is why we built swamp - https://swamp.club. We can integrate with any technology with an API, CLI, or code base and build repeatable, typed, validated automation workflows. There are no providers to wait for. No weird tool call paths trying to get the right concoction of MCP. The agent builds the integration itself, on the spot, in minutes.
The important part of MCP (that this misses) is that it's a machine interface you can quickly iterate on. In other words, an API is too slow-moving. You can't break it; it's a promise. A UI is too annoying for an LLM to deal with. An MCP is the perfect middleground: speaks JSON, but there's inference involved, so if you change the tools, the LLM will be just fine. (Just like how you can change your UI much faster than you change your API, because there's inference at runtime, ie in the human brain.)
For example, at my startup val.town, our MCP server is way more powerful than our API, because we added a bunch of tools to it willynilly because we're not worried about having to be stuck with those tools forever. We can remove them and nobody's code will break. (Just like we could remove buttons in our UI.) But an API change needs to be thought-through.
Some developers started asking a custumer of mine for a MCP server. They don't have one. They have an API on Postman (docs and examples) so they are exporting it as JSON and sending it to those developers. It might work but it's not what those developers want and maybe they will go to another similar service. So useless or not the availability a MCP server could be part of marketing and a checkbox on a due diligence sheet.
This feels misguided. MCP is still one of the best ways to execute deterministic sub-flows (i.e., stepwise processes) and secure tooling that an LLM would either lose itself while executing or should never access directly.
MCP solves a very specific problem: how do you ship a LLM’s tool/function so that it is callable by an LLM in an inter-process manner (so that you don’t need to modify OpenAI’s code to make your tool available in ChatGPT)? CLIs concern what happens inside such tools, namely a `bash` tool. As you can see they are different layers of the same stack.
> LLMs don’t need a special protocol ... LLMs are really good at using command-line tools.
The author's point only makes sense if LLMs all have a computer built-in - they don't. LLMs will only have a commandline if it is provided with commandline tools, and MCP is the standard way to provide tools.
If I have to find an analogy for this (nonsensical) MCP vs. CLI framing, it's like someone saying “ditch the browser, use html instead” - what is that supposed to mean?
MCP Servers are not simple wrappers around REST APIs, they can do much more and we will see more advanced use-cases surrounding MCP as MCP clients continually improve their conformance to the spec. Just wrapping REST APIs may be what MCP Servers are now, but that's just because MCP clients still need to catch up in supporting these more advanced features.
MCP Sampling (with tool calling) is one such example, where MCP servers will be able to generate responses using the MCP client's LLM - not requiring an API key themselves - including calling other MCP tools within the "sampling loop", and without corrupting the primary agent's context. This will generate an explosion in advanced MCP servers, although neither Claude Code, Gemini CLI, nor Opencode support this feature (yet).
Once MCP sampling becomes widely supported the pendulum will swing back and we'll see the boundary between MCP tools, async workflows, and generative responses begin to blur.
The opposite is true. CLI based integration does not exist in a single consumer grade ai agent product that I’m aware of. CLI is only used in products like Claude Claude and OpenClaw that are targeting technically competent users.
For the other 99% of the population, MCP offers security guardrails and simple consistent auth. Much better than CLI for the vast majority of use cases involving non-technical people.
One clear use case where MCP is better than anything else: design system documentation for an enterprise, or using a specific UI library. Daisy UI has an example: https://github.com/birdseyevue/daisyui-mcp
Context7 is a good MCP. If one were to point an agent to a docs website, the amount of tokens consumed would use up too much of the context window to be able to do a meaningfully complex task with it.
Figma MCP translates Figma to a language an agent understands.
Not everything can be a cli.
The only MCP server I use is Svelte's and every time I use it, I feel as though I'm just spamming my context window for little to no reason. I mostly only use it when I'm unsure about something.
However, it did feel useful when breaking changes were introduced, such as class->function component instantiation from Svelte 4 to Svelte 5.
This is probably true of any well-maintained MCP server provided for a project that has a rapidly-evolving API and highly opinionated maintainers who are unafraid to act on their opinions and break stuff. In that scenario, the Svelte MCP server seemed to act as a stop gap for context that the model's cutoff wouldn't allow it to have yet.
These are all evolving technologies and it's pretty evident that the big AI labs are trying different things to see what sticks. Some of it does and they keep evolving it.
The reason MCPs are so powerful are less a technological advantage over other tools and more how ridiculously easy they are to install and use.
Also given it's an official standard now (AAIF), it's easy for sharing across differently agent harnesses and tools.
Those are the two main reasons imho, they are still a mainstay.
If you'll allow some shameless plugs, my co-host and I talk about it in our podcast:
I somehow agree with this but want to add my two cents here. Cloudflare's Codemode[0] is a great "replacement" for MCP because AI is trained for writing code and handling errors. But it also doesn't fix security and sandboxing. For CLI and file operations we have Vercel's just-bash[1] but for everything else there is no safe solution. Therefore MCP still makes sense until somebody sandboxes this part as well without needing to use Cloudflare or something.
[0]: https://developers.cloudflare.com/agents/api-reference/codem... [1]: https://github.com/vercel-labs/just-bash
MCP makes sense when you're not running a full container-based Unix environment for your agent to run Bash commands inside of.
Strong take: MCP is the wrong default for agent runtimes.
It solves the wrong layer and adds operational drag: extra server lifecycle, protocol semantics, and tool-schema overhead in context.
CLI + skills is simpler and more robust for long-running agents: - composability (pipes, filters, redirection) - debuggability (human runs the exact same command) - clearer permission boundaries (allowlist by subcommand) - less moving parts (no always-on MCP daemon)
If MCP is used at all, it should be an edge adapter, not the core runtime contract.
I haven't been able to make a coherent argument against MCP, so I've settled for "I just don't like it".
CLI tools have an edge in that their definition live in model weights; MCP requires a portion of the context for tool definitions.
Having an extra server just to orchestrate the tools, I don't like it.
For anything that does not have a native CLI tool -- just write a wrapper, a shell script, whatever performs the task adequately. It folds into the workflow nicely. Leveraging decades of unix tooling philosophy has its benefits.
Having a shell runner is just... simpler. And as another comment mentions, you can create users for the various agents to restrict their access to things, almost as if that's what users were meant for!
As a counter argument to the kubectl example made in the article, I found the k8s MCP (https://github.com/containers/kubernetes-mcp-server) to be particularly usefuly in trying to restrict LLM access to certain tools such as exec and delete tools, something which is not doable out of box if you use the kubectl CLI (unless you use the --as or --as-group flags and don't tell the LLM what user/usergroup those are).
I have used the kk8s MCP directly inside Github Copilot Chat in VSCode and restricted the write tools in the Configure Tools prompt. With a pseudo protocol established via this MCP and the IDE integration, I find it much safer to prompt the LLM into debugging a live K8s cluster vs. without having any such primitives.
So I don't see why MCPs are or should be dead.
This author gets it. Ignore MCP, WebMCP, etc and instead build for humans like we always have. If LLM providers want usage they can push models to engage with tools like a human does - read docs, use a11y features, and when in doubt `--help`.
The problem with CLIs is that unless it's a super well documented CLI like `gh`, the LLM will have a hard time figuring out how to use it from `--help` alone unless it's a really simple tool. If you want to do something complex, like create a JIRA issue, you either need to put the full issue schema in `--help` so that the LLM knows how to pass an issue or else you can use MCP which bakes tool schemas into the protocol.
YES, I have been thinking the same and wrote a bit about it: https://vizzly.dev/blog/cli-json-output-llm-friendly/
Thank you so much to the GH CLI for making me realize this, really. The only MCPs I use still are ones that don’t have CLIs. Hell, I even just wrote a CLI for Bear Notes, for LLMs. It’s just better.
Seems like the last MCP use case is model to model communication but I’m sure others have approach’s for that?
Recently, I was wondering why http API don’t make use of the body of a http OPTIONS query to discover what an endpoint does.
It’s easy enough to send back the openapi definition for that endpoint only.
Also, when calling an endpoint, instead of a simple 404, we could have a 303 see others, or short description of all available endpoints
I've yet to play with Emacs MCPs thoroughly. Having said that, after initial exposure to agent skills directing agents to just use CLI/emacsclient, I no longer think I need to go deeper into MCP. emacsclient via CLI has been working remarkably well. Did a little video on that https://www.youtube.com/watch?v=ymMlftdGx4I
The skill-based approach has been a game changer for me. Instead of wrestling with MCP server configs, I just write a small markdown file describing the CLI tool and its common use cases. The agent loads it on demand when it detects the tool is relevant. Much simpler than maintaining a running process, and the documentation lives right next to my code rather than in some separate server config. The composability argument is what really sold me - piping through jq, chaining commands, redirecting to files... that's stuff I do daily and never have to think about.
Okay, MCP is useless if the agent has full CLI access, sure. But what if it's a remote cloud agent connecting to another equally remote service. Well, now I need to install said CLI tool. What if I dont want to install a local mcp server either (which was always a stupid idea), and I want for there to be an harness around what the agent can do instead of give it a whole API?
With that said, the total number of applications that should have a MCP before an API is 0, and all that go beyond that threshold are partaking in sin and sacrilege.
My success with LLMs has increased quite a bit since I stopped using MCP servers. I credit it to a couple things:
One, far less context usage Two, I replace it with better instructions to use the tools available.
The gist of it for me is that MCP is expensive and doesn't make up for better instructions using lighter weight tools.
Like the article mentions too, when you've got good tools available in the shell and good instructions for how to use them, the tokens required to do significant workloads is dramatically reduced specifically because the composability of tools in that environment is essentially unprecedented in computing.
In the rare case that Claude doesn't figure out good workflows on its own, you can just make a skill or add instructions to CLAUDE.md and the results are remarkably good
The only place MCP made sense for me, so I thought, was to give my Claude Web agents access to the same cli tools my Claude Code agents had. In this context, agents don't have shells.
However, then I discovered MCP servers on Claude Web are forced onto my laptop for Claude Code, which is very confusing. I don't know if there is a way to stop that, but it has messed up my Claude Code agents.
Is this experience common, and is there a known way to stop this?
CLI vs MCP debate misses the protocol's actual value prop: steering the agent: https://cra.mr/context-management-and-mcp
> When Claude does something unexpected with Jira, I can run the same jira issue view command and see exactly what it saw. Same input, same output, no mystery.
A sign of bad UX. There should be better ways to drill down into what actually happened than ctrl+o which still hides a lot and then ctrl+e is still not enough and there are some verbose flags that show absolutely everything instead of letting me check just what I want. So I'm vibe coding my own tool to do this based on the jsonl files in the Claude history directory. But this should work out of the box.
If the author is just using Claude Code on their own personal computer, they can do whatever they want.
As soon as there is a need to interact with the outside world in a safe, controlled manner at enterprise scale, the limitations of CLI quickly become obvious.
I wish people get more informed about a subject before they write a long blog post about it.
I've been building tools that use both approaches and the answer really depends on the context.
MCP shines when you need stateful, multi-step interactions - things like browsing a codebase, running tests iteratively, or managing deployment pipelines where each step depends on the last.
CLI wins when the task is well-defined and atomic. "Run this audit", "deploy this thing", "format this file." No ambiguity, no state to maintain.
The trap I see people falling into: using MCP for everything because it's new and shiny, when a simple CLI wrapper would be faster, more reliable, and easier to debug. The best tools I've built combine both - CLI for the happy path, MCP for the exploratory/interactive path.
For me, GitHub CLI is the prime example of this. This CLI is so incredibly powerful when combined with regular command line tools. Agents know how to use head, tail, jq and so on to only extract the parts it needs.
The best selling point of CLIs is the ability to chain, transform and combine. MCP cannot do this.
What, those job ads asking for 5 years of experience with MCP were useless after all?
> I tried to avoid writing this for a long time, but I'm convinced MCP provides no real-world benefit
IMO this is 100% correct and I'm glad someone finally said it. I run AI agents that control my entire dev workflow through shell commands and they are shockingly good at it. the agent figures out CLI flags it has never seen before just from --help output. meanwhile every MCP server i've used has been a flaky process that needs babysitting.
the composability argument is the one that should end this debate tbh. you can pipe CLI output through jq, grep it, redirect to files - try doing that with MCP. you can't. you're stuck with whatever the MCP server decided to return and if it's too verbose you're burning tokens for nothing.
> companies scrambled to ship MCP servers as proof they were "AI first"
FWIW this is the real story. MCP adoption is a marketing signal not a technical one. 242% growth in MCP servers means nothing if most of them are worse than the CLI that already existed