Skip to main content

crates_docs/server/
transport.rs

1//! 传输模块
2//!
3//! 提供 Stdio、HTTP 和 SSE 传输协议支持。
4//!
5//! # 支持的传输模式
6//!
7//! - **Stdio**: 标准输入输出,适合与 MCP 客户端集成
8//! - **HTTP**: Streamable HTTP,支持无状态请求
9//! - **SSE**: Server-Sent Events,支持服务器推送
10//! - **Hybrid**: 混合模式,同时支持 HTTP 和 SSE
11//!
12//! # 示例
13//!
14//! ```rust,no_run
15//! use crates_docs::server::transport::{run_stdio_server, TransportMode};
16//! use crates_docs::{AppConfig, CratesDocsServer};
17//!
18//! #[tokio::main]
19//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
20//!     let config = AppConfig::default();
21//!     let server = CratesDocsServer::new(config)?;
22//!
23//!     // 运行 Stdio 服务器
24//!     run_stdio_server(&server).await?;
25//!
26//!     Ok(())
27//! }
28//! ```
29
30use crate::error::Result;
31use crate::server::handler::CratesDocsHandler;
32use crate::server::CratesDocsServer;
33use rust_mcp_sdk::{
34    error::McpSdkError,
35    event_store,
36    mcp_server::{hyper_server, server_runtime, HyperServerOptions, McpServerOptions},
37    McpServer, StdioTransport, ToMcpServerHandler, TransportOptions,
38};
39use std::sync::Arc;
40
41/// 运行 Stdio 服务器
42///
43/// 通过标准输入输出与 MCP 客户端通信。
44///
45/// # 参数
46///
47/// * `server` - `CratesDocsServer` 实例
48///
49/// # 错误
50///
51/// 如果服务器启动失败,返回错误
52///
53/// # 示例
54///
55/// ```rust,no_run
56/// use crates_docs::server::transport::run_stdio_server;
57/// use crates_docs::{AppConfig, CratesDocsServer};
58///
59/// #[tokio::main]
60/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
61///     let config = AppConfig::default();
62///     let server = CratesDocsServer::new(config)?;
63///     run_stdio_server(&server).await?;
64///     Ok(())
65/// }
66/// ```
67pub async fn run_stdio_server(server: &CratesDocsServer) -> Result<()> {
68    tracing::info!("Starting Stdio MCP server...");
69
70    let server_info = server.server_info();
71    let handler = CratesDocsHandler::new(Arc::new(server.clone()));
72
73    // Create Stdio transport
74    let transport = StdioTransport::new(TransportOptions::default())
75        .map_err(|e| crate::error::Error::mcp("transport", e.to_string()))?;
76
77    // Create MCP server
78    let mcp_server: Arc<rust_mcp_sdk::mcp_server::ServerRuntime> =
79        server_runtime::create_server(McpServerOptions {
80            server_details: server_info,
81            transport,
82            handler: handler.to_mcp_server_handler(),
83            task_store: None,
84            client_task_store: None,
85            message_observer: None,
86        });
87
88    tracing::info!("Stdio MCP server started, waiting for connections...");
89    mcp_server
90        .start()
91        .await
92        .map_err(|e: McpSdkError| crate::error::Error::mcp("server_start", e.to_string()))?;
93
94    Ok(())
95}
96
97/// 运行 HTTP 服务器(Streamable HTTP)
98///
99/// 启动支持 Streamable HTTP 协议的 MCP 服务器。
100///
101/// # 参数
102///
103/// * `server` - `CratesDocsServer` 实例
104///
105/// # 错误
106///
107/// 如果服务器启动失败,返回错误
108///
109/// # 示例
110///
111/// ```rust,no_run
112/// use crates_docs::server::transport::run_http_server;
113/// use crates_docs::{AppConfig, CratesDocsServer};
114///
115/// #[tokio::main]
116/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
117///     let config = AppConfig::default();
118///     let server = CratesDocsServer::new(config)?;
119///     run_http_server(&server).await?;
120///     Ok(())
121/// }
122/// ```
123pub async fn run_http_server(server: &CratesDocsServer) -> Result<()> {
124    let config = server.config();
125    tracing::info!(
126        "Starting HTTP MCP server on {}:{}...",
127        config.server.host,
128        config.server.port
129    );
130
131    let server_info = server.server_info();
132    let handler = CratesDocsHandler::new(Arc::new(server.clone()));
133
134    // Create Hyper server options with security settings from config
135    let options = HyperServerOptions {
136        host: config.server.host.clone(),
137        port: config.server.port,
138        transport_options: Arc::new(TransportOptions::default()),
139        sse_support: false, // Pure HTTP mode
140        event_store: Some(Arc::new(event_store::InMemoryEventStore::default())),
141        task_store: None,
142        client_task_store: None,
143        allowed_hosts: Some(config.server.allowed_hosts.clone()),
144        allowed_origins: Some(config.server.allowed_origins.clone()),
145        health_endpoint: Some("/health".to_string()),
146        ..Default::default()
147    };
148
149    // Create HTTP server
150    let mcp_server =
151        hyper_server::create_server(server_info, handler.to_mcp_server_handler(), options);
152
153    tracing::info!(
154        "HTTP MCP server started, listening on {}:{}",
155        config.server.host,
156        config.server.port
157    );
158    mcp_server
159        .start()
160        .await
161        .map_err(|e: McpSdkError| crate::error::Error::mcp("server_start", e.to_string()))?;
162
163    Ok(())
164}
165
166/// 运行 SSE 服务器(Server-Sent Events)
167///
168/// 启动支持 Server-Sent Events 协议的 MCP 服务器。
169///
170/// # 参数
171///
172/// * `server` - `CratesDocsServer` 实例
173///
174/// # 错误
175///
176/// 如果服务器启动失败,返回错误
177///
178/// # 示例
179///
180/// ```rust,no_run
181/// use crates_docs::server::transport::run_sse_server;
182/// use crates_docs::{AppConfig, CratesDocsServer};
183///
184/// #[tokio::main]
185/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
186///     let config = AppConfig::default();
187///     let server = CratesDocsServer::new(config)?;
188///     run_sse_server(&server).await?;
189///     Ok(())
190/// }
191/// ```
192pub async fn run_sse_server(server: &CratesDocsServer) -> Result<()> {
193    let config = server.config();
194    tracing::info!(
195        "Starting SSE MCP server on {}:{}...",
196        config.server.host,
197        config.server.port
198    );
199
200    let server_info = server.server_info();
201    let handler = CratesDocsHandler::new(Arc::new(server.clone()));
202
203    // Create Hyper server options with SSE support and security settings from config
204    let options = HyperServerOptions {
205        host: config.server.host.clone(),
206        port: config.server.port,
207        transport_options: Arc::new(TransportOptions::default()),
208        sse_support: true, // Enable SSE support
209        event_store: Some(Arc::new(event_store::InMemoryEventStore::default())),
210        task_store: None,
211        client_task_store: None,
212        allowed_hosts: Some(config.server.allowed_hosts.clone()),
213        allowed_origins: Some(config.server.allowed_origins.clone()),
214        health_endpoint: Some("/health".to_string()),
215        ..Default::default()
216    };
217
218    // Create SSE server
219    let mcp_server =
220        hyper_server::create_server(server_info, handler.to_mcp_server_handler(), options);
221
222    tracing::info!(
223        "SSE MCP server started, listening on {}:{}",
224        config.server.host,
225        config.server.port
226    );
227    mcp_server
228        .start()
229        .await
230        .map_err(|e: McpSdkError| crate::error::Error::mcp("server_start", e.to_string()))?;
231
232    Ok(())
233}
234
235/// 运行混合服务器(同时支持 HTTP 和 SSE)
236///
237/// 启动同时支持 HTTP 和 SSE 协议的 MCP 服务器。
238///
239/// # 参数
240///
241/// * `server` - `CratesDocsServer` 实例
242///
243/// # 错误
244///
245/// 如果服务器启动失败,返回错误
246///
247/// # 示例
248///
249/// ```rust,no_run
250/// use crates_docs::server::transport::run_hybrid_server;
251/// use crates_docs::{AppConfig, CratesDocsServer};
252///
253/// #[tokio::main]
254/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
255///     let config = AppConfig::default();
256///     let server = CratesDocsServer::new(config)?;
257///     run_hybrid_server(&server).await?;
258///     Ok(())
259/// }
260/// ```
261pub async fn run_hybrid_server(server: &CratesDocsServer) -> Result<()> {
262    let config = server.config();
263    tracing::info!(
264        "Starting hybrid MCP server on {}:{}...",
265        config.server.host,
266        config.server.port
267    );
268
269    let server_info = server.server_info();
270    let handler = CratesDocsHandler::new(Arc::new(server.clone()));
271
272    // Create Hyper server options with SSE support and security settings from config
273    let options = HyperServerOptions {
274        host: config.server.host.clone(),
275        port: config.server.port,
276        transport_options: Arc::new(TransportOptions::default()),
277        sse_support: true, // Enable SSE support
278        event_store: Some(Arc::new(event_store::InMemoryEventStore::default())),
279        task_store: None,
280        client_task_store: None,
281        allowed_hosts: Some(config.server.allowed_hosts.clone()),
282        allowed_origins: Some(config.server.allowed_origins.clone()),
283        health_endpoint: Some("/health".to_string()),
284        ..Default::default()
285    };
286
287    // Create hybrid server (HTTP + SSE)
288    let mcp_server =
289        hyper_server::create_server(server_info, handler.to_mcp_server_handler(), options);
290
291    tracing::info!(
292        "Hybrid MCP server started, listening on {}:{} (HTTP + SSE)",
293        config.server.host,
294        config.server.port
295    );
296    mcp_server
297        .start()
298        .await
299        .map_err(|e: McpSdkError| crate::error::Error::mcp("server_start", e.to_string()))?;
300
301    Ok(())
302}
303
304/// 传输模式
305///
306/// 定义 MCP 服务器支持的传输协议类型。
307///
308/// # 变体
309///
310/// - `Stdio`: 标准输入输出,适合与 MCP 客户端集成
311/// - `Http`: Streamable HTTP,支持无状态请求
312/// - `Sse`: Server-Sent Events,支持服务器推送
313/// - `Hybrid`: 混合模式,同时支持 HTTP 和 SSE
314///
315/// # 示例
316///
317/// ```rust
318/// use crates_docs::server::transport::TransportMode;
319/// use std::str::FromStr;
320///
321/// let mode = TransportMode::from_str("http").unwrap();
322/// assert_eq!(mode, TransportMode::Http);
323/// assert_eq!(mode.to_string(), "http");
324/// ```
325#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
326pub enum TransportMode {
327    /// Stdio 传输(用于 CLI 集成)
328    Stdio,
329    /// HTTP 传输(Streamable HTTP)
330    Http,
331    /// SSE 传输(Server-Sent Events)
332    Sse,
333    /// 混合模式(同时支持 HTTP 和 SSE)
334    Hybrid,
335}
336
337impl std::str::FromStr for TransportMode {
338    type Err = String;
339
340    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
341        match s.to_lowercase().as_str() {
342            "stdio" => Ok(TransportMode::Stdio),
343            "http" => Ok(TransportMode::Http),
344            "sse" => Ok(TransportMode::Sse),
345            "hybrid" => Ok(TransportMode::Hybrid),
346            _ => Err(format!("Unknown transport mode: {s}")),
347        }
348    }
349}
350
351impl std::fmt::Display for TransportMode {
352    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
353        match self {
354            TransportMode::Stdio => write!(f, "stdio"),
355            TransportMode::Http => write!(f, "http"),
356            TransportMode::Sse => write!(f, "sse"),
357            TransportMode::Hybrid => write!(f, "hybrid"),
358        }
359    }
360}
361
362/// Run server with the specified transport mode
363pub async fn run_server_with_mode(server: &CratesDocsServer, mode: TransportMode) -> Result<()> {
364    match mode {
365        TransportMode::Stdio => run_stdio_server(server).await,
366        TransportMode::Http => run_http_server(server).await,
367        TransportMode::Sse => run_sse_server(server).await,
368        TransportMode::Hybrid => run_hybrid_server(server).await,
369    }
370}