McpSchemaVO 详解:MCP协议消息结构定义

📋 文件作用

McpSchemaVO.java 是一个值对象(Value Object),定义了 MCP(Model Context Protocol)协议的消息结构,用于:

  • 序列化:将Java对象转换为JSON字符串
  • 反序列化:将JSON字符串转换为Java对象

🏗️ 核心结构

1. 密封接口(Sealed Interface)

1
2
3
public sealed interface JSONRPCMessage permits JSONRPCRequest, JSONRPCResponse {
String jsonrpc();
}

作用

  • 定义所有MCP消息的公共接口
  • 限制只有 JSONRPCRequestJSONRPCResponse 可以实现该接口
  • 确保类型安全,防止非法实现

sealed关键字的优势

1
2
3
4
5
6
7
8
9
10
11
12
// Java 17+ 特性
public sealed interface JSONRPCMessage permits JSONRPCRequest, JSONRPCResponse {
String jsonrpc();
}

// 这样写会编译错误
public class IllegalMessage implements JSONRPCMessage { // ❌ 编译错误
@Override
public String jsonrpc() {
return "2.0";
}
}

2. 请求对象(JSONRPCRequest)

1
2
3
4
5
6
7
8
9
@JsonInclude(JsonInclude.Include.NON_ABSENT)
@JsonIgnoreProperties(ignoreUnknown = true)
public record JSONRPCRequest(
@JsonProperty("jsonrpc") String jsonrpc,
@JsonProperty("method") String method,
@JsonProperty("id") Object id,
@JsonProperty("params") Object params
) implements JSONRPCMessage {
}

作用:定义MCP请求消息的结构

字段说明

字段 类型 说明 示例
jsonrpc String 协议版本 "2.0"
method String 请求方法名 "initialize", "tools/list", "tools/call"
id Object 请求ID(用于匹配响应) "1", "2", "abc-123"
params Object 请求参数 {}, {"query":"Java"}

实际请求示例

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"jsonrpc": "2.0",
"method": "initialize",
"id": "1",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {
"name": "Java SDK MCP Client",
"version": "1.0.0"
}
}
}

转换为Java对象

1
2
3
4
5
6
7
8
9
10
11
12
13
JSONRPCRequest request = new JSONRPCRequest(
"2.0", // jsonrpc
"initialize", // method
"1", // id
Map.of( // params
"protocolVersion", "2024-11-05",
"capabilities", Map.of(),
"clientInfo", Map.of(
"name", "Java SDK MCP Client",
"version", "1.0.0"
)
)
);

3. 响应对象(JSONRPCResponse)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@JsonInclude(JsonInclude.Include.NON_ABSENT)
@JsonIgnoreProperties(ignoreUnknown = true)
public record JSONRPCResponse(
@JsonProperty("jsonrpc") String jsonrpc,
@JsonProperty("id") Object id,
@JsonProperty("result") Object result,
@JsonProperty("error") JSONRPCError error
) implements JSONRPCMessage {

@JsonInclude(JsonInclude.Include.NON_ABSENT)
@JsonIgnoreProperties(ignoreUnknown = true)
public record JSONRPCError(
@JsonProperty("code") int code,
@JsonProperty("message") String message,
@JsonProperty("data") Object data
) {
}
}

作用:定义MCP响应消息的结构

字段说明

字段 类型 说明 示例
jsonrpc String 协议版本 "2.0"
id Object 请求ID(与请求对应) "1", "2"
result Object 成功时的响应结果 {...}
error JSONRPCError 失败时的错误信息 {...}

注意resulterror 是互斥的,成功时有 result,失败时有 error

成功响应示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"jsonrpc": "2.0",
"id": "1",
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {
"tools": {},
"resources": {}
},
"serverInfo": {
"name": "MCP Weather Proxy Server",
"version": "1.0.0"
}
}
}

失败响应示例

1
2
3
4
5
6
7
8
9
{
"jsonrpc": "2.0",
"id": "1",
"error": {
"code": -32601,
"message": "Method not found",
"data": "tools/unknown"
}
}

4. 错误对象(JSONRPCError)

1
2
3
4
5
6
public record JSONRPCError(
@JsonProperty("code") int code,
@JsonProperty("message") String message,
@JsonProperty("data") Object data
) {
}

作用:定义错误信息的结构

字段说明

字段 类型 说明 示例
code int 错误码 -32601, -32700
message String 错误描述 "Method not found"
data Object 额外的错误数据 "tools/unknown"

常见错误码

错误码 说明
-32700 Parse error(JSON解析错误)
-32600 Invalid Request(无效请求)
-32601 Method not found(方法不存在)
-32602 Invalid params(无效参数)
-32603 Internal error(内部错误)

🔧 反序列化方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static JSONRPCMessage deserializeJsonRpcMessage(String jsonText)
throws IOException {

log.debug("Received JSON message: {}", jsonText);

// 1. 将JSON字符串转换为Map
var map = objectMapper.readValue(jsonText, MAP_TYPE_REF);

// 2. 判断是请求还是响应
if (map.containsKey("method") && map.containsKey("id")) {
// 请求:包含method和id
return objectMapper.convertValue(map, JSONRPCRequest.class);
} else if (map.containsKey("result") || map.containsKey("error")) {
// 响应:包含result或error
return objectMapper.convertValue(map, JSONRPCResponse.class);
}

throw new IllegalArgumentException("Cannot deserialize JSONRPCMessage: " + jsonText);
}

作用:自动识别消息类型并反序列化

判断逻辑

1
2
3
4
5
6
7
8
9
JSON消息

├── 包含 "method" 和 "id"?
│ ├── 是 → JSONRPCRequest(请求)
│ └── 否 ↓

├── 包含 "result" 或 "error"?
│ ├── 是 → JSONRPCResponse(响应)
│ └── 否 → 抛出异常

使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 示例1:反序列化请求
String jsonRequest = """
{
"jsonrpc": "2.0",
"method": "initialize",
"id": "1",
"params": {}
}
""";

JSONRPCMessage message = McpSchemaVO.deserializeJsonRpcMessage(jsonRequest);

if (message instanceof JSONRPCRequest request) {
System.out.println("这是请求");
System.out.println("方法: " + request.method());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 示例2:反序列化响应
String jsonResponse = """
{
"jsonrpc": "2.0",
"id": "1",
"result": {
"protocolVersion": "2024-11-05"
}
}
""";

JSONRPCMessage message = McpSchemaVO.deserializeJsonRpcMessage(jsonResponse);

if (message instanceof JSONRPCResponse response) {
System.out.println("这是响应");
System.out.println("结果: " + response.result());
}

💡 Jackson注解的作用

1. @JsonProperty

1
@JsonProperty("jsonrpc") String jsonrpc

作用:指定JSON字段名与Java字段名的映射

示例

1
2
3
4
5
6
7
// 如果没有注解
public record MyRecord(String jsonrpc) {}
// JSON: {"jsonrpc":"2.0"} // ✅ 正常

// 如果字段名不同
public record MyRecord(@JsonProperty("jsonrpc") String version) {}
// JSON: {"jsonrpc":"2.0"} // ✅ 使用注解映射

2. @JsonInclude

1
2
3
@JsonInclude(JsonInclude.Include.NON_ABSENT)
public record JSONRPCRequest(...) {
}

作用:控制哪些字段包含在序列化结果中

选项说明

选项 说明
ALWAYS 总是包含
NON_NULL 不包含null值
NON_ABSENT 不包含Optional.absent()或未设置的值
NON_EMPTY 不包含空值(null、空字符串、空集合)

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 使用 NON_ABSENT
JSONRPCRequest request = new JSONRPCRequest(
"2.0",
"initialize",
null, // id为null
null // params为null
);

// 序列化结果(使用NON_ABSENT)
{
"jsonrpc": "2.0",
"method": "initialize"
// id和params不会被包含
}

3. @JsonIgnoreProperties

1
2
3
@JsonIgnoreProperties(ignoreUnknown = true)
public record JSONRPCRequest(...) {
}

作用:忽略JSON中未知的属性

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// JSON中包含额外字段
String json = """
{
"jsonrpc": "2.0",
"method": "initialize",
"id": "1",
"params": {},
"extraField": "value" // 未定义的字段
}
""";

// 使用 ignoreUnknown = true
JSONRPCRequest request = objectMapper.readValue(json, JSONRPCRequest.class);
// ✅ 不会抛出异常,extraField被忽略

// 不使用 ignoreUnknown = true(默认)
JSONRPCRequest request = objectMapper.readValue(json, JSONRPCRequest.class);
// ❌ 抛出异常:UnrecognizedPropertyException

🎯 实际应用场景

场景1:接收客户端请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@PostMapping(value = "{gatewayId}/mcp/sse")
public Mono<ResponseEntity<Object>> handleMessage(@RequestBody String messageBody) {
// 1. 反序列化JSON消息
McpSchemaVO.JSONRPCMessage jsonrpcMessage =
McpSchemaVO.deserializeJsonRpcMessage(messageBody);

// 2. 判断消息类型
if (jsonrpcMessage instanceof McpSchemaVO.JSONRPCRequest request) {
// 处理请求
String method = request.method();
Object params = request.params();

// 根据method路由到不同的处理器
return handleRequest(method, params);
}

return Mono.just(ResponseEntity.ok().build());
}

场景2:发送响应给客户端

1
2
3
4
5
6
7
8
9
10
11
12
public McpSchemaVO.JSONRPCResponse createResponse(Object requestId, Object result) {
return new McpSchemaVO.JSONRPCResponse(
"2.0", // jsonrpc
requestId, // id
result, // result
null // error
);
}

// 序列化为JSON
String jsonResponse = objectMapper.writeValueAsString(response);
// 输出: {"jsonrpc":"2.0","id":"1","result":{...}}

场景3:处理错误

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public McpSchemaVO.JSONRPCResponse createErrorResponse(Object requestId, int code, String message) {
return new McpSchemaVO.JSONRPCResponse(
"2.0", // jsonrpc
requestId, // id
null, // result
new McpSchemaVO.JSONRPCResponse.JSONRPCError(
code, // code
message, // message
null // data
)
);
}

// 序列化为JSON
String errorResponse = objectMapper.writeValueAsString(response);
// 输出: {"jsonrpc":"2.0","id":"1","error":{"code":-32601,"message":"Method not found"}}

📊 完整的数据流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
客户端                          服务端
│ │
│── JSON请求 ──────────────────────▶│
│ { │
│ "jsonrpc":"2.0", │
│ "method":"initialize", │
│ "id":"1", │
│ "params":{...} │
│ } │
│ │
│ │ deserializeJsonRpcMessage()
│ │ ↓
│ │ JSONRPCRequest对象
│ │
│ │ 处理业务逻辑
│ │
│ │ ↓
│ │ JSONRPCResponse对象
│ │
│◀──── JSON响应 ────────────────────│
│ { │
│ "jsonrpc":"2.0", │
│ "id":"1", │
│ "result":{...} │
│ } │

🎓 设计模式

1. 值对象模式(Value Object)

1
2
3
4
5
public final class McpSchemaVO {
// 不可变的数据结构
public record JSONRPCRequest(...) implements JSONRPCMessage {}
public record JSONRPCResponse(...) implements JSONRPCMessage {}
}

特点

  • 不可变(immutable)
  • 无标识(no identity)
  • 可替换(replaceable)

2. 密封接口模式(Sealed Interface)

1
2
3
public sealed interface JSONRPCMessage permits JSONRPCRequest, JSONRPCResponse {
String jsonrpc();
}

特点

  • 限制实现类
  • 编译时类型检查
  • 支持模式匹配(Java 17+)

3. 记录模式(Record)

1
2
3
4
5
6
public record JSONRPCRequest(
@JsonProperty("jsonrpc") String jsonrpc,
@JsonProperty("method") String method,
@JsonProperty("id") Object id,
@JsonProperty("params") Object params
) implements JSONRPCMessage {}

特点

  • 自动生成构造器
  • 自动生成getter
  • 自动生成equals/hashCode/toString
  • 不可变

📝 总结

McpSchemaVO 的核心作用

作用 说明
协议定义 定义MCP协议的消息结构
类型安全 使用密封接口和record确保类型安全
序列化 将Java对象转换为JSON字符串
反序列化 将JSON字符串转换为Java对象
协议兼容 兼容JSON-RPC 2.0协议标准

核心组件

组件 作用 关键方法
JSONRPCMessage 消息接口 jsonrpc()
JSONRPCRequest 请求对象 method(), params()
JSONRPCResponse 响应对象 result(), error()
JSONRPCError 错误对象 code(), message()
deserializeJsonRpcMessage() 反序列化 自动识别消息类型

使用流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1. 接收JSON字符串

2. 调用 deserializeJsonRpcMessage()

3. 判断是请求还是响应

4. 转换为对应的Java对象

5. 处理业务逻辑

6. 创建响应对象

7. 序列化为JSON字符串

8. 发送给客户端

这就是 McpSchemaVO.java 的完整作用:定义MCP协议的消息结构,提供类型安全的序列化和反序列化能力