1use serde_json::Value;
8use tracing::debug;
9
10use crate::protocol::{
11 CallToolParams, InitializeParams, InitializeResult, JsonRpcRequest, JsonRpcResponse,
12 ServerCapabilities, ServerInfo, ToolsCapability, ToolsListResult, INTERNAL_ERROR,
13 INVALID_PARAMS, INVALID_REQUEST, METHOD_NOT_FOUND, PROTOCOL_VERSION, SERVER_NAME,
14 SERVER_VERSION,
15};
16use crate::state::SharedState;
17use crate::tools::ToolRegistry;
18
19pub struct McpServer {
24 state: SharedState,
25 tools: ToolRegistry,
26}
27
28impl McpServer {
29 pub const fn new(state: SharedState, tools: ToolRegistry) -> Self {
31 Self { state, tools }
32 }
33
34 pub async fn handle_request(&self, request: JsonRpcRequest) -> Option<JsonRpcResponse> {
38 if request.jsonrpc != "2.0" {
40 return Some(JsonRpcResponse::error(
41 request.id,
42 INVALID_REQUEST,
43 format!("Unsupported JSON-RPC version: {}", request.jsonrpc),
44 ));
45 }
46
47 if request.id.is_none() {
49 debug!(method = %request.method, "Received notification, no response");
50 return None;
51 }
52
53 let response = match request.method.as_str() {
54 "initialize" => Self::handle_initialize(request.id, request.params),
55 "tools/list" => self.handle_tools_list(request.id),
56 "tools/call" => self.handle_tools_call(request.id, request.params).await,
57 "ping" => JsonRpcResponse::success(request.id, Value::Object(serde_json::Map::new())),
58 method => {
59 debug!(method, "Unknown MCP method");
60 JsonRpcResponse::error(
61 request.id,
62 METHOD_NOT_FOUND,
63 format!("Method not found: {method}"),
64 )
65 }
66 };
67
68 Some(response)
69 }
70
71 fn handle_initialize(id: Option<Value>, params: Option<Value>) -> JsonRpcResponse {
73 if let Some(params) = params {
74 if let Ok(init) = serde_json::from_value::<InitializeParams>(params) {
75 debug!(
76 client = %init.client_info.name,
77 version = ?init.client_info.version,
78 protocol = %init.protocol_version,
79 capabilities = %init.capabilities,
80 "MCP client connected"
81 );
82 }
83 }
84
85 let result = InitializeResult {
86 protocol_version: PROTOCOL_VERSION.to_owned(),
87 capabilities: ServerCapabilities {
88 tools: Some(ToolsCapability {}),
89 },
90 server_info: ServerInfo {
91 name: SERVER_NAME.to_owned(),
92 version: SERVER_VERSION.to_owned(),
93 },
94 };
95
96 match serde_json::to_value(result) {
97 Ok(val) => JsonRpcResponse::success(id, val),
98 Err(e) => {
99 JsonRpcResponse::error(id, INTERNAL_ERROR, format!("Serialization error: {e}"))
100 }
101 }
102 }
103
104 fn handle_tools_list(&self, id: Option<Value>) -> JsonRpcResponse {
106 let result = ToolsListResult {
107 tools: self.tools.list_definitions(),
108 };
109
110 match serde_json::to_value(result) {
111 Ok(val) => JsonRpcResponse::success(id, val),
112 Err(e) => {
113 JsonRpcResponse::error(id, INTERNAL_ERROR, format!("Serialization error: {e}"))
114 }
115 }
116 }
117
118 async fn handle_tools_call(&self, id: Option<Value>, params: Option<Value>) -> JsonRpcResponse {
120 let call_params: CallToolParams = match params {
121 Some(p) => match serde_json::from_value(p) {
122 Ok(cp) => cp,
123 Err(e) => {
124 return JsonRpcResponse::error(
125 id,
126 INVALID_PARAMS,
127 format!("Invalid params: {e}"),
128 );
129 }
130 },
131 None => {
132 return JsonRpcResponse::error(
133 id,
134 INVALID_PARAMS,
135 "Missing params for tools/call".to_owned(),
136 );
137 }
138 };
139
140 let arguments = call_params
141 .arguments
142 .unwrap_or_else(|| Value::Object(serde_json::Map::new()));
143
144 let result = self
145 .tools
146 .execute(&call_params.name, &self.state, arguments)
147 .await;
148
149 match serde_json::to_value(result) {
150 Ok(val) => JsonRpcResponse::success(id, val),
151 Err(e) => JsonRpcResponse::error(
152 id,
153 INTERNAL_ERROR,
154 format!("Result serialization error: {e}"),
155 ),
156 }
157 }
158}