1pub mod client;
26pub mod cmd_utils;
27pub mod config;
28pub mod discovery;
29pub mod integrator;
30pub mod lifecycle;
31pub mod notifications;
32pub mod prompts;
33pub mod provision;
34pub mod registry;
35pub mod server;
36pub mod types;
37
38pub mod error;
41pub mod execution_mode;
42pub mod tool_inspection;
43
44pub use client::{McpClient, McpClientRegistry, get_mcp_client_registry};
46pub use config::{
47 McpJsonFile, McpScope, McpServerEntry, McpTool, McpTransportType, import_claude_desktop_servers,
48};
49pub use discovery::{
50 CacheStats as McpCacheStats, CachedTool, McpDiscoveryManager, McpServerConfig,
51 ServerInfo as McpServerInfo, ServerState,
52};
53pub use integrator::{LocalMcp, McpIntegrator, MdhResource, TokenInfo, get_mcp, mdh_translate};
54pub use lifecycle::{SessionManager, create_session_manager};
55pub use notifications::{
56 McpLogger, McpNotification, NotificationReceiver, NotificationSender, OperationProgress,
57 ProgressTracker, create_notification_channel,
58};
59pub use prompts::{PromptRegistry, RegisteredPrompt};
60pub use provision::{ProvisionResult, ProvisionStatus, provision_mcp_server};
61pub use registry::{
62 PopularMcpServer, RegistryBrowseEntry, RegistryBrowsePage, browse_mcp_registry,
63 list_popular_mcp_servers, normalize_mcp_server_name,
64};
65pub use server::{
66 JsonRpcError, JsonRpcRequest, JsonRpcResponse, McpRequestContext, McpResourceHandler,
67 McpServer, McpToolHandler,
68};
69pub use types::{
70 CancelledNotification, ClientCapabilities, ClientInfo, EmbeddedResource, InitializeParams,
71 InitializeResult, LogLevel, LoggingCapability, LoggingMessage, PROTOCOL_VERSION, PingParams,
72 PingResult, ProgressNotification, ProgressToken, Prompt, PromptArgument, PromptContent,
73 PromptMessage, PromptRole, PromptsCapability, PromptsGetParams, PromptsGetResult,
74 PromptsListParams, PromptsListResult, Resource, ResourceAnnotations, ResourceContent,
75 ResourceReference, ResourcesCapability, ResourcesListParams, ResourcesListResult,
76 ResourcesReadParams, ResourcesReadResult, ServerCapabilities, ServerInfo, SessionState,
77 TextContent, Tool, ToolAnnotations, ToolResultContent, ToolsCallParams, ToolsCallResult,
78 ToolsCapability, ToolsListParams, ToolsListResult, error_codes, mcp_error_codes,
79};
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 #[test]
86 fn test_protocol_version() {
87 assert_eq!(PROTOCOL_VERSION, "2025-11-25");
88 }
89
90 #[test]
91 fn test_server_info_default() {
92 let info = ServerInfo::default();
93 assert_eq!(info.name, "gestura");
94 assert!(!info.version.is_empty());
95 }
96
97 #[test]
98 fn test_session_lifecycle() {
99 let session = SessionManager::new();
100 assert_eq!(session.state(), SessionState::Uninitialized);
101
102 let params = InitializeParams {
103 protocol_version: PROTOCOL_VERSION.to_string(),
104 capabilities: ClientCapabilities::default(),
105 client_info: ClientInfo {
106 name: "test-client".to_string(),
107 version: "1.0.0".to_string(),
108 },
109 };
110
111 let result = session.initialize(params).unwrap();
112 assert_eq!(result.protocol_version, PROTOCOL_VERSION);
113 assert_eq!(session.state(), SessionState::Initializing);
114
115 session.initialized().unwrap();
116 assert_eq!(session.state(), SessionState::Ready);
117 assert!(session.is_ready());
118
119 session.shutdown().unwrap();
120 assert_eq!(session.state(), SessionState::Closed);
121 }
122
123 #[test]
124 fn test_prompt_registry() {
125 let registry = PromptRegistry::new();
126 let prompts = registry.list();
127 assert!(!prompts.is_empty());
128 assert!(registry.contains("voice-command"));
129
130 let mut args = std::collections::HashMap::new();
131 args.insert("command".to_string(), "hello world".to_string());
132 args.insert("context".to_string(), "testing".to_string());
133
134 let result = registry.get("voice-command", Some(&args)).unwrap();
135 assert!(
136 result.messages[0]
137 .content
138 .as_text()
139 .map(|t| t.text.contains("hello world"))
140 .unwrap_or(false)
141 );
142 }
143
144 #[test]
145 fn test_progress_tracker() {
146 let (sender, _receiver) = create_notification_channel();
147 let tracker = ProgressTracker::new(sender);
148
149 let id = tracker.start_operation("test-op".to_string(), Some(100.0));
150 assert!(!tracker.is_cancelled(&id));
151
152 tracker.update_progress(&id, 50.0, Some("Halfway".to_string()));
153 tracker.cancel_operation(&id, Some("User cancelled".to_string()));
154 assert!(tracker.is_cancelled(&id));
155 }
156}