Skip to main content

rust_mcp_actix/
server.rs

1use crate::options::ActixServerOptions;
2use crate::ActixRuntime;
3use rust_mcp_sdk::mcp_http::middleware::AuthMiddleware;
4use rust_mcp_sdk::mcp_http::{resolve_dns_middleware, Middleware};
5use rust_mcp_sdk::{
6    error::SdkResult,
7    id_generator::{FastIdGenerator, UuidGenerator},
8    mcp_http::McpAppState,
9    mcp_http::McpHttpHandler,
10    mcp_server::McpServerHandler,
11    schema::InitializeResult,
12    session_store::InMemorySessionStore,
13};
14use std::sync::Arc;
15
16/// Turnkey Actix MCP server.
17///
18/// Created via [`create_actix_server()`](crate::create_actix_server) and started
19/// with `.start()` or `.start_runtime()`.
20pub struct ActixServer {
21    pub(crate) state: Arc<McpAppState>,
22    pub(crate) handler: Arc<McpHttpHandler>,
23    pub(crate) options: ActixServerOptions,
24}
25
26impl ActixServer {
27    /// Creates a new `ActixServer` instance.
28    pub fn new(
29        server_details: InitializeResult,
30        handler: Arc<dyn McpServerHandler + 'static>,
31        mut server_options: ActixServerOptions,
32    ) -> Self {
33        let state: Arc<McpAppState> = Arc::new(McpAppState {
34            session_store: server_options
35                .session_store
36                .take()
37                .unwrap_or_else(|| Arc::new(InMemorySessionStore::default())),
38            id_generator: server_options
39                .session_id_generator
40                .take()
41                .map_or(Arc::new(UuidGenerator {}), |g| Arc::clone(&g)),
42            stream_id_gen: Arc::new(FastIdGenerator::new(Some("s_"))),
43            server_details: Arc::new(server_details),
44            handler,
45            ping_interval: server_options.ping_interval,
46            transport_options: Arc::clone(&server_options.transport_options),
47            enable_json_response: server_options.enable_json_response.unwrap_or(false),
48            event_store: server_options.event_store.as_ref().map(Arc::clone),
49            task_store: server_options.task_store.take(),
50            client_task_store: server_options.client_task_store.take(),
51            message_observer: server_options.message_observer.take(),
52        });
53
54        let mut middlewares: Vec<Arc<dyn Middleware>> = vec![];
55
56        if let Some(dns) = resolve_dns_middleware(
57            &mut server_options.dns_rebinding,
58            &server_options.host,
59            server_options.port,
60        ) {
61            middlewares.push(Arc::new(dns));
62        }
63
64        if let Some(auth_provider) = server_options.auth.take() {
65            middlewares.push(Arc::new(AuthMiddleware::new(auth_provider)));
66        }
67
68        let http_handler = Arc::new(McpHttpHandler::new(
69            None,
70            middlewares,
71            server_options.health_handler.clone(),
72        ));
73
74        ActixServer {
75            state,
76            handler: http_handler,
77            options: server_options,
78        }
79    }
80
81    /// Returns a shared reference to the application state.
82    pub fn state(&self) -> Arc<McpAppState> {
83        self.state.clone()
84    }
85
86    /// Returns the server configuration.
87    pub fn options(&self) -> &ActixServerOptions {
88        &self.options
89    }
90
91    /// Generates the server info string for startup logging.
92    pub fn server_info(&self, addr: Option<std::net::SocketAddr>) -> Result<String, String> {
93        let addr = addr.unwrap_or(self.options.resolve_server_address()?);
94        let mut info = format!(
95            "\n  Streamable HTTP Server is available at http://{}{}",
96            addr,
97            self.options.streamable_http_endpoint()
98        );
99        if self.options.sse_support {
100            info.push_str(&format!(
101                "\n  SSE Server is available at http://{}{}",
102                addr,
103                self.options.sse_endpoint()
104            ));
105        }
106        Ok(info)
107    }
108
109    /// Starts the server and blocks until shutdown.
110    pub async fn start(self) -> SdkResult<()> {
111        let runtime = ActixRuntime::create(self).await?;
112        runtime.await_server().await
113    }
114
115    /// Starts the server and returns a runtime handle.
116    pub async fn start_runtime(self) -> SdkResult<ActixRuntime> {
117        ActixRuntime::create(self).await
118    }
119}