Host / Client / Server 三层架构
MCP 采用严格的三层架构设计,每一层都有明确的职责边界。理解这个架构是所有 MCP 开发工作的基础。
╔═══════════════════════════════════════════════════════════════╗ ║ 第一层:MCP Host ║ ║ 用户界面 + LLM 推理引擎 + 对话管理 + 权限控制 ║ ║ ║ ║ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ ║ ║ │ MCP Client A │ │ MCP Client B │ │ MCP Client C │ ║ ║ │ 连接管理 │ │ 消息序列化 │ │ 能力缓存 │ ║ ║ └───────┬───────┘ └───────┬───────┘ └───────┬───────┘ ║ ╚═══════╪═══════════════════╪═══════════════════╪═══════════════╝ │ Transport │ Transport │ Transport ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄ ┌───────┴───────┐ ┌───────┴───────┐ ┌───────┴───────┐ │ MCP Server A │ │ MCP Server B │ │ MCP Server C │ │ Tools │ │ Tools │ │ Tools │ │ Resources │ │ Resources │ │ Resources │ │ Prompts │ │ Prompts │ │ Prompts │ └───────────────┘ └───────────────┘ └───────────────┘ 第三层:MCP Server(每个 Server 通过独立进程运行)
Host 层的职责
Host 是 MCP 架构中的协调者,它同时具备两个身份:一方面是 LLM 的运行环境和用户交互界面,另一方面是所有 MCP Client 的管理者。
- 管理用户与 AI 之间的对话流程
- 决定何时调用哪个 MCP Server 的能力
- 为每个 Server 连接维护独立的 MCP Client 实例
- 执行用户授权,控制 AI 可以访问的工具和数据
- 聚合多个 Server 的能力,统一呈现给 LLM
Client 层的职责
Client 是 Host 内部的协议适配器,每个 Client 对应一个 Server 连接。
- 维护与特定 Server 的持久连接
- 处理 JSON-RPC 消息的序列化与反序列化
- 管理请求-响应的匹配(通过消息 ID)
- 缓存 Server 的能力列表(capabilities)
- 处理连接断开与重连逻辑
Server 层的职责
Server 是能力提供者,通常是一个轻量级的独立进程,专注于特定领域的功能。
- 声明自身提供的能力(capabilities)
- 实现并暴露 Tools、Resources、Prompts
- 处理来自 Client 的调用请求并返回结果
- 访问底层资源(文件系统、数据库、API 等)
- 管理自身状态和资源生命周期
JSON-RPC 2.0 通信协议
MCP 使用 JSON-RPC 2.0 作为消息格式规范。这是一个轻量级的远程过程调用协议,消息格式简单清晰,易于调试。
三种消息类型
1. Request(请求)
需要对方响应的消息,包含唯一的 id 字段:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "read_file",
"arguments": {
"path": "/home/user/notes.txt"
}
}
}
2. Response(响应)
对 Request 的回复,id 必须与对应 Request 匹配:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "今日待办:学习 MCP 协议..."
}
]
}
}
3. Notification(通知)
不需要响应的单向消息,没有 id 字段:
{
"jsonrpc": "2.0",
"method": "notifications/resources/updated",
"params": {
"uri": "file:///home/user/notes.txt"
}
}
错误响应格式
当 Request 处理失败时,响应中包含 error 字段而非 result:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32602,
"message": "Invalid params",
"data": { "detail": "path is required" }
}
}
MCP 使用标准 JSON-RPC 错误码(-32700 到 -32603)加上自定义扩展错误码。
传输层:stdio / SSE / Streamable HTTP
MCP 支持多种传输方式,传输层负责将 JSON-RPC 消息在 Client 与 Server 之间物理传递。
stdio 传输
最简单、最常用的传输方式。Host 启动 Server 子进程,通过进程的标准输入输出(stdin/stdout)交换消息。
Host Process ┌──────────────────────────────────────┐ │ MCP Client │ │ │ │ │ │ spawn() Server Process │ │ │ ─────────►┌──────────────────┐ │ │ │ stdin │ │ │ │ ├──────────►│ MCP Server │ │ │ │ stdout │ │ │ │ │◄──────────│ node server.js │ │ │ │ stderr │ (日志输出) │ │ │ │ └──────────────────┘ │ └──────────────────────────────────────┘ 每行一个完整的 JSON 消息(换行符分隔)
适用场景:本地工具(文件系统、本地数据库、代码执行),Claude Desktop 配置的 MCP Server 几乎都使用 stdio。
HTTP + SSE 传输(旧规范)
MCP 1.0 之前的 HTTP 传输方式,使用 Server-Sent Events(SSE) 实现服务端推送。Client 通过 HTTP POST 发送请求,Server 通过 SSE 流推送响应和通知。
Streamable HTTP 传输(新规范)
MCP 1.0 引入的新传输方式,解决了旧 SSE 方案的多个问题:
- Client 向单一端点发送 HTTP POST 请求
- Server 可以返回普通 JSON 响应,也可以返回 SSE 流
- 支持无状态服务器(每次请求不需要维护连接状态)
- 更好的负载均衡和云端部署兼容性
POST /mcp HTTP/1.1
Host: api.example.com
Content-Type: application/json
Accept: application/json, text/event-stream
{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{...}}
消息生命周期
一次完整的 MCP 会话包含以下阶段:
Host / Client MCP Server ─── 阶段一:初始化 ──────────────────────────────────────────── initialize ──────────────────────────────► ◄──────────────────────────── InitializeResult initialized ─────────────────────────────► (notification) ─── 阶段二:能力发现 ─────────────────────────────────────────── tools/list ──────────────────────────────► ◄──────────────────────────── {tools: [...]} resources/list ──────────────────────────► ◄──────────────────────────── {resources: [...]} prompts/list ────────────────────────────► ◄──────────────────────────── {prompts: [...]} ─── 阶段三:正常使用 ─────────────────────────────────────────── tools/call ──────────────────────────────► ◄──────────────────────────── {content: [...]} resources/read ──────────────────────────► ◄──────────────────────────── {contents: [...]} ◄──────────────────────────── notifications/... (push) ─── 阶段四:关闭 ────────────────────────────────────────────── (关闭传输连接)
能力协商(Capability Negotiation)
MCP 连接建立时,Client 和 Server 都会通过 initialize 握手声明自己支持的能力。这使得协议具有良好的向后兼容性和扩展性。
初始化请求示例
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {
"sampling": {}, // Client 支持 sampling
"roots": {
"listChanged": true // 支持 roots 变更通知
}
},
"clientInfo": {
"name": "Claude Desktop",
"version": "1.5.0"
}
}
}
初始化响应示例
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {
"tools": { "listChanged": true }, // 支持工具列表动态变更
"resources": {
"subscribe": true, // 支持资源订阅
"listChanged": true
},
"prompts": { "listChanged": true }
},
"serverInfo": {
"name": "my-filesystem-server",
"version": "1.0.0"
}
}
}
可协商的 Server 能力
resources.subscribe 但不处理订阅请求——这会导致 Client 行为异常,也会破坏协议的信任机制。