2026 年,为什么一线团队开始从 MCP 撤回 CLI?

35 阅读9分钟

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 哲学的核心不是"命令多",而是"一个命令做好一件事,然后用管道串起来":

bash

git log --pretty=oneline | grep "hotfix" | awk '{print $2}' | sort | uniq -c | sort -nr

一条命令,从日志里捞出 hotfix 提交并按作者统计。MCP 做不到这种自由拼接——每个 Server 是一座孤岛,它的输出必须先被 Host 解析成 JSON,再塞给下一个 Server。组合点从"流"退化为"字段",每次拼接都像在写胶水代码。可组合性恰恰是 Agent 时代最值钱的能力,因为 Agent 的本质就是把许多小能力串成一条长链,而低摩擦串联的前提是:输出能天然成为输入。

三、一条管道与五次往返

抽象地谈效率容易失真,看一个具体任务:给目录里的横版照片批量加水印并上传。

MCP 模式下,这个需求会被拆成"读目录 → 查图片信息 → 筛选横版 → 加水印 → 上传"五步,每一步对应一次工具调用、一次模型思考、一次等待往返。

CLI 模式下,一条管道加一个循环就够了:

bash

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 侧。这对合规场景是刚需。

所以真实的落地形态不是替代,而是分层:

text

┌──────────────────────────────────────┐
│  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 更受欢迎。

text

# 好:输出即接口
$ 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 兜底":

typescript

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 学会使用简单的工具。