Skip to main content

mocopr_core/protocol/
router.rs

1//! Message routing for MCP protocol
2
3use super::*;
4use crate::{Result, utils::Utils};
5use std::sync::Arc;
6
7/// Message router for dispatching MCP messages to handlers
8pub struct MessageRouter {
9    handler: Arc<dyn MessageHandler>,
10}
11
12impl MessageRouter {
13    /// Create a new message router with the given handler
14    pub fn new(handler: Arc<dyn MessageHandler>) -> Self {
15        Self { handler }
16    }
17
18    /// Route a JSON-RPC message to the appropriate handler
19    pub async fn route_message(&self, message: JsonRpcMessage) -> Result<Option<JsonRpcMessage>> {
20        match message {
21            JsonRpcMessage::Request(request) => {
22                let response = self.route_request(request).await?;
23                Ok(Some(JsonRpcMessage::Response(response)))
24            }
25            JsonRpcMessage::Notification(notification) => {
26                self.route_notification(notification).await?;
27                Ok(None)
28            }
29            JsonRpcMessage::Response(_) => {
30                // Responses are handled by the caller, not routed
31                Ok(None)
32            }
33        }
34    }
35
36    /// Route a request message
37    async fn route_request(&self, request: JsonRpcRequest) -> Result<JsonRpcResponse> {
38        let result = self.dispatch_request(&request).await;
39
40        match result {
41            Ok(response_data) => Ok(Protocol::create_response(
42                request.id,
43                Some(response_data),
44                None,
45            )),
46            Err(error) => {
47                let jsonrpc_error = Protocol::error_to_jsonrpc(&error);
48                Ok(Protocol::create_response(
49                    request.id,
50                    None,
51                    Some(jsonrpc_error),
52                ))
53            }
54        }
55    }
56
57    /// Route a notification message
58    async fn route_notification(&self, notification: JsonRpcNotification) -> Result<()> {
59        self.dispatch_notification(&notification).await
60    }
61
62    /// Dispatch a request to the appropriate handler method
63    async fn dispatch_request(&self, request: &JsonRpcRequest) -> Result<serde_json::Value> {
64        match request.method.as_str() {
65            "initialize" => {
66                let req: InitializeRequest = self.deserialize_params(request.params.as_ref())?;
67                let response = self.handler.handle_initialize(req).await?;
68                Utils::to_json_value(&response)
69            }
70            "ping" => {
71                let req: PingRequest = self.deserialize_params(request.params.as_ref())?;
72                let response = self.handler.handle_ping(req).await?;
73                Utils::to_json_value(&response)
74            }
75            "resources/list" => {
76                let req: ResourcesListRequest = self.deserialize_params(request.params.as_ref())?;
77                let response = self.handler.handle_resources_list(req).await?;
78                Utils::to_json_value(&response)
79            }
80            "resources/read" => {
81                let req: ResourcesReadRequest = self.deserialize_params(request.params.as_ref())?;
82                let response = self.handler.handle_resources_read(req).await?;
83                Utils::to_json_value(&response)
84            }
85            "resources/subscribe" => {
86                let req: ResourcesSubscribeRequest =
87                    self.deserialize_params(request.params.as_ref())?;
88                let response = self.handler.handle_resources_subscribe(req).await?;
89                Utils::to_json_value(&response)
90            }
91            "resources/unsubscribe" => {
92                let req: ResourcesUnsubscribeRequest =
93                    self.deserialize_params(request.params.as_ref())?;
94                let response = self.handler.handle_resources_unsubscribe(req).await?;
95                Utils::to_json_value(&response)
96            }
97            "tools/list" => {
98                let req: ToolsListRequest = self.deserialize_params(request.params.as_ref())?;
99                let response = self.handler.handle_tools_list(req).await?;
100                Utils::to_json_value(&response)
101            }
102            "tools/call" => {
103                let req: ToolsCallRequest = self.deserialize_params(request.params.as_ref())?;
104                let response = self.handler.handle_tools_call(req).await?;
105                Utils::to_json_value(&response)
106            }
107            "prompts/list" => {
108                let req: PromptsListRequest = self.deserialize_params(request.params.as_ref())?;
109                let response = self.handler.handle_prompts_list(req).await?;
110                Utils::to_json_value(&response)
111            }
112            "prompts/get" => {
113                let req: PromptsGetRequest = self.deserialize_params(request.params.as_ref())?;
114                let response = self.handler.handle_prompts_get(req).await?;
115                Utils::to_json_value(&response)
116            }
117            "logging/setLevel" => {
118                let req: LoggingSetLevelRequest =
119                    self.deserialize_params(request.params.as_ref())?;
120                let response = self.handler.handle_logging_set_level(req).await?;
121                Utils::to_json_value(&response)
122            }
123            "sampling/createMessage" => {
124                let req: CreateMessageRequest = self.deserialize_params(request.params.as_ref())?;
125                let response = self.handler.handle_sampling_create_message(req).await?;
126                Utils::to_json_value(&response)
127            }
128            "roots/list" => {
129                let req: RootsListRequest = self.deserialize_params(request.params.as_ref())?;
130                let response = self.handler.handle_roots_list(req).await?;
131                Utils::to_json_value(&response)
132            }
133            method => {
134                // Handle custom methods
135                let response = self
136                    .handler
137                    .handle_custom_request(method, request.params.clone())
138                    .await?;
139                Ok(response)
140            }
141        }
142    }
143
144    /// Dispatch a notification to the appropriate handler method
145    async fn dispatch_notification(&self, notification: &JsonRpcNotification) -> Result<()> {
146        match notification.method.as_str() {
147            "initialized" => {
148                let notif: InitializedNotification =
149                    self.deserialize_params(notification.params.as_ref())?;
150                self.handler.handle_initialized(notif).await
151            }
152            "notifications/progress" => {
153                let notif: ProgressNotification =
154                    self.deserialize_params(notification.params.as_ref())?;
155                self.handler.handle_progress_notification(notif).await
156            }
157            "notifications/message" => {
158                let notif: LoggingNotification =
159                    self.deserialize_params(notification.params.as_ref())?;
160                self.handler.handle_logging_notification(notif).await
161            }
162            "notifications/cancelled" => {
163                let notif: CancelledNotification =
164                    self.deserialize_params(notification.params.as_ref())?;
165                self.handler.handle_cancelled_notification(notif).await
166            }
167            "notifications/resources/updated" => {
168                let notif: ResourcesUpdatedNotification =
169                    self.deserialize_params(notification.params.as_ref())?;
170                self.handler
171                    .handle_resources_updated_notification(notif)
172                    .await
173            }
174            "notifications/tools/updated" => {
175                let notif: ToolsListChangedNotification =
176                    self.deserialize_params(notification.params.as_ref())?;
177                self.handler.handle_tools_updated_notification(notif).await
178            }
179            "notifications/prompts/updated" => {
180                let notif: PromptsListChangedNotification =
181                    self.deserialize_params(notification.params.as_ref())?;
182                self.handler
183                    .handle_prompts_updated_notification(notif)
184                    .await
185            }
186            "notifications/roots/updated" => {
187                let notif: RootsListChangedNotification =
188                    self.deserialize_params(notification.params.as_ref())?;
189                self.handler.handle_roots_updated_notification(notif).await
190            }
191            method => {
192                // Handle custom notifications
193                self.handler
194                    .handle_custom_notification(method, notification.params.clone())
195                    .await
196            }
197        }
198    }
199
200    /// Deserialize request/notification parameters
201    fn deserialize_params<T: serde::de::DeserializeOwned>(
202        &self,
203        params: Option<&serde_json::Value>,
204    ) -> Result<T> {
205        match params {
206            Some(value) => Utils::from_json_value(value.clone()),
207            None => Utils::from_json_value(serde_json::Value::Object(serde_json::Map::new())),
208        }
209    }
210}