MCP 退潮:为什么一线工程团队开始转向 CLI-First 的 Agent 工具模式
2024 年底,MCP(Model Context Protocol)横空出世时,被冠以 "AI 世界的 USB‑C" 之名。统一工具调用、一次实现处处可用、终结 N×M 的适配噩梦 —— 这些承诺确实击中过痛点。
但到了 2026 年,一线工程团队的实践反馈呈现出另一幅图景:不是 "用不用",而是越用越亏。
需要先澄清一个被标题党消耗掉的事实:大厂并没有抛弃 MCP,而是在重新分层。真正发生的事,是工具接入层的重心从协议封装回摆到命令执行。这场回摆值得认真拆解,因为它暴露了 Agent 工程化最容易被忽略的一层 —— 上下文是稀缺资源,而不是免费的容器。
一、那笔没人愿意细算的 Token 账
MCP 的设计假设是:把工具的能力用结构化 schema 描述清楚,模型才能正确调用。这个假设在工具只有三五个时成立,在工具变成五十个时就崩了。
原因是 MCP 的加载方式偏中心化:客户端启动时倾向把全部工具的元信息 —— 名称、描述、入参 schema、示例 —— 一次性注入上下文。以 GitHub 的 MCP Server 为例,44 个工具的说明文字合计约 6.4 万字符,折算约 1.4 万 Token。单次加载就是这个量级,装三个 Server,对话还没开始干活,上下文预算已经先消耗掉一截。
保守估算一个工具 500–1000 Token,50 个工具就是 2.5 万到 5 万 Token 的固定开销。更糟的是这些 Token 并非 "有效推理",而是 "开机自检"—— 模型读完一堆它这次用不上的接口说明,才允许它拿起第一个螺丝刀。这就是业内所说的 Token 通货膨胀:成本随工具数量线性膨胀,收益却不随之增长。
CLI 的思路完全相反。它只向模型暴露一个 bash 工具,说明十几行。具体命令由模型现场写,常用命令(ls、grep、git、find、curl)早已内化在权重里,冷门命令现查 --help 或 man 即可。
差别在于加载时机:
- MCP:开机加载全家桶
- CLI:现查现用、用完即走
模型读文档同样花 Token,但它读的是用得上的那一段,而不是启动时把整本手册背一遍。
二、五个维度上的非对称
抛开成本,工程上的差异更值得摊开对比。
表格
| 维度 | MCP 常见实践 | CLI‑first 常见实践 |
|---|---|---|
| 上下文成本 | 启动时批量加载 schema | 按需读 --help / man / README |
| 调试体验 | JSON‑RPC 多层封装,错误淹没在嵌套对象里 | exit code + stderr + 日志,问题直接暴露 |
| 认证鉴权 | 每个服务各做一遍 OAuth / Key 分发 | 复用 OS 基建:SSH、环境变量、本地 config |
| 组合能力 | 组合点在 JSON 字段之间,需要胶水代码 | 组合点是 stdout → stdin,管道直接连 |
| 版本管理 | 客户端与 Server 版本耦合,SDK 升级易碎 | 独立二进制,semver 语义明确 |
逐条说。
调试
MCP 调用链路是典型的 "抽象泄漏" 场景:AI Client → MCP Client → Transport → MCP Server → 目标程序子进程。任何一层出错,暴露给用户的往往只是一句 Internal Error。一个参数类型写错,可能要翻三层日志才能定位。
CLI 的失败形态则极其直白:command not found 是没装,Permission denied 是权限,Connection refused 是服务没起。而且你可以本地复现 —— 在终端敲同一条命令,就能把 AI 层的问题隔离出去。
认证
这一点常被低估。Agent 不是接两个系统,它往往要接一整个开发环境甚至一整个企业的工具集合。若每个接入点都要重做一遍 OAuth 与密钥轮换,等于把操作系统几十年积累的认证基建全部弃用、从头再造。
CLI 世界早就有一套成熟到没人愿意重新发明的东西:~/.ssh/config、~/.gitconfig、~/.aws/credentials、GITHUB_TOKEN 这类环境变量约定。它们不优雅,但跑了几十年,有配套的审计与轮换工具链。
组合
这是差别最本质的一条。Unix 哲学的核心不是 "命令多",而是 "一个命令做好一件事,然后用管道串起来":
git log --pretty=oneline | grep "hotfix" | awk '{print $2}' | sort | uniq -c | sort -nr
一条命令,从日志里捞出 hotfix 提交并按作者统计。
MCP 做不到这种自由拼接 —— 每个 Server 是一座孤岛,它的输出必须先被 Host 解析成 JSON,再塞给下一个 Server。组合点从流退化为字段,每次拼接都像在写胶水代码。
可组合性恰恰是 Agent 时代最值钱的能力,因为 Agent 的本质就是把许多小能力串成一条长链,而低摩擦串联的前提是:输出能天然成为输入。
三、一条管道与五次往返
抽象地谈效率容易失真,看一个具体任务:给目录里的横版照片批量加水印并上传。
MCP 模式下,这个需求会被拆成「读目录 → 查图片信息 → 筛选横版 → 加水印 → 上传」五步,每一步对应一次工具调用、一次模型思考、一次等待往返。
CLI 模式下,一条管道加一个循环就够了:
for f in $(find ./photos -name '*.jpg' \
-exec identify -format '%w %h %i\n' {} \; \
| awk '$1>$2 {print $3}'); do
convert "$f" -gravity south -pointsize 36 -annotate +0+20 '© me' "wm_$(basename "$f")"
scp "wm_$(basename "$f")" user@server:/uploads/
done
find 负责遍历,ImageMagick 的 identify 报尺寸,awk 做宽高比筛选,convert 加水印,scp 上传。五个工具各司其职,没有一个是为此需求专门开发的。
需求一改(比如换成竖版、改水印位置),改几个参数重拼即可;而在 MCP 体系里,这通常意味着重新写一个工具、重新注册 schema、重新跑通协议。
这背后是两种设计哲学的差别:
- MCP:追求协议抽象,牺牲透明换取统一
- CLI:坚持语义透明,牺牲 "结构化" 换取可见、可预测、可组合
四、CLI 的软肋,恰恰是 MCP 的护城河
如果只讲到这里,会得出一个过于乐观的结论。CLI 有两个结构性问题必须正视。
第一是注入面。
让模型自由生成 shell 命令,等于把 rm -rf 的可能性交给了概率分布。引号与转义极易翻车,且错误往往隐蔽 —— 命令执行成功了,只是结果不对。企业云端环境不能接受 "靠模型自觉" 这种安全模型。
第二是权限边界。
MCP 的价值在于 "只允许设计内的操作":Server 暴露什么,模型就只能做什么,参数是 JSON,边界由 schema 定义清楚,鉴权与审计可以收敛在 Server 侧。这对合规场景是刚需。
所以真实的落地形态不是替代,而是分层:
┌──────────────────────────────────────┐
│ Agent / Coding Assistant │
├──────────────────────────────────────┤
│ CLI 工具层(git, gh, kubectl, aws) │ ← 强化
├──────────────────────────────────────┤
│ MCP Server 层(选择性保留) │ ← 精简
├──────────────────────────────────────┤
│ 原生 API / SDK │
└──────────────────────────────────────┘
保留 MCP 的场景通常是:跨网络边界的远程调用、需要强类型约束的多步工作流、第三方生态的官方集成。
转向 CLI 的场景通常是:本地开发工具链、高频低延迟操作、需要精细错误处理与重试的任务。
一句话概括:CLI 属于个人与内网,MCP 留在企业与云端边界。
五、为什么是现在:三个前提同时成立
有意思的问题不是 "CLI 更好",而是 "为什么这件事在 2026 年才发生"。CLI 一直在那里,五十年没变。变化的是另外三个前提。
- 模型能力越过了 "读文档" 的门槛
早期偏爱 schema,潜台词是 "模型太笨,必须给它标准答案"。当模型能自己读--help、读 man page、读 README,甚至通过试错理解输出结构时,把工具翻译成死板 JSON Schema 的收益就大幅下降。你只需要给它一个可探索的入口,而不是一份必须背诵的说明书。 - 上下文窗口变贵了,而不是变便宜了
即便窗口扩到百万级,"塞满" 依然是坏策略 —— 无关上下文会稀释注意力,抬高延迟与成本。工具描述属于典型的高频复用、低边际价值内容,最不该常驻。 - Agent 的运行形态从 "问答" 变成了 "干活"
问答场景下多几百 Token 无所谓;干活场景下,一次任务可能触发数十次工具调用,成本与延迟被放大一个量级。这也是为什么延迟数据会这么刺眼:有团队从 MCP 迁到 CLI 后,工具调用延迟从平均 230ms 降到 45ms—— 差值主要来自 JSON‑RPC 的序列化与链路转发,而非工具本身。
六、如果你在做工具:把 CLI 当产品来设计
这波转向对工具开发者的含义很具体:你的 CLI 就是你的 API。
判断标准只有三条:
- 用户是否已经在用 CLI 使用你的工具?
- 输出是否机器可解析?
- 错误信息是否清晰到能让 Agent 自我修复?
三个都 "是",一个设计良好的 CLI 往往比 MCP Server 更受欢迎。
✅ 好:输出即接口
$ mytool list --format=json --quiet
{"items":[{"id":1,"name":"foo"}],"total":1}
❌ 差:人类友好,机器灾难
$ mytool list
Here are your items:
Item #1: foo (created 2 days ago)
几个具体建议:
- 提供
--json / --format结构化输出,同时保留人类可读默认值 - 把
--help当作文档写,它是 Agent 的第一入口,不是给人扫一眼的备注 - 保持输出稳定:不要为了好看加 emoji、颜色码、动态进度条 —— 它们会让解析直接崩掉
- 把 exit code 语义做对:非 0 必须表示失败,别用 0 掩盖错误
- 把调试体验当产品功能:工程时间大半花在排错上,
-v / --trace的体验直接决定留存
对应用开发者,务实策略是 CLI 优先,MCP 兜底:
async function safeExec(cmd: string[], args: string[]) {
const r = await execa(cmd, args, { reject: false });
if (r.exitCode === 0) return r.stdout;
// CLI 失败时回退到结构化通道,或交由模型读 stderr 重试
return mcpFallback(cmd, args, r.stderr);
}
同时对自由生成的命令做白名单与沙箱约束 ——CLI 的灵活性必须由外部护栏平衡,而不是寄望模型自律。
结语:复杂度不会消失,只会搬家
MCP 和 CLI 之争,本质是 RPC 与本地命令执行这场古老辩论在 AI 时代的新一轮。封装从来不是为了消灭复杂度,而是把复杂度搬家:从 "用户操作" 搬到 "协议设计、schema 管理、上下文账单、鉴权集成与调试链路"。搬完之后常常发现,复杂度没少,账单反而更厚。
MCP 的愿景没有错,它解决的是治理问题;CLI 赢下的是干活问题。当模型足够聪明,最好的工具策略不再是替它把世界描述一遍,而是把它放进一个人类已经建好接口、建好认证、建好组合方式、建好调试方式的世界里,让它自己学。
如果只留一句话:
让工具保持简单,让 AI 学会使用简单的工具。
浙公网安备 33010602011771号