辩论双方,各有实证
怀疑派量出了 MCP 的真实上下文成本;捍卫派则指出 CLI 在多租户应用上失效、没有类型契约、agent 在不熟悉的 API 上浪费轮次解析文本。两边的论证都成立——也都没看到重点。
MCP:schema 全部预载
LLM(Agent)
MCP Client
JSON-RPC
MCP Server
Underlying API
所有 schema 开会即进上下文 · ~10K+ tokens
CLI:直接给个 shell
LLM(Agent)
Bash Tool
Unix shell
curl
jq
grep
无契约进上下文 · ~50 tokens(与工具集无关)
两种哲学:MCP 用预载 schema 换类型契约(vendor-neutral、JSON-RPC);CLI 用 shell 换近乎零上下文成本(但只有文本流,agent 靠猜)。
怀疑派的账单很具体——还没开始干活,schema 已经烧掉几万 tokens:
Playwright MCP
13.7K tokens
Chrome DevTools MCP
18K tokens
5-server 配置
55K tokens
← 干活之前先烧掉的上下文(每 1K ≈ 10px)
MCP 怀疑派的量化证据:一个 5-server 配置在 agent 开口前就占用 55K tokens。
重构:问题从来不是协议
2025-11-04,Anthropic 发布《Code execution with MCP》,对话从此改变。真正的病灶是「会话开始就把每个工具的完整描述加载进上下文」 的习惯——再加上工具返回的数据每步都穿过模型,一个工作流可以膨胀到 150K tokens。修法是翻转模型的工作:模型不再经上下文调工具,而是写代码、由代码在运行时里调工具 。
旧方式:工具经上下文调用
预载 Drive + Salesforce 双 schema
转录文本两次穿过模型
150K tokens
一个工作流即占掉大半上下文
新方式:模型写几行 TypeScript
import 需要的两个工具
数据在代码里流转,不碰模型
2K tokens
同一任务:Drive 转录 → CRM 更新
−98.7%
同一任务,两种走法:模型只看到它 import 的东西
Anthropic 的官方示例:Google Drive 会议转录流入 Salesforce CRM 更新——同一任务从 150K tokens 降到 2K,降幅 98.7%。
Cloudflare 把它推到极限:整个 2,500 端点的 API,只暴露 search 和 execute 两个函数——agent 写代码搜目录、只执行匹配的。实测(tiktoken,200k 上下文基准):
2,594 个工具的上下文成本(对数坐标,200k 上下文 = 100%)
Raw OpenAPI Spec 进 prompt
~2M · 977%
Native MCP(全 schema)
1.17M · 585%
Native MCP(仅必需参数)
244K · 122%
Code Mode(2 个函数)
1,069 · 0.5%
注:为可读性未严格按对数比例绘制,数值以标注为准——前三种方式全部超出 200k 上下文,Code Mode 只占 0.5%
Cloudflare 实测:前三种方式都装不进 200k 上下文(977% / 585% / 122%),Code Mode 只用 0.5%——三个数量级的差距。
Code Mode:两种原语,一个运行时
Code Mode 是这样一个运行时:agent 写的代码混合两种原语,按任务逐个挑选 。形象地说——旧模型里 agent 走进一个所有工具都摆在桌面上的房间;Code Mode 里 agent 走进一个墙上挂着工具目录的房间,只取下需要的。
Code Mode:typed contracts, loaded on demand
LLM(Agent)
写代码(而非发工具调用)
Code Sandbox
import(JIT 加载类型)
Tool Catalog(工具目录)
github
已 import(带类型)
slack
jira
search
+ more…
可用但签名未加载(零成本)
类型在 import 时加载 · ~2K tokens · 跳过的工具零成本
运行时提供整个工具目录,但只有被 import 的工具类型签名进入上下文——其余的全部免费。
代码长这样
// agent 写的代码;类型只在这两行 import 处进入上下文
import { searchFiles } from "@tools/github";
import { sendMessage } from "@tools/slack";
const files = await searchFiles({ pattern: "*.py", path: "./src" });
const summary = files.map(f => f.path).join("\n");
await sendMessage({
channel: "#engineering",
text: `Found ${files.length} Python files:\n${summary}`,
});
三个此前不可能的性质同时成立:① GitHub 和 Slack 的工具定义只在 import 行进入上下文,目录里其他工具全部在外;② 文件列表在代码中处理,模型永远看不到原始路径列表,只看到摘要;③ 循环与转换在真实代码里组合,不再每步 round-trip 经过模型。
收尾:两者都活了下来
How they layer together
Code Mode 采用 MCP 的类型契约 + CLI 的懒惰加载;agent 按任务挑选
Code Mode(agent 的运行时)
Bash(CLI 原语)
$PATH 上的任何二进制
git, gh, curl, jq, grep …
Typed module imports(MCP 原语)
专有 API——类型随 import JIT 加载
Salesforce / Stripe / 内部服务 …
文件搜索是 bash · Salesforce 更新是 typed import · 同一工作流几行代码混用两者
Code Mode 不是任何一方的替代者,而是使用双方的运行时。MCP 与 CLI 从「运行时」降格为「被运行时组合的原语」——这就是「MCP vs CLI」问错问题的原因。
原文的三方对比全景图与 Cloudflare 实测表(位图)
原文配图:三种哲学并排对比 + 分层组合。MCP 每调用一次孤立 round-trip;CLI 管道组合但无契约;Code Mode 取两者之长。
原文配图:Cloudflare 用 tiktoken 实测的 token 成本对照表。
「MCP 已死」是这场辩论最错的结论
MCP SDK 下载量从年初 1 亿涨到 3 亿(2026-05),是当时增长最快的 agent 基础设施;到 2026-07 月下载已超 4 亿。死掉的只有「预先加载所有工具」这一个做法——它从来就不是好主意。2026 年构建 agent 的规则很简单:工具定义属于代码,不属于上下文 。模型写几行代码调用它们,运行时做剩下的事。