gamecode_mcp2/
handlers.rs1use anyhow::Result;
5use serde_json::Value;
6use std::collections::HashMap;
7use tracing::{debug, error, info};
8
9use crate::protocol::*;
10use crate::tools::ToolManager;
11
12pub struct RequestHandler {
13 tool_manager: ToolManager,
14 injected_values: HashMap<String, String>,
15}
16
17impl RequestHandler {
18 pub fn new(tool_manager: ToolManager, injected_values: HashMap<String, String>) -> Self {
19 Self { tool_manager, injected_values }
20 }
21
22 pub async fn handle_request(&self, request: JsonRpcRequest) -> JsonRpcResponse {
24 debug!("Handling request: {} (id: {})", request.method, request.id);
25
26 let result = match request.method.as_str() {
27 "initialize" => self.handle_initialize(request.params).await,
28 "tools/list" => self.handle_tools_list().await,
29 "tools/call" => self.handle_tools_call(request.params).await,
30 _ => Err(JsonRpcError {
31 code: METHOD_NOT_FOUND,
32 message: format!("Method '{}' not found", request.method),
33 data: None,
34 }),
35 };
36
37 match result {
38 Ok(value) => JsonRpcResponse {
39 jsonrpc: "2.0".to_string(),
40 id: request.id,
41 result: Some(value),
42 error: None,
43 },
44 Err(error) => JsonRpcResponse {
45 jsonrpc: "2.0".to_string(),
46 id: request.id,
47 result: None,
48 error: Some(error),
49 },
50 }
51 }
52
53 pub async fn handle_notification(&self, notification: JsonRpcNotification) {
54 debug!("Handling notification: {}", notification.method);
55
56 match notification.method.as_str() {
57 "notifications/initialized" => {
58 info!("Client initialized");
59 }
60 "notifications/cancelled" => {
61 info!("Request cancelled");
62 }
63 _ => {
64 debug!("Unknown notification: {}", notification.method);
65 }
66 }
67 }
68
69 async fn handle_initialize(&self, params: Option<Value>) -> Result<Value, JsonRpcError> {
71 let _params: InitializeParams = if let Some(p) = params {
72 serde_json::from_value(p).map_err(|e| JsonRpcError {
73 code: INVALID_PARAMS,
74 message: format!("Invalid initialize params: {}", e),
75 data: None,
76 })?
77 } else {
78 return Err(JsonRpcError {
79 code: INVALID_PARAMS,
80 message: "Missing initialize params".to_string(),
81 data: None,
82 });
83 };
84
85 let result = InitializeResult {
86 protocol_version: "2024-11-05".to_string(),
87 capabilities: ServerCapabilities {
88 tools: ToolsCapability {},
89 },
90 server_info: ServerInfo {
91 name: "gamecode-mcp2".to_string(),
92 version: env!("CARGO_PKG_VERSION").to_string(),
93 },
94 instructions: Some(
95 "GameCode MCP Server v2 - Direct tool integration. Configure tools in tools.yaml"
96 .to_string(),
97 ),
98 };
99
100 Ok(serde_json::to_value(result).unwrap())
101 }
102
103 async fn handle_tools_list(&self) -> Result<Value, JsonRpcError> {
105 let tools = self.tool_manager.get_mcp_tools();
106
107 let result = ListToolsResult { tools };
108
109 Ok(serde_json::to_value(result).unwrap())
110 }
111
112 async fn handle_tools_call(&self, params: Option<Value>) -> Result<Value, JsonRpcError> {
114 let params: CallToolParams = if let Some(p) = params {
115 serde_json::from_value(p).map_err(|e| JsonRpcError {
116 code: INVALID_PARAMS,
117 message: format!("Invalid tool call params: {}", e),
118 data: None,
119 })?
120 } else {
121 return Err(JsonRpcError {
122 code: INVALID_PARAMS,
123 message: "Missing tool call params".to_string(),
124 data: None,
125 });
126 };
127
128 match self
130 .tool_manager
131 .execute_tool(¶ms.name, params.arguments, &self.injected_values)
132 .await
133 {
134 Ok(result) => {
135 let response = CallToolResult {
136 content: vec![ContentBlock::Text {
137 text: serde_json::to_string(&result).unwrap_or_else(|_| "null".to_string()),
138 }],
139 is_error: None,
140 };
141
142 Ok(serde_json::to_value(response).unwrap())
143 }
144 Err(e) => {
145 error!("Tool execution failed: {}", e);
146
147 let response = CallToolResult {
148 content: vec![ContentBlock::Text {
149 text: format!("Error: {}", e),
150 }],
151 is_error: Some(true),
152 };
153
154 Ok(serde_json::to_value(response).unwrap())
155 }
156 }
157 }
158}