JSON-RPC 2.0消息协议简介(附带实例)
JSON-RPC 2.0 是一种轻量级的、用于远程过程调用(Remote Procedure Call,RPC)的消息协议,其使用 JSON 作为数据格式。
注意,JSON-RPC 2.0 不是一个底层传输协议,只是一种应用层的消息格式标准。形象地说,就像两个人需要交换包裹,它规定了包裹应该如何打包、如何在内部分区、如何贴标签等,但并不规定如何运送。
比如,你需要调用远程 MCP 服务端上的一个计算器函数来计算“5+3”。这是一次远程过程调用。JSON-RPC 2.0 规定了你发送给 MCP 服务端的请求(Request)消息需要遵循类似这样的格式:
在 MCP 服务端处理完后,JSON-RPC 2.0 又规定了 MCP 服务端的响应(Response)消息必须类似于:
如果 MCP 服务端在处理时发生了异常(比如,你要求调用一个不存在的方法),那么你会收到这样的响应消息:
还有一种情况,当 MCP 服务端需要向客户端发送一个通知(Notification)消息时,需使用以下格式:
因为这是一种单向的通知,不需要对方回复,所以不携带请求标识符(id)。
所以,有了这样的消息协议做约定,通信双方就可以非常顺畅地完成请求与响应过程。上述的请求消息、响应消息、通知消息也是目前 MCP 规范所定义的 3 种基础消息类型,并对部分内部字段进行了必要的扩充。
很显然,这种消息协议的优势如下:
你可能会首先想到易于使用的 HTTP,下面编写简易的 MCP 服务端代码(这段代码存储于名为“mcp_server_raw.py”的文件中)来模拟处理上述请求:
1) 在实现这个模拟 MCP 服务端时,使用 HTTP 端点 /jsonrpc 提供一个 MCP 服务端的“工具”(calculate)的调用接口。这个接口需要使用 HTTP POST 方法来访问。
2) 此处的“calculate”工具仅为模拟演示,实际上 MCP 服务端的工具调用会通过统一的 tools/call 方法实现。
3) 然后,使用以下代码创建一个客户端来模拟调用 MCP 服务端的“工具”(这段代码存储于名为“mcp_client_raw.py”的文件中):
JSON-RPC 2.0 是一种专为网络环境设计的用于远程过程调用的消息协议。它能够与多种消息传输协议协同工作,以实现请求与响应的交互模式。
注意,JSON-RPC 2.0 不是一个底层传输协议,只是一种应用层的消息格式标准。形象地说,就像两个人需要交换包裹,它规定了包裹应该如何打包、如何在内部分区、如何贴标签等,但并不规定如何运送。
比如,你需要调用远程 MCP 服务端上的一个计算器函数来计算“5+3”。这是一次远程过程调用。JSON-RPC 2.0 规定了你发送给 MCP 服务端的请求(Request)消息需要遵循类似这样的格式:
{ "jsonrpc": "2.0", // 协议版本,固定为“2.0” "method": "calculate", // 要调用的方法(工具)名 "params": { // 方法参数,可以是对象或数组 "expression": "5+3" }, "id": 1 // 请求标识符,用于匹配响应 }
在 MCP 服务端处理完后,JSON-RPC 2.0 又规定了 MCP 服务端的响应(Response)消息必须类似于:
{ "jsonrpc": "2.0", // 协议版本 "result": 8, // 调用结果 "id": 1 // 对应请求的标识符 }
如果 MCP 服务端在处理时发生了异常(比如,你要求调用一个不存在的方法),那么你会收到这样的响应消息:
{ "jsonrpc": "2.0", "error": { "code": -32601, "message": "请求的方法不存在" }, "id": 1 }
还有一种情况,当 MCP 服务端需要向客户端发送一个通知(Notification)消息时,需使用以下格式:
{ "jsonrpc": "2.0", "method": "notifications", "params": { "message": "This is a message from server..." } }
因为这是一种单向的通知,不需要对方回复,所以不携带请求标识符(id)。
所以,有了这样的消息协议做约定,通信双方就可以非常顺畅地完成请求与响应过程。上述的请求消息、响应消息、通知消息也是目前 MCP 规范所定义的 3 种基础消息类型,并对部分内部字段进行了必要的扩充。
很显然,这种消息协议的优势如下:
- 与语言无关:几乎所有的语言都支持 JSON 数据格式。
- 简单、易用:结构简单,天然可读,易于调试。
- 轻量、灵活:可以适配各种传输模式,不绑定某种特殊的传输协议。
基于JSON-RPC 2.0的远程过程调用
一旦确定了消息的标准,选择了一种传输模式,我们就能轻松地模拟MCP的远程过程调用流程。你可能会首先想到易于使用的 HTTP,下面编写简易的 MCP 服务端代码(这段代码存储于名为“mcp_server_raw.py”的文件中)来模拟处理上述请求:
...... app = FastAPI() # 使用FastAPI快速开发一个MCP服务端 # 可调用的工具 def calculate(expression: str) -> float: ...... @app.post('/jsonrpc') async def jsonrpc_endpoint(request: Request): """处理所有JSON-RPC请求的FastAPI端点""" try: content = await request.json() # 解析请求与参数 method_name = content.get("method") params = content.get("params", {}) request_id = content.get("id", None) if method_name == "calculate": try: expression = params.get("expression", "") result = calculate(expression) response = { "jsonrpc": "2.0", "result": result, "id": request_id } except ValueError as ve: response = { "jsonrpc": "2.0", "error": {"code": -32603, "message": str(ve)}, "id": request_id } else: # 处理其他错误... return JSONResponse(content=response) except Exception as e: # 处理其他异常 ......对这段代码的解释如下:
1) 在实现这个模拟 MCP 服务端时,使用 HTTP 端点 /jsonrpc 提供一个 MCP 服务端的“工具”(calculate)的调用接口。这个接口需要使用 HTTP POST 方法来访问。
2) 此处的“calculate”工具仅为模拟演示,实际上 MCP 服务端的工具调用会通过统一的 tools/call 方法实现。
3) 然后,使用以下代码创建一个客户端来模拟调用 MCP 服务端的“工具”(这段代码存储于名为“mcp_client_raw.py”的文件中):
...... class McpClient: ...... def call(self, method, params=None, timeout=10): """调用远程方法""" # 注意这里的请求格式,遵循JSON-RPC 2.0 payload = { "jsonrpc": "2.0", "method": method, "params": params if params is not None else {}, "id": self.request_id } self.request_id += 1 headers = {'Content-Type': 'application/json'} try: response = requests.post( self.server_url, data=json.dumps(payload), headers=headers, timeout=timeout ) response.raise_for_status() return response.json() except Exception as e: ...... ......client.call("calculate", {"expression": "3+5"})这样就模拟了一个基于 JSON-RPC 2.0 的客户端与 MCP 服务端交互的原型:
- 客户端构建符合 JSON-RPC 2.0 的请求消息。
- 通过 HTTP POST 方法将请求消息发送至MCP服务端的指定端点(即 /jsonrpc)。
- MCP 服务端接收请求消息并进行解析,以确定客户端请求调用的方法(calculate)。
- MCP 服务端依据请求消息的参数执行相应的处理逻辑(calculate方法)。
- 在处理完毕后,MCP 服务端构造符合 JSON-RPC 2.0 的响应消息并返回,客户端随后接收到此消息。
JSON-RPC 2.0 是一种专为网络环境设计的用于远程过程调用的消息协议。它能够与多种消息传输协议协同工作,以实现请求与响应的交互模式。