MCP 协议通信详解:从握手到工具调用的完整流程

标签MCP Model Context Protocol JSON-RPC Agent 工具调用 协议
适合人群:希望理解 MCP 底层通信机制、或需要自行实现 MCP 客户端的开发者


一、MCP 是什么协议

MCP(Model Context Protocol)是 Anthropic 于 2024 年发布的开放协议,定义了 AI 模型与外部工具、资源之间的标准通信方式。它的底层是 JSON-RPC 2.0,支持三种传输方式:

传输方式 适用场景
Stdio 本地进程间通信,如 npx 启动的 MCP 服务器
SSE 基于 HTTP 的长连接,服务端推送事件
HTTP 标准 HTTP 请求/响应,无状态或带 session

无论选择哪种传输方式,上层的通信协议和握手流程完全一致。本文以 SSE 为主线介绍,Stdio 和 HTTP 的差异仅在连接建立阶段。


二、完整交互流程

一次完整的 MCP 通信分为四个阶段:

复制代码
客户端                                    服务器
  │                                        │
  │──── ① 建立连接 ─────────────────────> │
  │<─── 连接确认(endpoint / 进程就绪)─── │
  │                                        │
  │──── ② initialize 请求 ──────────────> │
  │<─── initialize 响应 ─────────────────  │
  │──── initialized 通知 ───────────────> │  ← 必须发送,否则服务器不接受后续请求
  │                                        │
  │         ✅ 握手完成                    │
  │                                        │
  │──── ③ tools/list ───────────────────> │
  │<─── 工具列表 ────────────────────────  │
  │                                        │
  │──── ③ tools/call ───────────────────> │
  │<─── 工具结果 ────────────────────────  │
  │                                        │
  │──── ④ 关闭连接 ─────────────────────> │

三、第一阶段:建立连接

Stdio 方式

本地启动 MCP 服务器进程,通过标准输入输出通信:

bash 复制代码
# 启动 MCP 服务器进程
uv --directory /path/to/mcp run mcp-server

# 通信方向
stdin  → 发送 JSON-RPC 请求
stdout ← 接收 JSON-RPC 响应
stderr ← 接收服务器日志

SSE 方式

先建立长连接获取消息端点,后续通过该端点收发消息:

bash 复制代码
# 第一步:连接 SSE 端点,保持长连接
GET http://127.0.0.1:8000/sse
Accept: text/event-stream

# 服务器推送 endpoint 事件,告知后续请求的地址
event: endpoint
data: /messages/?session_id=abc123

# 第二步:通过消息端点发送所有后续请求
POST http://127.0.0.1:8000/messages/?session_id=abc123

HTTP 方式

无需预先建立长连接,直接向固定端点发送请求:

bash 复制代码
POST http://127.0.0.1:8000/mcp
Accept: application/json, text/event-stream

⚠️ HTTP 方式的响应可能是 SSE 格式(data: 前缀的行),需要额外处理。


四、第二阶段:握手(必须完成三步)

这是整个流程中最容易出错的部分。握手由三个子步骤构成,缺少任何一步,服务器都不会接受后续的工具调用请求

步骤 2.1:客户端发送 initialize 请求

json 复制代码
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2024-11-05",
    "capabilities": {},
    "clientInfo": {
      "name": "my-mcp-client",
      "version": "1.0.0"
    }
  }
}

protocolVersion 固定为 "2024-11-05"capabilities 可以是空对象。

步骤 2.2:服务器响应 initialize

json 复制代码
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2024-11-05",
    "capabilities": {
      "tools": { "listChanged": false },
      "prompts": { "listChanged": false },
      "resources": { "subscribe": false, "listChanged": false }
    },
    "serverInfo": {
      "name": "Cognee",
      "version": "1.16.0"
    }
  }
}

capabilities 字段说明服务器支持哪些功能,客户端据此判断后续可以调用哪些方法。

步骤 2.3:客户端发送 initialized 通知

json 复制代码
{
  "jsonrpc": "2.0",
  "method": "notifications/initialized",
  "params": {}
}

这一步有两个细节容易忽略:

  • 没有 id 字段:这是"通知",不是"请求",服务器不会返回响应
  • 发送时机 :必须在收到 initialize 响应之后立即发送,只有发送此通知后,服务器才开始接受 tools/listtools/call 等请求

五、第三阶段:工具调用

握手完成后进入正常通信阶段。最常用的两个方法是列出工具和调用工具。

列出可用工具

json 复制代码
// 请求
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/list",
  "params": {}
}

// 响应
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "tools": [
      {
        "name": "search",
        "description": "Search for information",
        "inputSchema": {
          "type": "object",
          "properties": {
            "query": {
              "type": "string",
              "description": "Search query"
            }
          },
          "required": ["query"]
        }
      }
    ]
  }
}

inputSchema 是标准 JSON Schema 格式,可以直接转换成 Function Calling 所需的工具描述,交给支持工具调用的大模型使用。

调用工具

json 复制代码
// 请求
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "search",
    "arguments": {
      "query": "MCP protocol"
    }
  }
}

// 响应
{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "MCP (Model Context Protocol) is..."
      }
    ],
    "isError": false
  }
}

content 数组支持多态,type 字段可以是 textimageresource,需根据类型分别处理。

其他可用方法

方法 说明 关键参数
prompts/list 列出服务器预定义的提示词模板
prompts/get 获取并渲染某个提示词 namearguments(可选)
resources/list 列出服务器暴露的资源
resources/read 读取某个资源的内容 uri
resources/subscribe 订阅资源变更通知 uri
logging/setLevel 设置服务器日志级别 level

六、错误处理

服务器遇到错误时,响应体中会有 error 字段而非 result

json 复制代码
{
  "jsonrpc": "2.0",
  "id": 3,
  "error": {
    "code": -32602,
    "message": "Invalid params",
    "data": {
      "details": "Missing required field: query"
    }
  }
}

JSON-RPC 2.0 标准错误码:

错误码 含义 常见原因
-32700 Parse error 请求不是合法 JSON
-32600 Invalid Request 缺少 jsonrpcmethod 字段
-32601 Method not found 调用了服务器不支持的方法
-32602 Invalid params 参数类型错误或缺少必填字段
-32603 Internal error 服务器内部异常

七、第四阶段:关闭连接

Stdio 方式

java 复制代码
process.destroy();

SSE 方式

java 复制代码
eventSource.cancel();  // 关闭长连接

HTTP 方式

bash 复制代码
# 发送 DELETE 请求清理 session 资源
DELETE http://127.0.0.1:8000/mcp
mcp-session-id: abc123

八、Java 客户端代码示例

如果使用 j-langchain,上面所有步骤(连接建立、三步握手、工具列举、工具调用、连接关闭)都封装在 McpServerConnection 内部,不需要手动处理 JSON-RPC 报文:

java 复制代码
public void mcpClientFlow() throws Exception {

    // 1. 配置连接方式(SSE 示例)
    ServerConfig config = new ServerConfig();
    config.type = "sse";
    config.url  = "http://127.0.0.1:8000/sse";

    // 2. 建立连接,connect() 内部自动完成三步握手
    McpConnection conn = McpConnectionFactory.createConnection("cognee", config);
    conn.connect();

    // 3. 列出工具
    List<ToolDesc> tools = conn.listTools();
    System.out.println("可用工具数量:" + tools.size());

    // 4. 调用工具
    Map<String, Object> args = Map.of("query", "MCP protocol");
    ToolResult result = conn.callTool("search", args);
    System.out.println("工具返回:" + result.getFirstText());

    // 5. 关闭连接
    conn.close();
}

如果需要对接非标准 MCP 服务器或自行实现客户端,按照本文的协议流程逐步构造 JSON-RPC 报文即可。


九、常见问题速查

Q:为什么 tools/call 一直返回 "Method not found"?

A:最可能的原因是没有发送 initialized 通知,服务器还处于握手未完成状态,拒绝所有工具调用请求。

Q:SSE 连接建立后,请求发到哪个地址?

A:不是 /sse 端点,而是服务器推送的 endpoint 事件中的地址(通常是 /messages/?session_id=xxx)。

Q:请求的 id 字段有什么要求?

A:必须是数字或字符串,且在同一会话内唯一。通常用递增整数:initialize 用 1,后续依次 23......服务器响应会携带相同的 id,用于匹配请求和响应。

Q:通知和请求有什么区别?

A:请求有 id 字段,服务器会返回对应响应;通知没有 id,服务器不返回任何内容。initialized 是唯一必须发送的通知。


📎 相关资源

相关推荐
花千树-0103 小时前
内存(Memory)基础:ConversationBuffer、Summary Memory 等
agent·ai agent·上下文·长短期记忆·ai memory·ai 记忆压缩
GeeLark3 小时前
Android 16 is here. 行业首发
ai·自动化·aigc
samson_www4 小时前
EC2的GRUB引导程序问题
运维·ai
竹之却4 小时前
【Agent-阿程】OpenClaw v2026.4.15 版本更新全解析
人工智能·ai·openclaw
嵌入式小企鹅4 小时前
DeepSeek-V4昇腾首发、国芯抗量子MCU突破、AI编程Agent抢班夺权
人工智能·学习·ai·程序员·算力·risc-v
better_liang5 小时前
每日Java面试场景题知识点之-MCP协议在Java开发中的应用实践
java·spring boot·ai·mcp·企业级开发
猿来如此呀5 小时前
DeepAgent 完全教程:从零到精通构建智能体
agent·deepagent
俊哥V5 小时前
每日 AI 研究简报 · 2026-04-17
人工智能·ai
踏着七彩祥云的小丑6 小时前
AI——初识Dify
人工智能·ai