1use serde::{Deserialize, Serialize};
7use serde_json::Value;
8use std::collections::HashMap;
9
10use super::types::Implementation;
11
12#[derive(Debug, Clone, Default, Serialize, Deserialize)]
14#[serde(rename_all = "camelCase")]
15pub struct ServerCapabilities {
16 #[serde(skip_serializing_if = "Option::is_none")]
18 pub logging: Option<LoggingCapability>,
19
20 #[serde(skip_serializing_if = "Option::is_none")]
22 pub tools: Option<ToolsCapability>,
23
24 #[serde(skip_serializing_if = "Option::is_none")]
26 pub resources: Option<ResourcesCapability>,
27
28 #[serde(skip_serializing_if = "Option::is_none")]
30 pub prompts: Option<PromptsCapability>,
31
32 #[serde(skip_serializing_if = "Option::is_none")]
34 pub completion: Option<CompletionCapability>,
35
36 #[serde(skip_serializing_if = "Option::is_none")]
38 pub tasks: Option<TasksCapability>,
39
40 #[serde(skip_serializing_if = "Option::is_none")]
42 pub experimental: Option<HashMap<String, Value>>,
43}
44
45#[derive(Debug, Clone, Default, Serialize, Deserialize)]
47#[serde(rename_all = "camelCase")]
48pub struct ClientCapabilities {
49 #[serde(skip_serializing_if = "Option::is_none")]
51 pub roots: Option<RootsCapability>,
52
53 #[serde(skip_serializing_if = "Option::is_none")]
55 pub sampling: Option<SamplingCapability>,
56
57 #[serde(skip_serializing_if = "Option::is_none")]
59 pub elicitation: Option<ElicitationCapability>,
60
61 #[serde(skip_serializing_if = "Option::is_none")]
63 pub tasks: Option<TasksCapability>,
64
65 #[serde(skip_serializing_if = "Option::is_none")]
67 pub experimental: Option<HashMap<String, Value>>,
68}
69
70#[derive(Debug, Clone, Serialize, Deserialize)]
72pub struct LoggingCapability {}
73
74#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
76#[serde(rename_all = "camelCase")]
77pub struct ToolsCapability {
78 #[serde(skip_serializing_if = "Option::is_none")]
80 pub list_changed: Option<bool>,
81}
82
83#[derive(Debug, Clone, Serialize, Deserialize)]
85#[serde(rename_all = "camelCase")]
86pub struct ResourcesCapability {
87 #[serde(skip_serializing_if = "Option::is_none")]
89 pub subscribe: Option<bool>,
90
91 #[serde(skip_serializing_if = "Option::is_none")]
93 pub list_changed: Option<bool>,
94
95 #[serde(skip_serializing_if = "Option::is_none")]
97 pub list_templates: Option<bool>,
98}
99
100#[derive(Debug, Clone, Serialize, Deserialize)]
102#[serde(rename_all = "camelCase")]
103pub struct PromptsCapability {
104 #[serde(skip_serializing_if = "Option::is_none")]
106 pub list_changed: Option<bool>,
107}
108
109#[derive(Debug, Clone, Serialize, Deserialize)]
111pub struct CompletionCapability {}
112
113#[derive(Debug, Clone, Serialize, Deserialize)]
115#[serde(rename_all = "camelCase")]
116pub struct RootsCapability {
117 #[serde(skip_serializing_if = "Option::is_none")]
119 pub list_changed: Option<bool>,
120}
121
122#[derive(Debug, Clone, Serialize, Deserialize)]
124pub struct SamplingCapability {}
125
126#[derive(Debug, Clone, Serialize, Deserialize)]
128pub struct ElicitationCapability {}
129
130#[derive(Debug, Clone, Default, Serialize, Deserialize)]
132#[serde(rename_all = "camelCase")]
133pub struct TasksCapability {
134 #[serde(skip_serializing_if = "Option::is_none")]
136 pub list: Option<EmptyObject>,
137
138 #[serde(skip_serializing_if = "Option::is_none")]
140 pub cancel: Option<EmptyObject>,
141
142 #[serde(skip_serializing_if = "Option::is_none")]
144 pub requests: Option<TasksRequestsCapability>,
145}
146
147#[derive(Debug, Clone, Default, Serialize, Deserialize)]
149#[serde(rename_all = "camelCase")]
150pub struct TasksRequestsCapability {
151 #[serde(skip_serializing_if = "Option::is_none")]
153 pub tools: Option<TasksToolsCapability>,
154
155 #[serde(skip_serializing_if = "Option::is_none")]
157 pub sampling: Option<TasksSamplingCapability>,
158
159 #[serde(skip_serializing_if = "Option::is_none")]
161 pub elicitation: Option<TasksElicitationCapability>,
162}
163
164#[derive(Debug, Clone, Default, Serialize, Deserialize)]
166#[serde(rename_all = "camelCase")]
167pub struct TasksToolsCapability {
168 #[serde(skip_serializing_if = "Option::is_none")]
170 pub call: Option<EmptyObject>,
171}
172
173#[derive(Debug, Clone, Default, Serialize, Deserialize)]
175#[serde(rename_all = "camelCase")]
176pub struct TasksSamplingCapability {
177 #[serde(skip_serializing_if = "Option::is_none")]
179 pub create_message: Option<EmptyObject>,
180}
181
182#[derive(Debug, Clone, Default, Serialize, Deserialize)]
184#[serde(rename_all = "camelCase")]
185pub struct TasksElicitationCapability {
186 #[serde(skip_serializing_if = "Option::is_none")]
188 pub create: Option<EmptyObject>,
189}
190
191#[derive(Debug, Clone, Default, Serialize, Deserialize)]
193pub struct EmptyObject {}
194
195#[derive(Debug, Clone, Serialize, Deserialize)]
197#[serde(rename_all = "camelCase")]
198pub struct InitializeRequest {
199 pub protocol_version: String,
201
202 pub capabilities: ClientCapabilities,
204
205 pub client_info: Implementation,
207}
208
209#[derive(Debug, Clone, Serialize, Deserialize)]
211#[serde(rename_all = "camelCase")]
212pub struct InitializeResult {
213 pub protocol_version: String,
215
216 pub capabilities: ServerCapabilities,
218
219 pub server_info: Implementation,
221
222 #[serde(skip_serializing_if = "Option::is_none")]
224 pub instructions: Option<String>,
225}
226
227#[cfg(test)]
228mod tests {
229 use super::*;
230
231 #[test]
232 fn test_server_capabilities_default() {
233 let caps = ServerCapabilities::default();
234 assert!(caps.tools.is_none());
235 assert!(caps.resources.is_none());
236 }
237
238 #[test]
239 fn test_server_capabilities_serialization() {
240 let caps = ServerCapabilities {
241 tools: Some(ToolsCapability {
242 list_changed: Some(true),
243 }),
244 resources: Some(ResourcesCapability {
245 subscribe: Some(true),
246 list_changed: Some(true),
247 list_templates: Some(true),
248 }),
249 ..Default::default()
250 };
251
252 let json = serde_json::to_value(&caps).unwrap();
253 assert!(json["tools"].is_object());
254 assert!(json["resources"].is_object());
255 assert_eq!(json["tools"]["listChanged"], true);
256 assert_eq!(json["resources"]["listTemplates"], true);
257 }
258
259 #[test]
260 fn test_initialize_request_deserialization() {
261 let json = serde_json::json!({
262 "protocolVersion": "2025-11-25",
263 "capabilities": {},
264 "clientInfo": {
265 "name": "test-client",
266 "version": "1.0.0"
267 }
268 });
269
270 let req: InitializeRequest = serde_json::from_value(json).unwrap();
271 assert_eq!(req.protocol_version, "2025-11-25");
272 assert_eq!(req.client_info.name, "test-client");
273 }
274}