rust_mcp_sdk/mcp_runtimes/server_runtime/
mcp_server_runtime.rs

1use std::sync::Arc;
2
3use crate::schema::{
4    schema_utils::{
5        self, CallToolError, ClientMessage, MessageFromServer, NotificationFromClient,
6        RequestFromClient, ResultFromServer,
7    },
8    CallToolResult, ClientNotification, ClientRequest, InitializeResult, RpcError,
9};
10use async_trait::async_trait;
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            schema_utils::RequestFromClient::ClientRequest(client_request) => {
81                match client_request {
82                    ClientRequest::InitializeRequest(initialize_request) => self
83                        .handler
84                        .handle_initialize_request(initialize_request, runtime)
85                        .await
86                        .map(|value| value.into()),
87                    ClientRequest::PingRequest(ping_request) => self
88                        .handler
89                        .handle_ping_request(ping_request, runtime)
90                        .await
91                        .map(|value| value.into()),
92                    ClientRequest::ListResourcesRequest(list_resources_request) => self
93                        .handler
94                        .handle_list_resources_request(list_resources_request, runtime)
95                        .await
96                        .map(|value| value.into()),
97                    ClientRequest::ListResourceTemplatesRequest(
98                        list_resource_templates_request,
99                    ) => self
100                        .handler
101                        .handle_list_resource_templates_request(
102                            list_resource_templates_request,
103                            runtime,
104                        )
105                        .await
106                        .map(|value| value.into()),
107                    ClientRequest::ReadResourceRequest(read_resource_request) => self
108                        .handler
109                        .handle_read_resource_request(read_resource_request, runtime)
110                        .await
111                        .map(|value| value.into()),
112                    ClientRequest::SubscribeRequest(subscribe_request) => self
113                        .handler
114                        .handle_subscribe_request(subscribe_request, runtime)
115                        .await
116                        .map(|value| value.into()),
117                    ClientRequest::UnsubscribeRequest(unsubscribe_request) => self
118                        .handler
119                        .handle_unsubscribe_request(unsubscribe_request, runtime)
120                        .await
121                        .map(|value| value.into()),
122                    ClientRequest::ListPromptsRequest(list_prompts_request) => self
123                        .handler
124                        .handle_list_prompts_request(list_prompts_request, runtime)
125                        .await
126                        .map(|value| value.into()),
127
128                    ClientRequest::GetPromptRequest(prompt_request) => self
129                        .handler
130                        .handle_get_prompt_request(prompt_request, runtime)
131                        .await
132                        .map(|value| value.into()),
133                    ClientRequest::ListToolsRequest(list_tools_request) => self
134                        .handler
135                        .handle_list_tools_request(list_tools_request, runtime)
136                        .await
137                        .map(|value| value.into()),
138                    ClientRequest::CallToolRequest(call_tool_request) => {
139                        let result = self
140                            .handler
141                            .handle_call_tool_request(call_tool_request, runtime)
142                            .await;
143
144                        Ok(result.map_or_else(
145                            |err| CallToolResult::with_error(CallToolError::new(err)).into(),
146                            |value| value.into(),
147                        ))
148                    }
149                    ClientRequest::SetLevelRequest(set_level_request) => self
150                        .handler
151                        .handle_set_level_request(set_level_request, runtime)
152                        .await
153                        .map(|value| value.into()),
154                    ClientRequest::CompleteRequest(complete_request) => self
155                        .handler
156                        .handle_complete_request(complete_request, runtime)
157                        .await
158                        .map(|value| value.into()),
159                }
160            }
161            schema_utils::RequestFromClient::CustomRequest(value) => self
162                .handler
163                .handle_custom_request(value, runtime)
164                .await
165                .map(|value| value.into()),
166        }
167    }
168
169    async fn handle_error(
170        &self,
171        jsonrpc_error: RpcError,
172        runtime: &dyn McpServer,
173    ) -> SdkResult<()> {
174        self.handler.handle_error(jsonrpc_error, runtime).await?;
175        Ok(())
176    }
177
178    async fn handle_notification(
179        &self,
180        client_jsonrpc_notification: NotificationFromClient,
181        runtime: &dyn McpServer,
182    ) -> SdkResult<()> {
183        match client_jsonrpc_notification {
184            schema_utils::NotificationFromClient::ClientNotification(client_notification) => {
185                match client_notification {
186                    ClientNotification::CancelledNotification(cancelled_notification) => {
187                        self.handler
188                            .handle_cancelled_notification(cancelled_notification, runtime)
189                            .await?;
190                    }
191                    ClientNotification::InitializedNotification(initialized_notification) => {
192                        self.handler
193                            .handle_initialized_notification(initialized_notification, runtime)
194                            .await?;
195                        self.handler.on_initialized(runtime).await;
196                    }
197                    ClientNotification::ProgressNotification(progress_notification) => {
198                        self.handler
199                            .handle_progress_notification(progress_notification, runtime)
200                            .await?;
201                    }
202                    ClientNotification::RootsListChangedNotification(
203                        roots_list_changed_notification,
204                    ) => {
205                        self.handler
206                            .handle_roots_list_changed_notification(
207                                roots_list_changed_notification,
208                                runtime,
209                            )
210                            .await?;
211                    }
212                }
213            }
214            schema_utils::NotificationFromClient::CustomNotification(value) => {
215                self.handler.handle_custom_notification(value).await?;
216            }
217        }
218        Ok(())
219    }
220
221    async fn on_server_started(&self, runtime: &dyn McpServer) {
222        self.handler.on_server_started(runtime).await;
223    }
224}