crates_docs/server/
handler.rs1use crate::server::CratesDocsServer;
4use crate::tools::ToolRegistry;
5use async_trait::async_trait;
6use rust_mcp_sdk::{
7 mcp_server::{ServerHandler, ServerHandlerCore},
8 schema::{
9 CallToolError, CallToolRequestParams, CallToolResult, GetPromptRequestParams,
10 GetPromptResult, ListPromptsResult, ListResourcesResult, ListToolsResult,
11 NotificationFromClient, PaginatedRequestParams, ReadResourceRequestParams,
12 ReadResourceResult, RequestFromClient, ResultFromServer, RpcError,
13 },
14 McpServer,
15};
16use std::sync::Arc;
17
18pub struct CratesDocsHandler {
20 server: Arc<CratesDocsServer>,
21}
22
23impl CratesDocsHandler {
24 #[must_use]
26 pub fn new(server: Arc<CratesDocsServer>) -> Self {
27 Self { server }
28 }
29
30 fn tool_registry(&self) -> &ToolRegistry {
32 self.server.tool_registry()
33 }
34}
35
36#[async_trait]
37impl ServerHandler for CratesDocsHandler {
38 async fn handle_list_tools_request(
40 &self,
41 _request: Option<PaginatedRequestParams>,
42 _runtime: std::sync::Arc<dyn McpServer>,
43 ) -> std::result::Result<ListToolsResult, RpcError> {
44 let tools = self.tool_registry().get_tools();
45
46 Ok(ListToolsResult {
47 tools,
48 meta: None,
49 next_cursor: None,
50 })
51 }
52
53 async fn handle_call_tool_request(
55 &self,
56 params: CallToolRequestParams,
57 _runtime: std::sync::Arc<dyn McpServer>,
58 ) -> std::result::Result<CallToolResult, CallToolError> {
59 self.tool_registry()
60 .execute_tool(
61 ¶ms.name,
62 params
63 .arguments
64 .map_or_else(|| serde_json::Value::Null, serde_json::Value::Object),
65 )
66 .await
67 }
68
69 async fn handle_list_resources_request(
71 &self,
72 _request: Option<PaginatedRequestParams>,
73 _runtime: std::sync::Arc<dyn McpServer>,
74 ) -> std::result::Result<ListResourcesResult, RpcError> {
75 Ok(ListResourcesResult {
77 resources: vec![],
78 meta: None,
79 next_cursor: None,
80 })
81 }
82
83 async fn handle_read_resource_request(
85 &self,
86 _params: ReadResourceRequestParams,
87 _runtime: std::sync::Arc<dyn McpServer>,
88 ) -> std::result::Result<ReadResourceResult, RpcError> {
89 Err(RpcError::invalid_request().with_message("Resource not found".to_string()))
91 }
92
93 async fn handle_list_prompts_request(
95 &self,
96 _request: Option<PaginatedRequestParams>,
97 _runtime: std::sync::Arc<dyn McpServer>,
98 ) -> std::result::Result<ListPromptsResult, RpcError> {
99 Ok(ListPromptsResult {
101 prompts: vec![],
102 meta: None,
103 next_cursor: None,
104 })
105 }
106
107 async fn handle_get_prompt_request(
109 &self,
110 _params: GetPromptRequestParams,
111 _runtime: std::sync::Arc<dyn McpServer>,
112 ) -> std::result::Result<GetPromptResult, RpcError> {
113 Err(RpcError::invalid_request().with_message("Prompt not found".to_string()))
115 }
116}
117
118pub struct CratesDocsHandlerCore {
120 server: Arc<CratesDocsServer>,
121}
122
123impl CratesDocsHandlerCore {
124 #[must_use]
126 pub fn new(server: Arc<CratesDocsServer>) -> Self {
127 Self { server }
128 }
129}
130
131#[async_trait]
132impl ServerHandlerCore for CratesDocsHandlerCore {
133 async fn handle_request(
135 &self,
136 request: RequestFromClient,
137 _runtime: std::sync::Arc<dyn McpServer>,
138 ) -> std::result::Result<ResultFromServer, RpcError> {
139 match request {
140 RequestFromClient::ListToolsRequest(_params) => {
141 let tools = self.server.tool_registry().get_tools();
142 Ok(ListToolsResult {
143 tools,
144 meta: None,
145 next_cursor: None,
146 }
147 .into())
148 }
149 RequestFromClient::CallToolRequest(params) => {
150 let result = self
151 .server
152 .tool_registry()
153 .execute_tool(
154 ¶ms.name,
155 params
156 .arguments
157 .map_or_else(|| serde_json::Value::Null, serde_json::Value::Object),
158 )
159 .await
160 .map_err(|_e| CallToolError::unknown_tool(params.name.clone()))?;
161 Ok(result.into())
162 }
163 RequestFromClient::ListResourcesRequest(_params) => Ok(ListResourcesResult {
164 resources: vec![],
165 meta: None,
166 next_cursor: None,
167 }
168 .into()),
169 RequestFromClient::ReadResourceRequest(_params) => {
170 Err(RpcError::invalid_request().with_message("Resource not found".to_string()))
171 }
172 RequestFromClient::ListPromptsRequest(_params) => Ok(ListPromptsResult {
173 prompts: vec![],
174 meta: None,
175 next_cursor: None,
176 }
177 .into()),
178 RequestFromClient::GetPromptRequest(_params) => {
179 Err(RpcError::invalid_request().with_message("Prompt not found".to_string()))
180 }
181 RequestFromClient::InitializeRequest(_params) => {
182 Err(RpcError::method_not_found()
184 .with_message("Initialize request should be handled by runtime".to_string()))
185 }
186 _ => {
187 Err(RpcError::method_not_found()
189 .with_message("Unimplemented request type".to_string()))
190 }
191 }
192 }
193
194 async fn handle_notification(
196 &self,
197 _notification: NotificationFromClient,
198 _runtime: std::sync::Arc<dyn McpServer>,
199 ) -> std::result::Result<(), RpcError> {
200 Ok(())
202 }
203
204 async fn handle_error(
206 &self,
207 _error: &RpcError,
208 _runtime: std::sync::Arc<dyn McpServer>,
209 ) -> std::result::Result<(), RpcError> {
210 tracing::error!("MCP error: {:?}", _error);
212 Ok(())
213 }
214}