亚欧色一区w666天堂,色情一区二区三区免费看,少妇特黄A片一区二区三区,亚洲人成网站999久久久综合,国产av熟女一区二区三区

  • 發布文章
  • 消息中心
點贊
收藏
評論
分享
原創

【MCP-01】JSON-RPC2.0協議

2025-08-19 10:32:03
3
0

前言

了解Model Context Protocol(MCP),首先需要了解[jsonrpc2.0]協議。MCP使用jsonrpc2.0協議實現了MCPServer和MCPClient兩者交互的數據結構。

JSONRPC2.0

在[SpringAI MCP技術試用]文中說過,MCP只是一個standardized(標準化的;規范化的)協議,而MCP協議的核心是jsonrpc2.0,具體可以參考[官方文檔]和[MCP傳輸協議文檔]

為什么用jsonrpc2.0?

0)生態完善:JSON-RPC 2.0 有豐富的庫和工具支持。
1)和開發語言無關:基本上所有開發語言都支持json協議。
2)簡單實用:結構簡單易讀性好。
3)輕量級:能大大減少數據傳輸,減少AI數據交互過程中的延遲。

MCP中jsonrpc2.0的定義

下文主要以mcp tools原語為例。
企業微信截圖_4f5c8cd5-69b8-452a-a182-f01599fb02f4.png

initialize

# 請求
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2025-06-18",
    "capabilities": {
      "tools": {}
    },
    "clientInfo": {
      "name": "example-client",
      "version": "1.0.0"
    }
  }
}
 
# 響應
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2025-06-18",
    "capabilities": {
      "tools": {
        "listChanged": true
      },
      "resources": {}
    },
    "serverInfo": {
      "name": "example-server",
      "version": "1.0.0"
    }
  }
}

initialized

# 請求
{
  "jsonrpc": "2.0",
  "method": "notifications/initialized"
}
 
# 響應
無

tools/list

# 請求
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/list"
}
 
# 響應
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "tools": [
      {
        "name": "com.example.calculator/arithmetic",
        "title": "Calculator",
        "description": "Perform mathematical calculations including basic arithmetic, trigonometric functions, and algebraic operations",
        "inputSchema": {
          "type": "object",
          "properties": {
            "expression": {
              "type": "string",
              "description": "Mathematical expression to evaluate (e.g., '2 + 3 * 4', 'sin(30)', 'sqrt(16)')"
            }
          },
          "required": ["expression"]
        }
      }
    ]
  }
}

tools/call

# 請求
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "com.example.weather/current",
    "arguments": {
      "location": "San Francisco",
      "units": "imperial"
    }
  }
}
 
# 響應
{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "Current weather in San Francisco: 68°F, partly cloudy with light winds from the west at 8 mph. Humidity: 65%"
      }
    ]
  }
}

一些說明

1)MCP官方文檔寫的非常清楚,可以參考官方文檔中的Architecture Overview->Data Layer 模塊。
2)官方文檔主要以一個地區天氣查詢MCP為例,說明了MCP從連接建立到tool調用的過程中數據以jsonrpc2.0協議傳輸的數據結構,可以看到非常的簡單明了,易于理解和實現。

Demo

這里使用java spring boot簡單模擬mcp tool/call的調用過程。

# JsonRpcServerController.java
package cn.chinatelecom.dw.user.app.jsonrpc;
 
import cn.chinatelecom.dw.user.app.utils.JSONUtils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
 
/**
 * @Author: wanghaoguang
 * @CreateTime: 2025/7/28 15:22
 */
@RestController
public class JsonRpcServerController {
 
    private final static Logger LOG = LoggerFactory
            .getLogger(JsonRpcServerController.class);
 
    @PostMapping(value = "/jsonrpc", consumes = MediaType.APPLICATION_JSON_VALUE, produces =
            MediaType.APPLICATION_JSON_VALUE)
    private ResponseEntity<String> jsonrpc(@RequestBody String requestBody) {
        try {
            ObjectNode objNode = JSONUtils.parseObject(requestBody);
            String methodName = objNode.get("method").asText();
            JsonNode params = objNode.get("params");
            if (params == null) {
                params = JSONUtils.createObjectNode();
            }
            Integer requestId = objNode.get("id").asInt();
            LOG.info("jsonrpc_endpoint params {}", objNode);
            ObjectNode response = JSONUtils.createObjectNode();
            if ("calculate".equals(methodName)) {
                try {
                    String expression = params.get("expression").asText();
                    double result = safeCalculate(expression);
                    response.put("result", result);
                } catch (Exception e) {
                    int code = -32603;
                    String message = e.getMessage();
                    response = buildErrObjectNode(requestId, code, message);
                }
            } else {
                int code = -32601;
                String message = "Method not found";
                buildErrObjectNode(requestId, code, message);
            }
            return ResponseEntity.ok(JSONUtils.toJsonString(response));
        } catch (Exception e) {
            LOG.info("jsonrpc_endpoint Error: {}", e.getMessage());
            int code = -32000;
            String message = "Internal server error " + e.getMessage();
            return ResponseEntity.status(500).body(JSONUtils.toJsonString(buildErrObjectNode(0, code, message)));
        }
    }
 
    private ObjectNode buildErrObjectNode(int requestId, int code, String message) {
        ObjectNode response = JSONUtils.createObjectNode();
        response.put("id", requestId);
        response.put("jsonrpc", "2.0");
        ObjectNode error = JSONUtils.createObjectNode();
        error.put("code", code);
        error.put("message", message);
        response.set("error", error);
        return response;
    }
 
    private double safeCalculate(String expression) {
        try {
            return Double.parseDouble(String.valueOf(;
        } catch (Exception e) {
            throw new IllegalArgumentException("Invalid expression");
        }
    }
 
    private Object  {
        try {
            return new javax.script.ScriptEngineManager().getEngineByName("JavaScript").;
        } catch (Exception e) {
            throw new IllegalArgumentException("Invalid expression");
        }
    }
}
# JsonRpcClient.java
package cn.chinatelecom.dw.user.app.utils;
 
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
import java.io.IOException;
 
/**
 * @Author: wanghaoguang
 * @CreateTime: 2025/7/28 15:35
 */
public class JsonRpcClient {
 
    private final static Logger LOG = LoggerFactory
            .getLogger(JsonRpcClient.class);
    private final String serverUrl;
    private int requestId = 1;
 
    public JsonRpcClient(String serverUrl) {
        this.serverUrl = serverUrl;
    }
 
    public JsonNode call(String method, JsonNode params, int timeout) {
        ObjectNode payload = JSONUtils.createObjectNode();
        payload.put("jsonrpc", "2.0");
        payload.put("method", method);
        if (params == null) {
            params = JSONUtils.createObjectNode();
        }
        payload.set("params", params);
        payload.put("id", requestId++);
 
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(timeout, java.util.concurrent.TimeUnit.SECONDS)
                .readTimeout(timeout, java.util.concurrent.TimeUnit.SECONDS)
                .build();
 
        MediaType JSON = MediaType.get("application/json; charset=utf-8");
        try {
            RequestBody body = RequestBody.create(JSONUtils.toJsonString(payload), JSON);
            Request request = new Request.Builder()
                    .url(serverUrl)
                    .post(body)
                    .build();
 
            try (Response response = client.newCall(request).execute()) {
                if (response.isSuccessful()) {
                    String responseBody = response.body().string();
                    return JSONUtils.parseObject(responseBody);
                } else {
                    LOG.info("Request failed with code: {}", response.code());
                }
            }
        } catch (IOException e) {
            LOG.info("Error occurred while making the request: {}", e.getMessage());
        }
        return null;
    }
 
    public static void main(String[] args) {
        JsonRpcClient client = new JsonRpcClient("//127.0.0.1:9022/jsonrpc");
        ObjectNode params = JSONUtils.createObjectNode();
        params.put("expression", "3+5");
        JsonNode result = client.call("calculate", params, 10);
        System.out.println(result);
    }
}

企業微信截圖_1b661767-d8a8-4173-9a25-a8b6182716fa.png

企業微信截圖_854fe244-1d77-455b-a698-cd18cfed8af0.png

一些說明:
1)可以看到使用java啟動一個http服務,基于jsonrpc2.0協議可以模擬mcp協議的交互流程。
2)上文主要提供java版本實現,python可以參考官方文檔。

總結

1,MCP使用jsonrpc定義了MCPServer和MCPClient之間交互的數據結構,不管是stdio、sse、streamable-http、sampling那種協議。
 2,jsonrpc協議和語言無關,方便簡單易用,使用最簡單的json包處理即可,自己也可以用自己擅長的開發語言按MCP定義的交互協議編寫自己的MCPServer。

0條評論
0 / 1000
wanghg11
21文章數
4粉絲數
wanghg11
21 文章 | 4 粉絲
原創

【MCP-01】JSON-RPC2.0協議

2025-08-19 10:32:03
3
0

前言

了解Model Context Protocol(MCP),首先需要了解[jsonrpc2.0]協議。MCP使用jsonrpc2.0協議實現了MCPServer和MCPClient兩者交互的數據結構。

JSONRPC2.0

在[SpringAI MCP技術試用]文中說過,MCP只是一個standardized(標準化的;規范化的)協議,而MCP協議的核心是jsonrpc2.0,具體可以參考[官方文檔]和[MCP傳輸協議文檔]

為什么用jsonrpc2.0?

0)生態完善:JSON-RPC 2.0 有豐富的庫和工具支持。
1)和開發語言無關:基本上所有開發語言都支持json協議。
2)簡單實用:結構簡單易讀性好。
3)輕量級:能大大減少數據傳輸,減少AI數據交互過程中的延遲。

MCP中jsonrpc2.0的定義

下文主要以mcp tools原語為例。
企業微信截圖_4f5c8cd5-69b8-452a-a182-f01599fb02f4.png

initialize

# 請求
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2025-06-18",
    "capabilities": {
      "tools": {}
    },
    "clientInfo": {
      "name": "example-client",
      "version": "1.0.0"
    }
  }
}
 
# 響應
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2025-06-18",
    "capabilities": {
      "tools": {
        "listChanged": true
      },
      "resources": {}
    },
    "serverInfo": {
      "name": "example-server",
      "version": "1.0.0"
    }
  }
}

initialized

# 請求
{
  "jsonrpc": "2.0",
  "method": "notifications/initialized"
}
 
# 響應
無

tools/list

# 請求
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/list"
}
 
# 響應
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "tools": [
      {
        "name": "com.example.calculator/arithmetic",
        "title": "Calculator",
        "description": "Perform mathematical calculations including basic arithmetic, trigonometric functions, and algebraic operations",
        "inputSchema": {
          "type": "object",
          "properties": {
            "expression": {
              "type": "string",
              "description": "Mathematical expression to evaluate (e.g., '2 + 3 * 4', 'sin(30)', 'sqrt(16)')"
            }
          },
          "required": ["expression"]
        }
      }
    ]
  }
}

tools/call

# 請求
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "com.example.weather/current",
    "arguments": {
      "location": "San Francisco",
      "units": "imperial"
    }
  }
}
 
# 響應
{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "Current weather in San Francisco: 68°F, partly cloudy with light winds from the west at 8 mph. Humidity: 65%"
      }
    ]
  }
}

一些說明

1)MCP官方文檔寫的非常清楚,可以參考官方文檔中的Architecture Overview->Data Layer 模塊。
2)官方文檔主要以一個地區天氣查詢MCP為例,說明了MCP從連接建立到tool調用的過程中數據以jsonrpc2.0協議傳輸的數據結構,可以看到非常的簡單明了,易于理解和實現。

Demo

這里使用java spring boot簡單模擬mcp tool/call的調用過程。

# JsonRpcServerController.java
package cn.chinatelecom.dw.user.app.jsonrpc;
 
import cn.chinatelecom.dw.user.app.utils.JSONUtils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
 
/**
 * @Author: wanghaoguang
 * @CreateTime: 2025/7/28 15:22
 */
@RestController
public class JsonRpcServerController {
 
    private final static Logger LOG = LoggerFactory
            .getLogger(JsonRpcServerController.class);
 
    @PostMapping(value = "/jsonrpc", consumes = MediaType.APPLICATION_JSON_VALUE, produces =
            MediaType.APPLICATION_JSON_VALUE)
    private ResponseEntity<String> jsonrpc(@RequestBody String requestBody) {
        try {
            ObjectNode objNode = JSONUtils.parseObject(requestBody);
            String methodName = objNode.get("method").asText();
            JsonNode params = objNode.get("params");
            if (params == null) {
                params = JSONUtils.createObjectNode();
            }
            Integer requestId = objNode.get("id").asInt();
            LOG.info("jsonrpc_endpoint params {}", objNode);
            ObjectNode response = JSONUtils.createObjectNode();
            if ("calculate".equals(methodName)) {
                try {
                    String expression = params.get("expression").asText();
                    double result = safeCalculate(expression);
                    response.put("result", result);
                } catch (Exception e) {
                    int code = -32603;
                    String message = e.getMessage();
                    response = buildErrObjectNode(requestId, code, message);
                }
            } else {
                int code = -32601;
                String message = "Method not found";
                buildErrObjectNode(requestId, code, message);
            }
            return ResponseEntity.ok(JSONUtils.toJsonString(response));
        } catch (Exception e) {
            LOG.info("jsonrpc_endpoint Error: {}", e.getMessage());
            int code = -32000;
            String message = "Internal server error " + e.getMessage();
            return ResponseEntity.status(500).body(JSONUtils.toJsonString(buildErrObjectNode(0, code, message)));
        }
    }
 
    private ObjectNode buildErrObjectNode(int requestId, int code, String message) {
        ObjectNode response = JSONUtils.createObjectNode();
        response.put("id", requestId);
        response.put("jsonrpc", "2.0");
        ObjectNode error = JSONUtils.createObjectNode();
        error.put("code", code);
        error.put("message", message);
        response.set("error", error);
        return response;
    }
 
    private double safeCalculate(String expression) {
        try {
            return Double.parseDouble(String.valueOf(;
        } catch (Exception e) {
            throw new IllegalArgumentException("Invalid expression");
        }
    }
 
    private Object  {
        try {
            return new javax.script.ScriptEngineManager().getEngineByName("JavaScript").;
        } catch (Exception e) {
            throw new IllegalArgumentException("Invalid expression");
        }
    }
}
# JsonRpcClient.java
package cn.chinatelecom.dw.user.app.utils;
 
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
import java.io.IOException;
 
/**
 * @Author: wanghaoguang
 * @CreateTime: 2025/7/28 15:35
 */
public class JsonRpcClient {
 
    private final static Logger LOG = LoggerFactory
            .getLogger(JsonRpcClient.class);
    private final String serverUrl;
    private int requestId = 1;
 
    public JsonRpcClient(String serverUrl) {
        this.serverUrl = serverUrl;
    }
 
    public JsonNode call(String method, JsonNode params, int timeout) {
        ObjectNode payload = JSONUtils.createObjectNode();
        payload.put("jsonrpc", "2.0");
        payload.put("method", method);
        if (params == null) {
            params = JSONUtils.createObjectNode();
        }
        payload.set("params", params);
        payload.put("id", requestId++);
 
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(timeout, java.util.concurrent.TimeUnit.SECONDS)
                .readTimeout(timeout, java.util.concurrent.TimeUnit.SECONDS)
                .build();
 
        MediaType JSON = MediaType.get("application/json; charset=utf-8");
        try {
            RequestBody body = RequestBody.create(JSONUtils.toJsonString(payload), JSON);
            Request request = new Request.Builder()
                    .url(serverUrl)
                    .post(body)
                    .build();
 
            try (Response response = client.newCall(request).execute()) {
                if (response.isSuccessful()) {
                    String responseBody = response.body().string();
                    return JSONUtils.parseObject(responseBody);
                } else {
                    LOG.info("Request failed with code: {}", response.code());
                }
            }
        } catch (IOException e) {
            LOG.info("Error occurred while making the request: {}", e.getMessage());
        }
        return null;
    }
 
    public static void main(String[] args) {
        JsonRpcClient client = new JsonRpcClient("//127.0.0.1:9022/jsonrpc");
        ObjectNode params = JSONUtils.createObjectNode();
        params.put("expression", "3+5");
        JsonNode result = client.call("calculate", params, 10);
        System.out.println(result);
    }
}

企業微信截圖_1b661767-d8a8-4173-9a25-a8b6182716fa.png

企業微信截圖_854fe244-1d77-455b-a698-cd18cfed8af0.png

一些說明:
1)可以看到使用java啟動一個http服務,基于jsonrpc2.0協議可以模擬mcp協議的交互流程。
2)上文主要提供java版本實現,python可以參考官方文檔。

總結

1,MCP使用jsonrpc定義了MCPServer和MCPClient之間交互的數據結構,不管是stdio、sse、streamable-http、sampling那種協議。
 2,jsonrpc協議和語言無關,方便簡單易用,使用最簡單的json包處理即可,自己也可以用自己擅長的開發語言按MCP定義的交互協議編寫自己的MCPServer。

文章來自個人專欄
文章 | 訂閱
0條評論
0 / 1000
請輸入你的評論
0
0