MCP 核心架构与协议原理
大约 8 分钟
MCP 核心架构与协议原理
Host-Client-Server 三角色架构
架构总览
MCP 采用 Host(宿主)— Client(客户端)— Server(服务端) 三角色架构。这是理解 MCP 最重要的基础概念:
三个角色详解
| 角色 | 是什么 | 职责 | 举例 |
|---|---|---|---|
| Host(宿主) | 用户直接交互的 AI 应用 | 管理多个 Client,协调 LLM 与工具的交互 | Claude Desktop、ChatGPT、Cursor、VS Code |
| Client(客户端) | Host 内部的协议客户端 | 与一个 Server 维持 1:1 连接,处理能力协商和消息路由 | Host 内自动创建,开发者通常不直接操作 |
| Server(服务端) | 暴露特定能力的轻量程序 | 提供工具、资源、提示词等能力,通过标准化协议对外服务 | 文件系统 Server、数据库 Server、搜索 Server |
关键约束:
- 一个 Host 可以管理多个 Client
- 每个 Client 与一个 Server 保持 1:1 连接
- 每个 Server 专注于一个领域(如文件操作、数据库查询等)
真实场景示例
以 Claude Desktop 为例,展示完整的架构关系:
协议层:JSON-RPC 2.0
为什么选择 JSON-RPC 2.0
MCP 的所有通信都基于 JSON-RPC 2.0 协议。这是一个轻量级、无状态的远程过程调用协议,使用 JSON 编码。
选择 JSON-RPC 2.0 的原因:
| 特性 | 说明 |
|---|---|
| 简单 | 只有请求、响应、通知三种消息类型,学习成本低 |
| 通用 | 几乎所有编程语言都有成熟的 JSON-RPC 库 |
| 可读 | JSON 格式人类可读,便于调试和排查问题 |
| 灵活 | 支持双向通信,Client 和 Server 都可以发起请求 |
四种消息类型
1. Request(请求)— 期望得到响应
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "read_file",
"arguments": { "path": "/tmp/test.txt" }
}
}
2. Response(响应)— 对请求的回复
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{ "type": "text", "text": "Hello, World!" }
]
}
}
3. Notification(通知)— 单向消息,无需回复
{
"jsonrpc": "2.0",
"method": "notifications/message",
"params": {
"level": "info",
"data": "Server started successfully"
}
}
4. Error(错误)— 表示失败的响应
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32602,
"message": "Invalid params: missing required field 'path'"
}
}
消息字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
jsonrpc | string | 固定为 "2.0",标识 JSON-RPC 版本 |
id | number/string | 请求的唯一标识,Response 必须匹配对应的 Request 的 id |
method | string | 要调用的方法名(如 tools/call、resources/read) |
params | object | 方法参数,可选 |
result | any | 成功时的返回结果 |
error | object | 失败时的错误信息,包含 code 和 message |
[!tip] 区分 Request 和 Notification
带有id字段的是 Request(需要响应),没有id的是 Notification(单向通知,无需响应)。这个区别很重要。
连接生命周期
MCP 连接分为三个阶段:初始化 → 运行 → 关闭。
阶段一:初始化(Initialize)
初始化是 Client 和 Server 建立连接后的第一次交互,用于协商双方的能力和协议版本:
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"
}
}
}
initialize 响应示例:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2025-03-26",
"capabilities": {
"tools": { "listChanged": true },
"resources": { "subscribe": true, "listChanged": true },
"prompts": { "listChanged": true }
},
"serverInfo": {
"name": "filesystem-server",
"version": "1.0.0"
}
}
}
能力协商(Capability Negotiation)
初始化阶段最重要的工作是能力协商。双方各自声明自己支持哪些能力,只有在双方都支持的情况下,对应功能才能使用:
| 能力 | 声明方 | 说明 |
|---|---|---|
tools | Server | "我提供可调用的工具" |
resources | Server | "我提供可读取的数据资源" |
prompts | Server | "我提供提示词模板" |
sampling | Client | "我允许 Server 请求 LLM 推理" |
roots | Client | "我暴露工作区根目录给 Server" |
阶段二:运行(Operation)
初始化完成后,进入正常的运行阶段。Client 和 Server 通过请求/响应交换完成实际工作:
运行阶段支持的操作:
| 操作 | 方法名 | 方向 | 说明 |
|---|---|---|---|
| 列出工具 | tools/list | Client → Server | 获取 Server 提供的所有工具 |
| 调用工具 | tools/call | Client → Server | 执行指定工具 |
| 列出资源 | resources/list | Client → Server | 获取 Server 暴露的所有资源 |
| 读取资源 | resources/read | Client → Server | 读取指定资源的内容 |
| 列出提示词 | prompts/list | Client → Server | 获取所有提示词模板 |
| 获取提示词 | prompts/get | Client → Server | 获取指定提示词的完整内容 |
| 采样请求 | sampling/createMessage | Server → Client | Server 请求 Client 进行 LLM 推理 |
| 日志通知 | notifications/message | Server → Client | Server 发送日志信息 |
| 工具变更 | notifications/tools/list_changed | Server → Client | 工具列表发生变化 |
阶段三:关闭(Shutdown)
任何一方都可以主动关闭连接:
[!tip] 关闭是优雅的
MCP 推荐使用优雅关闭:先停止发送新请求,等待正在进行的请求完成,然后关闭传输通道。这样可以避免数据丢失。
协议版本管理
MCP 使用基于日期的版本号,格式为 YYYY-MM-DD:
| 版本 | 发布时间 | 重要变更 |
|---|---|---|
2024-11-05 | 2024.11 | 初始发布版本 |
2025-03-26 | 2025.03 | 新增 Streamable HTTP 传输,废弃 HTTP+SSE |
2025-06-18 | 2025.06 | 结构化输出,安全增强 |
2025-11-25 | 2025.11 | 一周年版本,进一步完善 |
在初始化阶段,Client 和 Server 会交换各自支持的协议版本。双方应使用共同支持的最高版本进行通信。
完整通信流程总览
将所有概念串联起来,一个完整的 MCP 通信流程如下:
总结
| 核心概念 | 要点 |
|---|---|
| 三角色架构 | Host 管理 Client,Client 连接 Server,1:1 关系 |
| 协议基础 | 基于 JSON-RPC 2.0,四种消息类型 |
| 生命周期 | 初始化(能力协商)→ 运行(请求/响应)→ 关闭(优雅断开) |
| 能力协商 | 双方在初始化时声明各自支持的能力,只有双方都支持才能使用 |
| 版本管理 | 基于日期的版本号,协商使用共同支持的最高版本 |