1use collections::HashMap;
2use serde::{Deserialize, Serialize};
3use url::Url;
4
5#[derive(Debug, Serialize)]
6#[serde(rename_all = "camelCase")]
7pub enum RequestType {
8 Initialize,
9 CallTool,
10 ResourcesUnsubscribe,
11 ResourcesSubscribe,
12 ResourcesRead,
13 ResourcesList,
14 LoggingSetLevel,
15 PromptsGet,
16 PromptsList,
17 CompletionComplete,
18 Ping,
19 ListTools,
20 ListResourceTemplates,
21}
22
23impl RequestType {
24 pub fn as_str(&self) -> &'static str {
25 match self {
26 RequestType::Initialize => "initialize",
27 RequestType::CallTool => "tools/call",
28 RequestType::ResourcesUnsubscribe => "resources/unsubscribe",
29 RequestType::ResourcesSubscribe => "resources/subscribe",
30 RequestType::ResourcesRead => "resources/read",
31 RequestType::ResourcesList => "resources/list",
32 RequestType::LoggingSetLevel => "logging/setLevel",
33 RequestType::PromptsGet => "prompts/get",
34 RequestType::PromptsList => "prompts/list",
35 RequestType::CompletionComplete => "completion/complete",
36 RequestType::Ping => "ping",
37 RequestType::ListTools => "tools/list",
38 RequestType::ListResourceTemplates => "resources/templates/list",
39 }
40 }
41}
42
43#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
44#[serde(untagged)]
45pub enum ProtocolVersion {
46 VersionString(String),
47 VersionNumber(u32),
48}
49
50#[derive(Debug, Serialize)]
51#[serde(rename_all = "camelCase")]
52pub struct InitializeParams {
53 pub protocol_version: ProtocolVersion,
54 pub capabilities: ClientCapabilities,
55 pub client_info: Implementation,
56}
57
58#[derive(Debug, Serialize)]
59#[serde(rename_all = "camelCase")]
60pub struct CallToolParams {
61 pub name: String,
62 #[serde(skip_serializing_if = "Option::is_none")]
63 pub arguments: Option<HashMap<String, serde_json::Value>>,
64}
65
66#[derive(Debug, Serialize)]
67#[serde(rename_all = "camelCase")]
68pub struct ResourcesUnsubscribeParams {
69 pub uri: Url,
70}
71
72#[derive(Debug, Serialize)]
73#[serde(rename_all = "camelCase")]
74pub struct ResourcesSubscribeParams {
75 pub uri: Url,
76}
77
78#[derive(Debug, Serialize)]
79#[serde(rename_all = "camelCase")]
80pub struct ResourcesReadParams {
81 pub uri: Url,
82}
83
84#[derive(Debug, Serialize)]
85#[serde(rename_all = "camelCase")]
86pub struct LoggingSetLevelParams {
87 pub level: LoggingLevel,
88}
89
90#[derive(Debug, Serialize)]
91#[serde(rename_all = "camelCase")]
92pub struct PromptsGetParams {
93 pub name: String,
94 #[serde(skip_serializing_if = "Option::is_none")]
95 pub arguments: Option<HashMap<String, String>>,
96}
97
98#[derive(Debug, Serialize)]
99#[serde(rename_all = "camelCase")]
100pub struct CompletionCompleteParams {
101 pub r#ref: CompletionReference,
102 pub argument: CompletionArgument,
103}
104
105#[derive(Debug, Serialize)]
106#[serde(untagged)]
107pub enum CompletionReference {
108 Prompt(PromptReference),
109 Resource(ResourceReference),
110}
111
112#[derive(Debug, Serialize)]
113#[serde(rename_all = "camelCase")]
114pub struct PromptReference {
115 pub r#type: PromptReferenceType,
116 pub name: String,
117}
118
119#[derive(Debug, Serialize)]
120#[serde(rename_all = "camelCase")]
121pub struct ResourceReference {
122 pub r#type: PromptReferenceType,
123 pub uri: Url,
124}
125
126#[derive(Debug, Serialize)]
127#[serde(rename_all = "snake_case")]
128pub enum PromptReferenceType {
129 #[serde(rename = "ref/prompt")]
130 Prompt,
131 #[serde(rename = "ref/resource")]
132 Resource,
133}
134
135#[derive(Debug, Serialize)]
136#[serde(rename_all = "camelCase")]
137pub struct CompletionArgument {
138 pub name: String,
139 pub value: String,
140}
141
142#[derive(Debug, Deserialize)]
143#[serde(rename_all = "camelCase")]
144pub struct InitializeResponse {
145 pub protocol_version: ProtocolVersion,
146 pub capabilities: ServerCapabilities,
147 pub server_info: Implementation,
148}
149
150#[derive(Debug, Deserialize)]
151#[serde(rename_all = "camelCase")]
152pub struct ResourcesReadResponse {
153 pub contents: Vec<ResourceContent>,
154}
155
156#[derive(Debug, Deserialize)]
157#[serde(rename_all = "camelCase")]
158pub struct ResourcesListResponse {
159 pub resources: Vec<Resource>,
160 #[serde(skip_serializing_if = "Option::is_none")]
161 pub next_cursor: Option<String>,
162}
163
164#[derive(Debug, Serialize, Deserialize)]
165#[serde(rename_all = "camelCase")]
166pub struct SamplingMessage {
167 pub role: SamplingRole,
168 pub content: SamplingContent,
169}
170
171#[derive(Debug, Serialize, Deserialize)]
172#[serde(rename_all = "lowercase")]
173pub enum SamplingRole {
174 User,
175 Assistant,
176}
177
178#[derive(Debug, Serialize, Deserialize)]
179#[serde(tag = "type")]
180pub enum SamplingContent {
181 #[serde(rename = "text")]
182 Text { text: String },
183 #[serde(rename = "image")]
184 Image { data: String, mime_type: String },
185}
186
187#[derive(Debug, Deserialize)]
188#[serde(rename_all = "camelCase")]
189pub struct PromptsGetResponse {
190 #[serde(skip_serializing_if = "Option::is_none")]
191 pub description: Option<String>,
192 pub messages: Vec<SamplingMessage>,
193}
194
195#[derive(Debug, Deserialize)]
196#[serde(rename_all = "camelCase")]
197pub struct PromptsListResponse {
198 pub prompts: Vec<Prompt>,
199 #[serde(skip_serializing_if = "Option::is_none")]
200 pub next_cursor: Option<String>,
201}
202
203#[derive(Debug, Deserialize)]
204#[serde(rename_all = "camelCase")]
205pub struct CompletionCompleteResponse {
206 pub completion: CompletionResult,
207}
208
209#[derive(Debug, Deserialize)]
210#[serde(rename_all = "camelCase")]
211pub struct CompletionResult {
212 pub values: Vec<String>,
213 #[serde(skip_serializing_if = "Option::is_none")]
214 pub total: Option<u32>,
215 #[serde(skip_serializing_if = "Option::is_none")]
216 pub has_more: Option<bool>,
217}
218
219#[derive(Debug, Deserialize, Serialize)]
220#[serde(rename_all = "camelCase")]
221pub struct Prompt {
222 pub name: String,
223 #[serde(skip_serializing_if = "Option::is_none")]
224 pub description: Option<String>,
225 #[serde(skip_serializing_if = "Option::is_none")]
226 pub arguments: Option<Vec<PromptArgument>>,
227}
228
229#[derive(Debug, Deserialize, Serialize)]
230#[serde(rename_all = "camelCase")]
231pub struct PromptArgument {
232 pub name: String,
233 #[serde(skip_serializing_if = "Option::is_none")]
234 pub description: Option<String>,
235 #[serde(skip_serializing_if = "Option::is_none")]
236 pub required: Option<bool>,
237}
238
239#[derive(Debug, Serialize, Deserialize)]
240#[serde(rename_all = "camelCase")]
241pub struct ClientCapabilities {
242 #[serde(skip_serializing_if = "Option::is_none")]
243 pub experimental: Option<HashMap<String, serde_json::Value>>,
244 #[serde(skip_serializing_if = "Option::is_none")]
245 pub sampling: Option<serde_json::Value>,
246}
247
248#[derive(Debug, Serialize, Deserialize)]
249#[serde(rename_all = "camelCase")]
250pub struct ServerCapabilities {
251 #[serde(skip_serializing_if = "Option::is_none")]
252 pub experimental: Option<HashMap<String, serde_json::Value>>,
253 #[serde(skip_serializing_if = "Option::is_none")]
254 pub logging: Option<serde_json::Value>,
255 #[serde(skip_serializing_if = "Option::is_none")]
256 pub prompts: Option<PromptsCapabilities>,
257 #[serde(skip_serializing_if = "Option::is_none")]
258 pub resources: Option<ResourcesCapabilities>,
259 #[serde(skip_serializing_if = "Option::is_none")]
260 pub tools: Option<ToolsCapabilities>,
261}
262
263#[derive(Debug, Serialize, Deserialize)]
264#[serde(rename_all = "camelCase")]
265pub struct PromptsCapabilities {
266 #[serde(skip_serializing_if = "Option::is_none")]
267 pub list_changed: Option<bool>,
268}
269
270#[derive(Debug, Serialize, Deserialize)]
271#[serde(rename_all = "camelCase")]
272pub struct ResourcesCapabilities {
273 #[serde(skip_serializing_if = "Option::is_none")]
274 pub subscribe: Option<bool>,
275 #[serde(skip_serializing_if = "Option::is_none")]
276 pub list_changed: Option<bool>,
277}
278
279#[derive(Debug, Serialize, Deserialize)]
280#[serde(rename_all = "camelCase")]
281pub struct ToolsCapabilities {
282 #[serde(skip_serializing_if = "Option::is_none")]
283 pub list_changed: Option<bool>,
284}
285
286#[derive(Debug, Serialize, Deserialize)]
287#[serde(rename_all = "camelCase")]
288pub struct Tool {
289 pub name: String,
290 #[serde(skip_serializing_if = "Option::is_none")]
291 pub description: Option<String>,
292 pub input_schema: serde_json::Value,
293}
294
295#[derive(Debug, Serialize, Deserialize)]
296#[serde(rename_all = "camelCase")]
297pub struct Implementation {
298 pub name: String,
299 pub version: String,
300}
301
302#[derive(Debug, Serialize, Deserialize)]
303#[serde(rename_all = "camelCase")]
304pub struct Resource {
305 pub uri: Url,
306 pub name: String,
307 #[serde(skip_serializing_if = "Option::is_none")]
308 pub description: Option<String>,
309 #[serde(skip_serializing_if = "Option::is_none")]
310 pub mime_type: Option<String>,
311}
312
313#[derive(Debug, Serialize, Deserialize)]
314#[serde(rename_all = "camelCase")]
315pub struct ResourceContent {
316 pub uri: Url,
317 #[serde(skip_serializing_if = "Option::is_none")]
318 pub mime_type: Option<String>,
319 #[serde(skip_serializing_if = "Option::is_none")]
320 pub text: Option<String>,
321 #[serde(skip_serializing_if = "Option::is_none")]
322 pub blob: Option<String>,
323}
324
325#[derive(Debug, Serialize, Deserialize)]
326#[serde(rename_all = "camelCase")]
327pub struct ResourceTemplate {
328 pub uri_template: String,
329 pub name: String,
330 #[serde(skip_serializing_if = "Option::is_none")]
331 pub description: Option<String>,
332 #[serde(skip_serializing_if = "Option::is_none")]
333 pub mime_type: Option<String>,
334}
335
336#[derive(Debug, Serialize, Deserialize)]
337#[serde(rename_all = "lowercase")]
338pub enum LoggingLevel {
339 Debug,
340 Info,
341 Warning,
342 Error,
343}
344
345#[derive(Debug, Serialize)]
346#[serde(rename_all = "camelCase")]
347pub enum NotificationType {
348 Initialized,
349 Progress,
350 Message,
351 ResourcesUpdated,
352 ResourcesListChanged,
353 ToolsListChanged,
354 PromptsListChanged,
355}
356
357impl NotificationType {
358 pub fn as_str(&self) -> &'static str {
359 match self {
360 NotificationType::Initialized => "notifications/initialized",
361 NotificationType::Progress => "notifications/progress",
362 NotificationType::Message => "notifications/message",
363 NotificationType::ResourcesUpdated => "notifications/resources/updated",
364 NotificationType::ResourcesListChanged => "notifications/resources/list_changed",
365 NotificationType::ToolsListChanged => "notifications/tools/list_changed",
366 NotificationType::PromptsListChanged => "notifications/prompts/list_changed",
367 }
368 }
369}
370
371#[derive(Debug, Serialize)]
372#[serde(untagged)]
373pub enum ClientNotification {
374 Initialized,
375 Progress(ProgressParams),
376}
377
378#[derive(Debug, Serialize)]
379#[serde(rename_all = "camelCase")]
380pub struct ProgressParams {
381 pub progress_token: ProgressToken,
382 pub progress: f64,
383 #[serde(skip_serializing_if = "Option::is_none")]
384 pub total: Option<f64>,
385}
386
387pub type ProgressToken = String;
388
389pub enum CompletionTotal {
390 Exact(u32),
391 HasMore,
392 Unknown,
393}
394
395impl CompletionTotal {
396 pub fn from_options(has_more: Option<bool>, total: Option<u32>) -> Self {
397 match (has_more, total) {
398 (_, Some(count)) => CompletionTotal::Exact(count),
399 (Some(true), _) => CompletionTotal::HasMore,
400 _ => CompletionTotal::Unknown,
401 }
402 }
403}
404
405pub struct Completion {
406 pub values: Vec<String>,
407 pub total: CompletionTotal,
408}
409
410#[derive(Debug, Deserialize)]
411#[serde(rename_all = "camelCase")]
412pub struct CallToolResponse {
413 pub tool_result: serde_json::Value,
414}
415
416#[derive(Debug, Deserialize)]
417#[serde(rename_all = "camelCase")]
418pub struct ListToolsResponse {
419 pub tools: Vec<Tool>,
420 #[serde(skip_serializing_if = "Option::is_none")]
421 pub next_cursor: Option<String>,
422}