Skip to main content

crates_docs/server/
mod.rs

1//! 服务器模块
2//!
3//! 提供 MCP 服务器实现,支持多种传输协议(stdio、HTTP、SSE、Hybrid)。
4//!
5//! # 主要组件
6//!
7//! - `CratesDocsServer`: 主服务器结构体
8//! - `handler`: MCP 请求处理
9//! - `transport`: 传输层实现
10//! - `auth`: OAuth 认证支持
11//!
12//! # Handler 设计模式
13//!
14//! 使用组合模式消除代码重复:
15//! - `HandlerCore`: 封装共享核心处理逻辑
16//! - `CratesDocsHandler`: 标准 MCP 处理器(委托给 `HandlerCore`)
17//! - `CratesDocsHandlerCore`: 核心处理器(委托给 `HandlerCore`)
18//! - `HandlerConfig`: 配置类,支持 merge 操作
19//!
20//! # 示例
21//!
22//! ```rust,no_run
23//! use crates_docs::{AppConfig, CratesDocsServer};
24//! use crates_docs::server::handler::{CratesDocsHandler, HandlerConfig};
25//! use std::sync::Arc;
26//!
27//! #[tokio::main]
28//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
29//!     let config = AppConfig::default();
30//!     let server = Arc::new(CratesDocsServer::new(config)?);
31//!     
32//!     // 使用 merge 配置创建 handler
33//!     let base_config = HandlerConfig::default();
34//!     let override_config = HandlerConfig::new().with_verbose_logging();
35//!     let handler = CratesDocsHandler::with_merged_config(
36//!         server,
37//!         base_config,
38//!         Some(override_config)
39//!     );
40//!     
41//!     // 运行 HTTP 服务器
42//!     crates_docs::server::transport::run_http_server(&handler.server()).await?;
43//!
44//!     Ok(())
45//! }
46//! ```
47
48pub mod auth;
49pub mod auth_middleware;
50pub mod handler;
51pub mod transport;
52
53use crate::cache::Cache;
54use crate::config::AppConfig;
55use crate::error::Result;
56use crate::tools::ToolRegistry;
57use rust_mcp_sdk::schema::{
58    Implementation, InitializeResult, ProtocolVersion, ServerCapabilities, ServerCapabilitiesTools,
59};
60use std::sync::Arc;
61
62/// 从配置模块重新导出 `ServerConfig` 以保持向后兼容
63pub use crate::config::ServerConfig;
64
65/// 从 handler 模块重新导出 `CratesDocsHandler`
66pub use handler::CratesDocsHandler;
67
68/// Crates Docs MCP 服务器
69///
70/// 主服务器结构体,管理配置、工具注册表和缓存。
71/// 支持多种传输协议:stdio、HTTP、SSE、Hybrid。
72///
73/// # 字段
74///
75/// - `config`: 应用配置
76/// - `tool_registry`: 工具注册表
77/// - `cache`: 缓存实例
78#[derive(Clone)]
79pub struct CratesDocsServer {
80    config: AppConfig,
81    tool_registry: Arc<ToolRegistry>,
82    cache: Arc<dyn Cache>,
83}
84
85impl CratesDocsServer {
86    /// 从组件创建服务器(内部初始化逻辑)
87    ///
88    /// # 参数
89    ///
90    /// * `config` - 应用配置
91    /// * `cache` - 缓存实例
92    ///
93    /// # 错误
94    ///
95    /// 如果文档服务创建失败,返回错误
96    fn from_parts(config: AppConfig, cache: Arc<dyn Cache>) -> crate::error::Result<Self> {
97        // Initialize global HTTP client with performance config for connection pool reuse
98        // This ensures all HTTP requests share the same connection pool
99        // Note: init_global_http_client will fail if already initialized, which is fine
100        let _ = crate::utils::init_global_http_client(&config.performance);
101
102        // Create document service with cache configuration
103        let doc_service = Arc::new(crate::tools::docs::DocService::with_config(
104            cache.clone(),
105            &config.cache,
106        )?);
107
108        // Create tool registry
109        let tool_registry = Arc::new(crate::tools::create_default_registry(&doc_service));
110
111        Ok(Self {
112            config,
113            tool_registry,
114            cache,
115        })
116    }
117
118    /// 创建新的服务器实例(同步)
119    ///
120    /// # 参数
121    ///
122    /// * `config` - 应用配置
123    ///
124    /// # 错误
125    ///
126    /// 如果缓存创建失败,返回错误
127    ///
128    /// # 注意
129    ///
130    /// 此方法仅支持内存缓存。如需使用 Redis,请使用 [`new_async`](Self::new_async) 方法。
131    ///
132    /// # 示例
133    ///
134    /// ```rust,no_run
135    /// use crates_docs::{AppConfig, CratesDocsServer};
136    ///
137    /// let config = AppConfig::default();
138    /// let server = CratesDocsServer::new(config).expect("Failed to create server");
139    /// ```
140    pub fn new(config: AppConfig) -> Result<Self> {
141        let cache_box: Box<dyn Cache> = crate::cache::create_cache(&config.cache)?;
142        let cache: Arc<dyn Cache> = Arc::from(cache_box);
143        Self::from_parts(config, cache)
144    }
145
146    /// 创建新的服务器实例(异步)
147    ///
148    /// # 参数
149    ///
150    /// * `config` - 应用配置
151    ///
152    /// # 错误
153    ///
154    /// 如果缓存创建失败,返回错误
155    ///
156    /// # 注意
157    ///
158    /// 支持内存缓存和 Redis 缓存(需要启用 `cache-redis` feature)。
159    ///
160    /// # 示例
161    ///
162    /// ```rust,no_run
163    /// use crates_docs::{AppConfig, CratesDocsServer};
164    ///
165    /// #[tokio::main]
166    /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
167    ///     let config = AppConfig::default();
168    ///     let server = CratesDocsServer::new_async(config).await?;
169    ///     Ok(())
170    /// }
171    /// ```
172    #[allow(unused_variables)]
173    #[allow(clippy::unused_async)]
174    pub async fn new_async(config: AppConfig) -> Result<Self> {
175        // Decide which creation method to use based on cache type and feature
176        #[cfg(feature = "cache-redis")]
177        {
178            let cache_box: Box<dyn Cache> = crate::cache::create_cache_async(&config.cache).await?;
179            let cache: Arc<dyn Cache> = Arc::from(cache_box);
180            Self::from_parts(config, cache)
181        }
182
183        #[cfg(not(feature = "cache-redis"))]
184        {
185            // No cache-redis feature, fall back to synchronous creation
186            let cache_box: Box<dyn Cache> = crate::cache::create_cache(&config.cache)?;
187            let cache: Arc<dyn Cache> = Arc::from(cache_box);
188            Self::from_parts(config, cache)
189        }
190    }
191
192    /// 获取服务器配置
193    #[must_use]
194    pub fn config(&self) -> &AppConfig {
195        &self.config
196    }
197
198    /// 获取工具注册表
199    #[must_use]
200    pub fn tool_registry(&self) -> &Arc<ToolRegistry> {
201        &self.tool_registry
202    }
203
204    /// 获取缓存实例
205    #[must_use]
206    pub fn cache(&self) -> &Arc<dyn Cache> {
207        &self.cache
208    }
209
210    /// 获取服务器信息
211    ///
212    /// 返回 MCP 初始化结果,包含服务器元数据和能力信息
213    #[must_use]
214    pub fn server_info(&self) -> InitializeResult {
215        InitializeResult {
216            server_info: Implementation {
217                name: self.config.server.name.clone(),
218                version: self.config.server.version.clone(),
219                title: Some("Crates Docs MCP Server".to_string()),
220                description: self.config.server.description.clone(),
221                icons: self.config.server.icons.clone(),
222                website_url: self.config.server.website_url.clone(),
223            },
224            capabilities: ServerCapabilities {
225                tools: Some(ServerCapabilitiesTools { list_changed: None }),
226                resources: None,
227                prompts: None,
228                experimental: None,
229                completions: None,
230                logging: None,
231                tasks: None,
232            },
233            protocol_version: ProtocolVersion::V2025_11_25.into(),
234            instructions: Some(
235                "Use this server to query Rust crate documentation. Supports crate lookup, crate search, and health check."
236                    .to_string(),
237            ),
238            meta: None,
239        }
240    }
241
242    /// 运行 Stdio 服务器
243    ///
244    /// # 错误
245    ///
246    /// 如果服务器启动失败,返回错误
247    pub async fn run_stdio(&self) -> Result<()> {
248        transport::run_stdio_server(self).await
249    }
250
251    /// 运行 HTTP 服务器
252    ///
253    /// # 错误
254    ///
255    /// 如果服务器启动失败,返回错误
256    pub async fn run_http(&self) -> Result<()> {
257        transport::run_http_server(self).await
258    }
259
260    /// 运行 SSE 服务器
261    ///
262    /// # 错误
263    ///
264    /// 如果服务器启动失败,返回错误
265    pub async fn run_sse(&self) -> Result<()> {
266        transport::run_sse_server(self).await
267    }
268}