MCP vs CLI
Should you give your coding agent tools through an MCP server, or just let it use the command line?

An MCP server describes its tools to the agent, which calls them directly without a terminal.
Docs for MCPThe agent runs the same command line tools you do, like gh or playwright-cli, in a terminal.
Docs for CLIUse a CLI when there's a good one, and MCP when there isn't. I gave Claude Code the same eight tasks through each one, and with Sonnet 5.5 both got every answer right. MCP used 2.1× the tokens to get there, though, and cost 2.1× as much. Most of that came down to how well Sonnet used the terminal, so let's take a look at what it actually did.
What each one sends and gets back
Let's start with a single job. Both routes end up doing the same thing behind the scenes, but the agent asks for things differently, and the amount of text that comes back can be very different. These are real calls Claude Code made during my test, so pick a job and compare them.
Nothing is loaded for gh. The model already knows it from training, so it went straight to the command.
It runs$ gh pr view 14578 -R cli/cli \ --json author,changedFiles,reviews,state,title \ --jq '{title, state, author: .author.login, changedFiles, approvers: [.reviews[] | select(.state=="APPROVED") | .author.login]}'It gets back135 characters
{"approvers":["BagToad"],"author":"williammartin",
"changedFiles":8,"state":"MERGED",
"title":"Replace extension browse with Bubble Tea"}Tool names load at the start. The full definition of pull_request_read, around 4,600 characters, loads when the agent asks for it.
It callspull_request_read({ method: "get", owner: "cli", repo: "cli", pullNumber: 14578 }) pull_request_read({ method: "get_reviews", owner: "cli", repo: "cli", pullNumber: 14578 })It gets back19,564 characters
{"additions":1781,"base":{"ref":"trunk","repo":{"description": "GitHub's official command line tool","full_name":"cli/cli"}, "sha":"6fc1c29d…"},"body":"<!--\nThank you for contributing to GitHub CLI!\n\nIf you are proposing a fix for a security issue… …plus every review, including two long Copilot review summaries
Both got it right: williammartin opened it, it changed 8 files and BagToad approved it. The CLI asked for five fields and used --jq to filter the reviews down, so only 135 characters ever reached the model.
The MCP tool sent back the whole pull request and every review instead. That's about 145 times as much text for the agent to read through, just to find the same three answers.
I've trimmed the outputs to fit, but the sizes are the full number of characters each tool sent back to the agent.
What the tools cost before your agent does anything
Before the agent runs anything, there's another cost to think about. An MCP server sends the agent a description of every tool it has, and that text sits in the context window for the whole session. A CLI only needs the terminal tool, whatever you run through it, so switch things on and off to see what I measured in Claude Code.
- Terminal (Bash tool) · 1,767Covers every CLI the agent runs
- GitHub MCP, 46 tools · 20,393Every tool definition, loaded up front
With every definition loaded, GitHub's server adds 20,393 tokens before your agent has done anything, and that's sent again on every turn. Switch Tool search on to see what Claude Code does by default now.
Try 95 tools as well. That's every toolset GitHub offers, and the cost more than doubles.
Measured on 15 October 2026 with Claude Code 2.1.300 and Sonnet 5.5, by starting a session that replies "OK" and subtracting the 2,887 tokens it uses with no tools at all. I added up the combinations from single measurements, so treat them as approximate.
I gave both the same jobs
So that's a single call and the cost of getting started. To see how it all adds up over a whole job, I ran Claude Code on eight read-only tasks, three times for each setup. Five use GitHub (gh against GitHub's MCP server) and three use a small shop running on my machine (playwright-cli against Playwright MCP).
Pick a task and hit Replay to watch the middle run of each three, by token count.
In the GitHub repo cli/cli, look at pull request #14578. Who opened it, how many files did it change, and who approved it?
- $ gh pr view 14578 -R cli/cli --json author,changedFiles,reviews,state,title --jq '{title,state,author:.author.login,changedFiles,approvers:[.reviews[]|select(.state=="APPROVED")|.author.login]}'135 chars
PR #14578 in cli/cli, "Replace extension browse with Bubble Tea" (merged): - Opened by: williammartin - Files changed: 8 - Approved by: BagToad
- ToolSearch: load pull_request_readloads tools
- pull_request_read {"method": "get", "pullNumber": 14578}5,953 chars
- pull_request_read {"method": "get_reviews", "pullNumber": 14578}13,611 chars
PR #14578, "Replace extension browse with Bubble Tea": - Opened by: williammartin - Files changed: 8 - Approved by: BagToad, on 2026-10-07. It was the only approval. The other reviews were comments from williammartin and the Copilot reviewer bot. The PR was merged on 2026-10-08, and williammartin did the merge.
- pull_request_read {"method": "get", "pullNumber": 14578}5,953 chars
- pull_request_read {"method": "get_reviews", "pullNumber": 14578}13,611 chars
PR #14578, "Replace extension browse with Bubble Tea": - Opened by: williammartin - Files changed: 8 - Approved by: BagToad, on 2026-10-07. This is the only approval. The other reviews were comments from Copilot and williammartin. The PR was merged on 2026-10-08.
Across three runs, MCP used a median of 27k tokens against 9.9k for the CLI, which is 2.7× as many.
All nine runs got this right. The CLI did it in a single command, while MCP had to search for the tool first and then make two calls, pulling back roughly 19,500 characters of pull request and review data along the way.
The amber lane is the same MCP server with tool search off, so every tool definition loads up front, which is how Claude Code worked before tool search. It used 59k tokens but cost $0.055, because those definitions get cached, and cached tokens are much cheaper.
Long commands and answers are trimmed, marked with …
Across every task
One task on its own doesn't tell you much, so here's the median for every task and setup.
- CLI
- MCP
- MCP, all tools loaded
With Sonnet, MCP used more tokens than the CLI on 8 of 8 tasks. The CLI got 24 of 24 answers right and MCP got 24 of 24.
Switch to Haiku 5.5 above to see how a smaller model did.
What other tests found
Saying that, my tasks are all reads on well known tools, which is a good fit for a CLI. Other people have tested different things, and their results don't all line up with mine.
Five read-only GitHub tasks on Sonnet 4. gh used 4 to 32 times fewer tokens than GitHub's MCP server and finished 25 of 25 runs. MCP finished 18 of 25, and all seven failures were connection timeouts.
scalekit.com ↗Twelve Stripe tasks, including writes, on Sonnet 4.6. Everything passed, but the stripe CLI was the most expensive at $2.22, against $1.60 for MCP. Creating an invoice took 19 turns through the CLI and 12 through MCP.
portofcontext.com ↗His own terminal tool built as both an MCP server and a CLI, tested alongside tmux and screen over 120 runs. Both versions of his tool succeeded every time, and the MCP one was 23% faster and 2.5% cheaper. His conclusion was that "MCP vs CLI truly is a wash".
mariozechner.at ↗When is MCP worth it?
My test is close to the best case for a CLI, with popular tools on a developer's laptop and one person signed in. Plenty of setups look different, so answer these about yours and I'll tell you which way I'd go.
- This is what my test looked like, and the CLI got the same answers using fewer tokens. You can also see and rerun every command the agent ran.
- If you find yourself explaining the same commands to the agent over and over, write them into a skill or AGENTS.md before reaching for a server.
Side by side
| Criterion | MCP | CLI |
|---|---|---|
| How the agent learns the tool | The server sends a definition for every tool | From training for popular tools, otherwise --help |
| Cost before it starts | About 20,000 tokens for GitHub's server, or 2,200 with tool search | About 1,800 tokens for the terminal tool, whatever you run |
| Trimming the output | Only if the tool has options for it, like tail_lines | Pipes, --jq, grep, head |
| Steps per turn | One per tool call, although the agent can make a few at once | Several, chained with && |
| Needs a terminal | No, so it works in Claude, ChatGPT and other chat apps | Yes |
| Signing in | Each user signs in with OAuth through their own client | Whoever's signed in on that machine |
| Limiting what it can do | Allow or deny each tool. Some servers have a read-only mode | Command permission rules, or a sandbox |
| In my test (Sonnet 5.5) | 24 of 24 right, $0.43 for all eight tasks (median runs) | 24 of 24 right, $0.21 for all eight tasks (median runs) |
When to pick which
- The agent has no terminal, like Claude on the web or ChatGPT
- The service has no decent CLI
- The agent works for other people who each have their own login
- You want to allow specific actions and nothing else
- There's a well known CLI for it, like git, gh, aws or stripe
- Your agent runs in a terminal, on your machine or in CI
- It'll pull back lots of data that it only needs part of
- You want to see and rerun every command the agent ran
How we tested
- Task
- Eight read-only tasks in Claude Code, run three times per setup. Five used GitHub, with gh against GitHub's remote MCP server, and three used a small shop running on my machine, with playwright-cli against Playwright MCP.
- Evidence
- 111 headless Claude Code sessions (claude -p) on 15 October 2026, with no other tools loaded. Each answer was checked against the real data.
- With
- Claude Code 2.1.300, Sonnet 5.5 and Haiku 5.5, gh 2.86.0, GitHub's remote MCP server, with and without tool search, @playwright/cli 0.1.22, @playwright/mcp 0.0.83, with tool search
Updates
Published.