MCP 科普

110 阅读7分钟

几个缩写

  • JSON: JavaScript Object Notation
  • RPC: Remote Procedure Call
  • MCP: Model Context Protocol

🎯 什么是 RPC?

JSON 是一种轻量级、纯文本的数据交换格式,它采用完全独立于编程语言的文本格式来存储和传输结构化数据。其核心特点是人类可读(使用大家熟悉的键值对、数组结构表示)和机器易解析,因此它成为了现代网络通信(如你正在使用的MCP协议)和应用程序配置中最主流的数据交换语言,几乎所有的编程语言都提供了对JSON的生成和解析支持。

🎯 什么是 RPC?

RPC远程过程调用。它是一种技术,允许一个计算机程序(客户端)调用另一个地址空间(通常是网络上的另一台机器)的程序(服务端)中的函数或过程,就像调用本地函数一样简单。

核心思想让你像调用本地函数一样去调用远程服务,而无需关心底层的网络通信、数据序列化等复杂细节。

举个简单的例子,假设你有一个本地的加法函数 add(1, 2)。使用RPC,你可以调用一个远在服务器上的函数,写法可能完全一样 add(1, 2),但实际的计算发生在服务器上,结果再传回给你。

📄 什么是 JSON-RPC?

JSON-RPC 是一种轻量级的、基于JSON的RPC协议。它定义了客户端和服务器之间如何进行结构化通信的简单规则。

核心特点:使用人类可读的JSON格式来编码请求和响应,这使得它非常通用,几乎任何支持JSON和网络的语言都能使用。

一个JSON-RPC 2.0请求和响应看起来就像这样,这正是MCP服务器一直在处理的东西:

请求 (Request):

{
  "jsonrpc": "2.0",
  "method": "get_weather", // 要调用的远程方法名
  "params": {"city": "Beijing"}, // 调用参数
  "id": 101 // 请求ID,用于匹配响应
}

成功响应 (Success Response):

{
  "jsonrpc": "2.0",
  "result": {"temperature": 22, "condition": "sunny"}, // 调用结果
  "id": 101 // 与请求ID对应
}

错误响应 (Error Response):

{
  "jsonrpc": "2.0",
  "error": {
    "code": -32601,
    "message": "Method not found"
  },
  "id": 101
}

📊 RPC 与 JSON-RPC 的关系与对比

特性RPCJSON-RPC
定位一种广泛的技术概念和模型RPC 概念的一种具体实现协议
数据格式不限定,可以是任何格式(如二进制、XML)。强制使用 JSON 格式。
核心实现“远程调用像本地调用”的思想实现该思想的一套具体JSON消息规则
类比就像“车辆”这个概念。就像是“车辆”概念下的一辆具体规范的公交车(有固定的颜色、票价、停靠站规则)。

🔗 它们与 MCP 的关系

MCP 是建立在 JSON-RPC 2.0 之上的一个更高层、更具体的协议。

  1. MCP 使用了 JSON-RPC 的“巴士”:所有MCP消息(见下文)都严格遵循上面看到的JSON-RPC请求和响应格式。
  2. MCP 定义了“巴士的路线和乘客规范”:MCP协议规定了在这条JSON-RPC线路上,必须有哪些“站点”(即必须实现的 method),以及每个站点“上下车的乘客”长什么样(即 paramsresult 的详细数据结构)。
    • 例如,MCP规定了一个叫 tools/call 的“站点”(方法),并且规定在这个站点,“乘客”(params)必须包含 namearguments 字段。

所以,当你写MCP服务器时,你本质上是在编写一个遵循了额外(MCP)规则的JSON-RPC服务器。之前代码中的 protocolVersionserverInfoinputSchema 等字段,都是MCP这个“上层协议”在JSON-RPC这个“基础交通工具”上额外规定的“乘客行为规范”。

初始化 initialize

initialize 是MCP协议会话中客户端发送的第一个、也是必需的请求,用于协商协议版本并建立连接。 它好比一次“握手”,客户端通过它询问“你能用什么版本协议?有哪些功能?”,而服务器则必须在响应中明确回答三个核心信息:

  • 本次会话使用的协议版本protocolVersion,例如 "2024-11-05")、
  • 关于自身的元信息serverInfo,如名称和版本)、
  • 以及所支持的功能列表capabilities,例如声明是否支持 toolsresourcesprompts 等)。

只有在成功完成 initialize 握手后,客户端才会发送 notifications/initialized 通知,并基于服务器的能力声明来发起后续的 tools/listresources/read 等具体交互。你之前服务器返回的 {"protocolVersion":"2024-11-05","serverInfo":{...},"capabilities":{...}} 正是一个标准的初始化响应。

一个完整的、符合 MCP 协议的 initialize 请求的成功响应消息示例如下:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2024-11-05",
    "serverInfo": {
      "name": "你的MCP服务器名称",
      "version": "1.0.0"
    },
    "capabilities": {
      "tools": {
        "listChanged": true
      },
      "resources": {
        "listChanged": true,
        "subscribe": false
      },
      "prompts": {
        "listChanged": false
      }
    },
    "implementation": {
      "name": "my-mcp-server",
      "version": "1.0.0"
    }
  }
}

📝 关键字段详解

这个响应中的所有字段都是为了让客户端理解如何与你的服务器正确交互:

字段路径是否必需说明与示例
jsonrpc必需固定为 "2.0",表明遵循 JSON-RPC 2.0 协议。
id必需必须与客户端 initialize 请求中的 id 完全一致,用于匹配请求与响应。
result必需初始化结果对象,包含所有协商信息。
result.protocolVersion必需协议版本。当前主流是 "2024-11-05",必须与客户端兼容。
result.serverInfo必需服务器元信息nameversion 用于客户端标识和日志显示。
result.capabilities必需能力声明,是最核心的部分。它用一个对象明确告知客户端你支持(或不支持)哪些MCP功能。
result.capabilities.tools可选声明 工具 相关能力。listChanged 设为 true 表示工具列表可能变化,客户端需要刷新。
result.capabilities.resources可选声明 资源 相关能力。subscribe 设为 false 表示不支持资源变更推送。
result.capabilities.prompts可选声明 提示词模板 相关能力。
result.implementation可选实现详情。用于更细致的调试,可包含服务器具体的实现名称和版本。

💡 核心解读

  1. capabilities 是功能开关:你只需在 capabilities 对象里包含你实际实现了的功能(如 toolsresources)。如果没实现 prompts,就不需要包含该字段。这直接决定了客户端之后是否会向你发送 prompts/list 等请求。
  2. listChanged 的作用:这是一个优化选项。如果设为 true,当服务器上的工具、资源或提示词列表发生变化时,服务器可以主动通知客户端刷新列表,无需客户端频繁轮询。
  3. 与请求的对应:响应中的 id 必须与请求中的 id 对应。如果请求是一个没有 id通知(理论上 initialize 必须是请求),则服务器不应回复。

这个结构就是MCP协议中“握手成功”的确认信号。你之前部署的服务器返回的响应已经包含了最核心的必需字段,是完全有效的。你可以根据服务器实际实现的功能,调整 capabilities 对象的内容。最权威的参考始终是 MCP 官方规范

MCP 消息

MCP 消息可以归纳为以下几类,它们都严格遵循 JSON-RPC 2.0 的格式:

  1. 生命周期与连接管理消息:这是会话的基础,包括 initialize(初始化握手)、ping/pong(连接健康检查),以及 notifications/initialized(客户端通知服务器初始化完成)。
  2. 三大核心能力消息:这是MCP功能的核心,对应三大模块:
    • 工具tools/list(列出工具)、tools/call(调用工具)。
    • 资源resources/list(列出资源URI)、resources/read(读取资源内容)、resources/subscribe(订阅资源变更)。
    • 提示词模板prompts/list(列出提示词模板)、prompts/get(获取模板内容)。
  3. 通知与变更消息:服务器主动向客户端推送变更,例如 notifications/resources/updated(通知资源列表已更新)。

简单来说,除了连接和工具类消息,MCP协议还定义了用于读取数据的资源类消息、管理预写提示词的提示词类消息,以及用于实时同步的服务器通知。 服务器通过在 initializecapabilities 字段中声明所支持的能力(如 toolsresources),来告知客户端可以提供哪些类型的消息交互。