mcp_context_server/handlers/
mod.rs1pub mod health;
2pub mod inspect_cache;
3pub mod list_caches;
4pub mod resolve_context;
5
6use crate::config::ServerConfig;
7use crate::protocol::{
8 InspectCacheParams, JsonRpcError, JsonRpcRequest, JsonRpcResponse, ResolveContextParams,
9 ToolCallParams, ToolResult,
10};
11
12pub async fn dispatch(
16 req: &JsonRpcRequest,
17 config: &ServerConfig,
18) -> Option<JsonRpcResponse> {
19 match req.method.as_str() {
20 "initialize" => {
21 let result = serde_json::json!({
22 "protocolVersion": "2024-11-05",
23 "capabilities": {
24 "tools": {}
25 },
26 "serverInfo": {
27 "name": "mcp-context-server",
28 "version": env!("CARGO_PKG_VERSION")
29 }
30 });
31 Some(JsonRpcResponse::success(req.id.clone(), result))
32 }
33
34 "notifications/initialized" => None,
35
36 "ping" => Some(JsonRpcResponse::success(req.id.clone(), serde_json::json!({}))),
37
38 "tools/list" => {
39 let result = serde_json::json!({
40 "tools": [
41 {
42 "name": "context.resolve",
43 "description": "Resolve context from a cache using a query and token budget",
44 "inputSchema": {
45 "type": "object",
46 "required": ["cache", "query", "budget"],
47 "properties": {
48 "cache": {
49 "type": "string",
50 "description": "Cache directory name (relative to CONTEXT_CACHE_ROOT)"
51 },
52 "query": {
53 "type": "string",
54 "description": "Search query for context selection"
55 },
56 "budget": {
57 "type": "integer",
58 "description": "Maximum token budget for selected context",
59 "minimum": 0
60 }
61 }
62 }
63 },
64 {
65 "name": "context.list_caches",
66 "description": "List available context caches under the server's cache root",
67 "inputSchema": {
68 "type": "object",
69 "properties": {}
70 }
71 },
72 {
73 "name": "context.inspect_cache",
74 "description": "Inspect cache structure, metadata, and validity",
75 "inputSchema": {
76 "type": "object",
77 "required": ["cache"],
78 "properties": {
79 "cache": {
80 "type": "string",
81 "description": "Cache directory name (relative to CONTEXT_CACHE_ROOT)"
82 }
83 }
84 }
85 }
86 ]
87 });
88 Some(JsonRpcResponse::success(req.id.clone(), result))
89 }
90
91 "tools/call" => {
92 let params: ToolCallParams = match &req.params {
93 Some(v) => match serde_json::from_value(v.clone()) {
94 Ok(p) => p,
95 Err(e) => {
96 return Some(JsonRpcResponse::error(
97 req.id.clone(),
98 JsonRpcError::invalid_params(format!(
99 "Invalid tools/call params: {e}"
100 )),
101 ));
102 }
103 },
104 None => {
105 return Some(JsonRpcResponse::error(
106 req.id.clone(),
107 JsonRpcError::invalid_params("Missing params for tools/call"),
108 ));
109 }
110 };
111
112 let tool_result = dispatch_tool_call(¶ms, config).await;
113 let result_json = serde_json::to_value(&tool_result).expect("ToolResult must serialize to JSON Value");
114 Some(JsonRpcResponse::success(req.id.clone(), result_json))
115 }
116
117 _ => Some(JsonRpcResponse::error(
118 req.id.clone(),
119 JsonRpcError::method_not_found(&req.method),
120 )),
121 }
122}
123
124async fn dispatch_tool_call(params: &ToolCallParams, config: &ServerConfig) -> ToolResult {
125 match params.name.as_str() {
126 "context.resolve" => {
127 let resolve_params: ResolveContextParams = match ¶ms.arguments {
128 Some(v) => match serde_json::from_value(v.clone()) {
129 Ok(p) => p,
130 Err(e) => {
131 return ToolResult::error(format!(
132 "Invalid arguments for context.resolve: {e}"
133 ));
134 }
135 },
136 None => {
137 return ToolResult::error(
138 "Missing arguments for context.resolve",
139 );
140 }
141 };
142 resolve_context::handle(resolve_params, config).await
143 }
144
145 "context.list_caches" => list_caches::handle(config).await,
146
147 "context.inspect_cache" => {
148 let inspect_params: InspectCacheParams = match ¶ms.arguments {
149 Some(v) => match serde_json::from_value(v.clone()) {
150 Ok(p) => p,
151 Err(e) => {
152 return ToolResult::error(format!(
153 "Invalid arguments for context.inspect_cache: {e}"
154 ));
155 }
156 },
157 None => {
158 return ToolResult::error(
159 "Missing arguments for context.inspect_cache",
160 );
161 }
162 };
163 inspect_cache::handle(inspect_params, config).await
164 }
165
166 "health" => health::handle().await,
167
168 _ => ToolResult::error(format!("Unknown tool: {}", params.name)),
169 }
170}