Short answer for a software company deciding this quarter: build an MCP server, and if your API is large, build it in the search-and-execute shape Cloudflare published in February. Build a CLI only if your users are developers who already live in a terminal. Do not build "code mode" as a product; it is a pattern the caller's host or your own MCP server applies. Then spend the time you saved on the decision that actually moves revenue: which outcomes your product will design, guarantee, and sell to the agents that show up.
That is the conclusion. The rest is the reasoning, because every sentence above has a condition attached, and the conditions are where most comparison posts go quiet.
Three transports, one job
A CLI, an MCP server, and code mode are three ways to get an agent to your product's primitives. They differ in where the agent runs, what it can touch, and how much of your API passes through the model's context window. That is the whole comparison.
When a CLI wins
A CLI wins when the caller has a shell. That sounds obvious, and it is the entire case.
A coding agent on a developer's machine has bash, a filesystem, and pipes, and it has read millions of man pages. Give it yourproduct export --since 30d | jq '.items[] | select(.status=="failed")' and it will compose, filter, and retry without any of that passing through its context. Mario Zechner's benchmark of MCP against a CLI for terminal control landed on the same place: "if you're building a tool from scratch and your users already have a shell tool available, just make a good CLI."
Okibi relaunched this week on exactly this bet. Its tagline is "Turn your product into a CLI, and agents into customers." It generates a CLI from your codebase or OpenAPI spec, verifies each command in a sandbox, and ships a binary plus a skill file. Production tier is $200 a month for one CLI and 500 authenticated agent users. If your customers are developers running Claude Code, Cursor, or Codex, that is a sensible product to buy.
The condition: your customer's agent has to have a shell. A widget in your app does not. Claude in a browser tab does not unless the host adds one. An email thread does not.
When an MCP server wins
An MCP server wins when the caller lives in a host: Claude, ChatGPT, an agent inside your own product, a customer's internal agent behind a load balancer. No filesystem, no pipes, remote auth, more than one tenant.
Two things changed this year. The 2026-07-28 MCP specification made the HTTP transport stateless, so "any request can land on any instance behind a plain round-robin load balancer." Simon Willison called the result "so much cleaner from both a client- and server-side implementation perspective." Authorization also got stricter, which enterprise buyers were waiting for.
The condition: a real product MCP server has dozens of tools, and Anthropic's own Advanced tool use numbers say a five-server setup of 58 tools costs about 55K tokens before the first message, with selection accuracy degrading past 30 to 50 tools. I wrote about the day our own agent drowned in 63 tools, so I will not retell it. The fix is the next section.
What code mode changes
Code mode is the observation that models write code against an API better than they call tools one at a time, and that when the model writes code, intermediate results never enter its context.
There are two versions, and people mix them up. The first, from Cloudflare in September 2025, runs on the caller's side. The agent builder's SDK turns your MCP server's schema into a TypeScript API, the model writes a script, and it runs in a disposable V8 isolate the builder hosts. Only console.log output comes back. Cloudflare's line for why: "LLMs have seen a lot of code. They have not seen a lot of 'tool calls'." Anthropic published the same idea two months later, with one Google Drive to Salesforce workflow dropping from 150,000 tokens to 2,000.
The second, from Cloudflare in February 2026, runs on the vendor's side, and it is the one to study. Cloudflare's own API MCP server exposes two tools. search takes model-written JavaScript that filters the vendor's OpenAPI document and returns whatever the code selected. execute takes model-written JavaScript with one authenticated helper for making requests. The model composes REST calls in code and returns a focused result:
// inside execute(): the model wrote this, the vendor's Worker runs it
// (shape adapted from Cloudflare's search-and-execute guide)
const response = await codemode.request({
method: "GET",
path: "/orders",
query: { status: "processing", limit: 20 },
});
return response.items.map(({ id, status }) => ({ id, status }));The whole Cloudflare API, about 2,500 endpoints, costs roughly 1,000 tokens of tool definition. The docs state the important property plainly: "The complete OpenAPI document remains inside the sandbox. Only the returned subset enters the model context." Auth stays outside the sandbox; the Worker attaches the caller's token, so generated code never sees a credential. Any vendor with an OpenAPI spec can copy the pattern.
The conditions, to be fair to it. Anthropic's post says it directly: "Running agent-generated code requires a secure execution environment with appropriate sandboxing, resource limits, and monitoring." The goose team measured that on single-step tasks with one or two servers "the overhead of writing and executing code might actually be more work than just calling the tool directly." Code mode pays off when the API is large and the task composes. For a 12-tool server, plain MCP is fine.
The Thariq and Tobi exchange, read carefully
This week Thariq, who works on Claude Code at Anthropic, posted: "I was not expecting things to go this way, but I think MCPs are better than CLIs for most integrations." His reasons, as reported: models have gotten much better at tool calling, tools can be deferred and loaded on demand, MCP is now stateless, and filtering can be pushed into query parameters instead of shell pipelines.
Tobi Lütke's reply: "i think this is true as long as the models can use the mcp(s) through some form of repl. Without that, bash and cli can act as a sort of repl."
They are both right, and the disagreement is narrower than the replies made it look. Thariq is describing a host that has done the work: deferred loading, server-side filtering, a stateless transport. Tobi is pointing at what happens when the host has not: the model needs somewhere to compose, and a shell is the one composition surface every coding agent already has.
Code mode is the REPL condition satisfied on the MCP side. execute is a REPL. Seen that way, the debate is not MCP versus CLI. It is: does the caller have a place to compose, and who provides it? For a developer in a terminal, the shell. For everyone else, the vendor or the host must supply it, and a search-and-execute MCP is the cheapest way that also carries auth.
All three are transport, and transport is going to zero
Here is where a software company should stop reading comparison posts.
Cloudflare took the best transport pattern anyone has published and gave it away as a free recipe. A YC company will compile the other transport for you for $200 a month. Every agent framework can consume an OpenAPI document as tools today. When a capability is free from one vendor and $200 from another, it is not where your margin lives.
Evil Martians put it well: "An MCP server is a product interface for the age of agents, not an AI feature itself." So is a CLI. So is code mode. They are the door. Nobody pays for the door.
So what does the buyer's agent still need from you once it can reach every primitive through any door? Four things, and none is a transport.
Privileged data. The agent composes whatever your public API exposes. It cannot compose what the API never exposes: cross-tenant benchmarks, internal risk scores, what your ops team knows about carrier delays this week.
Write authority with accountability. Nobody sane hands an arbitrary agent full headless control of their billing, their shipments, or their customer records. Outcomes with side effects exist only as vendor-sanctioned jobs with guardrails, limits, and an audit log. A codemode.request with method: "DELETE" is a primitive. "Cancel every unpaid order older than 30 days and send the summary" is a job someone stands behind.
Residency. The customer's agent is not running at 3am. It is not running when your webhook fires. Scheduled work and event-triggered work need a runtime on your side, with the customer's identity and permissions attached.
Amortized reliability. A job tested once and run ten thousand times on the cheapest model that passes beats a job re-derived by a frontier model every time. Honestly, this one erodes every quarter as models improve and should never be the only reason a customer pays you. But right now it is real.
Merchants did not need Shopify less when customers started shopping through aggregators. They needed it more, because someone had to own the catalog, the pricing, and the fulfillment behind the aggregator. The aggregator this time is your customer's agent.
What to ship this quarter, and what to decide alongside it
| Your situation | Ship | Shape |
|---|---|---|
| Customers are developers in a terminal | A CLI, then an MCP server | Generate the CLI from your OpenAPI spec (Okibi or your own), keep commands verified in CI |
| Customers work in Claude, ChatGPT, or inside your own app | An MCP server | Stateless HTTP, OAuth per user, tools scoped to what the signed-in user can do |
| API over roughly 50 operations | An MCP server in search-and-execute shape | Two tools, OpenAPI inside the sandbox, auth attached by your server, never by the model |
| API under roughly 50 operations | A plain MCP server | Well-described tools, query parameters for filtering, no code sandbox to run |
| Any of the above | The outcome list | Five to ten named jobs with inputs, allowed tools, limits, delivery, and a price |
The last row is the one that decides whether the first four rows make you money.
Write down the five to ten things your customers ask for by name. Not "list orders." The reorder forecast. The account audit. The weekly exception report. For each: inputs, which primitives it may touch, what it may never do, where the result goes, whether it runs on request, on a schedule, or on an event, and what it costs. Price it per outcome. Not per seat, because the agent is not a seat. Not as marked-up tokens, because Cloudflare just showed everyone that tokens are cheap, and your customer's agent can read that post too.
Primitives are not products. A door is not a store.
Where Aimdoc fits
We built Aimdoc as one customer agent for a software product: on the website, inside the app, over email, and through a public Gateway for other agents. It connects to the product's MCP server, and every call runs as the signed-in customer with their permissions. On top of that we added services: named outcomes defined on the product, each with inputs, allowed tools, limits, identity, entitlements, an optional price through your own Stripe account, delivery to app, email, Slack, or webhook, and runs that are scheduled or event-triggered. The free tier is 10,000 credits with no credit card. We built it because we hit the four things above in our own customers' products and concluded the transport was never the hard part.
The short version
CLI if the caller has a shell. MCP if it does not. Search-and-execute if your API is big. Code mode is what makes MCP satisfy Tobi's REPL condition, and Cloudflare will give you the recipe.
Then stop. All three are doors, and the doors are free now. Decide which outcomes you will design, guarantee, and sell through them, and price those. That is the one decision in this post nobody can copy from a blog.