types.rs

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