types.rs

  1use collections::HashMap;
  2use serde::{Deserialize, Serialize};
  3use url::Url;
  4
  5pub const LATEST_PROTOCOL_VERSION: &str = "2024-11-05";
  6
  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    ListRoots,
 22}
 23
 24impl RequestType {
 25    pub fn as_str(&self) -> &'static str {
 26        match self {
 27            RequestType::Initialize => "initialize",
 28            RequestType::CallTool => "tools/call",
 29            RequestType::ResourcesUnsubscribe => "resources/unsubscribe",
 30            RequestType::ResourcesSubscribe => "resources/subscribe",
 31            RequestType::ResourcesRead => "resources/read",
 32            RequestType::ResourcesList => "resources/list",
 33            RequestType::LoggingSetLevel => "logging/setLevel",
 34            RequestType::PromptsGet => "prompts/get",
 35            RequestType::PromptsList => "prompts/list",
 36            RequestType::CompletionComplete => "completion/complete",
 37            RequestType::Ping => "ping",
 38            RequestType::ListTools => "tools/list",
 39            RequestType::ListResourceTemplates => "resources/templates/list",
 40            RequestType::ListRoots => "roots/list",
 41        }
 42    }
 43}
 44
 45impl TryFrom<&str> for RequestType {
 46    type Error = ();
 47
 48    fn try_from(s: &str) -> Result<Self, Self::Error> {
 49        match s {
 50            "initialize" => Ok(RequestType::Initialize),
 51            "tools/call" => Ok(RequestType::CallTool),
 52            "resources/unsubscribe" => Ok(RequestType::ResourcesUnsubscribe),
 53            "resources/subscribe" => Ok(RequestType::ResourcesSubscribe),
 54            "resources/read" => Ok(RequestType::ResourcesRead),
 55            "resources/list" => Ok(RequestType::ResourcesList),
 56            "logging/setLevel" => Ok(RequestType::LoggingSetLevel),
 57            "prompts/get" => Ok(RequestType::PromptsGet),
 58            "prompts/list" => Ok(RequestType::PromptsList),
 59            "completion/complete" => Ok(RequestType::CompletionComplete),
 60            "ping" => Ok(RequestType::Ping),
 61            "tools/list" => Ok(RequestType::ListTools),
 62            "resources/templates/list" => Ok(RequestType::ListResourceTemplates),
 63            "roots/list" => Ok(RequestType::ListRoots),
 64            _ => Err(()),
 65        }
 66    }
 67}
 68
 69#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
 70#[serde(transparent)]
 71pub struct ProtocolVersion(pub String);
 72
 73#[derive(Debug, Serialize)]
 74#[serde(rename_all = "camelCase")]
 75pub struct InitializeParams {
 76    pub protocol_version: ProtocolVersion,
 77    pub capabilities: ClientCapabilities,
 78    pub client_info: Implementation,
 79    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
 80    pub meta: Option<HashMap<String, serde_json::Value>>,
 81}
 82
 83#[derive(Debug, Serialize)]
 84#[serde(rename_all = "camelCase")]
 85pub struct CallToolParams {
 86    pub name: String,
 87    #[serde(skip_serializing_if = "Option::is_none")]
 88    pub arguments: Option<HashMap<String, serde_json::Value>>,
 89    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
 90    pub meta: Option<HashMap<String, serde_json::Value>>,
 91}
 92
 93#[derive(Debug, Serialize)]
 94#[serde(rename_all = "camelCase")]
 95pub struct ResourcesUnsubscribeParams {
 96    pub uri: Url,
 97    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
 98    pub meta: Option<HashMap<String, serde_json::Value>>,
 99}
100
101#[derive(Debug, Serialize)]
102#[serde(rename_all = "camelCase")]
103pub struct ResourcesSubscribeParams {
104    pub uri: Url,
105    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
106    pub meta: Option<HashMap<String, serde_json::Value>>,
107}
108
109#[derive(Debug, Serialize)]
110#[serde(rename_all = "camelCase")]
111pub struct ResourcesReadParams {
112    pub uri: Url,
113    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
114    pub meta: Option<HashMap<String, serde_json::Value>>,
115}
116
117#[derive(Debug, Serialize)]
118#[serde(rename_all = "camelCase")]
119pub struct LoggingSetLevelParams {
120    pub level: LoggingLevel,
121    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
122    pub meta: Option<HashMap<String, serde_json::Value>>,
123}
124
125#[derive(Debug, Serialize)]
126#[serde(rename_all = "camelCase")]
127pub struct PromptsGetParams {
128    pub name: String,
129    #[serde(skip_serializing_if = "Option::is_none")]
130    pub arguments: Option<HashMap<String, String>>,
131    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
132    pub meta: Option<HashMap<String, serde_json::Value>>,
133}
134
135#[derive(Debug, Serialize)]
136#[serde(rename_all = "camelCase")]
137pub struct CompletionCompleteParams {
138    pub r#ref: CompletionReference,
139    pub argument: CompletionArgument,
140    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
141    pub meta: Option<HashMap<String, serde_json::Value>>,
142}
143
144#[derive(Debug, Serialize)]
145#[serde(untagged)]
146pub enum CompletionReference {
147    Prompt(PromptReference),
148    Resource(ResourceReference),
149}
150
151#[derive(Debug, Serialize)]
152#[serde(rename_all = "camelCase")]
153pub struct PromptReference {
154    pub r#type: PromptReferenceType,
155    pub name: String,
156}
157
158#[derive(Debug, Serialize)]
159#[serde(rename_all = "camelCase")]
160pub struct ResourceReference {
161    pub r#type: PromptReferenceType,
162    pub uri: Url,
163}
164
165#[derive(Debug, Serialize)]
166#[serde(rename_all = "snake_case")]
167pub enum PromptReferenceType {
168    #[serde(rename = "ref/prompt")]
169    Prompt,
170    #[serde(rename = "ref/resource")]
171    Resource,
172}
173
174#[derive(Debug, Serialize)]
175#[serde(rename_all = "camelCase")]
176pub struct CompletionArgument {
177    pub name: String,
178    pub value: String,
179}
180
181#[derive(Debug, Serialize, Deserialize)]
182#[serde(rename_all = "camelCase")]
183pub struct InitializeResponse {
184    pub protocol_version: ProtocolVersion,
185    pub capabilities: ServerCapabilities,
186    pub server_info: Implementation,
187    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
188    pub meta: Option<HashMap<String, serde_json::Value>>,
189}
190
191#[derive(Debug, Deserialize)]
192#[serde(rename_all = "camelCase")]
193pub struct ResourcesReadResponse {
194    pub contents: Vec<ResourceContentsType>,
195    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
196    pub meta: Option<HashMap<String, serde_json::Value>>,
197}
198
199#[derive(Debug, Deserialize)]
200#[serde(untagged)]
201pub enum ResourceContentsType {
202    Text(TextResourceContents),
203    Blob(BlobResourceContents),
204}
205
206#[derive(Debug, Deserialize)]
207#[serde(rename_all = "camelCase")]
208pub struct ResourcesListResponse {
209    pub resources: Vec<Resource>,
210    #[serde(skip_serializing_if = "Option::is_none")]
211    pub next_cursor: Option<String>,
212    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
213    pub meta: Option<HashMap<String, serde_json::Value>>,
214}
215
216#[derive(Debug, Serialize, Deserialize)]
217#[serde(rename_all = "camelCase")]
218pub struct SamplingMessage {
219    pub role: Role,
220    pub content: MessageContent,
221}
222
223#[derive(Debug, Serialize)]
224#[serde(rename_all = "camelCase")]
225pub struct CreateMessageRequest {
226    pub messages: Vec<SamplingMessage>,
227    #[serde(skip_serializing_if = "Option::is_none")]
228    pub model_preferences: Option<ModelPreferences>,
229    #[serde(skip_serializing_if = "Option::is_none")]
230    pub system_prompt: Option<String>,
231    #[serde(skip_serializing_if = "Option::is_none")]
232    pub include_context: Option<String>,
233    #[serde(skip_serializing_if = "Option::is_none")]
234    pub temperature: Option<f64>,
235    pub max_tokens: u32,
236    #[serde(skip_serializing_if = "Option::is_none")]
237    pub stop_sequences: Option<Vec<String>>,
238    #[serde(skip_serializing_if = "Option::is_none")]
239    pub metadata: Option<serde_json::Value>,
240}
241
242#[derive(Debug, Deserialize)]
243#[serde(rename_all = "camelCase")]
244pub struct CreateMessageResult {
245    pub role: Role,
246    pub content: MessageContent,
247    pub model: String,
248    #[serde(skip_serializing_if = "Option::is_none")]
249    pub stop_reason: Option<String>,
250}
251
252#[derive(Debug, Serialize, Deserialize)]
253#[serde(rename_all = "camelCase")]
254pub struct PromptMessage {
255    pub role: Role,
256    pub content: MessageContent,
257}
258
259#[derive(Debug, Serialize, Deserialize)]
260#[serde(rename_all = "lowercase")]
261pub enum Role {
262    User,
263    Assistant,
264}
265
266#[derive(Debug, Serialize, Deserialize)]
267#[serde(tag = "type")]
268pub enum MessageContent {
269    #[serde(rename = "text")]
270    Text {
271        text: String,
272        #[serde(skip_serializing_if = "Option::is_none")]
273        annotations: Option<MessageAnnotations>,
274    },
275    #[serde(rename = "image")]
276    Image {
277        data: String,
278        mime_type: String,
279        #[serde(skip_serializing_if = "Option::is_none")]
280        annotations: Option<MessageAnnotations>,
281    },
282    #[serde(rename = "resource")]
283    Resource {
284        resource: ResourceContents,
285        #[serde(skip_serializing_if = "Option::is_none")]
286        annotations: Option<MessageAnnotations>,
287    },
288}
289
290#[derive(Debug, Serialize, Deserialize)]
291#[serde(rename_all = "camelCase")]
292pub struct MessageAnnotations {
293    #[serde(skip_serializing_if = "Option::is_none")]
294    pub audience: Option<Vec<Role>>,
295    #[serde(skip_serializing_if = "Option::is_none")]
296    pub priority: Option<f64>,
297}
298
299#[derive(Debug, Deserialize)]
300#[serde(rename_all = "camelCase")]
301pub struct PromptsGetResponse {
302    #[serde(skip_serializing_if = "Option::is_none")]
303    pub description: Option<String>,
304    pub messages: Vec<PromptMessage>,
305    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
306    pub meta: Option<HashMap<String, serde_json::Value>>,
307}
308
309#[derive(Debug, Deserialize)]
310#[serde(rename_all = "camelCase")]
311pub struct PromptsListResponse {
312    pub prompts: Vec<Prompt>,
313    #[serde(skip_serializing_if = "Option::is_none")]
314    pub next_cursor: Option<String>,
315    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
316    pub meta: Option<HashMap<String, serde_json::Value>>,
317}
318
319#[derive(Debug, Deserialize)]
320#[serde(rename_all = "camelCase")]
321pub struct CompletionCompleteResponse {
322    pub completion: CompletionResult,
323    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
324    pub meta: Option<HashMap<String, serde_json::Value>>,
325}
326
327#[derive(Debug, Deserialize)]
328#[serde(rename_all = "camelCase")]
329pub struct CompletionResult {
330    pub values: Vec<String>,
331    #[serde(skip_serializing_if = "Option::is_none")]
332    pub total: Option<u32>,
333    #[serde(skip_serializing_if = "Option::is_none")]
334    pub has_more: Option<bool>,
335    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
336    pub meta: Option<HashMap<String, serde_json::Value>>,
337}
338
339#[derive(Debug, Deserialize, Serialize)]
340#[serde(rename_all = "camelCase")]
341pub struct Prompt {
342    pub name: String,
343    #[serde(skip_serializing_if = "Option::is_none")]
344    pub description: Option<String>,
345    #[serde(skip_serializing_if = "Option::is_none")]
346    pub arguments: Option<Vec<PromptArgument>>,
347}
348
349#[derive(Debug, Deserialize, Serialize)]
350#[serde(rename_all = "camelCase")]
351pub struct PromptArgument {
352    pub name: String,
353    #[serde(skip_serializing_if = "Option::is_none")]
354    pub description: Option<String>,
355    #[serde(skip_serializing_if = "Option::is_none")]
356    pub required: Option<bool>,
357}
358
359#[derive(Debug, Serialize, Deserialize)]
360#[serde(rename_all = "camelCase")]
361pub struct ClientCapabilities {
362    #[serde(skip_serializing_if = "Option::is_none")]
363    pub experimental: Option<HashMap<String, serde_json::Value>>,
364    #[serde(skip_serializing_if = "Option::is_none")]
365    pub sampling: Option<serde_json::Value>,
366    #[serde(skip_serializing_if = "Option::is_none")]
367    pub roots: Option<RootsCapabilities>,
368}
369
370#[derive(Default, Debug, Serialize, Deserialize)]
371#[serde(rename_all = "camelCase")]
372pub struct ServerCapabilities {
373    #[serde(skip_serializing_if = "Option::is_none")]
374    pub experimental: Option<HashMap<String, serde_json::Value>>,
375    #[serde(skip_serializing_if = "Option::is_none")]
376    pub logging: Option<serde_json::Value>,
377    #[serde(skip_serializing_if = "Option::is_none")]
378    pub prompts: Option<PromptsCapabilities>,
379    #[serde(skip_serializing_if = "Option::is_none")]
380    pub resources: Option<ResourcesCapabilities>,
381    #[serde(skip_serializing_if = "Option::is_none")]
382    pub tools: Option<ToolsCapabilities>,
383}
384
385#[derive(Debug, Serialize, Deserialize)]
386#[serde(rename_all = "camelCase")]
387pub struct PromptsCapabilities {
388    #[serde(skip_serializing_if = "Option::is_none")]
389    pub list_changed: Option<bool>,
390}
391
392#[derive(Debug, Serialize, Deserialize)]
393#[serde(rename_all = "camelCase")]
394pub struct ResourcesCapabilities {
395    #[serde(skip_serializing_if = "Option::is_none")]
396    pub subscribe: Option<bool>,
397    #[serde(skip_serializing_if = "Option::is_none")]
398    pub list_changed: Option<bool>,
399}
400
401#[derive(Debug, Serialize, Deserialize)]
402#[serde(rename_all = "camelCase")]
403pub struct ToolsCapabilities {
404    #[serde(skip_serializing_if = "Option::is_none")]
405    pub list_changed: Option<bool>,
406}
407
408#[derive(Debug, Serialize, Deserialize)]
409#[serde(rename_all = "camelCase")]
410pub struct RootsCapabilities {
411    #[serde(skip_serializing_if = "Option::is_none")]
412    pub list_changed: Option<bool>,
413}
414
415#[derive(Debug, Serialize, Deserialize)]
416#[serde(rename_all = "camelCase")]
417pub struct Tool {
418    pub name: String,
419    #[serde(skip_serializing_if = "Option::is_none")]
420    pub description: Option<String>,
421    pub input_schema: serde_json::Value,
422}
423
424#[derive(Debug, Serialize, Deserialize)]
425#[serde(rename_all = "camelCase")]
426pub struct Implementation {
427    pub name: String,
428    pub version: String,
429}
430
431#[derive(Debug, Serialize, Deserialize)]
432#[serde(rename_all = "camelCase")]
433pub struct Resource {
434    pub uri: Url,
435    pub name: String,
436    #[serde(skip_serializing_if = "Option::is_none")]
437    pub description: Option<String>,
438    #[serde(skip_serializing_if = "Option::is_none")]
439    pub mime_type: Option<String>,
440}
441
442#[derive(Debug, Serialize, Deserialize)]
443#[serde(rename_all = "camelCase")]
444pub struct ResourceContents {
445    pub uri: Url,
446    #[serde(skip_serializing_if = "Option::is_none")]
447    pub mime_type: Option<String>,
448}
449
450#[derive(Debug, Serialize, Deserialize)]
451#[serde(rename_all = "camelCase")]
452pub struct TextResourceContents {
453    pub uri: Url,
454    #[serde(skip_serializing_if = "Option::is_none")]
455    pub mime_type: Option<String>,
456    pub text: String,
457}
458
459#[derive(Debug, Serialize, Deserialize)]
460#[serde(rename_all = "camelCase")]
461pub struct BlobResourceContents {
462    pub uri: Url,
463    #[serde(skip_serializing_if = "Option::is_none")]
464    pub mime_type: Option<String>,
465    pub blob: String,
466}
467
468#[derive(Debug, Serialize, Deserialize)]
469#[serde(rename_all = "camelCase")]
470pub struct ResourceTemplate {
471    pub uri_template: String,
472    pub name: String,
473    #[serde(skip_serializing_if = "Option::is_none")]
474    pub description: Option<String>,
475    #[serde(skip_serializing_if = "Option::is_none")]
476    pub mime_type: Option<String>,
477}
478
479#[derive(Debug, Serialize, Deserialize)]
480#[serde(rename_all = "lowercase")]
481pub enum LoggingLevel {
482    Debug,
483    Info,
484    Notice,
485    Warning,
486    Error,
487    Critical,
488    Alert,
489    Emergency,
490}
491
492#[derive(Debug, Serialize, Deserialize)]
493#[serde(rename_all = "camelCase")]
494pub struct ModelPreferences {
495    #[serde(skip_serializing_if = "Option::is_none")]
496    pub hints: Option<Vec<ModelHint>>,
497    #[serde(skip_serializing_if = "Option::is_none")]
498    pub cost_priority: Option<f64>,
499    #[serde(skip_serializing_if = "Option::is_none")]
500    pub speed_priority: Option<f64>,
501    #[serde(skip_serializing_if = "Option::is_none")]
502    pub intelligence_priority: Option<f64>,
503}
504
505#[derive(Debug, Serialize, Deserialize)]
506#[serde(rename_all = "camelCase")]
507pub struct ModelHint {
508    #[serde(skip_serializing_if = "Option::is_none")]
509    pub name: Option<String>,
510}
511
512#[derive(Debug, Serialize)]
513#[serde(rename_all = "camelCase")]
514pub enum NotificationType {
515    Initialized,
516    Progress,
517    Message,
518    ResourcesUpdated,
519    ResourcesListChanged,
520    ToolsListChanged,
521    PromptsListChanged,
522    RootsListChanged,
523}
524
525impl NotificationType {
526    pub fn as_str(&self) -> &'static str {
527        match self {
528            NotificationType::Initialized => "notifications/initialized",
529            NotificationType::Progress => "notifications/progress",
530            NotificationType::Message => "notifications/message",
531            NotificationType::ResourcesUpdated => "notifications/resources/updated",
532            NotificationType::ResourcesListChanged => "notifications/resources/list_changed",
533            NotificationType::ToolsListChanged => "notifications/tools/list_changed",
534            NotificationType::PromptsListChanged => "notifications/prompts/list_changed",
535            NotificationType::RootsListChanged => "notifications/roots/list_changed",
536        }
537    }
538}
539
540#[derive(Debug, Serialize)]
541#[serde(untagged)]
542pub enum ClientNotification {
543    Initialized,
544    Progress(ProgressParams),
545    RootsListChanged,
546    Cancelled {
547        request_id: String,
548        #[serde(skip_serializing_if = "Option::is_none")]
549        reason: Option<String>,
550    },
551}
552
553#[derive(Debug, Serialize, Deserialize)]
554#[serde(untagged)]
555pub enum ProgressToken {
556    String(String),
557    Number(f64),
558}
559
560#[derive(Debug, Serialize)]
561#[serde(rename_all = "camelCase")]
562pub struct ProgressParams {
563    pub progress_token: ProgressToken,
564    pub progress: f64,
565    #[serde(skip_serializing_if = "Option::is_none")]
566    pub total: Option<f64>,
567    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
568    pub meta: Option<HashMap<String, serde_json::Value>>,
569}
570
571pub enum CompletionTotal {
572    Exact(u32),
573    HasMore,
574    Unknown,
575}
576
577impl CompletionTotal {
578    pub fn from_options(has_more: Option<bool>, total: Option<u32>) -> Self {
579        match (has_more, total) {
580            (_, Some(count)) => CompletionTotal::Exact(count),
581            (Some(true), _) => CompletionTotal::HasMore,
582            _ => CompletionTotal::Unknown,
583        }
584    }
585}
586
587pub struct Completion {
588    pub values: Vec<String>,
589    pub total: CompletionTotal,
590}
591
592#[derive(Debug, Deserialize)]
593#[serde(rename_all = "camelCase")]
594pub struct CallToolResponse {
595    pub content: Vec<ToolResponseContent>,
596    #[serde(skip_serializing_if = "Option::is_none")]
597    pub is_error: Option<bool>,
598    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
599    pub meta: Option<HashMap<String, serde_json::Value>>,
600}
601
602#[derive(Debug, Serialize, Deserialize)]
603#[serde(tag = "type")]
604pub enum ToolResponseContent {
605    #[serde(rename = "text")]
606    Text { text: String },
607    #[serde(rename = "image", rename_all = "camelCase")]
608    Image { data: String, mime_type: String },
609    #[serde(rename = "resource")]
610    Resource { resource: ResourceContents },
611}
612
613#[derive(Debug, Serialize, Deserialize)]
614#[serde(rename_all = "camelCase")]
615pub struct ListToolsResponse {
616    pub tools: Vec<Tool>,
617    #[serde(skip_serializing_if = "Option::is_none")]
618    pub next_cursor: Option<String>,
619    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
620    pub meta: Option<HashMap<String, serde_json::Value>>,
621}
622
623#[derive(Debug, Deserialize)]
624#[serde(rename_all = "camelCase")]
625pub struct ListResourceTemplatesResponse {
626    pub resource_templates: Vec<ResourceTemplate>,
627    #[serde(skip_serializing_if = "Option::is_none")]
628    pub next_cursor: Option<String>,
629    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
630    pub meta: Option<HashMap<String, serde_json::Value>>,
631}
632
633#[derive(Debug, Deserialize)]
634#[serde(rename_all = "camelCase")]
635pub struct ListRootsResponse {
636    pub roots: Vec<Root>,
637    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
638    pub meta: Option<HashMap<String, serde_json::Value>>,
639}
640
641#[derive(Debug, Serialize, Deserialize)]
642#[serde(rename_all = "camelCase")]
643pub struct Root {
644    pub uri: Url,
645    #[serde(skip_serializing_if = "Option::is_none")]
646    pub name: Option<String>,
647}