MCP 的使命已经完成
一个被验证的观察
今年参与开发了大量多端应用,得益于 AI Coding 的普及,个体的能动性和效率得到了极大的提升。为了保证各端体验一致性,一个人要开发 Android、iOS、HarmonyOS 三个端加前端的需求。公司给提供了几乎是不限量的 Qoder 服务,Qoder 体验确实非常好。为了支撑终端需求的开发,团队里提供了通用的工作流任务编排执行系统,这在 1M 上下文的 Qoder 里,体验很丝滑,但是在 Claude Code 里,如果是用的 opus 4.6,甚至连一个 Hi 都发不出去。排查下来,才发现原来是启动 Session,仅仅只是加载 MCP 工具,就已经用掉了 180K+ 的上下文,开局就陷入了无限 Compacting 的窘境。
在实际的工程实践中,MCP 比传统的 Function Calling 和 Skill 机制消耗更多的 token。这不是理论推测,而是已经被大量项目验证的现象。更令人深思的是,如今,行业正在脚投票:
- Perplexity:内部弃用 MCP,仅保留对外 Server。
- YC / Garry Tan:"MCP sucks honestly"。
- Thoughtworks:技术雷达警告 token 消耗和上下文污染。
- Cloudflare:2,500+ API 端点不用 MCP,改用 search() + execute() 两个工具,Agent 写 JS 查询。
- 新的 AAP(Agent Action Protocol):明确将"成本控制、权限模型、生命周期钩子"列为 MCP 的缺失项。
这不是"技术不成熟",而是设计哲学的根本分歧。
Token 浪费:MCP 最显性的痛点
协议层的结构性开销
MCP 的 token 浪费并非偶然,而是内嵌于其协议设计之中。首先,每个工具的定义都需要携带完整的 JSON Schema,包括参数结构、类型约束和自然语言描述。当工具数量增加时,这部分 schema 文本会作为系统提示的一部分反复送入模型上下文。以 GitHub MCP Server 为例,其 93 个工具的定义加载即消耗约 55,000 个 token,相当于 GPT-4o 一半的上下文窗口——这发生在用户尚未发出任何请求之前。连接 6 个常见 Server(GitHub、数据库、Slack、Jira、云基础设施、监控),工具定义本身就能消耗 60,000 至 90,000 token。在 Opus 模型的定价下,仅 schema 的月度开销可达 40,500 美元(按连接 6 个 Server、日均 10,000 次请求、每次请求均需完整加载 schema 估算)。
其次,MCP 的通信基于 Server-Sent Events 或 stdio,需要维持持续的双向连接。这意味着每次会话都要经历初始化、能力交换、工具列表获取等多轮协商,每一轮都携带大量协议元数据。最后,MCP 的 Resources 机制可以配置为自动注入上下文,容易导致"默认全量加载",进一步加剧上下文膨胀。
与 Function Calling 和 Skill 的对比
Function Calling(如 OpenAI/Claude 原生机制)遵循"按需索取"原则:模型在需要时调用特定函数,获取精简结果后继续推理。其 schema 相对紧凑,结果可控,没有冗余的上下文负担。Skill 机制(如 Kimi 的 Skill 系统)则采用高度封装的设计,预编排的工作流只暴露少量入口参数,内部逻辑对模型完全不可见,token 消耗最为节省。
MCP 则走了另一条路:它追求"通用转接头"式的生态互通,一个 MCP Server 可以被 Claude、Kimi、Cursor 等任意客户端使用。但这种通用性是有代价的——为了兼容所有可能的调用方,协议层必须携带完整的自描述信息,而这些信息每一次请求都要重新加载,无法摊薄。
按请求计费的"固定税"
在生产环境中,MCP 的 token 浪费呈现出"按请求计费"的特征,且服务端几乎无法通过缓存来优化。每个新用户请求都是一张独立的账单:
- Schema 是固定税 无论用户问什么,只要走模型+MCP 路径,就必须先加载 50,000 至 90,000 token 的工具描述。这部分不会因为"这是第 N 个用户"而减少。
- 工具结果是变动税 用户意图不可预测,查询参数组合无限,"查上个月的销售额"和"查这个月的销售额"是两个完全不同的查询,返回结果无法缓存复用。
- 模型没有记忆 即使服务端缓存了 Schema 的文本内容,每次请求仍然需要将其重新塞入模型的上下文窗口,模型必须"重新看到"才能"重新理解"。
对于大型项目,这种成本是毁灭性的。假设一个日活 10 万的中型 SaaS、10% 的请求走模型+MCP 路径(AI 渗透率偏乐观取值),按 GPT-4o 定价计算,月度成本约在 40-80 万元区间。实际成本取决于请求频率、schema 大小和结果截断策略。而传统 RPC 路径的同等请求,计算成本几乎为零,延迟仅为 10 至 100 毫秒。
有状态连接:与云原生架构的根本冲突
什么是有状态连接
MCP 的通信模型要求客户端与服务器之间维持一条持续的、双向的、有记忆的连接。这与传统的无状态 HTTP 请求截然不同:
- 无状态 HTTP 每个请求独立处理,服务器不记住之前的交互,响应完成后连接即可关闭,请求可以任意分发到后端节点。
- MCP 有状态连接 整个会话期间连接必须保持打开,服务器记住"你是谁、你有什么权限、你之前调用了什么、当前上下文是什么"。
生产环境中的具体冲突
这种设计假设与云原生架构存在多层面的冲突:
| 云原生组件 | 核心假设 | MCP 的冲突 |
|---|---|---|
| 负载均衡器 | 请求无状态,可任意分发到后端节点 | MCP 连接必须粘滞到同一节点,否则状态丢失 |
| 自动扩缩容 | 根据 QPS 动态增减实例 | 长连接导致实例无法优雅下线,缩容时连接中断 |
| Serverless(Lambda/Cloud Functions) | 函数执行完即销毁,按调用计费 | MCP 要求进程常驻,"冷启动"变成"热保持"成本 |
| 容器编排(K8s) | Pod 可任意重启、迁移 | 连接断开后,会话状态全部丢失 |
会话重建的灾难性成本
当连接意外断开(网络抖动、节点重启、超时),客户端必须重建整个会话环境:重新 TCP/TLS 握手、重新初始化、重新获取工具列表(再次加载 55,000 token 的 schema)、重新订阅资源、重新建立认证上下文。这不是"重试一次请求",而是"重建整个会话环境"。
在多实例部署场景下,问题更加隐蔽:如果请求路由到不同实例,MCP 会话无法共享;如果强制请求粘滞到同一实例,就回到了负载均衡的老问题;如果每个实例都独立维护会话池,那就是 N 条有状态连接乘以 M 个实例,内存占用随用户数线性增长,连接泄漏风险持续累积。
可组合性差:数据被迫流经模型
什么是可组合性
在软件工程中,可组合性指的是多个小组件可以像乐高一样直接拼接,不需要通过第三方中转。Unix 管道是最经典的可组合性设计:
cat log.txt | grep "ERROR" | awk '{print $1}' | sort | uniq -c | sort -nr
每个命令的输出直接成为下一个命令的输入,数据不经过用户空间的中转站。
MCP 的数据流瓶颈
MCP 的数据流却强制所有中间数据经过模型:
工具 A(查数据库)→ 模型(中转站)→ 工具 B(发邮件)
↑
│
所有中间数据必须经过模型
这带来了四个层面的效率损失:
1. 数据必须"流经模型"。如果工具 A 返回 10,000 行数据库查询结果,工具 B 只需要其中第 3 列的汇总统计,MCP 的标准流程要求工具 A 把全部结果返回给模型,模型将其塞进上下文,"理解"后提取关键信息,再调用工具 B。即使两个工具完全知道如何直接对话,它们也被强制通过模型中转。
2. 工具之间无法直接引用。MCP 没有"工具链"或"管道"的概念。每个 tool_call 是独立的,工具 A 返回的 resource_uri 对工具 B 来说只是一个字符串,无法直接读取内部状态或临时文件。
3. 无法并行组合。真正的可组合系统允许独立任务并行执行再合并结果,但 MCP 的架构是串行、单线程、模型协调的:模型决定调用工具 A,等待返回,再决定调用工具 B,再等待返回。即使工具 A 和 B 完全独立,也无法并行执行,因为调度权被垄断在模型手中。
4. 缺乏中间表示。Unix 有文本流,Docker 有容器镜像,WASM 有二进制模块,但 MCP 没有定义工具之间的通用数据格式。每个工具返回的结构由自己定义,模型必须在运行时动态理解这种格式,才能传递给下一个工具——JSON 转 CSV、图片 URL 转 base64,这些转换都靠模型完成。
一个具体场景的对比
场景:从数据库查询销售数据,生成图表,发送邮件报告。
Unix/CLI 方式:
psql -h db.company.com -c "SELECT * FROM sales WHERE date > '2026-01-01'" | python generate_chart.py --type bar | mutt -s "月度销售报告" manager@company.com -a /dev/stdin
数据以文本流传递,每个工具独立运行,不需要任何协调者,可以并行优化。
MCP 方式:
模型调用 query_database,等待 10,000 行 JSON 进入上下文; 模型调用 generate_chart,传递 10,000 行数据; 等待 base64 图片进入上下文; 模型调用 send_email,传递 base64 图片。
每步都必须等待模型决策,10,000 行数据在上下文中来回传递,三个工具无法并行,如果第 3 步失败,第 1 步的结果已经丢失上下文位置,需要重新查询。
生产架构中的 MCP:被关在服务端内部
实际部署模式与设计初衷的错位
在真实的生产环境中,MCP 很少以原生设计的方式使用。更常见的架构是:C 端客户端应用发起请求,到服务端后先过一层任务编排,如果无法准确识别意图,才交给模型决策,再由模型返回结果下发给客户端。MCP 的角色被限制在服务端内部,C 端无感知。
这与 MCP 的原生设计假设——客户端直连、长连接维持、有状态会话——形成了鲜明的错位。在这种架构下,MCP 的某些问题确实被缓解了:有状态连接发生在服务端内部,可以走内网直连或本地进程通信;工具 schema 不会暴露给 C 端;会话重建在内部网络中更快。
但核心问题并未消失
然而,token 浪费这个最致命的问题并未因为这种部署方式而减少:
- Schema 仍然每次都要加载 即使只有一条 MCP 连接,每次用户请求都要重新将 50,000 至 90,000 token 的 schema 塞进模型上下文。
- 工具返回仍然要中转 数据库返回的 10,000 行数据仍然要经过模型上下文,才能生成回复。
- 效率仍然低下 用户点击"查看销售额"按钮,传统前端调 API 查库返回 JSON 渲染,延迟小于 100 毫秒;走模型+MCP 路径,需要模型理解意图、选择工具、生成查询、等待返回、理解数据、生成回复,延迟数秒,且是概率性的——可能选错工具、生成错误查询。
MCP 把"确定性操作"变成了"概率性推理",这是效率低的根本原因。用户点击按钮时意图是明确的,但通过自然语言走模型+MCP,意图需要被"重新理解"一次。
服务端压力的真相
在这种架构下,"服务端压力非常大"的压力来源并非连接数,而是每次请求的上下文膨胀:模型必须"看到"工具描述才能选择工具,必须"看到"返回结果才能生成回复——这两步的 token 消耗是 MCP 的结构性成本,无论把 MCP 放在客户端还是服务端,这个成本都在。
更隐蔽的是,如果服务端是多实例部署,MCP 的有状态问题会以另一种形式存在:每个实例都独立维护 MCP 会话池,请求路由到不同实例时会话无法共享,强制粘滞则回到负载均衡困境,MCP Server 内部的数据库连接池、缓存、事务状态在实例重启时全部丢失。
优化策略:为什么大型项目都无法接受
面对这些问题,业界提出了若干优化策略,但在大型生产项目的尺度下,每一项都触及了不可接受的天花板:
| 策略 | 小型项目效果 | 大型项目的不可接受之处 |
|---|---|---|
| 精简 Schema | 少写描述,省 20% token | 工具从 50 个膨胀到 200 个,触及天花板;描述变模糊导致模型准确率下降 |
| 动态加载工具 | 3 个场景分类,准确率 90% | 100+ 场景边界模糊,意图识别本身需要另一个模型,引入二次推理延迟和成本 |
| 结果截断/摘要 | 用户问"总结",丢摘要没问题 | 用户问"找出第三行数据的异常值",截断直接丢信息 |
| 意图识别先行 | 已作为架构核心,挡住确定性请求 | 大型项目中真正需要模型灵活处理的复杂请求比例更高,这些请求绕不过 MCP,token 税照交 |
越大的项目,工具越多、场景越复杂、用户意图越不可预测,MCP 的"按请求固定税"就越沉重,而优化空间却越狭窄。最终,团队会自然地问:"既然我都关在服务端了,为什么不直接用更高效的调用方式?"。
通用性的迷思:协议层通用性是否是正确的抽象
通用性 ≠ 协议层通用性
MCP 的困境本质上是一个抽象层次错位的问题。通用性本身对 Agent 很重要,但 MCP 追求的是"协议层通用性"——任何工具都能插的 USB-C 口——而 Agent 真正需要的是"语义层通用性":理解意图、规划步骤、控制成本、保证安全。
| 层面 | 内容 | 是否必要 |
|---|---|---|
| 能力层(What) | Agent 能做什么:查询数据库、发邮件、部署代码 | 必须有 |
| 调用层(How) | 如何触发:REST API、CLI、MCP、函数调用 | 可以多样 |
| 治理层(Whether) | 能不能做、花多少预算、需不需要审批 | MCP 完全缺失 |
MCP 定义了"怎么调用",但完全不定义"是否该调用"。Agent 拿到数据库连接就能删表,协议层没有任何预算、权限、动作严重性的概念。这也是为什么新的 Agent Action Protocol(AAP)会明确将"成本控制、权限模型、生命周期钩子"列为 MCP 的缺失项。
真正被验证的通用性
2026 年的行业实践正在指向更务实的方向:
CLI 的隐性通用性:LLM 在训练数据中见过数百万次 git、curl、jq、kubectl 的使用。一个 git log --oneline -10 命令只需 200 token,而等价的 MCP 初始化需要 10,000+ token——50 倍差距。CLI 的通用性不是来自协议标准,而是来自训练数据的覆盖。
渐进式加载(Progressive Disclosure):Anthropic 和 Cloudflare 证明不需要一次性加载所有工具。Cloudflare 的 API 有 2,500+ 端点,如果每个都做成 MCP tool 需要 117 万 token。但他们只暴露 search() 和 execute() 两个工具,Agent 写 JavaScript 查询 API 规范,总成本降到 1,000 token——99.9% 的削减。
分层架构:最合理的演进方向不是"非 MCP 即 CLI",而是 MCP 负责能力发现和安全接入(认证、OAuth、权限范围),CLI/代码沙盒负责实际执行(组合、管道、过滤、调试)。
是否存在"没有 MCP 就不行"的场景
经过逐层剖析,我们可以直面最初的问题:是否存在"没有 MCP 就不行"的场景?
答案是:在当前的工程实践中,几乎没有。
MCP 能做的事都有替代方案,而且替代方案往往更成熟、更高效:
| MCP 能力 | 替代方案 | 优势 |
|---|---|---|
| 查询数据库 | 直接 SQL/ORM、GraphQL | 类型安全、编译期检查、无 schema token 开销 |
| 调用外部 API | HTTP client、gRPC、OpenAPI 生成 | 标准化、可追踪、可缓存、错误处理成熟 |
| 文件系统操作 | OS 调用、对象存储 SDK | 无中间层、权限控制原生 |
| 执行代码/脚本 | Docker、WASM、serverless | 沙箱更成熟、资源隔离、冷启动可控 |
| 知识库检索 | 向量数据库、Elasticsearch | 检索质量更高、延迟更低、成本可预测 |
| 多工具编排 | Temporal、Airflow、BPMN | 确定性执行、可重试、可观测、无幻觉风险 |
MCP 的真正独特之处不是技术能力,而是"让模型自己发现和调用工具"这个交互模式。它的价值在于:人描述目标,模型自己看工具列表、决定调用什么、处理结果——人只需要说"做什么",不需要知道"怎么做"。
但这个模式的价值边界非常清晰:只有当任务本身不可预定义,且执行者需要实时决策时,才可能有用。即便如此,替代方案仍然存在:专用 research agent 用更紧耦合的工具链,可观测平台用规则加异常检测,IDE 用代码补全加终端执行保留人的控制权。
真正接近"不可替代"的边界,可能是"有一个全新的、模型训练时没见过的工具,需要模型在零样本情况下学会使用,且人不能预先写适配代码"。但即使这里,用文档生成 OpenAPI spec、代码生成客户端、RAG 辅助生成代码片段等人 review 后执行,都是更可控的路径。
MCP 不是基础设施(如 TCP、HTTP),不是最佳实践(如 Docker、K8s),更像是一个实验性工具——探索模式,等待被更专精的方案取代。
另一个方向
WebSocket + 自定义 RPC(MCP 之前的路径)
如果放弃 MCP 的"协议层通用性"追求,最直接的选择是回到 MCP 之前的路:WebSocket 保持长连接,工具调用走 gRPC 或自定义 RPC,由代码路由而非模型选择。
┌─────────┐ WebSocket ┌─────────┐
│ 客户端 │ ←────────────→ │ 服务端 │
│ (Agent) │ (双向字节流) │ (工具集) │
└─────────┘ └─────────┘
│
▼
┌─────────────┐
│ gRPC/自定义 │
│ 直接调用 │
└─────────────┘
这本质上不是"MCP 的替代方案"——它是放弃了 MCP 要解决的问题。工具调用由代码硬编码路由,类型安全在编译期保证,不需要模型"理解"JSON Schema。工具描述不在模型上下文里,token 开销为零。
代价也很清楚:新增工具需要改代码、走部署流程,失去"模型动态发现"的能力。编排层(Harness)承担了工具调度的职责,模型退出工具选择路径——这让执行回归确定性的同时,也意味着 Agent 失去了自己探索未知工具的可能。
这是一个取舍,不是升级。对于工具集稳定、场景边界清晰的大型项目,这个取舍通常合理。正是这个原因,现在我们越来越重视编排层:让确定性执行回归编排层,模型只负责它擅长的判断和理解。
WebSocket + Agent 间对话协议(另一个范式)
"双向协作、主动对话"基本已经成为 AI Agent 设计的共识。如果彻底放弃协议层通用性的追求,另一种思路是:不要 MCP 的工具描述 + 调用语义,而是让 Agent 之间通过 WebSocket 用自然语言直接协商。
┌─────────┐ WebSocket ┌─────────┐
│ Agent A │ ←────────────→ │ Agent B │
│ (用户侧) │ │ (服务侧) │
└─────────┘ └─────────┘
│ │
▼ ▼
帮我查销售数据 收到,我需要调用数据库
↑ │
│ ▼
结果是什么? 正在查询...
↑ │
│ ▼
用户说预算 5 万 收到,继续执行...
这不是 MCP 的进化,而是对协议层通用性的彻底放弃——用 LLM 本身的语义理解能力来谈判协作,不再通过结构化工具协议做中介。它的优势和劣势来自同一个根源:没有 Schema 开销,但也没有 Schema 的确定性和契约保障。
这套思路的更远未来是 WebTransport——基于 QUIC 协议,原生支持多路复用和连接迁移,彻底解决队头阻塞。但 WebTransport 解决的是传输层问题(更快、更可靠),不是应用层问题(如何发现和调用工具)。它和 MCP 不是在同一个维度竞争。
架构选择的本质
MCP 的困境揭示了一个更深层的工程真理:通用性在协议层往往是反生产力的。
当 MCP 被关在服务端内部使用时,它的"通用协议"价值被架空了——C 端无感知、生态互通无从发挥、工具发现变成内部硬编码。与此同时,它的"模型上下文膨胀"成本却一分不少——每次请求都要交 Schema 入场费,每次结果都要经模型中转。既不够高效,也没发挥通用性。
大型生产项目的最终选择,不是"用不用 MCP",而是"在哪些边界情况下,愿意牺牲效率和可靠性,换取开发速度"。这个边界在成熟团队里通常被压得很窄:80% 的确定性请求走规则引擎(零 token),15% 的半复杂请求走小模型分类(低 token),只有 5% 的真正复杂/未知请求才交 full token 税给大模型加 MCP。
Agent 需要的不是"任何工具都能插的 USB-C 口",而是"知道该插什么、什么时候插、插进去之后怎么控制"的智能层。MCP 提供了前者,但后者才是生产环境的刚需。2026 年的趋势正在验证这一点:模型退居决策层,执行层回归标准编排——Temporal 做工作流、CLI 做数据管道、WASM 做沙箱执行,只在需要"判断"或"理解"的时候才调用模型。
这不是对通用性的否定,而是对通用性层次的重新定位:从"协议层的万能转接头",转向"语义层的意图理解",最终落实到"执行层的确定高效"。MCP 的探索是有价值的,它让我们更清楚地看到了 Agent 架构中真正需要被抽象的是什么——不是工具调用的协议格式,而是任务分解、成本控制、权限治理和可靠性保障这些更高阶的编排能力。