json_mcp_server/
lib.rs

1pub mod json_tools;
2pub mod mcp;
3
4#[cfg(test)]
5mod tests {
6    use crate::json_tools::JsonToolsHandler;
7    use crate::mcp::{
8        protocol::ToolCall,
9        server::{MCPServer, ToolHandler},
10    };
11    use serde_json::{json, Value};
12    use std::collections::HashMap;
13    use std::fs;
14    use std::path::PathBuf;
15
16    // Helper function to create test JSON file
17    fn create_test_json_file(content: &str) -> PathBuf {
18        let mut temp_path = std::env::temp_dir();
19        temp_path.push(format!("test_{}.json", std::process::id()));
20        fs::write(&temp_path, content).unwrap();
21        temp_path
22    }
23
24    // Helper function to create argument map
25    fn args_map(pairs: &[(&str, Value)]) -> HashMap<String, Value> {
26        pairs.iter()
27            .map(|(k, v)| (k.to_string(), v.clone()))
28            .collect()
29    }
30
31    #[tokio::test]
32    async fn test_json_help_default() {
33        let handler = JsonToolsHandler::new();
34        let args = HashMap::new();
35        
36        let result = handler.call_tool(ToolCall {
37            name: "json-help".to_string(),
38            arguments: args,
39        }).await;
40        
41        assert!(result.is_ok());
42        let tool_result = result.unwrap();
43        
44        if let Some(is_error) = tool_result.is_error {
45            assert!(!is_error, "Expected success but got error: {}", 
46                   tool_result.content.get(0).map(|c| c.text.as_str()).unwrap_or("<no text>"));
47        }
48        
49        let text = &tool_result.content[0].text;
50        assert!(text.contains("JSON MCP Server Help"));
51        assert!(text.contains("json-read"));
52        assert!(text.contains("json-write"));
53        assert!(text.contains("json-query"));
54        assert!(text.contains("json-validate"));
55    }
56
57    #[tokio::test]
58    async fn test_json_validate_valid_file() {
59        let test_data = r#"{"name": "test", "value": 42, "items": [1, 2, 3]}"#;
60        let file_path = create_test_json_file(test_data);
61        let handler = JsonToolsHandler::new();
62        
63        let args = args_map(&[("file_path", json!(file_path.to_string_lossy()))]);
64        let result = handler.call_tool(ToolCall {
65            name: "json-validate".to_string(),
66            arguments: args,
67        }).await;
68        
69        assert!(result.is_ok());
70        let tool_result = result.unwrap();
71        
72        if let Some(is_error) = tool_result.is_error {
73            assert!(!is_error, "Expected success but got error: {}", 
74                   tool_result.content.get(0).map(|c| c.text.as_str()).unwrap_or("<no text>"));
75        }
76        
77        let text = &tool_result.content[0].text;
78        assert!(text.contains("is valid"));
79        
80        // Cleanup
81        let _ = fs::remove_file(file_path);
82    }
83
84    #[tokio::test]
85    async fn test_mcp_server_tool_registration() {
86        let handler = JsonToolsHandler::new();
87        let mut server = MCPServer::new(handler);
88        
89        let result = server.register_tools().await;
90        assert!(result.is_ok());
91        
92        // Test that we can get the tool list through the MCP protocol
93        let tools_request = r#"{"jsonrpc": "2.0", "id": 1, "method": "tools/list"}"#;
94        let response = server.handle_request(tools_request).await;
95        assert!(response.is_ok());
96        
97        let response_str = response.unwrap();
98        assert!(response_str.contains("json-read"));
99        assert!(response_str.contains("json-write"));
100        assert!(response_str.contains("json-query"));
101        assert!(response_str.contains("json-validate"));
102        assert!(response_str.contains("json-help"));
103    }
104}