A 40-tool MCP server can put roughly 12,000 tokens of tool definitions in front of your agent before it does anything, while a one-line skill costs about 40 tokens until Claude decides to use it. That gap is the whole argument behind the "just use the CLI" camp, and a 686-point Hacker News thread shows it is only half the story.[1] My short answer: use a CLI plus a skill for anything that already has a good command line, use MCP when you need hosted auth, policy or non-terminal clients, and use a skill alone when the job is a procedure, not a capability. The sections below give a decision table, the same Postgres task done three ways, the token math, and a pick-this-when list.
What the 686-point thread actually argued
The thread is about an Earendil post titled "You said no MCP". The team behind the Pi agent harness had rejected MCP and now supports it in core. Their reasoning: MCP changed, and the changes Pi needed (deferred tools, tools exposed only to a code sandbox) were useful beyond MCP.[2] Their own line on CLIs is the one people quote: CLIs work because "the agent and model just wire stuff together with efficient bashisms."
So the headline "agents prefer CLIs" is a simplification. The comments split by use case, not by ideology:
Local developers with a terminal-capable agent mostly say a CLI or REST API plus a doc file is enough, and that many MCP servers could have been CLIs.
Several commenters argue the opposite on security: an MCP server holds the API key so the agent never sees it, and enterprises get per-tool policy and fast revocation.
Anyone shipping to chat apps like claude.ai or chatgpt.com points out a CLI does nothing there. MCP is the only door.
The context-bloat complaint is real but harness-dependent. Some harnesses load every tool definition up front; others defer them.
The catch: the "MCP is dead" take and the "MCP wins" take are both wrong for the same reason. They describe different deployments.
The three layers, defined by what they actually are
MCP is a JSON-RPC protocol where a server exposes tools, resources and prompts to a host. The current spec is dated 2026-07-28 and describes stateless, self-contained requests with per-request capability negotiation.[3] In Claude Code you add servers over HTTP (recommended for remote), stdio (local process), or SSE (deprecated).[4]
A CLI is any command the agent can run through its shell tool. No protocol, no registration. The agent reads --help, or you tell it the flags.
A skill is a folder with a SKILL.md. Per the Claude Code docs, "skill descriptions are loaded into context so Claude knows what's available, but full skill content only loads when invoked."[5] Skills live at ~/.claude/skills/<name>/SKILL.md for personal use or .claude/skills/<name>/SKILL.md for a repo, and a skill can pre-approve commands with allowed-tools.
These are not rivals at the same level. A skill is instructions. A CLI is a capability. MCP is a capability with a contract. The popular pairing, a skill that teaches the agent to drive a CLI, is just the first two stacked.
Decision table
| Criterion | MCP server | CLI | Skill |
|---|
| Auth | OAuth flow built in (claude mcp login), or headers and env vars. Server can hold the secret so the agent never sees it | Whatever the tool uses: env var, config file, SSO. The agent's shell can usually read it | None of its own. Inherits whatever the commands it calls use |
| Context cost | One definition per tool (name, description, JSON schema). Claude Code defers these through tool search by default | Zero until used, then the help text and output | Description only (capped at 1,536 characters in the listing), body loads on invoke |
| Discoverability | Best. tools/list is machine-readable | Weak unless --help is good | Good. Description is the trigger |
| Sandboxing | Server process boundary. Hosted servers keep credentials off your box | Runs with the shell's permissions | None. Permission rules still govern the commands it triggers |
| Works in CI | Yes, with care: MCP_CLIENT_SECRET for OAuth clients, project .mcp.json needs approval | Best. It is already a command | Yes, if the repo ships .claude/skills |
| Versioning | Protocol versioned by date; server versions are the vendor's. npx -y pkg@latest drifts | Pin the binary in your lockfile or image | Versioned by git with your repo |
| Maintainer | Vendor or community. You inherit their bugs | The tool's authors | You |
Read the table column by column and a pattern shows up. MCP buys you auth and policy at the price of definitions in context. A CLI is free but trusts the shell. A skill is the cheapest way to add judgment, and it adds no capability at all.
Recipe 1: query Postgres through an MCP server
Add a stdio server, passing the connection string as an env var. The -- separates Claude's flags from the server command:
claude mcp add --transport stdio --env DATABASE_URL=postgres://readonly@db.internal/app \
postgres -- npx -y
Replace the package with one you have audited. That placeholder is deliberate: the "npx @latest from a stranger" pattern is exactly what the thread's security commenters criticised, and a database server can run arbitrary SQL. Scope it with --scope project to write it to .mcp.json for the team, and use a read-only database role no matter what.
Wins: typed tool schemas, the agent cannot see your password in a shell command, one server serves every client that speaks MCP. Costs: every tool the server exposes shows up in discovery, and you now depend on someone else's SQL-safety claims.
Recipe 2: psql plus a skill
Skip the server. Create .claude/skills/pg-readonly/SKILL.md:
---
name: pg-readonly
description: Run read-only SQL against the app Postgres database with psql. Use when asked about table contents, row counts or schema.
allowed-tools: Bash(psql *)
---
Always connect with:
PGOPTIONS='-c default_transaction_read_only=on' psql "$DATABASE_URL" -v ON_ERROR_STOP=1 -c ""
Use \dt and \d tablename for schema. Add LIMIT 50 to every SELECT.
Never run INSERT, UPDATE, DELETE or DDL.
The default_transaction_read_only setting is the real guard. The prose "never run INSERT" is advice; the Postgres setting is enforcement. Claude can invoke the skill from the description, or you call it with /pg-readonly.
Wins: about 40 tokens resting cost, nothing to install, reviewable in a pull request. Costs: $DATABASE_URL lives in the shell environment, so the agent can read it. Use a read-only role and a host that only accepts your network.
Recipe 3: a skill that wraps a script
When the task has fixed steps, put them in a script and make the skill call only that script:
---
name: weekly-signup-report
description: Produce the weekly signups report as CSV. Use when asked for signup numbers by week.
disable-model-invocation: true
allowed-tools: Bash(./.claude/skills/weekly-signup-report/run.sh *)
---
Run ./.claude/skills/weekly-signup-report/run.sh and show the first 20 rows.
The script owns the SQL, the date maths and the output shape. Setting disable-model-invocation: true means Claude does not load it on its own and the description stays out of context; you trigger it with /weekly-signup-report. The agent cannot improvise a different query because the only pre-approved command is the script.
Wins: deterministic output, smallest blast radius, nearly zero context. Costs: it does one thing. A new question means a new script.
Token cost math for tool definitions
These are my estimates, not measurements from a vendor. A typical MCP tool definition (name, a two-sentence description, a JSON schema with four or five parameters) runs about 250 to 350 tokens. Take 300:
| Setup | Resting context | Per 100 sessions |
|---|
| 40-tool MCP server, all definitions loaded | 40 x 300 = ~12,000 tokens | ~1.2M input tokens |
| Same server with Claude Code tool search (names discovered on demand) | Only tools Claude actually searches for | Varies; far lower |
| One skill with a 160-character description | ~40 tokens | ~4,000 tokens |
| Three skills, same size | ~120 tokens | ~12,000 tokens |
Two corrections to the scary number. First, tool search is on by default in Claude Code, so the 12,000-token case mostly applies to harnesses without deferral, or when you set ENABLE_TOOL_SEARCH=false. Second, the real MCP cost shows up in output: the default cap is 25,000 tokens per tool result, and a warning fires at 10,000. A chatty query tool can burn more in one call than its definitions ever did. Measure your own setup with the WOWHOW token counter by pasting a tools/list response, and use the prompt bloat analyzer on a long SKILL.md body.
Pick this when
Pick a CLI plus skill when a good command exists (
psql,gh,kubectl), you run locally or in CI, and the credential is already yours.Pick MCP when the integration is hosted (OAuth, per-user consent), when the secret must stay away from the agent, when you need central policy, or when your users are in claude.ai or another non-terminal client.
Pick a skill alone when the job is a procedure: a review checklist, a release routine, a house style. No new capability is needed, only consistent judgment.
Pick a script-wrapping skill when the steps are fixed and you want the agent unable to deviate.
Pick two layers when the first alone leaks: MCP for the connection, a skill for how your team uses it.
On the skills side, the ecosystem is moving fast. The mattpocock/skills repository ("Skills for Real Engineers") had 287,917 GitHub stars when I checked on 13 October 2026. Popularity is not quality, so read a skill before installing it, the same way you would read a shell script.
Quick answers
Is MCP dead because of CLIs?
No. The thread's most-cited post comes from a team that rejected MCP and then added it to core. CLIs win locally; MCP wins for hosted auth, policy and non-terminal clients.
Do skills replace MCP servers?
They replace the instructions around a server, not the connection. A skill cannot authenticate to a SaaS API on its own. The MCP spec even lists "Skills over MCP" as an extension, so the two are converging.
Where should an MCP server config live?
Local scope (default) is private to you in ~/.claude.json. Project scope writes .mcp.json at the repo root for your team, and Claude Code asks each person to approve it once. User scope follows you across projects.
How do I stop a skill running a dangerous command?
allowed-tools only pre-approves commands for that turn. It does not restrict which tools exist. Enforcement comes from your permission rules and, better, from the system itself, such as a read-only database role.
Which is best for CI?
A plain CLI, with the binary pinned in your image. If you need MCP in CI, set MCP_CLIENT_SECRET for pre-registered OAuth clients and commit the server definition in .mcp.json.
Where to go next
If you are building a server of your own, our TypeScript MCP server build guide walks the full setup, and the MCP Server Starter Kit (TypeScript) ships the scaffolding. For the skill and settings side, the Claude Code Production Pack covers skills, hooks and permission rules for teams.
Sources
5. Claude Code docs: Skills
Originally published at wowhow.cloud
Top comments (0)