1. MCP 的范围 #
1.1 包含的内容 #
| 项目 | 说明 |
|---|---|
| MCP 规范 | 定义客户端和服务器的实现要求 |
| MCP SDK | 各语言的官方实现库 |
| MCP 开发工具 | 如 MCP Inspector,用于调试和开发 |
| 参考服务器 | 官方示例实现,供学习参考 |
1.2 不包含的内容 #
- MCP 只负责「上下文交换」的协议——即 AI 怎么从外部系统拿数据、调工具
- 不规定 AI 应用内部如何用 LLM、如何管理上下文
2. 核心角色:谁在和谁通信? #
2.1 三个关键角色 #
| 角色 | 通俗理解 | 举例 |
|---|---|---|
| MCP 主机 | 你用的 AI 应用,负责协调一切 | Claude Desktop、VS Code |
| MCP 客户端 | 主机里专门和某个服务器「对话」的组件 | 每个服务器对应一个客户端 |
| MCP 服务器 | 提供数据、工具、提示的程序 | 文件系统服务器、Sentry 服务器 |
2.2 通俗理解 #
- 主机 = 总指挥(AI 应用)
- 客户端 = 派去和每个服务器对接的「代表」
- 服务器 = 提供具体能力的一方(数据、工具等)
2.3 连接示意 #
flowchart TD
subgraph "MCP 主机(AI 应用)"
Client1["MCP 客户端 1"]
Client2["MCP 客户端 2"]
Client3["MCP 客户端 3"]
Client4["MCP 客户端 4"]
end
ServerA["MCP 服务器 A<br>(如:本地文件系统)"]
ServerB["MCP 服务器 B<br>(如:本地数据库)"]
ServerC["MCP 服务器 C<br>(如:远程 Sentry)"]
Client1 -->|专用连接| ServerA
Client2 -->|专用连接| ServerB
Client3 -->|专用连接| ServerC
Client4 -->|专用连接| ServerC
要点:一个主机可以连多个服务器;每个服务器对应一个客户端;本地服务器通常只服务一个客户端,远程服务器可服务多个。
3. 两层架构:数据层 + 传输层 #
MCP 由两层组成,可以理解为:
- 数据层(内层):约定「说什么」——消息格式、请求/响应类型
- 传输层(外层):约定「怎么传」——连接方式、认证方式
3.1 数据层 #
| 功能 | 说明 |
|---|---|
| 生命周期管理 | 连接建立、能力协商、连接终止 |
| 服务器功能 | 工具、资源、提示等「原语」的提供方式 |
| 客户端功能 | 采样、引导、日志等 |
| 实用功能 | 通知、进度跟踪等 |
3.2 传输层 #
| 传输方式 | 适用场景 | 特点 |
|---|---|---|
| Stdio | 本地进程 | 同一台机器上,直接进程通信,无网络开销 |
| Streamable HTTP | 远程服务 | 支持远程、支持 HTTP 认证(Bearer、API Key 等) |
4. 核心概念:原语 #
原语 是 MCP 里最重要的概念,指的是「客户端和服务器可以互相提供的内容类型」。
4.1 服务器提供的原语(AI 可用的) #
| 原语 | 通俗理解 | 举例 |
|---|---|---|
| 工具 | 可调用的函数 | 查天气、算数学、写文件 |
| 资源 | 可读取的数据 | 文件内容、数据库记录、API 响应 |
| 提示 | 可复用的提示模板 | 系统提示、少样本示例 |
4.2 客户端提供的原语(服务器可请求的) #
| 原语 | 通俗理解 | 举例 |
|---|---|---|
| 采样 | 向 AI 请求补全 | 服务器让客户端帮忙调用 LLM |
| 引导 | 向用户要更多信息 | 弹窗让用户填表单、确认操作 |
| 日志 | 向客户端发日志 | 调试、监控 |
4.3 通用原语 #
- 任务(实验性):支持长时间运行、延迟返回结果的操作
4.4 原语怎么用? #
每种原语都有对应的「发现」和「获取」方法,例如:
tools/list→ 列出工具tools/call→ 调用工具resources/list→ 列出资源resources/read→ 读取资源
5. 通知:实时更新 #
服务器可以在不等待请求的情况下,主动通知客户端「有变化了」。
例如:工具列表变了,服务器发 notifications/tools/list_changed,客户端收到后去刷新 tools/list。
好处:客户端不用轮询,就能保持信息最新。
6. 完整示例:从连接到工具调用 #
下面用一个简化流程,演示 MCP 客户端和服务器如何交互。
6.1 步骤 1:初始化(握手) #
客户端发 initialize 请求,双方协商协议版本和能力。
客户端请求示例:
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-06-18",
"capabilities": { "elicitation": {} },
"clientInfo": { "name": "example-client", "version": "1.0.0" }
}
}服务器响应会包含自己的 capabilities 和 serverInfo。协商成功后,客户端发 notifications/initialized 表示就绪。
关键点:
capabilities用来声明各自支持什么(工具、资源、提示、通知等),避免调用不支持的功能。
6.2 步骤 2:发现工具 #
客户端发 tools/list,服务器返回可用工具列表。
请求:
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list"
}响应中包含每个工具的 name、title、description、inputSchema 等,例如计算器、天气查询等。
6.3 步骤 3:调用工具 #
客户端用 tools/call 执行具体工具。
请求示例(查天气):
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "weather_current",
"arguments": {
"location": "San Francisco",
"units": "imperial"
}
}
}响应中 content 数组里是工具返回的结果(如文本、图片等)。
6.4 步骤 4:收到通知后刷新 #
当服务器工具列表变化时,会发通知:
{
"jsonrpc": "2.0",
"method": "notifications/tools/list_changed"
}客户端收到后,可再次发 tools/list 获取最新列表。
7. 在 AI 应用里是怎么跑的? #
| 阶段 | AI 应用做的事 |
|---|---|
| 初始化 | 建立与各服务器的连接,记录各自的能力 |
| 工具发现 | 从所有服务器收集工具,合并成统一列表供 LLM 使用 |
| 工具调用 | LLM 决定用哪个工具时,应用转发请求到对应服务器,拿到结果后塞回对话 |
| 通知 | 收到工具变更通知时,刷新工具列表,让 LLM 知道新能力 |
8. 本章小结 #
| 要点 | 说明 |
|---|---|
| 角色 | 主机(AI 应用)→ 客户端(对接代表)→ 服务器(提供能力) |
| 两层 | 数据层管「说什么」,传输层管「怎么传」 |
| 原语 | 工具、资源、提示(服务器提供);采样、引导、日志(客户端提供) |
| 流程 | 初始化 → 发现 → 调用 → 通知刷新 |