rust_mcp_sdk/mcp_runtimes/server_runtime/
mcp_server_runtime.rs

1use std::sync::Arc;
2
3#[cfg(feature = "hyper-server")]
4use crate::auth::AuthInfo;
5use crate::schema::{
6    schema_utils::{
7        self, CallToolError, ClientMessage, ClientMessages, MessageFromServer,
8        NotificationFromClient, RequestFromClient, ResultFromServer, ServerMessage, ServerMessages,
9    },
10    CallToolResult, ClientNotification, ClientRequest, InitializeResult, RpcError,
11};
12use async_trait::async_trait;
13
14use rust_mcp_transport::TransportDispatcher;
15
16use super::ServerRuntime;
17#[cfg(feature = "hyper-server")]
18use rust_mcp_transport::SessionId;
19
20use crate::{
21    error::SdkResult,
22    mcp_handlers::mcp_server_handler::ServerHandler,
23    mcp_traits::{McpServer, McpServerHandler},
24};
25
26/// Creates a new MCP server runtime with the specified configuration.
27///
28/// This function initializes a server for (MCP) by accepting server details, transport ,
29/// and a handler for server-side logic.
30/// The resulting `ServerRuntime` manages the server's operation and communication with MCP clients.
31///
32/// # Arguments
33/// * `server_details` - Server name , version and capabilities.
34/// * `transport` - An implementation of the `Transport` trait facilitating communication with the MCP clients.
35/// * `handler` - An implementation of the `ServerHandler` trait that defines the server's core behavior and response logic.
36///
37/// # Returns
38/// A `ServerRuntime` instance representing the initialized server, ready for asynchronous operation.
39///
40/// # Examples
41/// You can find a detailed example of how to use this function in the repository:
42///
43/// [Repository Example](https://github.com/rust-mcp-stack/rust-mcp-sdk/tree/main/examples/hello-world-mcp-server-stdio)
44pub fn create_server(
45    server_details: InitializeResult,
46    transport: impl TransportDispatcher<
47        ClientMessages,
48        MessageFromServer,
49        ClientMessage,
50        ServerMessages,
51        ServerMessage,
52    >,
53    handler: impl ServerHandler,
54) -> Arc<ServerRuntime> {
55    ServerRuntime::new(
56        server_details,
57        transport,
58        Arc::new(ServerRuntimeInternalHandler::new(Box::new(handler))),
59    )
60}
61
62#[cfg(feature = "hyper-server")]
63pub(crate) fn create_server_instance(
64    server_details: Arc<InitializeResult>,
65    handler: Arc<dyn McpServerHandler>,
66    session_id: SessionId,
67    auth_info: Option<AuthInfo>,
68) -> Arc<ServerRuntime> {
69    ServerRuntime::new_instance(server_details, handler, session_id, auth_info)
70}
71
72pub(crate) struct ServerRuntimeInternalHandler<H> {
73    handler: H,
74}
75impl ServerRuntimeInternalHandler<Box<dyn ServerHandler>> {
76    pub fn new(handler: Box<dyn ServerHandler>) -> Self {
77        Self { handler }
78    }
79}
80
81#[async_trait]
82impl McpServerHandler for ServerRuntimeInternalHandler<Box<dyn ServerHandler>> {
83    async fn handle_request(
84        &self,
85        client_jsonrpc_request: RequestFromClient,
86        runtime: Arc<dyn McpServer>,
87    ) -> std::result::Result<ResultFromServer, RpcError> {
88        match client_jsonrpc_request {
89            schema_utils::RequestFromClient::ClientRequest(client_request) => {
90                match client_request {
91                    ClientRequest::InitializeRequest(initialize_request) => self
92                        .handler
93                        .handle_initialize_request(initialize_request, runtime)
94                        .await
95                        .map(|value| value.into()),
96                    ClientRequest::PingRequest(ping_request) => self
97                        .handler
98                        .handle_ping_request(ping_request, runtime)
99                        .await
100                        .map(|value| value.into()),
101                    ClientRequest::ListResourcesRequest(list_resources_request) => self
102                        .handler
103                        .handle_list_resources_request(list_resources_request, runtime)
104                        .await
105                        .map(|value| value.into()),
106                    ClientRequest::ListResourceTemplatesRequest(
107                        list_resource_templates_request,
108                    ) => self
109                        .handler
110                        .handle_list_resource_templates_request(
111                            list_resource_templates_request,
112                            runtime,
113                        )
114                        .await
115                        .map(|value| value.into()),
116                    ClientRequest::ReadResourceRequest(read_resource_request) => self
117                        .handler
118                        .handle_read_resource_request(read_resource_request, runtime)
119                        .await
120                        .map(|value| value.into()),
121                    ClientRequest::SubscribeRequest(subscribe_request) => self
122                        .handler
123                        .handle_subscribe_request(subscribe_request, runtime)
124                        .await
125                        .map(|value| value.into()),
126                    ClientRequest::UnsubscribeRequest(unsubscribe_request) => self
127                        .handler
128                        .handle_unsubscribe_request(unsubscribe_request, runtime)
129                        .await
130                        .map(|value| value.into()),
131                    ClientRequest::ListPromptsRequest(list_prompts_request) => self
132                        .handler
133                        .handle_list_prompts_request(list_prompts_request, runtime)
134                        .await
135                        .map(|value| value.into()),
136
137                    ClientRequest::GetPromptRequest(prompt_request) => self
138                        .handler
139                        .handle_get_prompt_request(prompt_request, runtime)
140                        .await
141                        .map(|value| value.into()),
142                    ClientRequest::ListToolsRequest(list_tools_request) => self
143                        .handler
144                        .handle_list_tools_request(list_tools_request, runtime)
145                        .await
146                        .map(|value| value.into()),
147                    ClientRequest::CallToolRequest(call_tool_request) => {
148                        let result = self
149                            .handler
150                            .handle_call_tool_request(call_tool_request, runtime)
151                            .await;
152
153                        Ok(result.map_or_else(
154                            |err| {
155                                let result: CallToolResult = CallToolError::new(err).into();
156                                result.into()
157                            },
158                            Into::into,
159                        ))
160                    }
161                    ClientRequest::SetLevelRequest(set_level_request) => self
162                        .handler
163                        .handle_set_level_request(set_level_request, runtime)
164                        .await
165                        .map(|value| value.into()),
166                    ClientRequest::CompleteRequest(complete_request) => self
167                        .handler
168                        .handle_complete_request(complete_request, runtime)
169                        .await
170                        .map(|value| value.into()),
171                }
172            }
173            schema_utils::RequestFromClient::CustomRequest(value) => self
174                .handler
175                .handle_custom_request(value, runtime)
176                .await
177                .map(|value| value.into()),
178        }
179    }
180
181    async fn handle_error(
182        &self,
183        jsonrpc_error: &RpcError,
184        runtime: Arc<dyn McpServer>,
185    ) -> SdkResult<()> {
186        self.handler.handle_error(jsonrpc_error, runtime).await?;
187        Ok(())
188    }
189
190    async fn handle_notification(
191        &self,
192        client_jsonrpc_notification: NotificationFromClient,
193        runtime: Arc<dyn McpServer>,
194    ) -> SdkResult<()> {
195        match client_jsonrpc_notification {
196            schema_utils::NotificationFromClient::ClientNotification(client_notification) => {
197                match client_notification {
198                    ClientNotification::CancelledNotification(cancelled_notification) => {
199                        self.handler
200                            .handle_cancelled_notification(cancelled_notification, runtime)
201                            .await?;
202                    }
203                    ClientNotification::InitializedNotification(initialized_notification) => {
204                        self.handler
205                            .handle_initialized_notification(
206                                initialized_notification,
207                                runtime.clone(),
208                            )
209                            .await?;
210                        self.handler.on_initialized(runtime).await;
211                    }
212                    ClientNotification::ProgressNotification(progress_notification) => {
213                        self.handler
214                            .handle_progress_notification(progress_notification, runtime)
215                            .await?;
216                    }
217                    ClientNotification::RootsListChangedNotification(
218                        roots_list_changed_notification,
219                    ) => {
220                        self.handler
221                            .handle_roots_list_changed_notification(
222                                roots_list_changed_notification,
223                                runtime,
224                            )
225                            .await?;
226                    }
227                }
228            }
229            schema_utils::NotificationFromClient::CustomNotification(value) => {
230                self.handler.handle_custom_notification(value).await?;
231            }
232        }
233        Ok(())
234    }
235}