MCP vs API vs CLI: Which Should AI Agents Use?
MCP vs API vs CLI depends on whether an agent can finish the task. Our local invoice test shows how missing pagination can defeat a successful call.
- Category
- General
- Updated
- Author
- Stan Kharlap
An agent asks for all your invoices. The tool succeeds. The response is valid JSON. The list looks plausible. Only later do you discover that the answer covered the first page.
That is the test I would run before debating MCP vs API vs CLI. Use MCP when your agent host benefits from tool discovery, a CLI when it already works in a terminal, and a direct API when you need explicit control over a workflow. In every case, check that the interface can express the complete task and prove that it finished.
We replayed one read-only invoice task against Norman's actual interface code with synthetic data. The smallest fixture worked through all three. A larger fixture exposed a gap shared by our MCP and CLI list operations. This is a narrow comparison of interface contracts, not a ranking of models or a production reliability study.
How do MCP, APIs and CLIs differ for agents?
A REST API gives software endpoints, parameters and responses. A CLI packages operations as commands, options, standard output and exit codes. MCP provides a way for an agent client to discover and invoke named tools with input schemas. The MCP tools specification describes that discovery and invocation contract.
These are often layers of the same product. A CLI can call an API; an MCP tool can call that API too. Neither wrapper automatically inherits every backend capability. Someone decides which arguments to expose, which defaults to insert and which results to preserve.
The distinction has become timely. On September 1, AuditFile announced an agent orchestration suite accessible through CLI, API and MCP. On September 10, OpenAI introduced its Agents API in public beta, offering a managed harness. Those are vendor announcements, not evidence that one interface performs better. They make choosing the tools around an agent a concrete product decision.
Our earlier accounting MCP landscape asks which vendors offer a server. Here the question is narrower: can the particular operation you chose complete your task?
How did we compare the same invoice task?
The task was to retrieve the complete invoice list and verify that the number of unique records matched the fixture. A separate control retrieved one invoice by a known ID. We used a small collection that fit on one page, then a collection of a few dozen invoices requiring three pages under the test configuration.
The replay ran the published Norman CLI package, registered Norman MCP invoice tools through the real MCP SDK, and Norman's backend pagination class. All HTTP requests were intercepted and answered from synthetic fixtures. MCP used an in-memory connection. Credentials, production services, a database and a language model were outside the test.
That boundary matters. We measured which parameters reached pagination, which records returned and how many backend requests occurred. We did not measure network latency, authentication, autonomous planning, token cost or accounting accuracy. Nor did we replay the complete production view, filtering and serialization stack.
The direct API path followed the returned continuation links. The MCP and CLI paths used their advertised invoice-list operations. We inspected their schema and help output before testing recovery, rather than assuming every REST parameter had a matching tool argument or command flag.
What happened when the results needed another page?
All three paths returned the complete small fixture. All three retrieved the known invoice correctly in one backend request. The difference appeared when the invoice collection exceeded a single page.
| Path in the larger-fixture test | Backend requests | Result | Completion evidence |
|---|---|---|---|
| Direct API, following continuation links | 3 | Entire collection | Unique record count matched |
| MCP invoice-list tool | 1 | First page only | Count and next-page link showed more data |
| CLI invoice-list command in JSON mode | 1 | First page only | Count and next-page link showed more data |
The two first-page results contained fewer than half the fixture's records. Both calls reported success at their interface level. Neither response claimed that the rest of the records did not exist: the pagination metadata survived. A consumer that compared the total count with the received list could detect the incompleteness.
The cause was specific. The backend pagination class accepts page and page_size. The tested wrappers exposed limit, forwarded it unchanged and did not offer a page selector. Raising that limit did not enlarge the result. Using the actual API page-size parameter did return the larger fixture in a single request.
This matches the distinction between page-number and limit-based pagination in the REST framework documentation. A parameter with a sensible name has no effect unless the receiving contract consumes it.
A single REST request with default pagination also returned only the first page. The API did not complete the collection automatically; our caller supplied the loop. Its advantage here was the available continuation control.
One request looked cheaper than three, but it had done less work. That is why I would reject a benchmark that compares call counts before checking the result set.
Can an agent recover from a missing parameter?
We tried the obvious next action. The CLI rejected an unsupported --page option before making a backend request. Adding an unadvertised page argument to the MCP call, in the tested SDK configuration, produced another first page. The argument did not reach the backend.
Those are observations about these versions, not requirements of CLI or MCP. Another implementation could expose pagination correctly or fetch all pages internally. The MCP protocol also supports pagination for discovering tools; that does not automatically paginate the invoices returned by a tool.
The useful response from an agent here would be: I received one page and can see that more records exist, but this operation does not expose a continuation control. It should not declare a complete inventory or keep repeating an unchanged request.
A host with separately configured API access could use that route. That would be a workflow using two interfaces, and the comparison should record the switch. It would not prove that the original list command finished the task by itself.
Which interface should you choose for an AI workflow?
For a scheduled export or reconciliation input, I favour a direct API with explicit pagination and an assertion about completeness. The caller owns the loop and can keep its rules in code. That control is valuable when an omitted record changes the meaning of the answer.
For a terminal-based agent, a CLI can provide discoverable commands and machine-readable output without a separate tool integration. Our CLI introduction covers that workflow. Check the individual command's help and JSON output: a command catalogue does not establish parameter parity with the API.
For an assistant that already speaks MCP, named tools and schemas provide a natural discovery mechanism. Task-shaped tools can remove irrelevant choices. But the schema must include the controls that the task actually needs, or the tool must handle them itself and return clear completion evidence.
I would keep the backend operation shared and test every wrapper against the same fixtures. Our agent harness article discusses execution and verification around tools; interface coverage is another prerequisite. A stronger harness cannot make an absent argument appear.
How should you test before connecting an agent?
Start with a happy-path record lookup, then cross a page boundary. Keep the expected record IDs outside the agent's response so the evaluator can check the result independently. Test both a larger requested page and a continuation request; they exercise different capabilities.
For a stable test fixture, a reusable completion condition is:
assert next_page is None
assert len(set(returned_ids)) == expected_count
This is a test assertion, not a universal guarantee for a changing live dataset. Production collections may change while pages are fetched, so their consistency rules need separate treatment.
Then inspect the stopping behaviour. Can the caller identify missing data, explain the limitation and stop? Does a retry change the request in a meaningful way? Is there an available, explicitly configured alternative route? Record those outcomes before measuring speed or cost.
Our next comparison would add a model with the same task, fixtures and completion checks across all three paths. The replay reported here stops before that step. Its result is already actionable: choose the interface that preserves the operations your workflow needs, and make completeness something the system checks rather than something the assistant assumes.
Frequently asked questions
- What is the difference between MCP, an API and a CLI?
- An API exposes operations to software. A CLI turns operations into terminal commands. MCP lets an agent client discover named tools and their input schemas, then invoke them. These layers can share the same backend. Their practical differences come from exposed parameters, output structure and recovery paths, not simply the name of the interface.
- Does an MCP server replace a REST API?
- Often it sits on top of one. The MCP tool translates a task-shaped request into backend calls and returns the result. That translation can simplify a workflow, but it can also omit a needed parameter. In our local invoice-list replay, the MCP tool exposed a limit but no way to select the next data page.
- Is a CLI cheaper or faster than MCP for AI agents?
- This comparison does not establish a cost or speed winner. It used deterministic calls, synthetic invoices and an in-memory MCP transport, without a model or production network. A useful cost comparison must hold task completion constant and include discovery, retries, context and backend work. Returning one incomplete page is not a successful optimization.
Norman handles the operational finance work behind the scenes
From invoicing to bookkeeping, Norman keeps recurring finance work organized so you can stay on top of deadlines with less manual effort.