diff --git a/README.md b/README.md index 9847b498..6e935d09 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,8 @@ rmcp = { git = "https://github.com/modelcontextprotocol/rust-sdk", branch = "mai Basic dependencies: - [tokio required](https://github.com/tokio-rs/tokio) - [serde required](https://github.com/serde-rs/serde) - +Json Schema generation(Must follow the 2020-12 version): +- [shemars required](https://github.com/GREsau/schemars) ### Build a Client diff --git a/crates/rmcp/Cargo.toml b/crates/rmcp/Cargo.toml index 17b426cb..16a813c0 100644 --- a/crates/rmcp/Cargo.toml +++ b/crates/rmcp/Cargo.toml @@ -143,7 +143,7 @@ schemars = ["dep:schemars"] [dev-dependencies] tokio = { version = "1", features = ["full"] } -schemars = { version = "1.0", features = ["chrono04"] } +schemars = { version = "1.1.0", features = ["chrono04"] } anyhow = "1.0" tracing-subscriber = { version = "0.3", features = [ diff --git a/crates/rmcp/src/handler/server/common.rs b/crates/rmcp/src/handler/server/common.rs index b36696cb..ad144ae3 100644 --- a/crates/rmcp/src/handler/server/common.rs +++ b/crates/rmcp/src/handler/server/common.rs @@ -11,9 +11,8 @@ use crate::{ /// A shortcut for generating a JSON schema for a type. pub fn schema_for_type() -> JsonObject { // explicitly to align json schema version to official specifications. - // https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/schema/2025-03-26/schema.json - // TODO: update to 2020-12 waiting for the mcp spec update - let mut settings = SchemaSettings::draft07(); + // refer to https://github.com/modelcontextprotocol/modelcontextprotocol/pull/655 for details. + let mut settings = SchemaSettings::draft2020_12(); settings.transforms = vec![Box::new(schemars::transform::AddNullable::default())]; let generator = settings.into_generator(); let schema = generator.into_root_schema_for::(); diff --git a/crates/rmcp/tests/test_complex_schema.rs b/crates/rmcp/tests/test_complex_schema.rs index e3a49e8d..1bc9051a 100644 --- a/crates/rmcp/tests/test_complex_schema.rs +++ b/crates/rmcp/tests/test_complex_schema.rs @@ -43,24 +43,60 @@ impl Demo { } } +fn expected_schema() -> serde_json::Value { + serde_json::json!({ + "$defs": { + "ChatMessage": { + "properties": { + "content": { + "type": "string" + }, + "role": { + "$ref": "#/$defs/ChatRole" + } + }, + "required": [ + "role", + "content" + ], + "type": "object" + }, + "ChatRole": { + "enum": [ + "System", + "User", + "Assistant", + "Tool" + ], + "type": "string" + } + }, + "$schema": "https://json-schema.org/draft/2020-12/schema", + "properties": { + "messages": { + "items": { + "$ref": "#/$defs/ChatMessage" + }, + "type": "array" + }, + "system": { + "nullable": true, + "type": "string" + } + }, + "required": [ + "messages" + ], + "title": "ChatRequest", + "type": "object" + }) +} + #[test] fn test_complex_schema() { let attr = Demo::chat_tool_attr(); let input_schema = attr.input_schema; - let enum_number = input_schema - .get("definitions") - .unwrap() - .as_object() - .unwrap() - .get("ChatRole") - .unwrap() - .as_object() - .unwrap() - .get("enum") - .unwrap() - .as_array() - .unwrap() - .len(); - assert_eq!(enum_number, 4); - println!("{}", serde_json::to_string_pretty(&input_schema).unwrap()); + let expected = expected_schema(); + let produced = serde_json::Value::Object(input_schema.as_ref().clone()); + assert_eq!(produced, expected, "schema mismatch"); }