rust_mcp_sdk/mcp_runtimes/server_runtime/
mcp_server_runtime.rs

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