1use crate::Error;
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct Request {
10 pub jsonrpc: String,
12 pub method: String,
14 #[serde(default = "serde_json::Value::default")]
16 pub params: serde_json::Value,
17 #[serde(default = "default_null")]
19 pub id: serde_json::Value,
20}
21
22fn default_null() -> serde_json::Value {
23 serde_json::Value::Null
24}
25
26#[derive(Debug, Clone, Serialize, Deserialize)]
28pub struct Response {
29 pub jsonrpc: String,
31 #[serde(skip_serializing_if = "Option::is_none")]
33 pub result: Option<serde_json::Value>,
34 #[serde(skip_serializing_if = "Option::is_none")]
36 pub error: Option<Error>,
37 pub id: serde_json::Value,
39}
40
41#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct ProtocolVersion {
44 pub major: u32,
45 pub minor: u32,
46 pub patch: u32,
47}
48
49impl Default for ProtocolVersion {
50 fn default() -> Self {
51 Self {
52 major: 2024,
53 minor: 11,
54 patch: 5,
55 }
56 }
57}
58
59impl std::fmt::Display for ProtocolVersion {
60 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61 write!(f, "{:04}-{:02}-{:02}", self.major, self.minor, self.patch)
62 }
63}
64
65#[derive(Debug, Clone, Serialize, Deserialize)]
67pub struct Implementation {
68 pub name: String,
69 pub version: String,
70}
71
72#[derive(Debug, Clone, Serialize, Deserialize, Default)]
74pub struct ServerCapabilities {
75 #[serde(skip_serializing_if = "Option::is_none")]
76 pub tools: Option<ToolsCapability>,
77 #[serde(skip_serializing_if = "Option::is_none")]
78 pub resources: Option<ResourcesCapability>,
79 #[serde(skip_serializing_if = "Option::is_none")]
80 pub prompts: Option<PromptsCapability>,
81 #[serde(skip_serializing_if = "Option::is_none")]
82 pub logging: Option<LoggingCapability>,
83 #[serde(skip_serializing_if = "Option::is_none")]
84 pub sampling: Option<SamplingCapability>,
85}
86
87#[derive(Debug, Clone, Serialize, Deserialize, Default)]
88pub struct ToolsCapability {
89 #[serde(skip_serializing_if = "Option::is_none")]
90 pub list_changed: Option<bool>,
91}
92
93#[derive(Debug, Clone, Serialize, Deserialize, Default)]
94pub struct ResourcesCapability {
95 #[serde(skip_serializing_if = "Option::is_none")]
96 pub subscribe: Option<bool>,
97 #[serde(skip_serializing_if = "Option::is_none")]
98 pub list_changed: Option<bool>,
99}
100
101#[derive(Debug, Clone, Serialize, Deserialize, Default)]
102pub struct PromptsCapability {
103 #[serde(skip_serializing_if = "Option::is_none")]
104 pub list_changed: Option<bool>,
105}
106
107#[derive(Debug, Clone, Serialize, Deserialize, Default)]
108pub struct LoggingCapability {
109 #[serde(skip_serializing_if = "Option::is_none")]
110 pub level: Option<String>,
111}
112
113#[derive(Debug, Clone, Serialize, Deserialize, Default)]
114pub struct SamplingCapability {}
115
116impl ServerCapabilities {
117 pub fn builder() -> ServerCapabilitiesBuilder {
118 ServerCapabilitiesBuilder::default()
119 }
120}
121
122#[derive(Default)]
123pub struct ServerCapabilitiesBuilder {
124 capabilities: ServerCapabilities,
125}
126
127impl ServerCapabilitiesBuilder {
128 #[must_use]
129 pub fn enable_tools(mut self) -> Self {
130 self.capabilities.tools = Some(ToolsCapability {
131 list_changed: Some(true),
132 });
133 self
134 }
135
136 #[must_use]
137 pub fn enable_resources(mut self) -> Self {
138 self.capabilities.resources = Some(ResourcesCapability {
139 subscribe: Some(true),
140 list_changed: Some(true),
141 });
142 self
143 }
144
145 #[must_use]
146 pub fn enable_prompts(mut self) -> Self {
147 self.capabilities.prompts = Some(PromptsCapability {
148 list_changed: Some(true),
149 });
150 self
151 }
152
153 #[must_use]
154 pub fn enable_logging(mut self) -> Self {
155 self.capabilities.logging = Some(LoggingCapability {
156 level: Some("info".to_string()),
157 });
158 self
159 }
160
161 #[must_use]
162 pub fn enable_sampling(mut self) -> Self {
163 self.capabilities.sampling = Some(SamplingCapability {});
164 self
165 }
166
167 pub fn build(self) -> ServerCapabilities {
168 self.capabilities
169 }
170}
171
172#[derive(Debug, Clone, Serialize, Deserialize)]
174pub struct ServerInfo {
175 pub protocol_version: ProtocolVersion,
176 pub capabilities: ServerCapabilities,
177 pub server_info: Implementation,
178 pub instructions: Option<String>,
179}
180
181#[derive(Debug, Clone, Serialize, Deserialize)]
183#[serde(rename_all = "camelCase")]
184pub struct Tool {
185 pub name: String,
186 pub description: String,
187 pub input_schema: serde_json::Value,
188}
189
190#[derive(Debug, Clone, Serialize, Deserialize)]
192#[serde(rename_all = "camelCase")]
193pub struct ListToolsResult {
194 pub tools: Vec<Tool>,
195 #[serde(skip_serializing_if = "Option::is_none")]
196 pub next_cursor: Option<String>,
197}
198
199#[derive(Debug, Clone, Serialize, Deserialize)]
201pub struct PaginatedRequestParam {
202 pub cursor: Option<String>,
203}
204
205#[derive(Debug, Clone, Serialize, Deserialize)]
207pub struct CallToolRequestParam {
208 pub name: String,
209 pub arguments: Option<serde_json::Value>,
210}
211
212#[derive(Debug, Clone, Serialize, Deserialize)]
214#[serde(tag = "type")]
215pub enum Content {
216 #[serde(rename = "text")]
217 Text { text: String },
218 #[serde(rename = "image")]
219 Image { data: String, mime_type: String },
220 #[serde(rename = "resource")]
221 Resource {
222 resource: String,
223 text: Option<String>,
224 },
225}
226
227impl Content {
228 pub fn text(text: impl Into<String>) -> Self {
229 Self::Text { text: text.into() }
230 }
231
232 pub fn image(data: impl Into<String>, mime_type: impl Into<String>) -> Self {
233 Self::Image {
234 data: data.into(),
235 mime_type: mime_type.into(),
236 }
237 }
238
239 pub fn resource(resource: impl Into<String>, text: Option<String>) -> Self {
240 Self::Resource {
241 resource: resource.into(),
242 text,
243 }
244 }
245
246 pub fn as_text(&self) -> Option<&Self> {
248 match self {
249 Self::Text { .. } => Some(self),
250 _ => None,
251 }
252 }
253}
254
255pub struct TextContent {
257 pub text: String,
258}
259
260impl Content {
261 pub fn as_text_content(&self) -> Option<TextContent> {
263 match self {
264 Self::Text { text } => Some(TextContent { text: text.clone() }),
265 _ => None,
266 }
267 }
268}
269
270#[derive(Debug, Clone, Serialize, Deserialize)]
272pub struct CallToolResult {
273 pub content: Vec<Content>,
274 pub is_error: Option<bool>,
275}
276
277impl CallToolResult {
278 pub fn success(content: Vec<Content>) -> Self {
279 Self {
280 content,
281 is_error: Some(false),
282 }
283 }
284
285 pub fn error(content: Vec<Content>) -> Self {
286 Self {
287 content,
288 is_error: Some(true),
289 }
290 }
291
292 pub fn text(text: impl Into<String>) -> Self {
293 Self::success(vec![Content::text(text)])
294 }
295
296 pub fn error_text(text: impl Into<String>) -> Self {
297 Self::error(vec![Content::text(text)])
298 }
299}
300
301#[derive(Debug, Clone, Serialize, Deserialize)]
303pub struct Resource {
304 pub uri: String,
305 pub name: String,
306 pub description: Option<String>,
307 pub mime_type: Option<String>,
308 pub annotations: Option<Annotations>,
309 #[serde(skip_serializing_if = "Option::is_none")]
310 pub raw: Option<RawResource>,
311}
312
313#[derive(Debug, Clone, Serialize, Deserialize, Default)]
315pub struct Annotations {
316 pub audience: Option<Vec<String>>,
317 pub priority: Option<f32>,
318}
319
320#[derive(Debug, Clone, Serialize, Deserialize)]
322pub struct ListResourcesResult {
323 pub resources: Vec<Resource>,
324 #[serde(skip_serializing_if = "Option::is_none")]
325 pub next_cursor: Option<String>,
326}
327
328#[derive(Debug, Clone, Serialize, Deserialize)]
330pub struct ReadResourceRequestParam {
331 pub uri: String,
332}
333
334#[derive(Debug, Clone, Serialize, Deserialize)]
336pub struct ResourceContents {
337 pub uri: String,
338 pub mime_type: Option<String>,
339 pub text: Option<String>,
340 pub blob: Option<String>,
341}
342
343#[derive(Debug, Clone, Serialize, Deserialize)]
345pub struct ReadResourceResult {
346 pub contents: Vec<ResourceContents>,
347}
348
349#[derive(Debug, Clone, Serialize, Deserialize)]
351pub struct RawResource {
352 pub uri: String,
353 pub data: Vec<u8>,
354 pub mime_type: Option<String>,
355 pub name: Option<String>,
356 pub description: Option<String>,
357 pub size: Option<usize>,
358}
359
360impl PromptMessage {
361 pub fn new_text(role: PromptMessageRole, text: impl Into<String>) -> Self {
363 Self {
364 role,
365 content: PromptMessageContent::Text { text: text.into() },
366 }
367 }
368
369 pub fn new_image(
371 role: PromptMessageRole,
372 data: impl Into<String>,
373 mime_type: impl Into<String>,
374 ) -> Self {
375 Self {
376 role,
377 content: PromptMessageContent::Image {
378 data: data.into(),
379 mime_type: mime_type.into(),
380 },
381 }
382 }
383}
384
385impl CompleteResult {
386 pub fn simple(completion: impl Into<String>) -> Self {
388 Self {
389 completion: vec![CompletionInfo {
390 completion: completion.into(),
391 has_more: Some(false),
392 }],
393 }
394 }
395}
396
397#[derive(Debug, Clone, Serialize, Deserialize)]
399pub struct Prompt {
400 pub name: String,
401 pub description: Option<String>,
402 pub arguments: Option<Vec<PromptArgument>>,
403}
404
405#[derive(Debug, Clone, Serialize, Deserialize)]
407pub struct PromptArgument {
408 pub name: String,
409 pub description: Option<String>,
410 pub required: Option<bool>,
411}
412
413#[derive(Debug, Clone, Serialize, Deserialize)]
415pub struct ListPromptsResult {
416 pub prompts: Vec<Prompt>,
417 #[serde(skip_serializing_if = "Option::is_none")]
418 pub next_cursor: Option<String>,
419}
420
421#[derive(Debug, Clone, Serialize, Deserialize)]
423pub struct GetPromptRequestParam {
424 pub name: String,
425 pub arguments: Option<HashMap<String, String>>,
426}
427
428#[derive(Debug, Clone, Serialize, Deserialize)]
430#[serde(rename_all = "lowercase")]
431pub enum PromptMessageRole {
432 User,
433 Assistant,
434 System,
435}
436
437#[derive(Debug, Clone, Serialize, Deserialize)]
439#[serde(tag = "type")]
440pub enum PromptMessageContent {
441 #[serde(rename = "text")]
442 Text { text: String },
443 #[serde(rename = "image")]
444 Image { data: String, mime_type: String },
445}
446
447#[derive(Debug, Clone, Serialize, Deserialize)]
449pub struct PromptMessage {
450 pub role: PromptMessageRole,
451 pub content: PromptMessageContent,
452}
453
454#[derive(Debug, Clone, Serialize, Deserialize)]
456pub struct GetPromptResult {
457 pub description: Option<String>,
458 pub messages: Vec<PromptMessage>,
459}
460
461#[derive(Debug, Clone, Serialize, Deserialize)]
463pub struct InitializeRequestParam {
464 #[serde(rename = "protocolVersion")]
465 pub protocol_version: String,
466 pub capabilities: serde_json::Value,
467 #[serde(rename = "clientInfo")]
468 pub client_info: Implementation,
469}
470
471#[derive(Debug, Clone, Serialize, Deserialize)]
473pub struct InitializeResult {
474 #[serde(rename = "protocolVersion")]
475 pub protocol_version: String,
476 pub capabilities: ServerCapabilities,
477 #[serde(rename = "serverInfo")]
478 pub server_info: Implementation,
479 #[serde(skip_serializing_if = "Option::is_none")]
480 pub instructions: Option<String>,
481}
482
483#[derive(Debug, Clone, Serialize, Deserialize)]
485pub struct CompleteRequestParam {
486 pub ref_: String,
487 pub argument: serde_json::Value,
488}
489
490#[derive(Debug, Clone, Serialize, Deserialize)]
492pub struct CompletionInfo {
493 pub completion: String,
494 pub has_more: Option<bool>,
495}
496
497#[derive(Debug, Clone, Serialize, Deserialize)]
499pub struct CompleteResult {
500 pub completion: Vec<CompletionInfo>,
501}
502
503#[derive(Debug, Clone, Serialize, Deserialize)]
505pub struct SetLevelRequestParam {
506 pub level: String,
507}
508
509#[derive(Debug, Clone, Serialize, Deserialize)]
511pub struct ResourceTemplate {
512 #[serde(rename = "uriTemplate")]
513 pub uri_template: String,
514 pub name: String,
515 pub description: Option<String>,
516 #[serde(rename = "mimeType")]
517 pub mime_type: Option<String>,
518}
519
520#[derive(Debug, Clone, Serialize, Deserialize)]
522pub struct ListResourceTemplatesResult {
523 #[serde(rename = "resourceTemplates")]
524 pub resource_templates: Vec<ResourceTemplate>,
525 #[serde(rename = "nextCursor", skip_serializing_if = "Option::is_none")]
526 pub next_cursor: Option<String>,
527}
528
529#[derive(Debug, Clone, Serialize, Deserialize)]
531pub struct SubscribeRequestParam {
532 pub uri: String,
533}
534
535#[derive(Debug, Clone, Serialize, Deserialize)]
537pub struct UnsubscribeRequestParam {
538 pub uri: String,
539}