Chapter 05
设计权衡、选型与前沿
01–04 把 MCP 的结构、机制、双向性、安全都拆开了。这一章站远一点:为什么是这些取舍、什么时候该用 MCP、它正往哪走。
本章你将建立的 schema
- 每个核心设计(JSON-RPC、能力协商、双向、stateful)的备选方案与被牺牲掉的东西
- MCP 与 function calling / OpenAPI / A2A / LangChain 不是同一层——各自补位,不是替代
- 一棵选型决策树:什么场景 raw function calling 就够,什么场景 MCP 才回本
- 带日期的规范演进时间线,以及一个 2024 年的心智模型今天错在哪
这一章不再引入新机制,而是把已学的结构放进取舍与对照里。两类读者用得上:要在面试里讲清"MCP 和 function calling 什么区别"的人,和要在真实项目里决定"这套到底上不上 MCP"的人。判据全部落到具体场景与具体日期上。
5.1设计权衡:每个选择牺牲了什么
MCP 的每个核心设计都不是免费的最优解,而是一次有代价的取舍——理解它牺牲了什么,才知道它适合什么。
02–03 章讲的是"MCP 怎么做",没讲"为什么不那么做"。一个设计的轮廓,是由它拒绝的备选方案勾出来的。下面四个选择各回放一遍 02/03 的决定,并钉死代价——代价就是 5.6 选型的反面判据:当代价压过收益,就别上 MCP。
底层机制(比文档深一层):四个取舍可以串成一条因果链。选 JSON-RPC(02 章)决定了消息是人类可读、对称的 RPC,代价是放弃 HTTP 缓存、静态类型与原生流式;选能力协商(02 章)决定了用按需拼装的互操作替代单一版本号闸门;选双向(03 章)用 server→client 回调换来了 agentic 深度,代价是简单性与横向扩展;选 stateful 会话(02/03 章)用可持久的上下文换来了 sampling / 订阅这些能力,代价是负载均衡不再 trivial。前一个选择往往逼出后一个:要双向回调,就几乎必须 stateful;要 stateful,就难再用无脑轮转的负载均衡。
| 选择 | 备选方案 | 得到 | 牺牲 |
|---|---|---|---|
| JSON-RPC(02) | REST / gRPC | 人类可读、对称的双向 RPC,请求与通知同构 | HTTP 缓存语义、静态类型契约、原生流式 |
| 能力协商(02) | 单一版本号闸门 | 按需拼装、各取所需的互操作,新能力可渐进加入 | "一个版本对齐一切"的简单心智 |
| 双向(03) | 无状态工具调用 | server→client 回调,撑起 sampling / elicitation 的 agentic 深度 | 简单性、以及无脑横向扩展 |
| stateful 会话(02/03) | 无状态 HTTP | 可持久的上下文,使 sampling / 订阅 / 通知得以成立 | trivial 的负载均衡(会话需粘连) |
这张表不是"MCP 很全面"的赞歌,而是一张反向清单:右两列正是 5.6 里"什么时候别上 MCP"的判据。无状态 HTTP + REST 的工具调用在简单场景里更省事——MCP 的整套机制只有在需要它买到的那些能力(双向、持久上下文、跨端复用)时才回本。
5.2MCP vs 原生 function calling(头号误解)
function calling 是模型能力,MCP 是供给并执行工具的基础设施——两者不在同一层,既非替代也非竞争。
这是关于 MCP 最常见的错误对立。把它讲清楚需要先分清两件根本不同的事。
- function calling 是一种模型能力:LLM 在生成时输出一条"用参数 Y 调用工具 X"的结构化意图。它只发出意图,从不执行——模型既不知道工具住在哪,也不负责跑它。这正是 01 章 §1.5 钉死的那条:tools = model-controlled = function calling。
- MCP 是供给并执行这些工具的基础设施:运行时发现(
tools/list)、会话生命周期(02 章的握手)、传输、进程外执行。模型依旧通过普通 function calling 选出要调的工具——MCP 只是把工具目录送进那套机制,并在工具被选中后真正执行它。
底层机制(比文档深一层):两者是协作关系,不是二选一。一次完整调用里,MCP 通过 tools/list 把目录注入模型的可选清单 → 模型用它原生的 function calling 选出工具 X 与参数 → MCP 把这次调用路由到进程外的 server 执行 → 结果回填进上下文。抽掉 function calling,MCP 没有任何东西可调(模型不再会"选工具");抽掉 MCP,function calling 发出的意图无处落地(没有目录、没有执行)。把"MCP vs function calling"当成对立,等于问"USB 协议 vs 手指按键"哪个更好——一个供给与执行,一个发起选择。
一个应用只接 3 个稳定工具、只用一家 LLM、执行也由这个应用自己管。上 MCP 还是裸用 function calling?(先停十秒)
展开答案(先自己答)
裸用 function calling。<5–10 个工具、单一 provider、单一应用自管执行——这正是 MCP 的过度工程区:直接在应用里声明工具 schema、自己执行,"20–30 行"就够。MCP 的握手、传输、进程外执行在这里全是没被摊销的额外成本。MCP 在 10+ 工具、多 provider、或工具要跨团队 / 跨 client 复用时才回本——见 5.6。注意这不是"哪个更先进",是规模与复用度决定的临界点。
5.3MCP vs OpenAPI / GPT Actions
GPT Actions 是上传一份静态 OpenAPI、单向、只连公网、锁定 OpenAI 的 REST 调用;MCP 是 stateful、双向、运行时动态发现、能触达本地私有资源的中立协议。
底层机制(比文档深一层):GPT Actions(即 ChatGPT 里的自定义 GPT 动作)在配置期上传一份静态 OpenAPI schema,运行时就是无状态 HTTPS REST 调用——单向、只能打公网公开端点、绑定在 OpenAI 平台内。MCP 走的是另一条路:stateful 会话、双向(server 能推 notifications/list_changed 等通知)、运行时动态发现工具、并且可以是跑在本地的 stdio server,直接读私有文件 / 数据库而完全不暴露到公网,且 vendor-neutral。判据落到三点:工具集是否在运行时变、资源是否私有、是否只服务 ChatGPT。
| 维度 | GPT Actions / OpenAPI | MCP |
|---|---|---|
| 状态 | 无状态 HTTPS REST | stateful 会话 |
| 方向 | 单向(client→endpoint) | 双向(server 可推送 list_changed 等通知) |
| 工具发现 | 配置期上传静态 OpenAPI schema | 运行时动态发现(tools/list) |
| 资源触达 | 只能打公网公开端点 | 本地 stdio server 可读私有文件 / DB,不暴露公网 |
| 归属 | 锁定 OpenAI / ChatGPT | vendor-neutral,多 client 复用 |
选 Actions:已经有一份公开的 OpenAPI REST API,且只面向 ChatGPT。选 MCP:要触达本地 / 私有资源、要多 client 复用同一套工具、或工具集会在运行时变化。
5.4MCP vs A2A(Agent2Agent)
不同层、互补而非竞争:MCP 管 agent↔tool,A2A 管 agent↔agent;一个 A2A agent 内部正是用 MCP 触达自己的工具。
底层机制(比文档深一层):MCP 与 A2A 处在不同层,routinely 叠在一起用。MCP 连的是 agent 与它的工具 / 数据;A2A 连的是 agent 与另一个 agent——通过 Agent Cards 做能力发现、做任务编排。典型组合:一个对外用 A2A 暴露能力的 agent,对内用 MCP 去调它自己的 GitHub server、数据库。要杀死的误解是"MCP vs A2A 是一场协议战争"——它们正交,不抢同一个生态位。
A2A 已捐给 Linux Foundation,发布 v1.0,引入 Signed Agent Cards(签名的能力卡,防伪造),150+ 组织参与。MCP 自身则于 2025-12-09 迁入 Agentic AI Foundation(Linux Foundation 旗下,由 Anthropic / OpenAI / Block 共同发起)。两者都进了 Linux Foundation,但落在不同治理项目里——这本身就印证了它们是正交的两层,而非一场零和的标准之争。
5.5MCP vs LangChain tools
LangChain tools 是进程内、零开销但框架锁定的 Python 对象;MCP 是进程外、跨语言跨框架、可在多个 client 间复用的协议——那一跳是 sub-millisecond。
底层机制(比文档深一层):LangChain tools 是进程内的 Python 对象,调用开销约 0ms,但锁定在 LangChain 框架里、只在这一个 Python 进程里能用。MCP 是进程外协议,语言 / 框架无关,同一个 server 能被 Claude、Cursor、VS Code 复用;代价是一次 proxy 跳转,但这一跳是 sub-millisecond 级,相对 LLM 本身 100ms–10s 的延迟可忽略。官方的 langchain-mcp-adapters 桥接把 MCP server 直接暴露成 LangChain tools——两者不是二选一,可以接起来。
| 维度 | function calling | GPT Actions | LangChain tools | MCP |
|---|---|---|---|---|
| 本质层 | 模型能力(发起选择) | 平台集成 | 框架内工具对象 | 工具供给 + 执行协议 |
| 执行位置 | 不执行(仅发意图) | 公网 REST 端点 | 进程内 | 进程外 server |
| 状态 / 方向 | —(由载体决定) | 无状态 / 单向 | 进程内 / 单向 | stateful / 双向 |
| 延迟开销 | — | 网络往返 | ~0ms | sub-ms 代理跳转 |
| 复用范围 | 单 provider 的调用约定 | 锁定 ChatGPT | 锁定 LangChain | 跨 client / 框架 / 语言 |
"MCP 多一跳、慢"是常见的错误否决理由。那一跳是 sub-millisecond,淹没在 LLM 的 100ms–10s 延迟里,工程上不可感知。真正该用来否决 MCP 的是未被摊销的运维成本——多养一个进程 / 一套部署,在只有一个应用、几个稳定工具时不划算。否决点是运维负担,不是网络延迟。
5.6选型决策
把"上不上 MCP"压成几条可判定的标准:复用度、私有资源、运行时可变性、解耦、中立性——其一成立就倾向 MCP,全不成立就别上。
底层机制(比文档深一层):选型不是"谁更先进",是把 5.1 那张代价表反过来读。四个候选各有其成立条件:
- 选 MCP:工具要跨多个 client / agent / 框架复用;要触达本地 / 私有资源而不公网暴露;工具集在运行时会变;工具维护要与 agent 代码解耦;要 vendor 中立。命中其一即倾向 MCP。
- 选 raw function calling:单一应用、单一 provider、一把稳定的少量工具。MCP 在这里是过度工程。
- 选 OpenAPI / Actions:已经有一份公开的 REST + OpenAPI API,且只服务 ChatGPT。
- 选 A2A:集成单元是另一个自治 agent(与 MCP 正交——通常是叠加,不是替换)。
5.7前沿时间线(带日期)
MCP 的规范在一年多里改了四版,加过又删过同一个特性;用 2024 年的心智模型套今天的 MCP,会在传输、OAuth、批处理三处全错。
底层机制(比文档深一层):规范不是单调累加,而是试错。最典型的是 JSON-RPC batching:2025-03-26 加入,2025-06-18 又删除——只活了一个版本周期。把每一版"改了什么"摊开看,才不会拿着一个过期的 MCP 形象去面试或选型。
| 日期版本 | 状态 | 关键交付 | 同时废弃 / 移除 |
|---|---|---|---|
2024-11-05 | 初版 | MCP 发布;stdio + HTTP+SSE 双端点传输 | — |
2025-03-26 | 历史 | Streamable HTTP 取代 HTTP+SSE;OAuth 2.1;新增 JSON-RPC batching | HTTP+SSE 双端点传输(此版起弃用) |
2025-06-18 | 历史 | elicitation;结构化工具输出;OAuth 升为 resource-server + RFC 8707 / 9728;引入 MCP-Protocol-Version 头 | 移除 JSON-RPC batching(仅存活 2025-03→2025-06) |
2025-11-25 | 当前稳定 | URL-mode elicitation;实验性 tasks 异步;sampling-with-tools;Client ID Metadata Documents 取代 DCR;JSON Schema 2020-12 成为默认 | DCR 作为 OAuth 主要 onboarding 方式(被 CIMD 取代) |
2025-11-25;2025-06-18 那个 − batching 显式标出"加了又删"。注意:最右的 2026-07-28-RC 是 release candidate,尚未稳定,不要当成已交付的特性来用或在面试里宣称。采用与治理(带日期):OpenAI 于 2025-03 采用,Google DeepMind 于 2025-04 采用,Microsoft / GitHub 于 2025-05 加入指导委员会;治理在 2025-12-09 迁入 Agentic AI Foundation / Linux Foundation。规模上,到 2025-12 月度 SDK 下载约 97M、社区 server 超过 10,000 个。
一个停在 2024-11 的 MCP 形象会在三处出错:① 传输——还以为是 HTTP+SSE 双端点,实际自 2025-03-26 起已是 Streamable HTTP;② OAuth——还以为是 DCR + 朴素 OAuth,实际 2025-06-18 已升为 resource-server(RFC 8707 / 9728),2025-11-25 又用 CIMD 取代 DCR;③ 批处理——以为有 JSON-RPC batching 可用,它只在 2025-03→2025-06 间存在,现已移除。三处都按旧模型写,代码与论述都会对不上当前规范。
面试官说"MCP 支持 JSON-RPC 批处理,可以一次发多条请求降低往返"。这句话对吗?(先停十秒)
展开答案(先自己答)
不对——以当前稳定规范看是错的。JSON-RPC batching 确实进过规范,但只活在 2025-03-26→2025-06-18 一个周期,2025-06-18 已显式移除。当前 2025-11-25 不支持批处理。正确表述是"批处理曾短暂存在、现已废弃"。这道题考的就是"别拿过期版本特性当现状"——规范是试错演进的,不是单调累加。
§本章 self-check
先合上教程,把答案写在纸上或编辑器里。写完再点开对照——直接点开等于把这一节当再读一遍。
- 用一句话说清 function calling 与 MCP 各自负责什么;抽掉其中一个会发生什么?
- 给出两个"裸 function calling 就够、上 MCP 是过度工程"的具体条件,再给出两个"该上 MCP"的条件。
- "MCP vs A2A 是协议战争"错在哪?一个 A2A agent 内部如何用到 MCP?
- JSON-RPC batching 在哪一版加入、哪一版移除?当前稳定规范是哪一版、还支持它吗?
答案(先做完再展开)
- function calling 是模型能力:模型发出"调工具 X、参数 Y"的意图,但不执行。MCP 是基础设施:供给工具目录(
tools/list)并在进程外执行。抽掉 function calling,MCP 无可调之物;抽掉 MCP,意图无处落地。 - 过度工程:单一应用、单一 provider(外加少量稳定工具、自管执行)。该上 MCP:工具跨多 client / 框架复用、需触达私有资源不公网暴露(外加运行时可变工具集、与 agent 代码解耦、vendor 中立)。
- 错在把正交的两层当成同一生态位。MCP 管 agent↔tool,A2A 管 agent↔agent(Agent Cards 做能力发现 + 任务编排)。一个 A2A agent 对外暴露能力,对内用 MCP 去调自己的 server / 数据——两者叠加而非择一。
2025-03-26加入,2025-06-18移除(仅存活一个周期)。当前稳定是2025-11-25,不支持批处理。
给一个真实系统做选型
一个内部研发助手平台:要同时服务 Web 端和 IDE 插件两个 client;要读公司私有代码库与内网数据库(绝不能暴露公网);工具集随业务每周增删;未来还想接入一个独立的"运维 agent"自动处理告警。把这个系统的集成需求逐项映射到 function calling / MCP / OpenAPI Actions / A2A——哪部分用哪个,为什么?
提示(卡住再展开)
逐项对照 5.6 的成立条件:① 同一套工具要被 Web + IDE 两个 client 复用 → MCP(跨 client 复用);② 读私有代码库 / 内网 DB 不暴露公网 → MCP(本地 stdio server,命中"私有资源");③ 工具集每周增删 → MCP(运行时动态发现,命中"运行时可变");④ 接入独立"运维 agent" → A2A(集成单元是另一个自治 agent),而那个运维 agent 内部触达它自己的工具时仍用 MCP——A2A 与 MCP 叠加,不是替换。整套里几乎没有"裸 function calling 就够"的位置——因为复用、私有、可变三条全部命中。注意 function calling 仍在每次工具调用的底层发生(模型选工具那步),只是不需要单独为它做架构选择。