1use super::types::*;
9use crate::jsonrpc::{JsonRpcError, JsonRpcRequest, JsonRpcResponse};
10use serde_json::json;
11use tracing::{error, info};
12
13pub async fn handle_initialize(
15 request: JsonRpcRequest,
16 oauth_config: &OAuthConfig,
17) -> Option<JsonRpcResponse> {
18 request.id.as_ref()?;
20
21 let requested_version = request
23 .params
24 .as_ref()
25 .and_then(|params| params.get("protocolVersion").and_then(|v| v.as_str()));
26
27 let protocol_version = match requested_version {
29 Some(version) => {
30 if SUPPORTED_VERSIONS.contains(&version) {
31 version.to_string()
32 } else {
33 info!(
35 "Client requested unsupported protocol version '{}', using latest '{}'",
36 version, SUPPORTED_VERSIONS[0]
37 );
38 SUPPORTED_VERSIONS[0].to_string()
39 }
40 }
41 None => {
42 SUPPORTED_VERSIONS[0].to_string()
44 }
45 };
46
47 info!("Negotiated protocol version: {}", protocol_version);
48
49 let mut capabilities = json!({
51 "tools": {
52 "listChanged": false
53 },
54 "completions": {},
55 "elicitation": {},
56 "tasks": {
57 "list": {},
58 "create": {},
59 "update": {}
60 }
61 });
62
63 if oauth_config.enabled {
65 capabilities["authorization"] = json!({
66 "enabled": true,
67 "issuer": oauth_config.issuer.clone().unwrap_or_default(),
68 "audience": oauth_config.audience.clone().unwrap_or_default(),
69 "scopes": oauth_config.scopes
70 });
71 }
72
73 let result = InitializeResult {
74 protocol_version,
75 capabilities,
76 server_info: json!({
77 "name": "do-memory-mcp-server",
78 "version": env!("CARGO_PKG_VERSION")
79 }),
80 };
81
82 match serde_json::to_value(result) {
83 Ok(value) => Some(JsonRpcResponse {
84 jsonrpc: "2.0".to_string(),
85 id: request.id,
86 result: Some(value),
87 error: None,
88 }),
89 Err(e) => {
90 error!("Failed to serialize initialize response: {}", e);
91 Some(JsonRpcResponse {
92 jsonrpc: "2.0".to_string(),
93 id: request.id,
94 result: None,
95 error: Some(JsonRpcError {
96 code: -32603,
97 message: "Internal error".to_string(),
98 data: Some(json!({"details": format!("Response serialization failed: {}", e)})),
99 }),
100 })
101 }
102 }
103}
104
105pub async fn handle_list_tools(
107 request: JsonRpcRequest,
108 tools: Vec<McpTool>,
109) -> Option<JsonRpcResponse> {
110 request.id.as_ref()?;
112 info!("Handling tools/list request");
113
114 let result = ListToolsResult { tools };
115
116 match serde_json::to_value(result) {
117 Ok(value) => Some(JsonRpcResponse {
118 jsonrpc: "2.0".to_string(),
119 id: request.id,
120 result: Some(value),
121 error: None,
122 }),
123 Err(e) => {
124 error!("Failed to serialize list_tools response: {}", e);
125 Some(JsonRpcResponse {
126 jsonrpc: "2.0".to_string(),
127 id: request.id,
128 result: None,
129 error: Some(JsonRpcError {
130 code: -32603,
131 message: "Internal error".to_string(),
132 data: Some(json!({"details": format!("Response serialization failed: {}", e)})),
133 }),
134 })
135 }
136 }
137}
138
139pub async fn handle_shutdown(request: JsonRpcRequest) -> Option<JsonRpcResponse> {
141 request.id.as_ref()?;
143 info!("Handling shutdown request");
144
145 Some(JsonRpcResponse {
146 jsonrpc: "2.0".to_string(),
147 id: request.id,
148 result: Some(json!(null)),
149 error: None,
150 })
151}
152
153pub fn handle_list_tools_with_lazy(
168 request: JsonRpcRequest,
169 tools: Vec<crate::types::Tool>,
170) -> Option<JsonRpcResponse> {
171 request.id.as_ref()?;
173 info!("Handling tools/list request");
174
175 let lazy = request
177 .params
178 .as_ref()
179 .and_then(|p| p.get("lazy"))
180 .and_then(|v| v.as_bool())
181 .unwrap_or(false);
182
183 if lazy {
184 let tool_stubs: Vec<ToolStub> = tools
186 .into_iter()
187 .map(|tool| ToolStub {
188 name: tool.name,
189 title: None,
190 description: tool.description,
191 })
192 .collect();
193
194 let result = ListToolStubsResult { tools: tool_stubs };
195
196 match serde_json::to_value(result) {
197 Ok(value) => Some(JsonRpcResponse {
198 jsonrpc: "2.0".to_string(),
199 id: request.id,
200 result: Some(value),
201 error: None,
202 }),
203 Err(e) => {
204 error!("Failed to serialize list_tools response: {}", e);
205 Some(JsonRpcResponse {
206 jsonrpc: "2.0".to_string(),
207 id: request.id,
208 result: None,
209 error: Some(JsonRpcError {
210 code: -32603,
211 message: "Internal error".to_string(),
212 data: Some(
213 json!({"details": format!("Response serialization failed: {}", e)}),
214 ),
215 }),
216 })
217 }
218 }
219 } else {
220 let mcp_tools: Vec<McpTool> = tools
222 .into_iter()
223 .map(|tool| McpTool {
224 name: tool.name,
225 title: None,
226 description: tool.description,
227 input_schema: tool.input_schema,
228 })
229 .collect();
230
231 let result = ListToolsResult { tools: mcp_tools };
232
233 match serde_json::to_value(result) {
234 Ok(value) => Some(JsonRpcResponse {
235 jsonrpc: "2.0".to_string(),
236 id: request.id,
237 result: Some(value),
238 error: None,
239 }),
240 Err(e) => {
241 error!("Failed to serialize list_tools response: {}", e);
242 Some(JsonRpcResponse {
243 jsonrpc: "2.0".to_string(),
244 id: request.id,
245 result: None,
246 error: Some(JsonRpcError {
247 code: -32603,
248 message: "Internal error".to_string(),
249 data: Some(
250 json!({"details": format!("Response serialization failed: {}", e)}),
251 ),
252 }),
253 })
254 }
255 }
256 }
257}
258
259pub fn handle_describe_tool<F>(request: JsonRpcRequest, get_tool: F) -> Option<JsonRpcResponse>
272where
273 F: FnOnce(&str) -> Option<crate::types::Tool>,
274{
275 request.id.as_ref()?;
276 info!("Handling tools/describe request");
277
278 let tool_name = request
280 .params
281 .as_ref()
282 .and_then(|p| p.get("name"))
283 .and_then(|v| v.as_str());
284
285 let tool_name = match tool_name {
286 Some(name) => name,
287 None => {
288 return Some(JsonRpcResponse {
289 jsonrpc: "2.0".to_string(),
290 id: request.id,
291 result: None,
292 error: Some(JsonRpcError {
293 code: -32602,
294 message: "Invalid params".to_string(),
295 data: Some(json!({"details": "Missing required parameter: name"})),
296 }),
297 });
298 }
299 };
300
301 let tool = get_tool(tool_name);
302
303 match tool {
304 Some(tool) => {
305 let mcp_tool = McpTool {
306 name: tool.name,
307 title: None,
308 description: tool.description,
309 input_schema: tool.input_schema,
310 };
311
312 let result = DescribeToolResult { tool: mcp_tool };
313
314 match serde_json::to_value(result) {
315 Ok(value) => Some(JsonRpcResponse {
316 jsonrpc: "2.0".to_string(),
317 id: request.id,
318 result: Some(value),
319 error: None,
320 }),
321 Err(e) => {
322 error!("Failed to serialize describe_tool response: {}", e);
323 Some(JsonRpcResponse {
324 jsonrpc: "2.0".to_string(),
325 id: request.id,
326 result: None,
327 error: Some(JsonRpcError {
328 code: -32603,
329 message: "Internal error".to_string(),
330 data: Some(
331 json!({"details": format!("Response serialization failed: {}", e)}),
332 ),
333 }),
334 })
335 }
336 }
337 }
338 None => {
339 info!("Tool not found: {}", tool_name);
340 Some(JsonRpcResponse {
341 jsonrpc: "2.0".to_string(),
342 id: request.id,
343 result: None,
344 error: Some(JsonRpcError {
345 code: -32602,
346 message: "Tool not found".to_string(),
347 data: Some(json!({"tool_name": tool_name})),
348 }),
349 })
350 }
351 }
352}
353
354pub fn handle_describe_tools<F>(request: JsonRpcRequest, get_tool: F) -> Option<JsonRpcResponse>
367where
368 F: Fn(&str) -> Option<crate::types::Tool>,
369{
370 request.id.as_ref()?;
371 info!("Handling tools/describe_batch request");
372
373 let tool_names = request
375 .params
376 .as_ref()
377 .and_then(|p| p.get("names"))
378 .and_then(|v| v.as_array());
379
380 let tool_names = match tool_names {
381 Some(names) => names
382 .iter()
383 .filter_map(|v| v.as_str())
384 .map(String::from)
385 .collect::<Vec<_>>(),
386 None => {
387 return Some(JsonRpcResponse {
388 jsonrpc: "2.0".to_string(),
389 id: request.id,
390 result: None,
391 error: Some(JsonRpcError {
392 code: -32602,
393 message: "Invalid params".to_string(),
394 data: Some(json!({"details": "Missing required parameter: names (array)"})),
395 }),
396 });
397 }
398 };
399
400 let mut mcp_tools = Vec::new();
402 for tool_name in &tool_names {
403 if let Some(tool) = get_tool(tool_name) {
404 mcp_tools.push(McpTool {
405 name: tool.name,
406 title: None,
407 description: tool.description,
408 input_schema: tool.input_schema,
409 });
410 }
411 }
412
413 let result = DescribeToolsResult { tools: mcp_tools };
414
415 match serde_json::to_value(result) {
416 Ok(value) => Some(JsonRpcResponse {
417 jsonrpc: "2.0".to_string(),
418 id: request.id,
419 result: Some(value),
420 error: None,
421 }),
422 Err(e) => {
423 error!("Failed to serialize describe_tools response: {}", e);
424 Some(JsonRpcResponse {
425 jsonrpc: "2.0".to_string(),
426 id: request.id,
427 result: None,
428 error: Some(JsonRpcError {
429 code: -32603,
430 message: "Internal error".to_string(),
431 data: Some(json!({"details": format!("Response serialization failed: {}", e)})),
432 }),
433 })
434 }
435 }
436}