第 2 章 — 揭开 Model Context Protocol(MCP)
LLM Primer IV: Designing AI Cognition with MCP 章节走读的第二篇。这一章把心智模型搭起来 — 三个角色、一种 JSON-RPC 线协议、一层动态发现表面、一套会话生命周期 — 搭得足够稳,后面整本书才能站在它上面。
这一章为什么存在
第 1 章给问题起了名字。这一章给答案搭出心智模型。MCP 一句话就能讲完,一段话就能讲错,所以这一章慢慢走:这个协议在线层面是什么,三个角色各自管什么,它跟 REST API 在那些生产里真正重要的场景里有什么不一样,以及一个会话从连接到拆解中间会发生什么。目标是读完这一章,你能在看下一章之前预判 — server 原语必然是什么样子、client 原语必然是什么样子、为什么 MCP 长成现在这个结构是有道理的。
2.1 MCP 是什么,"AI 的 USB-C" 到底指什么
Model Context Protocol 是一份开放规范,讲 LLM 应用怎么发现、描述、调用外部能力。线层面它是 JSON-RPC 2.0,跑在少数几种传输里的一种之上。架构层面它是一份合同,让一个 host 能跟任何符合协议的 server 工作,不用写定制集成代码。一个工具按协议写一次,所有说这个协议的 host 都能用。一个 host 按协议写一次,所有说这个协议的工具都能接进来。
沉淀下来那个说法是 "AI 的 USB-C"。结构上的形状确实像 USB-C — 一种连接标准,中介一群开放的设备和一群开放的 host。这个比喻的边界值得讲清楚:USB-C 标准化了一个接头加上面一层栈;MCP 只标准化了协议。USB-C 跑在电气时间尺度上、靠硬件强制成帧;MCP 跑在网络时间尺度上、由软件定义成帧,所以 MCP 能更灵活,也得自己处理丢连接、慢节点这些 USB-C 不需要管的事。
对工程师来说,更接近的类比是 LSP。Language Server Protocol 定义了一份让任何编辑器和任何语言服务器互相说得通的协议;MCP 定义了让任何 LLM host 和任何能力提供者说得通的协议。赢面的形状一模一样 — 多对多被一层共享协议塌成可加性增长。MCP 选 JSON-RPC 2.0 而不是自己发明一份线协议,是有意的:JSON-RPC 小、成熟、跟语言无关、毫不性感。真正有意思的架构选择不在线层面。它们在 Host、Client、Server 怎么分工这件事上。
2.2 Host、Client、Server — 各自管什么
MCP 定义了三个角色,而第一件要搞清楚的事是 "Client" 和 "Server" 在这里不是它们在别处常常意思的那个意思。Server 暴露能力 — 工具、资源、prompt。Client 是某个更大应用里管着的一根 protocol 协议连接,一个连到一个 server。那个更大的应用是 Host。Host 管模型、管用户会话、管模型能做什么的策略。Server 管它各自的能力表面。Client 是连在两者之间的线,一个 server 一根。
这个拆分有意义,因为每个角色责任不同、信任姿态不同。从用户的视角看,Host 是真正那个信任边界;其他的东西都是 Host 决定放进来的。一个 Host 同时连五个 Server,里面就跑着五个 Client,各自有自己的会话状态、自己的订阅、自己关于哪些能力被协商过的视图。如果一个 Server 崩了,对应那个 Client 崩;其他 Client 继续跑;Host 还活着。Client 是一种按连接做隔离的机制,挡住一个坏的 Server 毒到整个会话。
这个拆分还有安全上的理由。每一个 Server 最少也是别人写的代码。Client 中介一切影响 Host 的事 — 通知、elicitation、sampling 请求、发布出来的资源 — 它就是那个应该装 "每 Server 一份策略" 的地方。Host、Client、Server 是逻辑角色,不一定严格对应物理拆分:本地部署里 Server 经常就是 stdio 上的一个子进程;远程部署里它是一个 HTTP 传输上的服务。协议不在乎这个;角色边界在乎。
2.3 MCP 跟 REST — 动态发现和语义描述到底买到了什么
合理的问题是 "这不就是 REST 吗?"。区别不是表面的。最有后果的几条是动态发现、写给 LLM 看的语义描述、以及双向消息模型。
REST API 在写给人类开发者看的文档里公布端点。Client 用哪些端点是 build 时定死的;加新端点要重发部署。MCP 把这件事反过来。会话开始时,Client 问 "你能提供什么?",Server 回一份带类型的目录 — schema、描述、元数据 — host 用程序方式去消费。后面 Server 加了一个工具,一个 listChanged 通知会在会话中更新到 Client,不用重启。Server 是它自己能力的权威事实来源;描述跟实现不会漂移,因为根本没有一份分散在客户端的副本可漂。
第二个差别是语义描述。REST 端点的文档是写给将来要读它做决定的开发者看的。MCP 工具的描述是写给 LLM 看的 — 它会把它当成 prompt 的一部分,自主做决定。一段写着 "POST 到 /users/:id/orders" 的描述对 LLM 没用,LLM 需要知道这个工具在概念上做什么操作、什么时候应该优先选它、有什么副作用、输入在业务上指什么。把 API 翻译成 LLM 读得懂的语言这件事被推到 Server 一次完成,在最靠近能力的人那里维护。
第三个差别是双向性。REST 是请求响应;连接关掉。MCP 设计上就是双向的。Server 可以在任何时候发通知、可以反过来向 Client 发起 sampling 请求、可以在流程中向用户 elicit 答案。这些事在 REST 上不是技术上做不到。是都做得别扭。在 MCP 里,它们是标准的一部分。
2.4 能力协商与会话生命周期
一个会话从 Client 打开传输、发出 initialize 请求开始,请求里带它的协议版本和能力。Server 回它自己的能力 — 暴不暴露工具、暴不暴露资源、支不支持订阅、支不支持高级特性。Client 用 initialized 通知确认。这时候会话进入运转态,可用的消息类型刚好是双方协商重叠的那一部分。
这个协商是不同特性集的 Client 和 Server 能高效共处的原因。也是版本管理被处理的地方:Server 挑双方都支持的最高版本。运转上,这个生命周期是有后果的。初始化不免费 — 有一次往返的成本,远程 server 还要加一次连接建立。长会话是首选模式;能力变化以通知的形式流过去,而不是断开重连。尊重这一点的 host — 把会话保温、网络抖动后在后台重连 — 延迟会明显好。每次请求都拆掉重建的 host 能跑得对,但跑得不值。
一个值得钉死的不对称性:请求有回复;通知没有。List-changed 事件是通知,所以漏接一个 Client 必须能通过重新调 list_tools 来刷新自己的视图。通知是优化,不是保证。健壮的 MCP 代码把它当提示,不当记录。
第 2 章接下去会怎么走
心智模型现在到位了。MCP 是带三角色的 JSON-RPC 协议,有让 Server 对自己能力具权威性的动态发现、写给 LLM 看的描述、带通知和服务器侧发起请求的双向消息模型,以及一个从显式能力协商开始、在双方协商出的子集里运转的生命周期。这一套搭子已经够稳,可以具体讨论 Server 和 Client 各自暴露什么了,接下来两章就走这件事。
明天 — 第 3 章:服务器原语 — Resources、Prompts、Tools。Server 能给的三个名词,每一个为什么重要,以及挑对原语而不是把一个塞进另一个领地的纪律。