#![allow(clippy::exhaustive_structs)] //cargo test --test test_tool_builder_methods --features "client server macros" use rmcp::model::{JsonObject, Tool}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, JsonSchema)] pub struct InputData { pub name: String, pub age: u32, } #[derive(Serialize, Deserialize, JsonSchema)] pub struct OutputData { pub greeting: String, pub is_adult: bool, } #[test] fn test_with_output_schema() { let tool = Tool::new("test", "Test tool", JsonObject::new()).with_output_schema::(); assert!(tool.output_schema.is_some()); let schema = tool.output_schema.as_ref().unwrap(); assert_eq!(schema.get("type"), Some(&serde_json::json!("object"))); } #[test] fn test_with_input_schema() { let tool = Tool::new("test", "Test tool", JsonObject::new()).with_input_schema::(); // Verify the schema contains expected fields let schema_str = serde_json::to_string(&tool.input_schema).unwrap(); assert!(schema_str.contains("name")); assert!(schema_str.contains("age")); } #[test] fn test_chained_builder_methods() { let tool = Tool::new("test", "Test tool", JsonObject::new()) .with_input_schema::() .with_output_schema::() .annotate(rmcp::model::ToolAnnotations::new().read_only(true)); assert!(tool.output_schema.is_some()); assert!(tool.annotations.is_some()); assert_eq!( tool.annotations.as_ref().unwrap().read_only_hint, Some(true) ); // Verify both schemas are set correctly let input_schema_str = serde_json::to_string(&tool.input_schema).unwrap(); assert!(input_schema_str.contains("name")); assert!(input_schema_str.contains("age")); let output_schema = tool.output_schema.as_ref().unwrap(); assert_eq!( output_schema.get("type"), Some(&serde_json::json!("object")) ); } #[test] fn test_with_output_schema_primitive() { let tool = Tool::new("test", "Test tool", JsonObject::new()).with_output_schema::(); assert!(tool.output_schema.is_some()); let schema = tool.output_schema.as_ref().unwrap(); assert_eq!(schema.get("type"), Some(&serde_json::json!("integer"))); // title should be stripped from output schema assert!(schema.get("title").is_none()); } #[test] fn test_with_output_schema_array() { let tool = Tool::new("test", "Test tool", JsonObject::new()).with_output_schema::>(); assert!(tool.output_schema.is_some()); let schema_str = serde_json::to_string(tool.output_schema.as_ref().unwrap()).unwrap(); assert!(schema_str.contains("\"type\":\"array\"")); assert!(schema_str.contains("items")); // title should be stripped from output schema assert!(!schema_str.contains("title")); } #[test] fn test_with_output_schema_option() { let tool = Tool::new("test", "Test tool", JsonObject::new()).with_output_schema::>(); assert!(tool.output_schema.is_some()); let schema_str = serde_json::to_string(tool.output_schema.as_ref().unwrap()).unwrap(); // Option generates a composition schema (anyOf/oneOf/type array with null) assert!( schema_str.contains("anyOf") || schema_str.contains("oneOf") || schema_str.contains("null"), "Expected composition schema for Option, got: {schema_str}" ); assert!(!schema_str.contains("title")); }