Skip to content

Commit a00cf1b

Browse files
committed
fix(shemars): use JSON Schema 2020-12 as Default Dialect
1 parent 1d38d68 commit a00cf1b

File tree

4 files changed

+61
-22
lines changed

4 files changed

+61
-22
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ rmcp = { git = "https://github.com/modelcontextprotocol/rust-sdk", branch = "mai
2828
Basic dependencies:
2929
- [tokio required](https://github.com/tokio-rs/tokio)
3030
- [serde required](https://github.com/serde-rs/serde)
31-
31+
Json Schema generation(Must follow the 2020-12 version):
32+
- [shemars required](https://github.com/GREsau/schemars)
3233

3334

3435
### Build a Client

crates/rmcp/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ schemars = ["dep:schemars"]
143143

144144
[dev-dependencies]
145145
tokio = { version = "1", features = ["full"] }
146-
schemars = { version = "1.0", features = ["chrono04"] }
146+
schemars = { version = "1.1.0", features = ["chrono04"] }
147147

148148
anyhow = "1.0"
149149
tracing-subscriber = { version = "0.3", features = [

crates/rmcp/src/handler/server/common.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,8 @@ use crate::{
1111
/// A shortcut for generating a JSON schema for a type.
1212
pub fn schema_for_type<T: JsonSchema>() -> JsonObject {
1313
// explicitly to align json schema version to official specifications.
14-
// https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/schema/2025-03-26/schema.json
15-
// TODO: update to 2020-12 waiting for the mcp spec update
16-
let mut settings = SchemaSettings::draft07();
17-
settings.transforms = vec![Box::new(schemars::transform::AddNullable::default())];
14+
// refer to https://github.com/modelcontextprotocol/modelcontextprotocol/pull/655 for details.
15+
let settings = SchemaSettings::draft2020_12();
1816
let generator = settings.into_generator();
1917
let schema = generator.into_root_schema_for::<T>();
2018
let object = serde_json::to_value(schema).expect("failed to serialize schema");

crates/rmcp/tests/test_complex_schema.rs

Lines changed: 56 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use rmcp::{
33
tool_router,
44
};
55
use serde::{Deserialize, Serialize};
6+
use serde_json; // ensure json macro path
67

78
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
89
pub enum ChatRole {
@@ -43,24 +44,63 @@ impl Demo {
4344
}
4445
}
4546

47+
// Build expected schema using json! macro to avoid raw string parsing issues with procedural macros.
48+
fn expected_schema() -> serde_json::Value {
49+
serde_json::json!({
50+
"$defs": {
51+
"ChatMessage": {
52+
"properties": {
53+
"content": {
54+
"type": "string"
55+
},
56+
"role": {
57+
"$ref": "#/$defs/ChatRole"
58+
}
59+
},
60+
"required": [
61+
"role",
62+
"content"
63+
],
64+
"type": "object"
65+
},
66+
"ChatRole": {
67+
"enum": [
68+
"System",
69+
"User",
70+
"Assistant",
71+
"Tool"
72+
],
73+
"type": "string"
74+
}
75+
},
76+
"$schema": "https://json-schema.org/draft/2020-12/schema",
77+
"properties": {
78+
"messages": {
79+
"items": {
80+
"$ref": "#/$defs/ChatMessage"
81+
},
82+
"type": "array"
83+
},
84+
"system": {
85+
"type": [
86+
"string",
87+
"null"
88+
]
89+
}
90+
},
91+
"required": [
92+
"messages"
93+
],
94+
"title": "ChatRequest",
95+
"type": "object"
96+
})
97+
}
98+
4699
#[test]
47100
fn test_complex_schema() {
48101
let attr = Demo::chat_tool_attr();
49102
let input_schema = attr.input_schema;
50-
let enum_number = input_schema
51-
.get("definitions")
52-
.unwrap()
53-
.as_object()
54-
.unwrap()
55-
.get("ChatRole")
56-
.unwrap()
57-
.as_object()
58-
.unwrap()
59-
.get("enum")
60-
.unwrap()
61-
.as_array()
62-
.unwrap()
63-
.len();
64-
assert_eq!(enum_number, 4);
65-
println!("{}", serde_json::to_string_pretty(&input_schema).unwrap());
103+
let expected = expected_schema();
104+
let produced = serde_json::Value::Object(input_schema.as_ref().clone());
105+
assert_eq!(produced, expected, "schema mismatch");
66106
}

0 commit comments

Comments
 (0)