turbomcp_server/routing/
bidirectional.rs

1//! Server-initiated request handling (bidirectional communication)
2
3use turbomcp_protocol::RequestContext;
4use turbomcp_protocol::types::{
5    CreateMessageRequest, ElicitRequest, ElicitResult, ListRootsResult, PingRequest, PingResult,
6};
7
8use crate::{ServerError, ServerResult};
9
10use super::traits::ServerRequestDispatcher;
11
12/// Bidirectional communication methods for server-initiated requests
13pub struct BidirectionalRouter {
14    dispatcher: Option<std::sync::Arc<dyn ServerRequestDispatcher>>,
15}
16
17impl std::fmt::Debug for BidirectionalRouter {
18    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19        f.debug_struct("BidirectionalRouter")
20            .field("has_dispatcher", &self.dispatcher.is_some())
21            .finish()
22    }
23}
24
25impl BidirectionalRouter {
26    /// Create a new bidirectional router
27    pub fn new() -> Self {
28        Self { dispatcher: None }
29    }
30
31    /// Set the server request dispatcher
32    pub fn set_dispatcher<D>(&mut self, dispatcher: D)
33    where
34        D: ServerRequestDispatcher + 'static,
35    {
36        self.dispatcher = Some(std::sync::Arc::new(dispatcher));
37    }
38
39    /// Get the server request dispatcher
40    pub fn get_dispatcher(&self) -> Option<&std::sync::Arc<dyn ServerRequestDispatcher>> {
41        self.dispatcher.as_ref()
42    }
43
44    /// Check if bidirectional communication is supported
45    pub fn supports_bidirectional(&self) -> bool {
46        self.dispatcher.is_some()
47    }
48
49    /// Send an elicitation request to the client (server-initiated)
50    pub async fn send_elicitation_to_client(
51        &self,
52        request: ElicitRequest,
53        ctx: RequestContext,
54    ) -> ServerResult<ElicitResult> {
55        if let Some(dispatcher) = &self.dispatcher {
56            dispatcher.send_elicitation(request, ctx).await
57        } else {
58            Err(ServerError::Handler {
59                message: "Server request dispatcher not configured for bidirectional communication"
60                    .to_string(),
61                context: Some("elicitation".to_string()),
62            })
63        }
64    }
65
66    /// Send a ping request to the client (server-initiated)
67    pub async fn send_ping_to_client(
68        &self,
69        request: PingRequest,
70        ctx: RequestContext,
71    ) -> ServerResult<PingResult> {
72        if let Some(dispatcher) = &self.dispatcher {
73            dispatcher.send_ping(request, ctx).await
74        } else {
75            Err(ServerError::Handler {
76                message: "Server request dispatcher not configured for bidirectional communication"
77                    .to_string(),
78                context: Some("ping".to_string()),
79            })
80        }
81    }
82
83    /// Send a create message request to the client (server-initiated)
84    pub async fn send_create_message_to_client(
85        &self,
86        request: CreateMessageRequest,
87        ctx: RequestContext,
88    ) -> ServerResult<turbomcp_protocol::types::CreateMessageResult> {
89        if let Some(dispatcher) = &self.dispatcher {
90            dispatcher.send_create_message(request, ctx).await
91        } else {
92            Err(ServerError::Handler {
93                message: "Server request dispatcher not configured for bidirectional communication"
94                    .to_string(),
95                context: Some("create_message".to_string()),
96            })
97        }
98    }
99
100    /// Send a list roots request to the client (server-initiated)
101    pub async fn send_list_roots_to_client(
102        &self,
103        request: turbomcp_protocol::types::ListRootsRequest,
104        ctx: RequestContext,
105    ) -> ServerResult<ListRootsResult> {
106        if let Some(dispatcher) = &self.dispatcher {
107            dispatcher.send_list_roots(request, ctx).await
108        } else {
109            Err(ServerError::Handler {
110                message: "Server request dispatcher not configured for bidirectional communication"
111                    .to_string(),
112                context: Some("list_roots".to_string()),
113            })
114        }
115    }
116}
117
118impl Default for BidirectionalRouter {
119    fn default() -> Self {
120        Self::new()
121    }
122}
123
124impl Clone for BidirectionalRouter {
125    fn clone(&self) -> Self {
126        Self {
127            dispatcher: self.dispatcher.clone(),
128        }
129    }
130}