MCP 协议设计与实现
第1章 为什么需要 MCP
第1章 为什么需要 MCP
"We shape our tools, and thereafter our tools shape us." —— Marshall McLuhan
本章要点
- 碎片化困局:每个 Agent 框架都在各自发明工具集成方案,导致生态严重割裂
- USB 类比:MCP 之于 AI Agent 工具生态,正如 USB 之于计算机外设生态
- 协议本质:MCP 是基于 JSON-RPC 2.0 的开放协议,定义了 Host-Client-Server 三层架构
- 三大原语:Tool(模型控制)、Resource(应用控制)、Prompt(用户控制)的分层设计是 MCP 的精髓
- 生态爆发:从 2024 年 11 月首次发布到 Claude Code、Cursor、VS Code 全面采用,MCP 正在成为事实标准
1.1 一个真实的痛点:工具集成的碎片化
假设你是一个全栈开发者,刚刚构建了一个连接 PostgreSQL 数据库的工具——它能执行 SQL 查询、分析表结构、生成数据报告。现在你希望把这个工具接入各种 AI 应用,让不同的 AI 助手都能使用它。
你很快会发现一个令人沮丧的现实:
- 要接入 Claude Desktop,你需要按照 Anthropic 的工具格式包装一层
- 要接入 ChatGPT,你需要按照 OpenAI 的 function calling 格式再包装一层
- 要接入 LangChain 应用,你需要继承
BaseTool类,实现_run()方法 - 要接入 Cursor,又是另一套接口
- 要接入你自己写的 Agent,你可能直接用了 REST API
同一个工具,五种接口。每增加一个 AI 应用,就要多写一套适配代码。每增加一个工具,就要为所有已接入的 AI 应用分别适配。这是一个典型的 M×N 问题。
各框架工具接口的真实面貌
让我们看看这些不兼容的接口到底长什么样。
OpenAI Function Calling 格式:
{
"type": "function",
"function": {
"name": "query_database",
"description": "Execute SQL query on PostgreSQL",
"parameters": {
"type": "object",
"properties": {
"sql": { "type": "string", "description": "SQL statement" }
},
"required": ["sql"]
}
}
}
LangChain BaseTool:
from langchain.tools import BaseTool
from pydantic import Field
class DatabaseQueryTool(BaseTool):
name: str = "query_database"
description: str = "Execute SQL query on PostgreSQL"
def _run(self, sql: str) -> str:
# 执行查询逻辑
return result
async def _arun(self, sql: str) -> str:
# 异步执行逻辑
return result
Claude Code 内置工具格式:
const tool = {
name: "query_database",
description: "Execute SQL query on PostgreSQL",
inputSchema: {
type: "object" as const,
properties: {
sql: { type: "string", description: "SQL statement" }
},
required: ["sql"]
},
async call(input: { sql: string }) {
// 执行查询逻辑
return { result };
}
};
表面上看,这些定义的核心信息是一样的:工具名、描述、参数 schema、执行逻辑。但包装方式完全不同——有的用 JSON,有的用类继承,有的用对象字面量。更关键的是,传输协议、生命周期管理、错误处理、安全模型都各不相同。
M×N 问题的本质
graph TB
subgraph "没有 MCP 的世界:M×N 适配"
A1["Claude Desktop"] ---|"适配层 A1"| T1["数据库工具"]
A1 ---|"适配层 A2"| T2["文件系统工具"]
A1 ---|"适配层 A3"| T3["GitHub 工具"]
A2["ChatGPT Plugin"] ---|"适配层 B1"| T1
A2 ---|"适配层 B2"| T2
A2 ---|"适配层 B3"| T3
A3["Cursor"] ---|"适配层 C1"| T1
A3 ---|"适配层 C2"| T2
A3 ---|"适配层 C3"| T3
end
style A1 fill:#dbeafe,stroke:#3b82f6
style A2 fill:#dbeafe,stroke:#3b82f6
style A3 fill:#dbeafe,stroke:#3b82f6
style T1 fill:#fef3c7,stroke:#f59e0b
style T2 fill:#fef3c7,stroke:#f59e0b
style T3 fill:#fef3c7,stroke:#f59e0b
3 个 AI 应用 × 3 个工具 = 9 个适配层。当应用和工具各增长到 100 个时,就需要 10,000 个适配层。这显然不可持续。
这不是一个新问题。计算机历史上每一次外设接口标准化都经历过同样的阶段——打印机、显示器、存储设备,在 USB 出现之前,每种设备都有自己的专用接口。
1.2 USB 类比:为什么标准协议改变一切
USB(Universal Serial Bus)在 1996 年发布时,PC 世界的外设接口是一团混乱:串口连调制解调器,并口连打印机,PS/2 连键盘鼠标,SCSI 连硬盘,游戏端口连手柄。每种设备需要专用的物理接口、专用的驱动程序、专用的通信协议。
USB 做了什么?它定义了:
- 统一的物理接口——一种接口连接所有设备
- 标准的通信协议——设备自描述,即插即用
- 清晰的角色分工——Host(主机)控制总线,Device(设备)响应请求
- 可扩展的设备类型——键盘、鼠标、存储、音频,都通过同一协议描述
USB 把 M×N 问题变成了 M+N 问题:设备厂商只需实现一次 USB 协议,计算机厂商也只需实现一次 USB 主控,两边独立发展,互不干扰。
MCP 在 AI Agent 领域做的,正是同样的事情。
graph TB
subgraph "有 MCP 的世界:M+N 标准化"
A1["Claude Desktop"] --- P["MCP 协议"]
A2["Cursor"] --- P
A3["VS Code"] --- P
A4["自定义 Agent"] --- P
P --- T1["数据库 Server"]
P --- T2["文件系统 Server"]
P --- T3["GitHub Server"]
P --- T4["Slack Server"]
end
style P fill:#dcfce7,stroke:#22c55e,stroke-width:3px
style A1 fill:#dbeafe,stroke:#3b82f6
style A2 fill:#dbeafe,stroke:#3b82f6
style A3 fill:#dbeafe,stroke:#3b82f6
style A4 fill:#dbeafe,stroke:#3b82f6
style T1 fill:#fef3c7,stroke:#f59e0b
style T2 fill:#fef3c7,stroke:#f59e0b
style T3 fill:#fef3c7,stroke:#f59e0b
style T4 fill:#fef3c7,stroke:#f59e0b
4 个应用 + 4 个工具 = 只需要 8 次实现,而不是 16 次。当两边各增长到 100 个时,只需要 200 次实现,而不是 10,000 次。
这个类比不只是修辞手法。USB 的成功有三个关键因素,MCP 同样具备:
| 特征 | USB | MCP |
|---|---|---|
| 统一接口 | 标准物理插口 + 电气协议 | JSON-RPC 2.0 + 标准消息格式 |
| 设备自描述 | USB 描述符(Device Descriptor) | 能力协商(Capability Negotiation) |
| 角色分工 | Host / Device | Host / Client / Server |
| 即插即用 | 热插拔 + 自动驱动 | 动态发现 + 运行时注册 |
| 开放标准 | USB-IF 组织维护 | Anthropic 开源 + 社区共建 |
1.3 MCP 到底是什么
让我们给 MCP 一个精确的定义。
Model Context Protocol(MCP)是一个开放协议,它标准化了 AI 应用(如 Claude Desktop、Cursor、IDE 插件)与外部数据源和工具之间的通信方式。
这个定义来自 MCP 规范的官方描述:
"Model Context Protocol (MCP) is an open protocol that enables seamless integration between LLM applications and external data sources and tools."
让我们拆解这个定义中的每一个关键词:
- 开放协议(Open Protocol):MCP 是完全开源的,规范文档、Schema 定义、多语言 SDK 全部公开可用。任何人都可以实现 MCP 的客户端或服务端,不需要 Anthropic 的授权
- 标准化:不是某个框架的内部接口,而是跨框架、跨语言、跨平台的统一标准
- LLM 应用:MCP 的客户端不是人类用户,而是包含大语言模型的应用程序
- 外部数据源和工具:MCP 不关心你用什么数据库、什么 API、什么编程语言——它只关心通信协议
技术基础:JSON-RPC 2.0
MCP 建立在 JSON-RPC 2.0 之上。这不是随意的选择,而是经过深思熟虑的技术决策。
JSON-RPC 2.0 是一个轻量级的远程过程调用协议,它的消息格式极其简洁:
请求(Request):
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}
响应(Response):
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [
{
"name": "query_database",
"description": "Execute SQL query",
"inputSchema": {
"type": "object",
"properties": {
"sql": { "type": "string" }
},
"required": ["sql"]
}
}
]
}
}
通知(Notification)——没有 id 字段,不需要响应:
{
"jsonrpc": "2.0",
"method": "notifications/tools/list_changed"
}
为什么选择 JSON-RPC 而不是其他协议?这个问题的答案与 MCP 的设计哲学密切相关,我们将在 1.6 节详细讨论。
MCP 的灵感来源
MCP 规范明确提到了它的灵感来源:
"MCP takes some inspiration from the Language Server Protocol (LSP), which standardizes how to add support for programming languages across a whole ecosystem of development tools."
LSP 解决的问题和 MCP 几乎完全对称:在 LSP 出现之前,每个编辑器(VS Code、Vim、Emacs、Sublime)要单独实现每种编程语言的支持(语法高亮、自动补全、跳转定义),这也是一个 M×N 问题。LSP 通过定义一个标准的 Language Server 协议,把问题变成了 M+N——编辑器只需要实现 LSP 客户端,语言工具只需要实现 LSP 服务端。
MCP 在 AI 领域做了同样的事,但它面对的挑战更复杂:
| 维度 | LSP | MCP |
|---|---|---|
| 通信发起方 | 人类输入触发 | 模型自主决策触发 |
| 安全模型 | 相对简单(读代码) | 复杂(可能执行任意操作) |
| 状态管理 | 文件系统为中心 | 多数据源、多工具 |
| 结果类型 | 结构化(补全列表、诊断) | 非结构化(文本、图片、音频) |
1.4 Host-Client-Server:三层架构的精妙设计
理解 MCP 的架构是理解整个协议的钥匙。MCP 采用的不是简单的客户端-服务端两层模型,而是 Host-Client-Server 三层架构。
graph LR
subgraph "Application Host Process"
H["Host<br>(如 Claude Desktop)"]
C1["Client 1"]
C2["Client 2"]
C3["Client 3"]
H --> C1
H --> C2
H --> C3
end
subgraph "Local Machine"
S1["Server 1<br>文件系统"]
S2["Server 2<br>数据库"]
R1[("本地<br>文件")]
R2[("本地<br>数据库")]
C1 --> S1
C2 --> S2
S1 <--> R1
S2 <--> R2
end
subgraph "Internet"
S3["Server 3<br>GitHub API"]
R3[("远程<br>仓库")]
C3 --> S3
S3 <--> R3
end
style H fill:#dcfce7,stroke:#22c55e,stroke-width:2px
style C1 fill:#dbeafe,stroke:#3b82f6
style C2 fill:#dbeafe,stroke:#3b82f6
style C3 fill:#dbeafe,stroke:#3b82f6
style S1 fill:#fef3c7,stroke:#f59e0b
style S2 fill:#fef3c7,stroke:#f59e0b
style S3 fill:#fef3c7,stroke:#f59e0b
为什么是三层而不是两层?
这是 MCP 最容易被误解的设计决策之一。直觉上,似乎"应用直接连服务器"更简单。但三层架构解决了几个关键问题:
Host(宿主) 是用户直接交互的应用程序,比如 Claude Desktop、Cursor、VS Code。它的职责是:
- 创建和管理多个 Client 实例
- 控制 Client 的连接权限和生命周期
- 执行安全策略和用户授权
- 协调 AI/LLM 集成
- 聚合来自多个 Client 的上下文
Client(客户端) 是 Host 内部的连接器,每个 Client 与一个 Server 保持一对一的连接:
- 与 Server 建立有状态的会话
- 处理协议协商和能力交换
- 双向路由协议消息
- 维护服务器之间的安全隔离
Server(服务端) 提供具体的工具和数据:
- 通过 MCP 原语暴露资源、工具和提示
- 独立运行,职责单一
- 可以是本地进程,也可以是远程服务
安全隔离:为什么每个 Server 看不到其他 Server
这是三层架构最重要的设计意图之一。MCP 规范的设计原则明确指出:
"Servers should not be able to read the whole conversation, nor 'see into' other servers."
这意味着:
- Server 只收到执行当前任务所需的信息,不会收到完整的对话历史
- 不同 Server 之间完全隔离,文件系统 Server 不知道数据库 Server 的存在
- 跨 Server 的交互由 Host 统一控制
- Host 负责执行安全边界
这种设计直接源于安全考量。想象一下:如果你同时连接了一个"公司内部数据库"Server 和一个"第三方天气查询"Server,你绝对不希望天气 Server 能看到你的数据库查询内容。三层架构通过 Client 的隔离确保了这一点。
能力协商:渐进式功能发现
MCP 的另一个精妙设计是**能力协商(Capability Negotiation)**机制。在连接建立时,Client 和 Server 会交换各自支持的功能列表:
// Client 发送 initialize 请求
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-03-26",
"capabilities": {
"roots": { "listChanged": true },
"sampling": {}
},
"clientInfo": {
"name": "claude-desktop",
"version": "1.0.0"
}
}
}
// Server 响应,声明自己支持的能力
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2025-03-26",
"capabilities": {
"tools": { "listChanged": true },
"resources": { "subscribe": true }
},
"serverInfo": {
"name": "database-server",
"version": "2.1.0"
}
}
}
这种设计的好处是渐进式兼容——旧版本的 Client 遇到新版本的 Server 不会崩溃,它只是看不到新功能。MCP 规范对此的设计原则是:
"Features can be added to servers and clients progressively. Core protocol provides minimal required functionality. Additional capabilities can be negotiated as needed."
这和 USB 的设备描述符机制如出一辙:你把一个 USB 3.0 设备插到 USB 2.0 端口,它不会报错,只是降级到 USB 2.0 速度运行。
1.5 三大原语:Tool、Resource、Prompt
MCP 定义了三种核心原语,这是理解整个协议最关键的概念。它们不是按"功能类型"划分的,而是按**"谁来控制调用"**划分的。
| 原语 | 控制方 | 类比 | 典型用例 |
|---|---|---|---|
| Tool | 模型控制(Model-controlled) | 函数 | 执行 SQL、调用 API、文件操作 |
| Resource | 应用控制(Application-controlled) | 数据源 | 读取文件内容、获取数据库 schema |
| Prompt | 用户控制(User-controlled) | 模板 | 代码审查模板、SQL 生成模板 |
这个三分法看似简单,实则蕴含深意。
Tool:模型自主决策的执行能力
Tool 是最容易理解的原语。MCP 规范对 Tool 的定义是:
"Tools in MCP are designed to be model-controlled, meaning that the language model can discover and invoke tools automatically based on its contextual understanding and the user's prompts."
当你对 Claude 说"帮我查一下数据库中用户表有多少条记录",模型会自主决定调用数据库查询工具。模型发现可用工具列表、选择合适的工具、构造参数、发起调用——整个过程都是模型驱动的。
一个 MCP Tool 的定义包含以下关键字段:
{
"name": "query_database",
"description": "Execute a read-only SQL query on the PostgreSQL database",
"inputSchema": {
"type": "object",
"properties": {
"sql": {
"type": "string",
"description": "The SQL query to execute (SELECT only)"
}
},
"required": ["sql"]
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false
}
}
注意 annotations 字段——它提供了关于工具行为的元数据提示,比如这个工具是否只读、是否会产生副作用。但规范特别提醒:
"For trust & safety and security, clients MUST consider tool annotations to be untrusted unless they come from trusted servers."
这意味着工具的 annotations 仅供参考,Host 不应该盲目信任它们来做安全决策。
Resource:应用程序控制的上下文数据
Resource 的控制逻辑与 Tool 完全不同。MCP 规范明确说:
"Resources in MCP are designed to be application-driven, with host applications determining how to incorporate context based on their needs."
Resource 不是模型自主去取的,而是应用程序决定什么时候、以什么方式把数据提供给模型。典型的场景包括:
- 用户在 Claude Desktop 中手动选择一个文件作为上下文
- IDE 自动将当前打开的文件内容注入模型上下文
- 应用基于启发式规则自动附加相关的数据库 schema
每个 Resource 由一个 URI 唯一标识,支持订阅和变更通知:
{
"uri": "file:///project/src/main.rs",
"name": "main.rs",
"description": "Primary application entry point",
"mimeType": "text/x-rust"
}
Resource 还支持模板化的 URI,这意味着服务端可以暴露动态的资源空间。比如一个数据库 Server 可以暴露 db://{schema}/{table} 模板,让应用程序根据需要查询任意表的结构。
Prompt:用户显式选择的交互模板
Prompt 是三个原语中最"人性化"的一个。MCP 规范说:
"Prompts are designed to be user-controlled, meaning they are exposed from servers to clients with the intention of the user being able to explicitly select them for use."
Prompt 通常以斜杠命令(slash command)的形式暴露给用户。比如在 Claude Desktop 中,数据库 Server 可能提供一个 /analyze-table 提示模板:
{
"name": "analyze-table",
"description": "Generate a comprehensive analysis of a database table",
"arguments": [
{
"name": "table_name",
"description": "Name of the table to analyze",
"required": true
}
]
}
当用户选择这个命令时,Server 返回一组预构造的消息,引导模型按照特定的方式分析数据。
为什么这个三分法很重要?
你可能会想:Tool、Resource、Prompt 的底层不都是"向 Server 请求数据或执行操作"吗?为什么要分成三种?
关键在于安全模型和用户体验。
Tool 涉及执行(execution)。模型调用工具可能产生副作用——修改文件、发送邮件、删除数据。因此 MCP 规范要求:
"There SHOULD always be a human in the loop with the ability to deny tool invocations."
Host 必须在工具执行前展示确认对话框,让用户审批。
Resource 涉及读取(reading)。读取操作通常是安全的,不会修改外部状态。应用程序可以自动、静默地把相关资源注入上下文,不需要每次都征求用户同意。
Prompt 涉及引导(guidance)。它改变的不是外部世界,而是模型的行为方式。用户需要显式选择使用哪个 Prompt 模板,因为不同的模板会导致完全不同的分析视角和输出格式。
这三种控制层级构成了一个安全梯度:
用户控制(Prompt)→ 应用控制(Resource)→ 模型控制(Tool)
安全性最高 中等 需要人工审批
这种分层与操作系统的权限设计有异曲同工之妙。读取文件不需要特殊权限,执行程序需要执行权限,修改系统配置需要管理员权限——MCP 的三大原语用类似的逻辑把 AI Agent 的操作按风险等级分层。
1.6 MCP vs 替代方案:为什么不用已有的协议?
在 MCP 出现之前,已经有很多成熟的通信协议和工具集成方案。一个自然的问题是:为什么不直接用它们?
为什么不用 REST API?
REST API 是 Web 开发的基石,几乎所有后端服务都暴露 REST 接口。但它不适合做 AI 工具协议,原因有三:
第一,REST 是无状态的,MCP 需要有状态的会话。 MCP 的会话从 initialize 开始,经过能力协商,到 shutdown 结束。在整个会话期间,Client 和 Server 维持着共享状态——哪些能力已协商、哪些资源已订阅、哪些工具可用。REST 的每个请求都是独立的,无法优雅地管理这种有状态的交互。
第二,REST 缺少双向通信。 REST 是请求-响应模式,Server 无法主动向 Client 推送消息。但 MCP 需要 Server 主动发送通知,比如"工具列表发生了变化"(notifications/tools/list_changed)或"资源内容更新了"(notifications/resources/updated)。
第三,REST 没有标准的能力协商机制。 每个 REST API 都自定义自己的认证方式、版本管理、错误格式。MCP 通过 initialize 请求统一解决了这些问题。
为什么不用 gRPC?
gRPC 是 Google 开发的高性能 RPC 框架,支持双向流、Protocol Buffers 序列化、强类型。它看起来很适合 MCP 的场景。
但 gRPC 的门槛太高了。 MCP 规范的第一条设计原则是:
"Servers should be extremely easy to build."
gRPC 需要预定义 .proto 文件,需要代码生成步骤,需要 HTTP/2 服务器。而 MCP 的 stdio 传输模式只需要从标准输入读 JSON、向标准输出写 JSON——一个 Python 初学者用 json.loads() 和 print() 就能实现一个最简 MCP Server。
gRPC 的 Protocol Buffers 虽然高效,但牺牲了可读性。当你在调试 MCP 通信问题时,JSON 可以直接用肉眼阅读,而 protobuf 的二进制格式需要专用工具解码。对于一个主要传输文本(代码、文档、SQL 查询结果)的协议来说,JSON 的序列化开销并不是瓶颈。
为什么不用 OpenAI Function Calling 格式?
OpenAI 的 function calling 格式已经是事实上的行业标准——很多框架都兼容或参考了它。为什么 MCP 不直接采用?
因为 function calling 不是协议,它只是一种消息格式。 function calling 定义了"工具长什么样"和"调用参数是什么",但没有定义:
- 工具如何被发现和注册
- 工具的生命周期如何管理
- 客户端和服务端如何建立连接
- 错误如何分类和处理
- 安全边界如何划定
MCP 在消息层面与 function calling 是兼容的(工具定义的 inputSchema 格式一致),但它在此基础上增加了完整的协议层——传输、会话、能力协商、安全模型。
为什么不用 LSP 直接扩展?
LSP 是 MCP 的直接灵感来源,为什么不直接扩展 LSP 而是另起炉灶?
因为 LSP 的假设是"一个语言服务器对应一种编程语言",它的消息类型都围绕代码编辑场景设计:textDocument/completion、textDocument/definition、textDocument/diagnostic。AI Agent 的工具生态远超代码编辑——数据库查询、API 调用、文件操作、网络搜索——这些用例需要不同的抽象模型。
MCP 借鉴了 LSP 的协议设计思路(JSON-RPC、能力协商、渐进式功能),但定义了全新的消息类型和原语体系。
对比总结
| 维度 | REST API | gRPC | Function Calling | LSP | MCP |
|---|---|---|---|---|---|
| 传输 | HTTP | HTTP/2 | 嵌入 LLM API | JSON-RPC | JSON-RPC |
| 状态 | 无状态 | 有状态 | 无状态 | 有状态 | 有状态 |
| 双向通信 | 否 | 是 | 否 | 是 | 是 |
| 能力协商 | 无 | 无 | 无 | 有 | 有 |
| 易于实现 | 高 | 低 | 中 | 中 | 高 |
| 序列化 | JSON | Protobuf | JSON | JSON | JSON |
| 安全模型 | 自定义 | 自定义 | 依赖平台 | 有限 | 完整 |
| 工具发现 | 无标准 | 反射 | 静态 | 静态 | 动态 |
| 场景覆盖 | 通用 Web | 微服务 | LLM 调用 | 代码编辑 | AI Agent |
MCP 不是要替代这些协议,而是在 AI Agent 工具集成这个特定领域,填补了一个空白。
1.7 从发布到生态爆发:MCP 的发展时间线
MCP 的发展速度超出了大多数人的预期。以下是关键里程碑:
2024 年 11 月:首次发布
Anthropic 在 2024 年 11 月 25 日发布了 MCP 的第一个版本(协议版本 2024-11-05),同步开源了:
- 完整的协议规范文档
- TypeScript SDK
- Python SDK
- Claude Desktop 的 MCP 集成
首版协议定义了核心架构(Host-Client-Server)、三大原语(Tool/Resource/Prompt)、两种传输方式(stdio 和 HTTP+SSE),以及完整的生命周期管理。
2025 年 3 月:重大版本更新
协议版本 2025-03-26 带来了多项重要改进:
- Streamable HTTP 传输:替代了原来的 HTTP+SSE 传输,更灵活、更高效
- 工具注解(Tool Annotations):允许服务端声明工具的行为特征,如是否只读、是否幂等
- 结构化输出(Structured Output):工具可以同时返回结构化和非结构化结果
- Elicitation:服务端可以向用户请求额外信息
- OAuth 2.1 授权框架:标准化了远程 MCP Server 的认证流程
2025 年中:生态爆发
多个主流 AI 开发工具宣布支持 MCP:
- Claude Code:Anthropic 的命令行 AI 编程助手,内置完整的 MCP 客户端,支持通过配置文件动态加载 MCP Server
- Cursor:AI 代码编辑器,集成 MCP 支持
- VS Code:微软的 GitHub Copilot 扩展开始支持 MCP Server
- Windsurf(Codeium):集成 MCP 支持
- 社区贡献了数百个 MCP Server:从数据库连接器到云服务 API,从文件系统操作到搜索引擎集成
2025 年底至 2026 年:持续演进
协议版本 2025-06-18 和 2025-11-25 继续推进:
- 更成熟的安全模型
- 更完善的错误处理
- 更丰富的传输选项
- 社区治理模型的建立
MCP 的规范仓库中维护着完整的版本历史,每个版本的 Schema 定义都保存在 schema/ 目录下,从 2024-11-05 到最新的 draft,清晰地记录了协议的演进轨迹。
schema/
├── 2024-11-05/ # 首版
├── 2025-03-26/ # 重大更新
├── 2025-06-18/ # 持续演进
├── 2025-11-25/ # 最新稳定版
└── draft/ # 开发中的下一版
├── schema.json
├── schema.ts # TypeScript 类型定义(权威源)
└── schema.mdx
值得注意的是,MCP 规范明确指出 TypeScript Schema(schema.ts)是权威定义源:
"This specification defines the authoritative protocol requirements, based on the TypeScript schema in schema.ts."
这意味着所有语言的 SDK 实现都以这个 TypeScript 定义为准。
1.8 本书的范围:教什么,不教什么
你将学到什么
本书将从协议规范和 SDK 源码出发,系统地教你:
协议层面(第 2-7 章):
- MCP 的完整架构设计和设计原则
- JSON-RPC 2.0 在 MCP 中的应用
- 连接生命周期:初始化、能力协商、操作、关闭
- 三大原语(Tool、Resource、Prompt)的完整协议细节
- 每个消息类型的 JSON 格式、请求/响应流程
实现层面(第 8-11 章):
- 用 TypeScript SDK 实现 MCP Server 和 Client
- 用 Python SDK 实现 MCP Server 和 Client
- SDK 的内部架构:传输层、协议层、应用层
传输与安全(第 12-16 章):
- stdio 传输的实现细节
- Streamable HTTP 传输的完整流程
- SSE 和 WebSocket 扩展
- OAuth 2.1 授权框架在 MCP 中的应用
- Server 发现与注册机制
高级特性(第 17-18 章):
- Sampling:让 Server 反向请求 LLM 推理
- Elicitation 和 Roots:Server 向用户和文件系统的交互
实战(第 19-21 章):
- Claude Code 中的 MCP 集成分析
- 从零构建生产级 MCP Server
- 设计模式与最佳实践
不教什么
- 不教 LLM 基础知识:本书假设你理解大语言模型的基本概念——Prompt、Token、上下文窗口、Tool Use
- 不教特定 Agent 框架:LangChain、CrewAI、AutoGen 等框架有各自的教程,本书关注的是它们底层共享的协议标准
- 不教前端 UI 开发:MCP 是后端协议,不涉及用户界面的构建
- 不做 API 参考手册:本书不是对规范文档的逐字翻译,而是通过源码分析揭示设计背后的"为什么"
阅读前提
- 你需要有基本的 TypeScript 或 Python 编程经验
- 你需要理解 JSON 格式和 HTTP 基础知识
- 你需要对"AI Agent 调用工具"这个概念有基本认知
- 如果你曾经用过 Claude Code、Cursor 或任何 AI 编程工具,理解会更顺畅
1.8.1 实测:MCP "M+N" 在两个官方 SDK 里的真实工程量
§1.1 抽象提到"M×N → M+N" 的协议价值——本书 ch03-ch19 已对两个官方 SDK 做了11 处具体实测——把这些数字汇总成 MCP 的 "M+N 真实账本"——
TS SDK 全家桶(mcp-typescript-sdk)——
| 模块 | 行 | 章节实测出处 |
|---|---|---|
packages/core |
10871 | ch08 §8.8.1 |
packages/server |
3989 | ch08 §8.8.1 |
packages/client |
5937 | ch08 §8.8.1 |
packages/middleware |
703 | ch08 §8.8.1 |
| 其中 OAuth (client+core) | 2888 | ch15 §15.9.4 |
| 其中 STDIO (server+client) | 398 | ch12 §12.11.1 |
| 其中 Streamable HTTP | 2003 | ch13 §13.9.1 |
| 其中 Discovery (auth.ts 内联) | ~700 | ch16 §16.9.1 |
| 其中 Prompt | ~120 | ch07 §7.11.1 |
| 其中 Resource | ~420 | ch06 §6.9.1 |
| 合计 | 49370 | — |
Python SDK 全家桶(mcp-python-sdk)——
| 模块 | 行 | 章节实测出处 |
|---|---|---|
| OAuth (client + server + utils) | 3313 | ch15 §15.9.4 |
| Streamable HTTP | 1940 | ch13 §13.9.1 |
| STDIO + os/win32 | 740 | ch12 §12.11.1 |
| Discovery utils | 339 | ch16 §16.9.1 |
| Prompt | ~302 | ch07 §7.11.1 |
| Resource | 513 | ch06 §6.9.1 |
| Core (shared/auth.py + types/_types.py + ...) | 余下 | — |
两条值得记住的"M+N"物理证据——
- "M+N 一次实现、所有用户共享"在 MCP 里就是这两个 SDK ~50K + ~30K ≈ 80K 行——支撑全球数百个 MCP Server + 几十个 Client 集成——按 GitHub 上 1000+ MCP Server 项目估算,M+N 路线节省的总工程量是 80K 的几个数量级——和 §1.4 抽象描述对上号;这是 ch01 §1.9.1 测得的 Serde "26000 行基础设施 vs M=50/N=8 全部用户算 30 倍代码减少" 在 MCP 协议层的同款论证
- 两个 SDK 实现一致性"按功能模块决定"(本书 7 处实测确认:§13.9.1 Streamable HTTP 双 SDK 严格对称 / §15.9.4 OAuth 服务端 Python 1572 vs TS 0 / §16.9.1 Discovery Python 多文件 vs TS 单文件 / §17.10.1 Sampling 双 SDK 对称 / §12.11.1 STDIO Windows Python 333 vs TS 0 / §7.11.1 Prompt Python 2.5x / §6.9.1 Resource 1.22x)——印证 §1.6.4 提到的 "MCP 不是 Anthropic 私有、而是开放规范" 在工程现实层面:两个 SDK 各自演进、各按语言生态做最适合的取舍、不强求一致——这正是开放治理的真实样貌
对照本书 ch01 §1.4.1 测得的 Claude Code Harness 379K TypeScript——MCP 两 SDK 加起来只占 Claude Code 的 ~21%——印证 §1.5.1 "MCP 是协议、不是产品"——一个 MCP 协议层只占典型生产 Agent 1/5 的工程量、其余 4/5 是产品特定的 Harness。
1.9 本章小结
本章从一个真实的工程痛点出发——AI 工具集成的碎片化——引出了 MCP 协议存在的意义。我们看到:
- 碎片化是真实存在的。每个 Agent 框架的工具接口互不兼容,导致工具开发者面临 M×N 的适配困境
- MCP 是 AI 领域的 USB。它通过定义标准协议,把 M×N 问题降维为 M+N 问题
- MCP 建立在 JSON-RPC 2.0 之上,这是一个深思熟虑的技术选择——简单、可读、易于实现
- 三层架构(Host-Client-Server) 不是过度设计,而是安全隔离和可组合性的必然要求
- 三大原语(Tool/Resource/Prompt) 按控制方而非功能类型划分,构成了清晰的安全梯度
- MCP 不是要替代 REST、gRPC 或 function calling,而是在 AI Agent 工具集成这个特定领域填补空白
- MCP 的生态增长速度远超预期,正在成为 AI 工具集成的事实标准
从下一章开始,我们将深入 MCP 的架构设计,逐层拆解协议的每一个组成部分。在那之前,建议你先尝试一件事:打开 Claude Desktop 或 Claude Code,配置一个简单的 MCP Server(比如官方的 filesystem server),亲身体验一下"即插即用"的工具集成是什么感觉。这个体验会让后续章节的每一个技术细节都变得更加生动。
延伸阅读:MCP 为什么能快速成为标准
MCP 从 2024 年 11 月由 Anthropic 发布、到 2025-2026 年被 OpenAI、Google、Microsoft 等大厂广泛采纳——用了不到一年时间。这种"标准化速度"在计算机历史上很罕见——HTTP 标准化用了 5 年、REST 成为事实标准用了 10 年。为什么 MCP 这么快?有几个原因。第一、"痛点明确且普遍"——每个 AI 应用都在重复造轮子做工具集成、大家都在寻找统一方案。第二、"Anthropic 的中立性和权威性"——不像某个创业公司出的提议、Anthropic 作为头部 LLM 公司的提案有足够分量。第三、"开放治理"——MCP 不是 Anthropic 私有、而是建立在开放规范之上、让其他公司能平等参与。第四、"技术选型简单务实"——基于 JSON-RPC 这种成熟协议、门槛低、容易实现。
这四个条件缺一不可——缺了"痛点"、再好的标准也没人用;缺了"权威性"、没人信任;缺了"开放治理"、大厂不愿意加入;缺了"技术简单"、小团队没资源实现。MCP 的成功、是天时地利人和。对读者的启示是——如果你希望推动某个标准、先看看这四个条件是否都具备——缺一个、成功概率就大打折扣。
延伸阅读:MCP 与 USB 类比的深层含义
"MCP 是 AI 时代的 USB"——这个类比在社区广为流传、很贴切。USB 之前、外设连接是"每家厂商一套接口"——鼠标有 PS/2、键盘有 DIN、打印机有并口、扫描仪有 SCSI——用户要配一堆转接线。USB 统一之后、所有外设用同一个接口——插上就用、换设备不用改配置。MCP 解决的是同类问题——不同 LLM 连不同工具、之前要各自适配、现在一套接口搞定。
但 USB 的类比还有更深层含义——"USB 催生了一个庞大的外设生态"。USB 之前、外设是"专业硬件厂商"的领域;USB 之后、任何小公司都能做 USB 设备(因为接口统一、门槛低)——催生了 U 盘、USB 音箱、USB 摄像头、USB 灯等海量消费级产品。MCP 可能也会催生类似的"长尾 Agent 工具"——个人开发者可以做小众工具(比如"查北京天气"的 MCP Server)、放到市场、被全世界用户用。这种"长尾创新"、是 MCP 最令人激动的未来。
延伸阅读:MCP 之前的几次失败尝试
工具集成标准化、在 MCP 之前有过几次尝试——都没成。OpenAI 的 Plugins(2023)——想建立"ChatGPT 插件市场"——因为只能在 OpenAI 生态用、没被其他公司接受;LangChain 的 Tool 抽象——是库层面的抽象、不是协议、无法跨框架使用;Agent Protocol(2023 由 AI Engineer Foundation 推动)——太早了、生态没跟上、逐渐淡化。这些失败尝试、都积累了经验——让 MCP 避开了他们踩过的坑。
MCP 的设计、明显吸收了前辈教训——不绑定 Anthropic 的生态(任何 LLM 都能用)、不只是库(有正式协议规范)、不过度设计(一开始只做最核心的三原语、慢慢扩展)。这种"站在前辈失败肩膀上"的智慧、让 MCP 能成为第一个真正成功的 AI 工具标准。对有志推动标准化的读者——了解前人的失败、比了解前人的成功更有价值——失败告诉你"不能这样"、成功告诉你"这样能行"——两者结合、你才能找到自己的路。
延伸阅读:MCP 三原语的设计智慧
本章提到 MCP 的三原语(Tool / Resource / Prompt)——这个划分有深层的设计智慧。Tool 是"Agent 可以主动调用的能力"(读文件、查询 API);Resource 是"Agent 可以读取的内容"(文件内容、数据库记录);Prompt 是"用户或开发者提供的指令模板"。三者的区别、不是"功能类别"、而是"谁控制、谁调用"。
Tool 由 Agent 主动决定调用(高自由度、需要权限控制);Resource 由 Agent 按需读取(低风险、主要是数据);Prompt 由用户显式选择(完全可控、无隐藏行为)。这种"按安全梯度划分"的设计、让权限管理变得自然——Tool 需要严格权限控制、Resource 需要轻度控制、Prompt 基本不需要控制。这比"按功能划分"(比如"文件工具、网络工具、数据库工具")更有智慧——因为安全性是跨功能的横切关注点、按安全划分能统一权限模型。
延伸阅读:MCP 的未来:双向 MCP
2026 年 MCP 的发展方向之一——"双向 MCP"(Bidirectional MCP)。当前 MCP 是单向的——LLM 调用 Server、Server 提供工具。双向 MCP 的愿景——Server 也能调用 LLM——比如一个 MCP Server 想在特定条件下问 LLM 一个问题、或者让 LLM 生成某段文本。这种双向流动、会让 MCP 更像"真正的协议"(双方对等)而不是"客户端-服务端模式"。
双向 MCP 的挑战——"安全和信任"。如果 Server 能调 LLM、怎么防止恶意 Server 消耗大量 token?怎么防止 Server 通过调 LLM 进行 prompt injection?这些问题的答案可能要靠更严格的权限模型、更细粒度的 rate limiting、更完整的审计日志。双向 MCP 目前还在 RFC 阶段、未来 1-2 年可能会有初步方案。读者如果对协议演化感兴趣、可以关注 MCP GitHub 的 proposals 目录——那里是协议未来的第一现场——能看到不同公司的工程师在讨论、辩论、妥协。
延伸阅读:MCP 对个人开发者的机会
MCP 生态的开放性——对个人开发者是一个罕见的机会窗口。写一个 MCP Server、比写一个独立的 AI 产品容易得多——不用做前端、不用做计费、不用做用户系统——只要把"一个有用的能力"包装成 MCP Server、发布到 MCP Registry、就能被全世界用户接入。这种"低门槛高杠杆"的分发模式、让个人开发者能触达以前只有大公司才能触达的用户群。
好的 MCP Server 机会——"领域专家的能力"(法律检索、医疗查询、财务分析)、"垂直工具"(SEO 分析、社交媒体发布、海关查询)、"特定地区的服务"(中国的各种政务数据、电商数据)——这些都是大公司不容易覆盖、个人开发者有机会深耕的领域。2026 年是 MCP 生态的"淘金期"——早入场的开发者、有机会在某个细分领域建立不可替代的地位。《LangChain 源码》第 17 章讨论的 Partner 包生态、也是类似机会——AI 时代、"做生态基础设施"比"做终端产品"门槛更低、回报更高。
延伸阅读:MCP 与微服务的相似性
MCP Server 的概念、和微服务有深度相似性——每个 Server 提供一个或几个相关功能、通过标准协议对外服务、可以独立部署和演化。这种相似性不是偶然——MCP 借鉴了微服务架构 15 年的成熟经验。微服务的服务发现、负载均衡、版本管理、健康检查、监控告警——这些概念都可以迁移到 MCP Server 生态。
但 MCP 和微服务也有关键差异——"调用方"不同。微服务的调用方是"其他服务"(确定的、可预测的);MCP Server 的调用方是"LLM"(概率性的、可能调也可能不调)。这个差异让 MCP Server 的设计要考虑"LLM 友好"——描述清楚、参数简单、错误消息可解释——让 LLM 能理解怎么用。懂微服务架构的工程师、学 MCP 会很快——只需要再学"怎么让接口对 LLM 友好"这一个维度——这种"迁移式学习"、让老工程师在 AI 时代有巨大优势。
延伸阅读:MCP 与 GraphQL 的对比
做工具集成、除了 MCP、还有 GraphQL 这种选择——能不能用 GraphQL 解决 AI 工具集成?理论上可以、实际上不合适。GraphQL 面向"前端开发者显式写查询"——查询由开发者写、执行计划由 GraphQL 服务器优化、返回精确的字段组合。AI 工具集成面向"LLM 自动生成调用"——调用由 LLM 根据自然语言生成、执行没有优化空间(就是调用一个函数)、返回的是完整结果。两者的目标用户和使用方式完全不同。
MCP 针对"LLM 调用"这个新场景、做了专门设计——简单的 JSON-RPC 格式(LLM 容易生成)、清晰的 tool description(LLM 容易理解)、结构化的 output schema(LLM 容易解析)。这些设计让 MCP 在 AI 工具集成场景比 GraphQL 更合适。不同协议、不同场景——没有银弹——这是协议设计的基本真理。
延伸阅读:MCP 的文化意义
MCP 不只是一个技术协议、更是一个文化符号——它代表 AI 时代的"开放 vs 封闭"之争里、开放阵营的一次胜利。在 MCP 之前、AI 工具集成的主流是各家 LLM 公司封闭生态——OpenAI 的 Plugins 只能在 ChatGPT 里用、Claude 的 MCP 只能和 Claude 用——用户被锁定。MCP 打破了这种封闭——让工具能跨 LLM 使用——用户有了真正的选择权。
这种"开放胜过封闭"的价值观、在互联网历史上反复上演——HTTP 胜过各种专有协议、HTML 胜过 Flash/Silverlight、Linux 胜过各种 Unix 变种——开放总是最终获胜。MCP 的成功、延续了这个传统——AI 时代的基础设施、依然遵循"开放胜过封闭"的规律。作为工程师、选择开放标准而非封闭方案、不只是技术选择、更是对"用户自由"的支持——这种价值观、值得每个技术决策者铭记——技术人的选择、塑造了技术世界的形态。
延伸阅读:MCP 与国内生态
MCP 在国内的落地、正在快速推进。几大国产 LLM 厂商(通义、文心、智谱、Kimi)都在或已经支持 MCP——让国产 LLM 也能享受 MCP 生态的工具。国内社区也在快速搭建 MCP Server——有做微信公众号发布、飞书文档管理、企业微信自动化、钉钉办公、小红书分析——各种国内特有工具的 MCP Server。这让国内开发者能在国产 LLM + 国产工具的全栈下、享受 MCP 带来的便利。
这种"国产 + 国产"的生态、在合规、支付、本地化方面有独特优势——企业客户不用担心数据出境、不用操心外币付费、文档和客服都是中文。对服务国内企业市场的 AI 创业公司——基于国产 LLM + MCP 搭建方案、可能是比"OpenAI + LangChain"更务实的选择。《LangChain 源码》第 17 章提到的本土化 Partner 包、也是类似思路——用开放标准 + 本土适配、服务本土市场。
延伸阅读:MCP Server 的开发者体验
好的 MCP Server、除了"LLM 友好"、还要"开发者友好"——让其他开发者能快速理解、部署、扩展。"开发者友好"的几个维度——"文档清晰"(README 能让人 5 分钟上手)、"配置简单"(环境变量或 YAML、不要复杂的初始化脚本)、"错误信息友好"(报错时告诉用户怎么修)、"有示例"(提供典型用法的示例代码)、"维护活跃"(issues 及时回复、PR 及时 review)。
这些看起来和普通开源项目一样——确实一样——MCP Server 本质上就是一个开源库。但在 MCP 生态刚起步的阶段、"开发者友好"尤其重要——因为用户在比较"这个 MCP 还是那个 MCP"时、文档质量、社区活跃度往往比功能本身更有决定作用。对有志做 MCP Server 的开发者——投入 30% 精力写代码、70% 精力做文档和社区——这个比例可能更有回报、也更符合开源项目的成功规律。