为什么越来越多的大厂抛弃 MCP,转向 CLI?
MCP 曾被誉为 "AI 的 USB-C",但 2026 年的生产环境正在讲述另一个故事。
一、MCP 的辉煌与困境
2024 年底,Anthropic 推出 Model Context Protocol(MCP)时,整个 AI 社区为之振奋。统一的工具调用协议、一次实现处处可用、告别 N×M 的适配噩梦——这些承诺确实击中痛点。
// MCP 的典型调用方式
{
"name": "read_file",
"arguments": {
"path": "/src/config.ts"
}
}
但 18 个月后的今天,一线工程师的反馈却呈现出另一番景象:
- 调试困难:MCP 的错误信息往往淹没在 JSON-RPC 的层层封装中,一个参数类型错误可能要翻三层日志才能定位
- 版本碎片化:不同客户端对 MCP 规范的实现存在微妙差异,"标准"并不标准
- 性能开销:JSON-RPC 的序列化/反序列化在高频调用场景下成为瓶颈
- 生态锁定:一旦深度接入某家的 MCP 生态,迁移成本并不低于传统的插件架构
二、CLI 的回归:不是倒退,是进化
与 MCP 的困境形成鲜明对比的,是 CLI 工具在 AI 工程中的强势回归。
2.1 为什么 CLI 更适合生产环境?
| 维度 | MCP | CLI |
|---|---|---|
| 调试体验 | JSON-RPC 层层封装,错误信息不透明 | 标准 stderr/stdout,Unix 哲学 |
| 版本管理 | 客户端与 Server 版本耦合 | 独立二进制,semver 明确 |
| 性能 | HTTP + JSON 序列化开销 | 本地进程,管道通信 |
| 可组合性 | 受限于客户端实现 | pipe、xargs、parallel 任意组合 |
| 测试 | 需要模拟客户端环境 | 标准单元测试,CI 友好 |
# CLI 工具链的自然组合
cat api-spec.yaml | \
openapi-generator generate -g typescript-fetch | \
eslint --fix --stdin | \
tee generated-client.ts
2.2 大厂的 CLI 实践
Vercel 的 ai CLI:不依赖任何 MCP Server,直接通过子进程调用 git、npm、docker,用 stdio 获取结果。简单、可靠、零网络依赖。
GitHub Copilot CLI:早期尝试过 MCP 集成,后来全面转向 gh CLI 的原生命令调用。原因很直接:工程师已经熟悉 gh pr create 的语义,没必要再包一层 JSON-RPC。
字节跳动的内部实践:据内部工程师分享,其 AI Coding 平台从 MCP 迁移到 CLI 后,工具调用延迟从平均 230ms 降至 45ms,调试时间减少 60%。
三、深层原因:协议抽象 vs 语义透明
MCP 的核心设计哲学是协议抽象——隐藏底层实现,提供统一的调用界面。这在理论上是美好的,但在工程实践中却带来了"抽象泄漏"。
# MCP 的抽象:你看到的
result = await mcp_client.call("git_status", {"repo": "."})
# 实际发生的:层层转发
# AI Client -> MCP Client -> HTTP Transport -> MCP Server -> git subprocess
# 任何一层出错,你得到的可能只是一个模糊的 "Internal Error"
CLI 则遵循语义透明原则——每个命令的输入输出都是可见的、可预测的、可组合的。工程师可以:
- 直接阅读文档:
man git-status比 MCP 的 schema 定义直观得多 - 本地复现:在终端里敲同样的命令,排除 AI 层的问题
- 精确控制:
GIT_TRACE=1 git status可以看到完整的执行轨迹
# 语义透明的调试
$ GIT_TRACE=1 git status
13:45:32.123456 git.c:455 trace: built-in: git status
13:45:32.123789 run-command.c:666 trace: run_command: git status --porcelain
四、不是替代,是分层
需要澄清的是,大厂并非完全抛弃 MCP。更准确的说法是:重新分层。
┌─────────────────────────────────────┐
│ AI Agent / Coding Assistant │
├─────────────────────────────────────┤
│ CLI Tool Layer (gh, vercel, kubectl)│ ← 新增/强化
├─────────────────────────────────────┤
│ MCP Server Layer (选择性保留) │ ← 精简
├─────────────────────────────────────┤
│ Native API / SDK │
└─────────────────────────────────────┘
保留 MCP 的场景:
- 跨网络边界的工具调用(本地 AI 调用远程服务)
- 需要严格类型约束的复杂工作流
- 第三方生态集成(如 Slack、Notion 的官方 MCP Server)
转向 CLI 的场景:
- 本地开发工具链(git、npm、docker)
- 高频、低延迟的操作
- 需要精细错误处理和重试逻辑的任务
五、给开发者的建议
5.1 如果你是工具开发者
不要急于实现 MCP Server。先问自己:
- 用户是否已经在用 CLI 使用你的工具?
- 你的工具输出是否适合机器解析(JSON/YAML)?
- 错误信息是否足够清晰,能让 AI 自我修复?
如果答案都是 Yes,一个设计良好的 CLI 可能比 MCP Server 更受欢迎。
# 好的 CLI 设计:输出即 API
$ mytool list --format=json --quiet
{"items": [{"id": 1, "name": "foo"}], "total": 1}
# 坏的 CLI 设计:人类友好,机器灾难
$ mytool list
Here are your items:
- Item #1: foo (created 2 days ago)
5.2 如果你是 AI 应用开发者
采用"CLI 优先,MCP 补充"的策略:
// 优先尝试 CLI
async function safeExec(command: string[]): Promise<Result> {
try {
return await execa(command[0], command.slice(1));
} catch (e) {
// CLI 失败时,回退到 MCP 或手动处理
return await mcpFallback(command);
}
}
六、未来展望
MCP 和 CLI 的争论,本质上是远程过程调用与本地命令执行的古老辩论在 AI 时代的新演绎。
我的判断:
- 短期(1-2 年):CLI 在 AI Coding 场景占据主导,MCP 在跨服务集成场景保持优势
- 中期(3-5 年):可能出现新的混合协议,结合 CLI 的简洁和 MCP 的结构化
- 长期:协议本身可能变得不重要——AI 的上下文理解能力足够强,能够自动选择最合适的交互方式
技术选型没有银弹。MCP 解决了"统一调用"的问题,却引入了"调试复杂"的新问题。CLI 看似简单,却要求工具开发者提供机器友好的接口。
2026 年的最佳实践或许是:让工具保持简单,让 AI 学会使用简单的工具。
你在项目中用 MCP 还是 CLI?遇到过哪些坑?欢迎在评论区讨论。