crates_docs/server/
mod.rs1pub mod auth;
6pub mod handler;
7pub mod transport;
8
9use crate::cache::Cache;
10use crate::config::AppConfig;
11use crate::error::Result;
12use crate::tools::ToolRegistry;
13use rust_mcp_sdk::schema::{
14 Implementation, InitializeResult, ProtocolVersion, ServerCapabilities, ServerCapabilitiesTools,
15};
16use std::sync::Arc;
17
18pub use crate::config::ServerConfig;
20
21#[derive(Clone)]
23pub struct CratesDocsServer {
24 config: AppConfig,
25 tool_registry: Arc<ToolRegistry>,
26 cache: Arc<dyn Cache>,
27}
28
29impl CratesDocsServer {
30 pub fn new(config: AppConfig) -> Result<Self> {
34 let cache_box: Box<dyn Cache> = crate::cache::create_cache(&config.cache)?;
35 let cache: Arc<dyn Cache> = Arc::from(cache_box);
36
37 let doc_service = Arc::new(crate::tools::docs::DocService::new(cache.clone()));
39
40 let tool_registry = Arc::new(crate::tools::create_default_registry(&doc_service));
42
43 Ok(Self {
44 config,
45 tool_registry,
46 cache,
47 })
48 }
49
50 #[allow(unused_variables)]
54 #[allow(clippy::unused_async)]
55 pub async fn new_async(config: AppConfig) -> Result<Self> {
56 #[cfg(feature = "cache-redis")]
58 {
59 let cache_box: Box<dyn Cache> = crate::cache::create_cache_async(&config.cache).await?;
60 let cache: Arc<dyn Cache> = Arc::from(cache_box);
61
62 let doc_service = Arc::new(crate::tools::docs::DocService::new(cache.clone()));
64
65 let tool_registry = Arc::new(crate::tools::create_default_registry(&doc_service));
67
68 Ok(Self {
69 config,
70 tool_registry,
71 cache,
72 })
73 }
74
75 #[cfg(not(feature = "cache-redis"))]
76 {
77 let cache_box: Box<dyn Cache> = crate::cache::create_cache(&config.cache)?;
79 let cache: Arc<dyn Cache> = Arc::from(cache_box);
80
81 let doc_service = Arc::new(crate::tools::docs::DocService::new(cache.clone()));
83
84 let tool_registry = Arc::new(crate::tools::create_default_registry(&doc_service));
86
87 Ok(Self {
88 config,
89 tool_registry,
90 cache,
91 })
92 }
93 }
94
95 #[must_use]
97 pub fn config(&self) -> &AppConfig {
98 &self.config
99 }
100
101 #[must_use]
103 pub fn tool_registry(&self) -> &Arc<ToolRegistry> {
104 &self.tool_registry
105 }
106
107 #[must_use]
109 pub fn cache(&self) -> &Arc<dyn Cache> {
110 &self.cache
111 }
112
113 #[must_use]
115 pub fn server_info(&self) -> InitializeResult {
116 InitializeResult {
117 server_info: Implementation {
118 name: self.config.server.name.clone(),
119 version: self.config.server.version.clone(),
120 title: Some("Crates Docs MCP Server".to_string()),
121 description: self.config.server.description.clone(),
122 icons: self.config.server.icons.clone(),
123 website_url: self.config.server.website_url.clone(),
124 },
125 capabilities: ServerCapabilities {
126 tools: Some(ServerCapabilitiesTools { list_changed: None }),
127 resources: None,
128 prompts: None,
129 experimental: None,
130 completions: None,
131 logging: None,
132 tasks: None,
133 },
134 protocol_version: ProtocolVersion::V2025_11_25.into(),
135 instructions: Some(
136 "Use this server to query Rust crate documentation. Supports crate lookup, crate search, and health check."
137 .to_string(),
138 ),
139 meta: None,
140 }
141 }
142
143 pub async fn run_stdio(&self) -> Result<()> {
145 transport::run_stdio_server(self).await
146 }
147
148 pub async fn run_http(&self) -> Result<()> {
150 transport::run_http_server(self).await
151 }
152
153 pub async fn run_sse(&self) -> Result<()> {
155 transport::run_sse_server(self).await
156 }
157}