
2026 年围绕 MCP 和 CLI 的争论又热了一轮。一个常见说法是：MCP 会把大量工具 schema 塞进上下文，token 成本高；CLI 更便宜，模型也更熟悉，所以 MCP 没有必要。

这个判断有一半是对的。CLI 在本地开发工具、单人工作流、已知命令集合里确实更直接，也经常更省 token。但把这个结论推到所有 Agent 场景，就会漏掉另一个更关键的问题：

**Agent 到底是在代表谁工作？**

如果 Agent 只是代表开发者本人，在本机调用 `git`、`docker`、`kubectl`、`ffmpeg` 这类成熟工具，CLI 通常是更好的默认选择。如果 Agent 代表客户、员工或租户去访问远程系统，工具选择就不再只是 token 成本问题，而是身份、授权、作用域、审计和隔离问题。

这也是 MCP 和 CLI 最容易被混在一起讨论的地方。它们都能让模型调用外部能力，但服务的边界不同。

## CLI 做得好的地方

CLI 的优势很朴素：它是现有工程系统的原生接口。

对模型来说，CLI 还有一个额外优势：大量训练材料里本来就有命令行、Shell、GitHub issue、StackOverflow 答案、CI 日志和教程。模型对这类文本接口比较熟悉，知道如何组合命令、查看帮助、过滤输出、把一个命令的结果交给下一个命令。

例如本地开发里，下面这些操作本身就适合 CLI：

```bash
git log --oneline -n 10
git diff --stat
docker ps
kubectl get pods -n default
ffmpeg -i input.mp4 output.mp3
```

这里强行套一层 MCP，通常只是把已经清楚的命令包装成 JSON schema。Agent 需要先知道有哪些工具、每个工具有哪些参数，再发起结构化调用。对于 `git status` 这类简单任务，schema 本身可能比任务还大。

第三方 benchmark 也能看到类似现象。Smithery 做过 MCP、CLI、raw API 的对比实验，结论不是「CLI 永远赢」，而是更细：在一些简单操作上 CLI 的 token 使用更低；但在远程服务和不熟悉 API 上，MCP 的结构化集成更容易提升成功率。[^smithery]

所以 CLI 的适用边界可以先这样记：

1. 工具已经有成熟 CLI。
2. Agent 运行在开发者自己的环境里。
3. 凭证继承当前用户上下文是可接受的。
4. 任务主要是本地文件、代码仓库、容器、系统工具。
5. 失败影响面主要限于当前操作者。

这个范围里，CLI 简单、便宜、可调试，没必要为了协议统一而替换掉它。

## CLI 开始变弱的地方

CLI 的问题通常不是「不能用」，而是它默认假设调用者就是当前机器上的人。

这在单人开发环境里没问题。`gh` 读的是当前用户登录态，`kubectl` 读的是当前 kubeconfig，`aws` 读的是本地 profile。Agent 继承这些凭证后，就像你自己在终端里操作。

但一旦 Agent 开始代表「别人」工作，这个模型就会变得危险。比如：

1. SaaS 产品里的 Agent 读取客户的 GitHub repo。
2. 内部 Agent 代表某个员工查询工单、日历、文档。
3. 客服 Agent 代表用户修改订单、退款或发送消息。
4. 多租户系统里的 Agent 同时连接多个客户的数据源。

这些场景里，问题不再是「命令能不能跑」，而是：

- 这次访问属于哪个用户？
- 用户是否同意 Agent 访问这个资源？
- token 是否只允许当前动作需要的 scope？
- A 租户的数据是否可能进入 B 租户的上下文？
- 事后能否追踪哪个 Agent 在什么时间访问了什么资源？

传统 CLI 并不是为这些问题设计的。它可以通过外层系统补鉴权、补审计、补租户隔离，但这些能力不是 CLI 接口本身自然表达出来的。越往产品化、多用户、合规环境走，这些补丁越容易变成主系统的一部分。

## MCP 真正要解决的问题

MCP 的价值不在于替代所有 CLI，而在于给 Agent 和外部系统之间提供一个更明确的协议边界。

MCP 的基础协议使用 JSON-RPC。工具、资源、提示词、传输、授权都被放进协议模型里。尤其在远程 HTTP 传输场景下，MCP 的授权规范已经把 OAuth 2.1、PKCE、Protected Resource Metadata、客户端注册、scope 选择等机制放进设计范围。[^mcp-auth]

这意味着 MCP 更适合表达下面这些生产化问题：

1. **用户级身份**：Agent 是代表哪个 resource owner 发起请求。
2. **作用域控制**：读、写、删除、管理等能力可以拆成不同 scope。
3. **授权与同意**：用户可以看到并批准 Agent 需要的访问范围。
4. **动态连接**：Agent 可以在运行时发现授权服务器和注册方式。
5. **审计基础**：结构化请求更容易进入日志、策略系统和 SIEM。

这些能力不是 MCP 服务器一启动就自动拥有。你仍然需要实现租户隔离、日志、策略、权限映射和安全运营。但 MCP 给了这些能力一个合适的位置；CLI 则更像是在已有的人类工具外面再包一层。

## schema 开销是真问题，但不是根本问题

反对 MCP 时最常见的理由是 schema 开销。

这个问题真实存在。早期 MCP server 往往把大量工具定义一次性暴露给模型。连接几个大型服务后，上下文里可能塞满工具名、参数、描述和返回结构。任务还没开始，token 已经花掉一截。

MCP 在 Agent 里容易花 token，通常不是因为一次 `tools/call` 本身有多复杂，而是成本叠在了几个地方：

1. **工具目录预加载**：Client 往往会先把 MCP Server 暴露的 tools 列表、名称、说明、参数 schema 放进上下文。工具越多，启动成本越高。
2. **参数 schema 很详细**：为了让模型知道怎么调用工具，schema 里会包含字段名、类型、枚举、必填项、描述和嵌套结构。复杂 API 的参数说明可能比实际任务大很多。
3. **多个 server 叠加**：Agent 同时接 GitHub、Slack、Notion、数据库、工单系统时，每个 server 都带一套工具说明。单个 server 看起来还能接受，叠起来就会挤占上下文。
4. **调用结果也会进入上下文**：MCP 返回的结构化结果通常会被模型继续读取和推理。如果工具返回了大量 JSON、列表、日志或文档片段，后续对话还会继续为这些内容付 token。
5. **工具选择也要消耗上下文**：模型需要在一堆工具里判断该用哪个、参数怎么填。工具越多，选择空间越大，提示词和推理成本也会增加。

CLI 的成本结构不同。模型不需要一开始看到完整的 `git` 或 `kubectl` 命令全集；它可以先执行一个小命令，再根据 stdout 继续下一步。比如 `git status` 的上下文成本主要是命令和输出，而不是整套 Git API 的结构化说明。

但这更像是实现方式问题，不是协议本身的死结。

Cloudflare 的 Code Mode 就是一个例子。它没有把大量 API endpoint 全部展开成工具，而是把访问能力收敛到 `search()` 和 `execute()` 两个工具，让 Agent 先搜索再执行，避免把完整 API schema 预加载进上下文。Cloudflare 官方文章把这个模式描述为用大约 1000 token 暴露整个 API，并把工具发现变成渐进式过程。[^cloudflare-code-mode]

Anthropic 也提出过类似的 code execution with MCP 模式：不要让模型在上下文里背完整工具目录，而是通过代码执行环境按需加载工具、过滤数据、组合调用。它解决的是同一个问题：减少一次性工具暴露，把上下文留给当前任务。[^anthropic-code-exec]

所以更准确的说法不是「MCP schema 开销太大，所以 MCP 不适合 Agent」，而是：

**把所有工具 schema 一次性塞进上下文，是不适合大规模 Agent 的 MCP 使用方式。**

合理的 MCP 设计会走向渐进发现、工具搜索、代码执行、按需加载，而不是无限扩展工具列表。

## 选择标准：看 Agent 代表谁

可以把选择压缩成一个问题：

**这次工具调用的影响面是否超出当前开发者自己？**

如果答案是否，CLI 通常够用。  
如果答案是，MCP 或类似的结构化远程工具协议就应该进入设计。

```mermaid
flowchart TD
    A["Agent 需要调用外部能力"] --> B{"是否只是代表当前开发者本人？"}
    B -->|是| C{"是否已有成熟本地 CLI？"}
    C -->|是| D["优先 CLI：低成本、易调试、符合现有工作流"]
    C -->|否| E["考虑 API SDK 或轻量工具封装"]
    B -->|否| F{"是否涉及用户数据、租户、权限或审计？"}
    F -->|是| G["优先 MCP / 结构化远程协议：身份、scope、授权、审计"]
    F -->|否| H["按服务复杂度选择 API、MCP 或专用工具"]
```

更具体一点：

| 场景 | 更适合 |
|---|---|
| 本机代码修改、Git 操作、容器调试 | CLI |
| 单人自动化脚本、可信环境里的批处理 | CLI |
| 已有成熟 CLI，且凭证继承当前用户可接受 | CLI |
| SaaS Agent 访问客户资源 | MCP |
| 企业内部 Agent 代表员工访问业务系统 | MCP |
| 多租户、合规、审计敏感场景 | MCP |
| 不熟悉的远程 API，需要结构化发现和参数约束 | MCP 或 API SDK |

## 一个更实际的混合形态

最终大概率不会是 MCP 或 CLI 谁消灭谁，而是混合使用：

1. 本地开发工具继续走 CLI。
2. 远程服务优先提供清晰 API。
3. 面向 Agent 的访问层用 MCP 或类似协议做结构化封装。
4. 大型 API 不直接暴露完整工具列表，而是使用搜索、执行、按需加载。
5. 授权、scope、审计、租户隔离放到协议和平台层统一治理。

这也符合工程系统的常识：不要为了统一接口替换掉已经稳定的工具，也不要把人类 CLI 当成多租户 Agent 平台的安全边界。

## 结论

MCP 和 CLI 不是同一个层面的替代关系。

CLI 适合开发者本地环境：工具成熟、模型熟悉、token 低、调试简单。它的问题是默认继承人的身份和凭证，不擅长表达用户级授权、租户隔离和审计。

MCP 适合 Agent 产品化后的远程服务访问：它能把工具、资源、授权、scope 和结构化调用放进一个协议边界里。它的问题是早期实现容易一次性暴露过多 schema，需要用渐进发现、代码执行、工具搜索等方式降低上下文成本。

所以真正的问题不是「MCP 还是 CLI 更先进」，而是：

**Agent 是在替你操作本机，还是在代表别人访问系统？**

前者优先 CLI。后者要认真考虑 MCP。

[^smithery]: Smithery, [MCP vs CLI is the wrong fight](https://smithery.ai/blog/mcp-vs-cli-is-the-wrong-fight).
[^mcp-auth]: Model Context Protocol, [Authorization specification](https://modelcontextprotocol.io/specification/draft/basic/authorization).
[^cloudflare-code-mode]: Cloudflare, [Code Mode: give agents an entire API in 1,000 tokens](https://blog.cloudflare.com/code-mode-mcp/).
[^anthropic-code-exec]: Anthropic, [Code execution with MCP: building more efficient AI agents](https://www.anthropic.com/engineering/code-execution-with-mcp).

