1pub mod forge;
36pub mod schema;
37pub mod server;
38pub mod stdio;
39pub mod tools;
40
41pub use schema::{coerce_type, extract_enum_values, openapi_to_json_schema, validate_input};
42pub use server::McpServer;
43pub use stdio::{init_tracing, StdioConfig, StdioTransport};
44pub use tools::McpTool;
45
46#[cfg(test)]
47mod tests {
48 use allframe_core::router::Router;
49
50 use super::*;
51
52 #[test]
55 fn test_mcp_server_creation() {
56 let router = Router::new();
57 let mcp_server = McpServer::new(router);
58
59 assert_eq!(mcp_server.tool_count(), 0);
61 }
62
63 #[test]
64 fn test_mcp_server_discovers_handlers() {
65 let mut router = Router::new();
66 router.register("get_user", || async { "User data".to_string() });
67 router.register("create_user", || async { "Created".to_string() });
68 router.register("update_user", || async { "Updated".to_string() });
69
70 let mcp_server = McpServer::new(router);
71
72 assert_eq!(mcp_server.tool_count(), 3);
74 }
75
76 #[tokio::test]
77 async fn test_mcp_server_lists_tools() {
78 let mut router = Router::new();
79 router.register("get_user", || async { "User data".to_string() });
80 router.register("create_user", || async { "Created".to_string() });
81
82 let mcp_server = McpServer::new(router);
83 let tools = mcp_server.list_tools().await;
84
85 assert_eq!(tools.len(), 2);
87
88 let tool_names: Vec<String> = tools.iter().map(|t| t.name.clone()).collect();
90 assert!(tool_names.contains(&"get_user".to_string()));
91 assert!(tool_names.contains(&"create_user".to_string()));
92 }
93
94 #[tokio::test]
95 async fn test_mcp_tool_has_required_fields() {
96 let mut router = Router::new();
97 router.register("get_user", || async { "User data".to_string() });
98
99 let mcp_server = McpServer::new(router);
100 let tools = mcp_server.list_tools().await;
101 let tool = &tools[0];
102
103 assert_eq!(tool.name, "get_user");
105
106 assert!(!tool.description.is_empty());
108
109 assert!(tool.input_schema.contains("type"));
111 }
112
113 #[tokio::test]
114 async fn test_mcp_server_calls_tool_successfully() {
115 let mut router = Router::new();
116 router.register("get_user", || async { "User data".to_string() });
117
118 let mcp_server = McpServer::new(router);
119
120 let result = mcp_server
122 .call_tool("get_user", serde_json::json!({}))
123 .await;
124 assert!(result.is_ok());
125 assert_eq!(result.unwrap(), serde_json::json!("User data"));
126 }
127
128 #[tokio::test]
129 async fn test_mcp_server_calls_tool_with_arguments() {
130 let mut router = Router::new();
131 router.register("echo", || async { "echoed".to_string() });
132
133 let mcp_server = McpServer::new(router);
134
135 let args = serde_json::json!({
137 "message": "Hello, World!"
138 });
139 let result = mcp_server.call_tool("echo", args).await;
140 assert!(result.is_ok());
141 }
142
143 #[tokio::test]
144 async fn test_mcp_server_error_on_unknown_tool() {
145 let router = Router::new();
146 let mcp_server = McpServer::new(router);
147
148 let result = mcp_server
150 .call_tool("unknown_tool", serde_json::json!({}))
151 .await;
152
153 assert!(result.is_err());
155 let error_msg = result.unwrap_err();
156 assert!(error_msg.contains("unknown_tool") || error_msg.contains("not found"));
157 }
158
159 #[tokio::test]
160 async fn test_mcp_server_handles_handler_errors() {
161 let mut router = Router::new();
162 router.register("failing_handler", || async { "".to_string() });
164
165 let mcp_server = McpServer::new(router);
166
167 let result = mcp_server
169 .call_tool("failing_handler", serde_json::json!({}))
170 .await;
171 assert!(result.is_ok()); }
173
174 #[test]
175 fn test_mcp_tool_creation() {
176 let tool = McpTool::new("test_tool", "A test tool", r#"{"type": "object"}"#);
177
178 assert_eq!(tool.name, "test_tool");
179 assert_eq!(tool.description, "A test tool");
180 assert_eq!(tool.input_schema, r#"{"type": "object"}"#);
181 }
182
183 #[test]
184 fn test_mcp_tool_from_handler_name() {
185 let tool = McpTool::from_handler_name("get_user");
186
187 assert!(!tool.description.is_empty());
189
190 assert!(tool.input_schema.contains("object"));
192 }
193
194 #[tokio::test]
195 async fn test_mcp_server_multiple_tool_calls() {
196 let mut router = Router::new();
197 router.register("tool1", || async { "result1".to_string() });
198 router.register("tool2", || async { "result2".to_string() });
199
200 let mcp_server = McpServer::new(router);
201
202 let result1 = mcp_server.call_tool("tool1", serde_json::json!({})).await;
204 assert!(result1.is_ok());
205 assert_eq!(result1.unwrap(), serde_json::json!("result1"));
206
207 let result2 = mcp_server.call_tool("tool2", serde_json::json!({})).await;
209 assert!(result2.is_ok());
210 assert_eq!(result2.unwrap(), serde_json::json!("result2"));
211 }
212
213 #[tokio::test]
214 async fn test_mcp_server_tool_isolation() {
215 let mut router = Router::new();
216 router.register("tool_a", || async { "A".to_string() });
217 router.register("tool_b", || async { "B".to_string() });
218
219 let mcp_server = McpServer::new(router);
220
221 let _ = mcp_server.call_tool("tool_a", serde_json::json!({})).await;
223 let result_b = mcp_server.call_tool("tool_b", serde_json::json!({})).await;
224
225 assert_eq!(result_b.unwrap(), serde_json::json!("B"));
226 }
227
228 #[test]
229 fn test_mcp_server_empty_router() {
230 let router = Router::new();
231 let mcp_server = McpServer::new(router);
232
233 assert_eq!(mcp_server.tool_count(), 0);
235 }
236
237 #[tokio::test]
238 async fn test_mcp_server_list_tools_empty() {
239 let router = Router::new();
240 let mcp_server = McpServer::new(router);
241 let tools = mcp_server.list_tools().await;
242
243 assert_eq!(tools.len(), 0);
245 }
246}