第2章 MCP协议深度解析
前言
理解MCP协议是掌握整个生态的基础。本章将从通信原理、核心概念、消息格式、安全机制等多个维度深入解析MCP协议的设计哲学和实现细节。
2.1 MCP架构与设计原理
2.1.1 客户端-服务器模型
MCP采用经典的客户端-服务器(Client-Server)架构 ,但与传统Web API不同,它实现了双向异步通信。
传统CS模型 vs MCP模型
MCP模型的核心特点:
-
双向通信
- 客户端可以主动调用工具、访问资源
- 服务器可以主动推送资源变化通知
- 形成一个真正的对话通道,而不只是请求-响应
-
异步处理
- 消息不需要立即响应
- 支持长时间运行的操作
- 请求可以被取消
-
多路复用
- 单个连接上支持多个并发请求
- 每个请求有唯一的ID来追踪
- 避免了连接阻塞
2.1.2 通信机制与消息格式
MCP基于JSON-RPC 2.0规范构建,选择这个标准是因为:
- 轻量级、易于解析
- 平台无关、语言无关
- 已有成熟的实现库
- 广泛被业界接受
MCP通信的三个层级
JSON-RPC 2.0基础
一个标准的JSON-RPC请求:
json
{
"jsonrpc": "2.0",
"id": "req_123",
"method": "tools/call",
"params": {
"name": "query_sales",
"arguments": {
"start_date": "2025-01-01",
"end_date": "2025-12-31"
}
}
}
响应格式:
json
{
"jsonrpc": "2.0",
"id": "req_123",
"result": {
"content": [
{
"type": "text",
"text": "销售总额:$5,000,000"
}
]
}
}
或者错误响应:
json
{
"jsonrpc": "2.0",
"id": "req_123",
"error": {
"code": -32602,
"message": "Invalid params",
"data": {
"details": "start_date format must be YYYY-MM-DD"
}
}
}
关键概念:
| 字段 | 说明 | 示例 |
|---|---|---|
jsonrpc |
协议版本 | "2.0" |
id |
请求唯一标识 | "req_123"(字符串或数字) |
method |
调用的方法 | "tools/call"、"resources/read" |
params |
方法参数 | 对象或数组 |
result |
成功时的结果 | 任意JSON值 |
error |
失败时的错误 | {code, message, data} |
2.1.3 MCP消息类型完整体系
2.1.4 协议的演进与版本管理
版本兼容性策略:
- 主版本号变更:不保证向后兼容
- 次版本号变更:向后兼容
- 修订号变更:bug修复和澄清
客户端和服务器应该在初始化时协商协议版本。
2.2 MCP的核心概念
2.2.1 工具(Tools)的定义与作用
定义 :工具是LLM可以调用的功能,用于执行具体的操作或计算任务。
本质 :工具 = 元数据 + 实现
json
{
"name": "transfer_funds",
"description": "转账资金到指定账户",
"inputSchema": {
"type": "object",
"properties": {
"from_account": {
"type": "string",
"description": "源账户ID"
},
"to_account": {
"type": "string",
"description": "目标账户ID"
},
"amount": {
"type": "number",
"description": "转账金额"
},
"reason": {
"type": "string",
"description": "转账原因"
}
},
"required": ["from_account", "to_account", "amount"]
}
}
工具的生命周期:
工具的分类:
| 类型 | 特点 | 示例 |
|---|---|---|
| 查询类 | 只读,返回信息 | 查询账户余额、搜索文档 |
| 操作类 | 修改状态,有副作用 | 创建订单、发送邮件 |
| 计算类 | 数学运算、数据处理 | 分析数据、生成报告 |
| 转换类 | 格式转换、数据映射 | 导出Excel、格式化文本 |
2.2.2 资源(Resources)的含义
定义 :资源是LLM可以访问的数据源或信息,代表持久化的内容。
本质 :资源 = 标识 + 内容 + 元数据
资源 vs 工具的区别:
资源URI方案:
bash
resources://authority/path?query=value
示例:
- resources://salesdb/reports/q1_2025.xlsx
- resources://docs/product_manual.pdf
- resources://config/system_settings.json
- resources://employees/dept_001/team_list.csv
资源的三种访问模式:
2.2.3 提示模板(Prompts)的角色
定义 :提示模板是预定义的、参数化的提示词,用于指导LLM的行为。
作用:
- 标准化:确保相同的任务获得一致的处理
- 参数化:支持动态参数注入
- 知识编码:将专家知识编码到提示中
- 复用:跨项目、跨团队共享
提示模板示例:
json
{
"name": "analyze_sales_trends",
"description": "分析销售趋势的专家级提示",
"arguments": [
{
"name": "time_period",
"description": "分析的时间周期",
"required": true
},
{
"name": "product_category",
"description": "产品类别(可选)",
"required": false
}
]
}
模板内容示例:
bash
请作为销售分析专家,分析{time_period}的销售数据。
关注点:
1. 销售额趋势
2. 产品结构变化
3. 区域表现差异
{#if product_category}
4. 特别关注{product_category}类别的表现
{/if}
请提供具体的建议和预测。
2.2.4 取样(Sampling)机制
定义 :取样是让服务器能够请求LLM进行推理 的机制。这形成了一个循环。
应用场景:
- 服务器需要LLM帮助做决策
- 数据验证或复杂的业务逻辑判断
- 需要LLM的自然语言理解能力
取样流程:
这创造了一个自反馈循环,让MCP系统具有更高的智能性。
2.3 MCP的通信协议
2.3.1 JSON-RPC 2.0详细解析
请求类型
1. 标准请求(期望响应)
json
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {
"roots": {},
"sampling": {}
},
"clientInfo": {
"name": "Claude Desktop",
"version": "1.0.0"
}
}
}
2. 通知(不期望响应)
json
{
"jsonrpc": "2.0",
"method": "notifications/resources/list_changed"
}
通知用于单向通信,不需要响应。
响应类型
1. 成功响应
json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {
"resources": {},
"tools": {}
},
"serverInfo": {
"name": "Sales Database",
"version": "2.1.0"
}
}
}
2. 错误响应
json
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32601,
"message": "Method not found",
"data": {
"method": "unknown_method"
}
}
}
JSON-RPC 2.0错误码标准:
| 错误码 | 含义 | 说明 |
|---|---|---|
| -32700 | Parse error | JSON解析失败 |
| -32600 | Invalid Request | 请求格式不正确 |
| -32601 | Method not found | 方法不存在 |
| -32602 | Invalid params | 参数不合法 |
| -32603 | Internal error | 服务器内部错误 |
| -32000到-32099 | Server error | 服务器自定义错误 |
2.3.2 请求-响应模式详解
请求ID的重要性
在异步环境中,请求ID用于匹配请求和响应:
多路复用示例
python
# 伪代码:客户端同时发起多个请求
async def call_multiple_tools():
# 发起三个并发请求
task1 = client.call_tool("query_sales", id="req1")
task2 = client.call_tool("calculate_average", id="req2")
task3 = client.call_tool("fetch_report", id="req3")
# 等待所有响应(无需按顺序)
results = await asyncio.gather(task1, task2, task3)
return results
2.3.3 流式与实时通信
MCP支持多种传输方式,适应不同场景:
各传输方式对比:
| 方式 | 延迟 | 连接管理 | 实时性 | 适用场景 |
|---|---|---|---|---|
| stdio | 极低 | 简单 | 同步 | 本地工具、桌面应用 |
| HTTP | 中 | 无状态 | 低 | REST API、无状态服务 |
| WebSocket | 低 | 持久连接 | 高 | 实时推送、长连接 |
2.4 MCP的安全性与权限控制
2.4.1 身份验证机制
多层验证体系
API Key验证
最简单的验证方式:
json
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"clientInfo": {
"name": "Claude",
"version": "1.0"
},
"authentication": {
"type": "api_key",
"key": "sk-1234567890abcdef"
}
}
}
OAuth 2.0集成
对于复杂的企业场景:
json
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"authentication": {
"type": "oauth2",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"scope": ["tools:read", "resources:read"]
}
}
}
2.4.2 权限模型
细粒度权限控制
权限定义示例:
json
{
"version": "2024-11-05",
"permissions": {
"tools": {
"query_sales": {
"allowed": true,
"timeRange": {
"startDate": "2025-01-01",
"endDate": "2025-12-31"
}
},
"transfer_funds": {
"allowed": true,
"maxAmount": 100000,
"requiresApproval": true
}
},
"resources": {
"resources://finance/*": {
"read": true,
"write": false
}
}
}
}
2.4.3 数据隐私保护
数据敏感化策略
个人数据脱敏示例:
python
# 返回客户信息前进行脱敏
def anonymize_customer_data(customer):
return {
"id": customer["id"],
"email": mask_email(customer["email"]), # 隐藏部分邮箱
"phone": mask_phone(customer["phone"]), # 隐藏部分电话
"name": customer["name"], # 完整名字
# 注意:不返回敏感字段如密码、SSN等
}
def mask_email(email):
# example@domain.com -> exa***@domain.com
parts = email.split("@")
return parts[0][:3] + "***@" + parts[1]
def mask_phone(phone):
# 13812345678 -> 1381****5678
return phone[:4] + "****" + phone[-4:]
HIPAA/GDPR合规
对于医疗和欧洲客户:
json
{
"security": {
"encryption": {
"transport": "TLS 1.3",
"storage": "AES-256"
},
"compliance": ["HIPAA", "GDPR"],
"dataRetention": {
"logs": "30 days",
"personalData": "user configurable"
},
"audit": {
"enabled": true,
"retention": "90 days",
"immutable": true
}
}
}
2.5 MCP协议在实践中的应用
2.5.1 完整的工具调用流程
2.5.2 错误处理最佳实践
python
# 客户端侧的完善错误处理
class MCPClient:
async def call_tool(self, tool_name, arguments):
try:
request = {
"jsonrpc": "2.0",
"id": self.generate_request_id(),
"method": "tools/call",
"params": {
"name": tool_name,
"arguments": arguments
}
}
# 发送请求并设置超时
response = await self.send_request(request, timeout=30)
# 检查是否有错误
if "error" in response:
error = response["error"]
if error["code"] == -32602:
raise InvalidParamsError(error["message"])
elif error["code"] == -32601:
raise MethodNotFoundError(error["message"])
else:
raise MCPError(error["message"])
return response.get("result")
except asyncio.TimeoutError:
raise TimeoutError(f"Tool {tool_name} execution timeout")
except ConnectionError:
raise ConnectionError("Lost connection to MCP server")
本章总结
| 核心概念 | 关键点 |
|---|---|
| 架构模型 | 客户端-服务器,双向异步通信 |
| 通信基础 | JSON-RPC 2.0,轻量级、标准化 |
| 核心概念 | 工具、资源、提示、取样 |
| 消息类型 | 请求、响应、通知、资源更新 |
| 多路复用 | 单连接并发多个请求,按ID匹配 |
| 传输方式 | stdio、HTTP、WebSocket等 |
| 安全认证 | API Key、OAuth 2.0、JWT |
| 权限控制 | 细粒度的工具、资源、操作权限 |
| 数据隐私 | 脱敏、加密、审计、合规 |
常见问题
Q1: 为什么MCP选择JSON-RPC而不是gRPC或REST? A: JSON-RPC相比gRPC更轻量级,更易于跨语言实现;相比REST更适合双向通信。这是在简洁性和功能性之间的最优平衡。
Q2: 单个连接如何支持并发请求? A: 通过为每个请求分配唯一的id,响应时返回相同的id,客户端据此匹配。这样即使响应顺序打乱也能正确处理。
Q3: 通知(notification)和请求有什么区别? A: 通知没有id字段,发送端不期望响应,用于单向消息。请求有id,发送端期望收到响应。
Q4: 资源和工具如何选择使用? A: 规则是:如果内容是持久的、不变的数据 用资源;如果是动态计算、有副作用的操作用工具。
Q5: MCP如何保证消息安全? A: 多层防护:传输层TLS加密、应用层身份验证和授权、资源层细粒度权限控制、审计日志记录。
关键代码片段
TypeScript中的请求处理
typescript
interface MCPRequest {
jsonrpc: "2.0";
id: string | number;
method: string;
params?: Record<string, any>;
}
interface MCPResponse {
jsonrpc: "2.0";
id: string | number;
result?: any;
error?: {
code: number;
message: string;
data?: any;
};
}
async function sendRequest(request: MCPRequest): Promise<MCPResponse> {
const response = await fetch("http://mcp-server/rpc", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(request)
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return response.json();
}
延伸阅读
- JSON-RPC 2.0规范:www.jsonrpc.org/specificati...
- MCP协议规范:spec.modelcontextprotocol.io
- 安全认证最佳实践:参见第23章
下一章预告:第3章将讲述MCP与LLM的协同机制,包括工具调用、上下文注入、循环推理等核心互动方式。