Skip to main content

vtcode_utility_tool_specs/
mcp_tool.rs

1use rmcp::model::Tool;
2use serde_json::Value;
3
4#[derive(Clone, Debug, PartialEq)]
5pub struct ParsedMcpTool {
6    pub name: String,
7    pub description: String,
8    pub input_schema: Value,
9    pub output_schema: Option<Value>,
10}
11
12#[must_use]
13pub fn parse_mcp_tool(tool: &Tool) -> ParsedMcpTool {
14    ParsedMcpTool {
15        name: tool.name.to_string(),
16        description: tool.description.clone().unwrap_or_default().to_string(),
17        input_schema: serde_json::to_value(&tool.input_schema).unwrap_or(Value::Null),
18        output_schema: tool.output_schema.as_ref().and_then(|schema| serde_json::to_value(schema).ok()),
19    }
20}
21
22#[cfg(test)]
23mod tests {
24    use super::{ParsedMcpTool, parse_mcp_tool};
25    use rmcp::model::Tool;
26    use serde_json::json;
27    use std::sync::Arc;
28
29    #[test]
30    fn parse_mcp_tool_preserves_name_description_and_input_schema() {
31        let input_schema = Arc::new(
32            serde_json::from_value(json!({
33                "type": "object",
34                "properties": {
35                    "query": {"type": "string"}
36                }
37            }))
38            .expect("json object"),
39        );
40        let tool = Tool::new("search-docs", "Search documentation", input_schema);
41
42        let parsed = parse_mcp_tool(&tool);
43        assert_eq!(
44            parsed,
45            ParsedMcpTool {
46                name: "search-docs".to_string(),
47                description: "Search documentation".to_string(),
48                input_schema: json!({
49                    "type": "object",
50                    "properties": {
51                        "query": {"type": "string"}
52                    }
53                }),
54                output_schema: None,
55            }
56        );
57    }
58
59    #[test]
60    fn parse_mcp_tool_defaults_missing_description() {
61        let input_schema = Arc::new(serde_json::from_value(json!({})).expect("json object"));
62        let tool = Tool::new_with_raw("search-docs", None, input_schema);
63
64        let parsed = parse_mcp_tool(&tool);
65        assert_eq!(parsed.description, "");
66        assert_eq!(parsed.input_schema, json!({}));
67        assert_eq!(parsed.output_schema, None);
68    }
69
70    #[test]
71    fn parse_mcp_tool_captures_output_schema() {
72        let input_schema = Arc::new(serde_json::from_value(json!({})).expect("json object"));
73        let output_schema = Arc::new(
74            serde_json::from_value(json!({
75                "type": "object",
76                "properties": {
77                    "answer": {"type": "string"}
78                },
79                "required": ["answer"]
80            }))
81            .expect("json object"),
82        );
83        let mut tool = Tool::new_with_raw("ask_question", None, input_schema);
84        tool.output_schema = Some(output_schema);
85
86        let parsed = parse_mcp_tool(&tool);
87        assert_eq!(
88            parsed.output_schema,
89            Some(json!({
90                "type": "object",
91                "properties": {
92                    "answer": {"type": "string"}
93                },
94                "required": ["answer"]
95            }))
96        );
97    }
98}