use schemars::JsonSchema; use serde_json::json; pub fn success(id: serde_json::Value, result: serde_json::Value) -> serde_json::Value { json!({ "jsonrpc": "2.0", "id": id, "result": result }) } pub fn error(id: serde_json::Value, code: i32, message: &str) -> serde_json::Value { json!({ "jsonrpc": "2.0", "id": id, "error": { "code": code, "message": message } }) } pub fn tool_def(name: &str, fallback_desc: &str) -> serde_json::Value { let schema = schemars::schema_for!(T); let schema_val = serde_json::to_value(&schema).unwrap_or_default(); let desc = schema_val .get("description") .and_then(|d| d.as_str()) .unwrap_or(fallback_desc) .to_string(); // MCP expects standard JSON schema. Schemars returns draft-07. json!({ "name": name, "description": desc, "inputSchema": schema_val }) } #[cfg(test)] mod tests { use super::*; use schemars::JsonSchema; use serde::Serialize; #[derive(JsonSchema, Serialize)] struct DummyTool { name: String, age: i32, } #[test] fn test_success_response() { let res = success(json!(1), json!({"status": "ok"})); assert_eq!(res["jsonrpc"], "2.0"); assert_eq!(res["id"], 1); assert_eq!(res["result"]["status"], "ok"); } #[test] fn test_error_response() { let err = error(json!(2), -32603, "internal error"); assert_eq!(err["jsonrpc"], "2.0"); assert_eq!(err["id"], 2); assert_eq!(err["error"]["code"], -32603); assert_eq!(err["error"]["message"], "internal error"); } #[test] fn test_tool_def_generation() { let def = tool_def::("dummy", "A dummy tool"); assert_eq!(def["name"], "dummy"); assert_eq!(def["description"], "A dummy tool"); assert!(def["inputSchema"].is_object()); let schema = def["inputSchema"].as_object().unwrap(); let properties = schema["properties"].as_object().unwrap(); assert!(properties.contains_key("name")); assert!(properties.contains_key("age")); } }