• 数据层: 定义了基于 JSON-RPC 定义客户端-服务器通信协议,协议层包含生命周期管理和核心原语;同时支持对工具、资源和提示等对象的操作
  • 传输层: 定义了客户端和服务器之间进行数据交换的通信机制和通道,包括特定于传输的连接建立、消息帧和授权

数据层的标准化

JSON-RPC协议

所有工具都必须用统一的格式描述——包括工具名、使用说明、参数结构、返回格式等
Agent 向 MCP Server 索取所有工具说明清单这一步在 MCP 中称为 "初始化", 对应一次 JSON-RPC 请求
MCP 中的每一次请求,本质上都是在交换 JSON-RPC 2.0 标准的数据包


是什么?

JSON-RPC 是两个服务之间通过发送 JSON 数据来进行沟通的一种“通用语言”

  • RPC (Remote Procedure Call):就是指远程过程调用。在 A 服务上调用一个函数,但实际上这个函数是在 B 服务上运行的,B 把结果运行完再传回给 A
  • JSON:所有的数据传输都使用最通用的 JSON 格式,无论Agent是用什么编程语言写的,大家都能看懂对方发来的信息
  • 无状态 (Stateless):每一次请求都是独立的,就像寄信一样,寄出去一封,收回来一封,协议本身不记忆之前的状态

JSON-RPC格式

请求体:

{
  "jsonrpc": "2.0",          // 1. 版本号:必须是 "2.0"
  "method": "tools/call",    // 2. 方法名:需要执行的操作
  "params": {                // 3. 参数:执行操作需要的数据
    "name": "get_weather",   // 4. 调用的函数名
    "arguments": {
      "city": "Beijing"      // 5. 函数入参
    }
  },
  "id": 1                    // 6. ID:请求的编号号,用于匹配回信
}

响应体:

{
  "jsonrpc": "2.0",
  "result": {                // 1. 结果:成功时的返回数据
    "content": [
      {
        "type": "text",
        "text": "北京今天晴,气温 25 度"
      }
    ]
  },
  "id": 1                    // 2. ID:对应请求的 ID
}

错误结构:

{
  "jsonrpc": "2.0",
  "error": {                 // 错误对象
    "code": -32601,          // 标准错误码
    "message": "Method not found" // 错误信息
  },  
  "id": 1
}

MCP 如何利用 JSON-RPC 工作?

初始化阶段-建立连接与能力协商

  • 能力协商: 客户端和服务端会确认协议版本、功能支持等信息。
  • 就绪通知: 初始化完成后,客户端会发送 notifications/initialized 告知服务器已准备好。

意义: 保证双方在同一协议下通信,建立通信基础,为后续工具发现和调用做好准备。

示例
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2024-11-05",
    "capabilities": {
      "roots": {
        "listChanged": true
      },
      "sampling": {},
      "elicitation": {}
    },
    "clientInfo": {
      "name": "ExampleClient",
      "title": "Example Client Display Name",
      "version": "1.0.0"
    }
  }
}

初始化成功后,客户端必须发送​initialized​通知,表明其已准备好开始正常运行
如果没有这步,服务端会认为客户端并未准备好,所以将禁止后续的其他操作。

{
  "jsonrpc": "2.0",
  "method": "notifications/initialized"
}

工具发现阶段-索取工具列表清单

  • 标准化描述: 每隔工具都以Json描述名称、参数类型、返回值格式和使用说明
  • 无需理解内部逻辑: agent不需要知道具体实现,只需要知道工具需要什么和能返回什么
  • 动态发现: 工具可能随时变化,每次获取都是最新工具列表
对外提供的能力
  • Resources(资源): 供外部直接读取的外部数据,如文件、API结果等
  • Tools(工具): 供外部调用工具服务
  • Prompts(提示): 预定义的提示词模板
示例
{
  "jsonrpc": "2.0",
  "method": "tools/list",
  "params": {},
  "id": 100
}

调用阶段

LLM 决策需要调用某个 MCP 服务时,Agent 会构建标准 JSON-RPC 请求发送给 MCP Server

示例
{
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "name": "get_weather",
    "arguments": {
      "city": "Beijing"
    }
  },
  "id": 101
}
MCP Server执行流程
  1. 解析工具名和参数,根据name找到对应工具执行
  2. 执行工具
  3. 返回结果,构造符合JSON-RPC格式的结果返回

工具变更阶段-处理工具列表更新

  • 变更通知: 服务端通过 notifications/tools/list/changed 通知客户端工具列表已更新
  • 重新获取: 客户端收到通知后重新请求获取清单并更新内部工具注册表
  • 保证一致性: Agent始终知道最新可用工具,实现动态适应和高可扩展性
示例
{
  "jsonrpc": "2.0",
  "method": "notifications/tools/list_changed",
  "params": {}
}

传输层标准化

stido-标准输入输出

父子进程 Stdio 传输不涉及任何网络协议 (TCP/HTTP), 本质是进程间通信


SSE-Server-Sent Events

单向通讯只推不收, 因此需双端方案实现, 即接收通道和发送通道

痛点

  • 状态维护,client必须维护一个长连接接收和一个短连接发送
  • 重连机制,无法自动断点重连,需要双方定时心跳维护长连接

Streamable HTTP

解决 SSE 模式中读写分离带来的架构复杂度和传统 HTTP 的一次性交互无法满足 MCP 双向异步通知、以及无法断点重连 等问题。

原理

Streamable HTTP 把所有交互集中到一个 HTTP POST 请求中, 利用 HTTP 流式能力承载 JSON-RPC 协议

  • 单一连接,只维护一个端点
  • 请求发送,报文放在POST请求的body发送
  • 流式响应,利用分块传输编码(Chunked Encoding),将结果分批次实时吸入响应body中

优势

  • 简化架构,一个端点实现双向异步通讯并且不区分读写
  • 灵活性高,可以根据场景选择是否使用流式响应
  • 资源效率高,不用一直维持sse长连接
  • 更可靠的恢复机制,支持断点重连,可通过Session ID + Last‑Event-ID恢复会话
  • 基础设施更友好,标准的HTTP基础设施(API网关、负载均衡等)兼容性更好