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,就难再用无脑轮转的负载均衡。

MCP 四个核心设计的 why-bank
选择备选方案得到牺牲
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。

MCP vs OpenAPI / GPT Actions
维度GPT Actions / OpenAPIMCP
状态无状态 HTTPS RESTstateful 会话
方向单向(client→endpoint)双向(server 可推送 list_changed 等通知)
工具发现配置期上传静态 OpenAPI schema运行时动态发现(tools/list)
资源触达只能打公网公开端点本地 stdio server 可读私有文件 / DB,不暴露公网
归属锁定 OpenAI / ChatGPTvendor-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 是一场协议战争"——它们正交,不抢同一个生态位。

2026 治理现状(带日期)

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——两者不是二选一,可以接起来。

5.2–5.5 候选横向对照
维度function callingGPT ActionsLangChain toolsMCP
本质层模型能力(发起选择)平台集成框架内工具对象工具供给 + 执行协议
执行位置不执行(仅发意图)公网 REST 端点进程内进程外 server
状态 / 方向—(由载体决定)无状态 / 单向进程内 / 单向stateful / 双向
延迟开销—网络往返~0mssub-ms 代理跳转
复用范围单 provider 的调用约定锁定 ChatGPT锁定 LangChain跨 client / 框架 / 语言
洞察 · 别用"延迟"否决 MCP

"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 正交——通常是叠加,不是替换)。
集成单元是另一个 agent? 而非工具 / 数据 是 A2A 与 MCP 正交,可叠加 否 跨多 client 复用? 或私有 / 运行时变 是 MCP 复用 / 私有 / 中立 否 已有公网 OpenAPI? 且只服务 ChatGPT 是 OpenAPI / Actions 公开 REST + 锁 ChatGPT 否 裸 function calling 单应用 / 单 provider / 少量稳定工具
图 5.1四个候选不是优劣排序,而是由场景条件分流:先问集成单元是不是另一个 agent,再问复用 / 私有 / 运行时可变,再问是否只服务 ChatGPT。注意:A2A 那条岔路是正交的——选了 A2A 通常仍在内部叠 MCP,不是与 MCP 二选一;只有最底下"少量稳定工具"才真正轮到裸 function calling。

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 batchingHTTP+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 取代)
2024-11-05 初版发布 HTTP+SSE 双端点 2025-03-26 Streamable HTTP OAuth 2.1 + batching 2025-06-18 elicitation − batching 结构化输出 2025-11-25 当前稳定 CIMD 取代 DCR Schema 2020-12 2026-07-28 RC · 未稳定
图 5.2四个稳定修订左→右排开,红色节点是当前稳定的 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 年的心智模型今天错在哪

一个停在 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

先合上教程,把答案写在纸上或编辑器里。写完再点开对照——直接点开等于把这一节当再读一遍。

  1. 用一句话说清 function calling 与 MCP 各自负责什么;抽掉其中一个会发生什么?
  2. 给出两个"裸 function calling 就够、上 MCP 是过度工程"的具体条件,再给出两个"该上 MCP"的条件。
  3. "MCP vs A2A 是协议战争"错在哪?一个 A2A agent 内部如何用到 MCP?
  4. JSON-RPC batching 在哪一版加入、哪一版移除?当前稳定规范是哪一版、还支持它吗?
答案(先做完再展开)
  1. function calling 是模型能力:模型发出"调工具 X、参数 Y"的意图,但不执行。MCP 是基础设施:供给工具目录(tools/list)并在进程外执行。抽掉 function calling,MCP 无可调之物;抽掉 MCP,意图无处落地。
  2. 过度工程:单一应用、单一 provider(外加少量稳定工具、自管执行)。该上 MCP:工具跨多 client / 框架复用、需触达私有资源不公网暴露(外加运行时可变工具集、与 agent 代码解耦、vendor 中立)。
  3. 错在把正交的两层当成同一生态位。MCP 管 agent↔tool,A2A 管 agent↔agent(Agent Cards 做能力发现 + 任务编排)。一个 A2A agent 对外暴露能力,对内用 MCP 去调自己的 server / 数据——两者叠加而非择一。
  4. 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 仍在每次工具调用的底层发生(模型选工具那步),只是不需要单独为它做架构选择。