2.3 通信协议
🎯 学习目标:掌握MCP的通信协议规范、消息格式和交互模式
⏱️ 预计时间:45分钟
📊 难度等级:⭐⭐
📡 MCP通信协议概述
MCP协议是基于JSON-RPC 2.0的标准化通信协议,就像互联网的HTTP协议一样,它定义了Client和Server之间的"语言规则"。
🎪 协议的比喻理解
想象MCP协议就像是外交礼仪:
🤝 外交会议
──────────────────────────────────
📋 议程表(协议规范) - 定义会议流程
🗣️ 发言格式(消息格式) - 统一表达方式
🔄 对话规则(交互模式) - 谁先说,怎么回应
📝 会议记录(日志追踪) - 记录所有交流
🔧 协议基础架构
📊 协议栈层次
各层职责:
- 🔝 应用层:MCP特定的业务逻辑(工具调用、资源访问等)
- 📨 消息层:JSON-RPC 2.0标准消息格式
- 🚀 传输层:底层传输机制(WebSocket、HTTP、标准输入输出)
- 🌐 网络层:基础网络通信
🎯 JSON-RPC 2.0基础
MCP基于JSON-RPC 2.0协议,这是一个轻量级的远程过程调用协议:
javascript
// JSON-RPC 2.0 请求格式
{
"jsonrpc": "2.0", // 协议版本(必须)
"method": "methodName", // 调用的方法名(必须)
"params": {...}, // 参数对象(可选)
"id": 123 // 请求ID(必须,用于匹配响应)
}
// JSON-RPC 2.0 响应格式
{
"jsonrpc": "2.0", // 协议版本(必须)
"result": {...}, // 成功结果(成功时必须)
"error": {...}, // 错误信息(失败时必须)
"id": 123 // 对应的请求ID(必须)
}
// JSON-RPC 2.0 通知格式(无需响应)
{
"jsonrpc": "2.0", // 协议版本(必须)
"method": "notify", // 通知方法名(必须)
"params": {...} // 参数对象(可选)
// 注意:通知没有id字段
}
🔄 MCP消息类型
📋 三种核心消息类型
1. 🔍 请求消息(Request)
用于Client向Server发起调用:
javascript
// 工具调用请求
{
"jsonrpc": "2.0",
"id": "req-001",
"method": "tools/call",
"params": {
"name": "calculator",
"arguments": {
"operation": "add",
"a": 123,
"b": 456
}
}
}
2. ✅ 响应消息(Response)
Server对Request的回复:
javascript
// 成功响应
{
"jsonrpc": "2.0",
"id": "req-001",
"result": {
"content": [
{
"type": "text",
"text": "579"
}
]
}
}
// 错误响应
{
"jsonrpc": "2.0",
"id": "req-001",
"error": {
"code": "INVALID_PARAMS",
"message": "参数a必须是数字类型"
}
}
3. 📢 通知消息(Notification)
单向消息,无需响应:
javascript
// 初始化完成通知
{
"jsonrpc": "2.0",
"method": "notifications/initialized"
}
// 资源变更通知
{
"jsonrpc": "2.0",
"method": "notifications/resources/list_changed"
}
🚀 MCP标准方法
📖 核心方法分类
MCP定义了一系列标准方法,按功能分为几大类:
🔧 初始化流程
连接建立的完整握手过程
初始化请求详解
javascript
// Client发送的initialize请求
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-01-07",
"capabilities": {
"roots": {
"listChanged": true
},
"sampling": {}
},
"clientInfo": {
"name": "My MCP Client",
"version": "1.0.0"
}
}
}
// Server返回的响应
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2025-01-07",
"capabilities": {
"logging": {},
"tools": {
"listChanged": true
},
"resources": {
"subscribe": true,
"listChanged": true
},
"prompts": {
"listChanged": true
}
},
"serverInfo": {
"name": "Example MCP Server",
"version": "1.0.0"
}
}
}
🛠️ 工具相关方法
tools/list - 获取工具列表
javascript
// 请求
{
"jsonrpc": "2.0",
"id": "tools-list-001",
"method": "tools/list"
}
// 响应
{
"jsonrpc": "2.0",
"id": "tools-list-001",
"result": {
"tools": [
{
"name": "calculator",
"description": "基础数学计算器",
"inputSchema": {
"type": "object",
"properties": {
"operation": {
"type": "string",
"enum": ["add", "subtract", "multiply", "divide"]
},
"a": { "type": "number" },
"b": { "type": "number" }
},
"required": ["operation", "a", "b"]
}
},
{
"name": "weather",
"description": "获取天气信息",
"inputSchema": {
"type": "object",
"properties": {
"city": { "type": "string" },
"country": { "type": "string", "default": "CN" }
},
"required": ["city"]
}
}
]
}
}
tools/call - 调用工具
javascript
// 调用计算器工具
{
"jsonrpc": "2.0",
"id": "calc-001",
"method": "tools/call",
"params": {
"name": "calculator",
"arguments": {
"operation": "add",
"a": 123,
"b": 456
}
}
}
// 成功响应
{
"jsonrpc": "2.0",
"id": "calc-001",
"result": {
"content": [
{
"type": "text",
"text": "计算结果:123 + 456 = 579"
}
],
"isError": false
}
}
// 错误响应
{
"jsonrpc": "2.0",
"id": "calc-001",
"error": {
"code": "INVALID_PARAMS",
"message": "不支持的运算操作: modulo",
"data": {
"operation": "modulo"
}
}
}
📚 资源相关方法
资源是Server提供的可读取内容,如文件、数据库记录等:
resources/list - 获取资源列表
javascript
// 请求
{
"jsonrpc": "2.0",
"id": "res-list-001",
"method": "resources/list"
}
// 响应
{
"jsonrpc": "2.0",
"id": "res-list-001",
"result": {
"resources": [
{
"uri": "file:///home/user/documents/report.txt",
"name": "报告文件",
"description": "项目进度报告",
"mimeType": "text/plain"
},
{
"uri": "db://localhost/users/123",
"name": "用户数据",
"description": "用户ID 123的详细信息",
"mimeType": "application/json"
}
]
}
}
resources/read - 读取资源内容
javascript
// 请求读取文件
{
"jsonrpc": "2.0",
"id": "read-001",
"method": "resources/read",
"params": {
"uri": "file:///home/user/documents/report.txt"
}
}
// 响应
{
"jsonrpc": "2.0",
"id": "read-001",
"result": {
"contents": [
{
"uri": "file:///home/user/documents/report.txt",
"mimeType": "text/plain",
"text": "项目进度报告\n\n本月完成情况:\n1. 需求分析 - 100%\n2. 设计阶段 - 80%\n3. 开发阶段 - 60%"
}
]
}
}
🔒 错误处理机制
📋 标准错误代码
MCP定义了一系列标准错误代码:
错误代码 | 含义 | 示例场景 |
---|---|---|
PARSE_ERROR | JSON解析错误 | 无效的JSON格式 |
INVALID_REQUEST | 无效请求 | 缺少必需字段 |
METHOD_NOT_FOUND | 方法不存在 | 调用不支持的方法 |
INVALID_PARAMS | 参数无效 | 参数类型或值错误 |
INTERNAL_ERROR | 内部错误 | 服务器内部异常 |
TOOL_NOT_FOUND | 工具不存在 | 调用不存在的工具 |
RESOURCE_NOT_FOUND | 资源不存在 | 访问不存在的资源 |
🛠️ 错误处理示例
javascript
// 复杂的错误响应
{
"jsonrpc": "2.0",
"id": "req-001",
"error": {
"code": "INVALID_PARAMS",
"message": "工具参数验证失败",
"data": {
"tool": "calculator",
"errors": [
{
"field": "operation",
"message": "必须是 add, subtract, multiply, divide 之一",
"received": "modulo"
},
{
"field": "a",
"message": "必须是数字类型",
"received": "abc"
}
]
}
}
}
🔄 传输层实现
🌐 多种传输方式
MCP支持多种底层传输机制:
1. 标准输入输出(Stdio)
适用于本地进程通信:
javascript
// Node.js Stdio传输实现
class StdioTransport {
constructor() {
this.messageBuffer = '';
}
send(message) {
const messageStr = JSON.stringify(message) + '\n';
process.stdout.write(messageStr);
}
onMessage(callback) {
process.stdin.on('data', (chunk) => {
this.messageBuffer += chunk.toString();
// 处理完整的消息行
const lines = this.messageBuffer.split('\n');
this.messageBuffer = lines.pop(); // 保留不完整的行
lines.forEach(line => {
if (line.trim()) {
try {
const message = JSON.parse(line);
callback(message);
} catch (error) {
console.error('JSON解析错误:', error);
}
}
});
});
}
}
2. WebSocket传输
适用于Web应用和实时通信:
javascript
// WebSocket传输实现
class WebSocketTransport {
constructor(url) {
this.ws = new WebSocket(url);
this.setupEventHandlers();
}
send(message) {
if (this.ws.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify(message));
} else {
throw new Error('WebSocket连接未开启');
}
}
onMessage(callback) {
this.messageCallback = callback;
}
setupEventHandlers() {
this.ws.onmessage = (event) => {
try {
const message = JSON.parse(event.data);
if (this.messageCallback) {
this.messageCallback(message);
}
} catch (error) {
console.error('消息解析错误:', error);
}
};
this.ws.onopen = () => {
console.log('WebSocket连接已建立');
};
this.ws.onclose = () => {
console.log('WebSocket连接已关闭');
};
this.ws.onerror = (error) => {
console.error('WebSocket错误:', error);
};
}
}
3. HTTP传输
适用于无状态的请求-响应模式:
javascript
// HTTP传输实现
class HttpTransport {
constructor(baseUrl) {
this.baseUrl = baseUrl;
this.requestId = 1;
}
async send(message) {
const response = await fetch(`${this.baseUrl}/mcp`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(message)
});
if (!response.ok) {
throw new Error(`HTTP错误: ${response.status}`);
}
return await response.json();
}
// HTTP传输通常是同步的请求-响应模式
async request(method, params) {
const message = {
jsonrpc: '2.0',
id: this.requestId++,
method,
params
};
return await this.send(message);
}
}
🎯 协议最佳实践
✅ 实现建议
1. 连接管理
javascript
class MCPConnection {
constructor(transport) {
this.transport = transport;
this.pendingRequests = new Map();
this.requestTimeout = 30000; // 30秒超时
this.setupMessageHandler();
}
async request(method, params) {
const id = this.generateRequestId();
const message = {
jsonrpc: '2.0',
id,
method,
params
};
return new Promise((resolve, reject) => {
// 设置超时
const timeoutId = setTimeout(() => {
this.pendingRequests.delete(id);
reject(new Error(`请求超时: ${method}`));
}, this.requestTimeout);
// 存储待响应请求
this.pendingRequests.set(id, {
resolve,
reject,
timeoutId
});
// 发送请求
this.transport.send(message);
});
}
handleResponse(message) {
const { id, result, error } = message;
const pending = this.pendingRequests.get(id);
if (pending) {
clearTimeout(pending.timeoutId);
this.pendingRequests.delete(id);
if (error) {
pending.reject(new MCPError(error.message, error.code));
} else {
pending.resolve(result);
}
}
}
}
2. 消息验证
javascript
class MessageValidator {
static validateRequest(message) {
const errors = [];
if (message.jsonrpc !== '2.0') {
errors.push('jsonrpc字段必须是"2.0"');
}
if (!message.method || typeof message.method !== 'string') {
errors.push('method字段必须是非空字符串');
}
if (message.id !== undefined &&
typeof message.id !== 'string' &&
typeof message.id !== 'number') {
errors.push('id字段必须是字符串或数字');
}
return errors;
}
static validateResponse(message) {
const errors = [];
if (message.jsonrpc !== '2.0') {
errors.push('jsonrpc字段必须是"2.0"');
}
if (message.id === undefined) {
errors.push('响应必须包含id字段');
}
if (!message.result && !message.error) {
errors.push('响应必须包含result或error字段');
}
if (message.result && message.error) {
errors.push('响应不能同时包含result和error字段');
}
return errors;
}
}
🎯 本节小结
通过这一小节,你应该已经掌握了:
✅ 协议基础:JSON-RPC 2.0协议和MCP的消息格式
✅ 消息类型:请求、响应、通知三种消息类型的使用
✅ 标准方法:初始化、工具调用、资源访问等核心方法
✅ 错误处理:标准错误代码和错误处理机制
✅ 传输层:Stdio、WebSocket、HTTP等传输方式的实现
✅ 最佳实践:连接管理、消息验证等实现建议
🤔 协议思考
- 💭 在你的使用场景中,哪种传输方式最合适?
- 🔍 如何设计自定义的错误处理机制?
- 🛠️ 你会如何优化协议的性能和可靠性?
理解了通信协议的细节,想知道数据在整个MCP系统中是如何流转的吗?