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
 45#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
 46#[serde(transparent)]
 47pub struct ProtocolVersion(pub String);
 48
 49#[derive(Debug, Serialize)]
 50#[serde(rename_all = "camelCase")]
 51pub struct InitializeParams {
 52    pub protocol_version: ProtocolVersion,
 53    pub capabilities: ClientCapabilities,
 54    pub client_info: Implementation,
 55    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
 56    pub meta: Option<HashMap<String, serde_json::Value>>,
 57}
 58
 59#[derive(Debug, Serialize)]
 60#[serde(rename_all = "camelCase")]
 61pub struct CallToolParams {
 62    pub name: String,
 63    #[serde(skip_serializing_if = "Option::is_none")]
 64    pub arguments: Option<HashMap<String, serde_json::Value>>,
 65    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
 66    pub meta: Option<HashMap<String, serde_json::Value>>,
 67}
 68
 69#[derive(Debug, Serialize)]
 70#[serde(rename_all = "camelCase")]
 71pub struct ResourcesUnsubscribeParams {
 72    pub uri: Url,
 73    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
 74    pub meta: Option<HashMap<String, serde_json::Value>>,
 75}
 76
 77#[derive(Debug, Serialize)]
 78#[serde(rename_all = "camelCase")]
 79pub struct ResourcesSubscribeParams {
 80    pub uri: Url,
 81    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
 82    pub meta: Option<HashMap<String, serde_json::Value>>,
 83}
 84
 85#[derive(Debug, Serialize)]
 86#[serde(rename_all = "camelCase")]
 87pub struct ResourcesReadParams {
 88    pub uri: Url,
 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 LoggingSetLevelParams {
 96    pub level: LoggingLevel,
 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 PromptsGetParams {
104    pub name: String,
105    #[serde(skip_serializing_if = "Option::is_none")]
106    pub arguments: Option<HashMap<String, String>>,
107    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
108    pub meta: Option<HashMap<String, serde_json::Value>>,
109}
110
111#[derive(Debug, Serialize)]
112#[serde(rename_all = "camelCase")]
113pub struct CompletionCompleteParams {
114    pub r#ref: CompletionReference,
115    pub argument: CompletionArgument,
116    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
117    pub meta: Option<HashMap<String, serde_json::Value>>,
118}
119
120#[derive(Debug, Serialize)]
121#[serde(untagged)]
122pub enum CompletionReference {
123    Prompt(PromptReference),
124    Resource(ResourceReference),
125}
126
127#[derive(Debug, Serialize)]
128#[serde(rename_all = "camelCase")]
129pub struct PromptReference {
130    pub r#type: PromptReferenceType,
131    pub name: String,
132}
133
134#[derive(Debug, Serialize)]
135#[serde(rename_all = "camelCase")]
136pub struct ResourceReference {
137    pub r#type: PromptReferenceType,
138    pub uri: Url,
139}
140
141#[derive(Debug, Serialize)]
142#[serde(rename_all = "snake_case")]
143pub enum PromptReferenceType {
144    #[serde(rename = "ref/prompt")]
145    Prompt,
146    #[serde(rename = "ref/resource")]
147    Resource,
148}
149
150#[derive(Debug, Serialize)]
151#[serde(rename_all = "camelCase")]
152pub struct CompletionArgument {
153    pub name: String,
154    pub value: String,
155}
156
157#[derive(Debug, Deserialize)]
158#[serde(rename_all = "camelCase")]
159pub struct InitializeResponse {
160    pub protocol_version: ProtocolVersion,
161    pub capabilities: ServerCapabilities,
162    pub server_info: Implementation,
163    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
164    pub meta: Option<HashMap<String, serde_json::Value>>,
165}
166
167#[derive(Debug, Deserialize)]
168#[serde(rename_all = "camelCase")]
169pub struct ResourcesReadResponse {
170    pub contents: Vec<ResourceContents>,
171    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
172    pub meta: Option<HashMap<String, serde_json::Value>>,
173}
174
175#[derive(Debug, Deserialize)]
176#[serde(rename_all = "camelCase")]
177pub struct ResourcesListResponse {
178    pub resources: Vec<Resource>,
179    #[serde(skip_serializing_if = "Option::is_none")]
180    pub next_cursor: Option<String>,
181    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
182    pub meta: Option<HashMap<String, serde_json::Value>>,
183}
184#[derive(Debug, Serialize, Deserialize)]
185#[serde(rename_all = "camelCase")]
186pub struct SamplingMessage {
187    pub role: Role,
188    pub content: MessageContent,
189}
190
191#[derive(Debug, Serialize, Deserialize)]
192#[serde(rename_all = "camelCase")]
193pub struct PromptMessage {
194    pub role: Role,
195    pub content: MessageContent,
196}
197
198#[derive(Debug, Serialize, Deserialize)]
199#[serde(rename_all = "lowercase")]
200pub enum Role {
201    User,
202    Assistant,
203}
204
205#[derive(Debug, Serialize, Deserialize)]
206#[serde(tag = "type")]
207pub enum MessageContent {
208    #[serde(rename = "text")]
209    Text { text: String },
210    #[serde(rename = "image")]
211    Image { data: String, mime_type: String },
212    #[serde(rename = "resource")]
213    Resource { resource: ResourceContents },
214}
215
216#[derive(Debug, Deserialize)]
217#[serde(rename_all = "camelCase")]
218pub struct PromptsGetResponse {
219    #[serde(skip_serializing_if = "Option::is_none")]
220    pub description: Option<String>,
221    pub messages: Vec<PromptMessage>,
222    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
223    pub meta: Option<HashMap<String, serde_json::Value>>,
224}
225
226#[derive(Debug, Deserialize)]
227#[serde(rename_all = "camelCase")]
228pub struct PromptsListResponse {
229    pub prompts: Vec<Prompt>,
230    #[serde(skip_serializing_if = "Option::is_none")]
231    pub next_cursor: Option<String>,
232    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
233    pub meta: Option<HashMap<String, serde_json::Value>>,
234}
235
236#[derive(Debug, Deserialize)]
237#[serde(rename_all = "camelCase")]
238pub struct CompletionCompleteResponse {
239    pub completion: CompletionResult,
240    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
241    pub meta: Option<HashMap<String, serde_json::Value>>,
242}
243
244#[derive(Debug, Deserialize)]
245#[serde(rename_all = "camelCase")]
246pub struct CompletionResult {
247    pub values: Vec<String>,
248    #[serde(skip_serializing_if = "Option::is_none")]
249    pub total: Option<u32>,
250    #[serde(skip_serializing_if = "Option::is_none")]
251    pub has_more: Option<bool>,
252    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
253    pub meta: Option<HashMap<String, serde_json::Value>>,
254}
255
256#[derive(Debug, Deserialize, Serialize)]
257#[serde(rename_all = "camelCase")]
258pub struct Prompt {
259    pub name: String,
260    #[serde(skip_serializing_if = "Option::is_none")]
261    pub description: Option<String>,
262    #[serde(skip_serializing_if = "Option::is_none")]
263    pub arguments: Option<Vec<PromptArgument>>,
264}
265
266#[derive(Debug, Deserialize, Serialize)]
267#[serde(rename_all = "camelCase")]
268pub struct PromptArgument {
269    pub name: String,
270    #[serde(skip_serializing_if = "Option::is_none")]
271    pub description: Option<String>,
272    #[serde(skip_serializing_if = "Option::is_none")]
273    pub required: Option<bool>,
274}
275
276#[derive(Debug, Serialize, Deserialize)]
277#[serde(rename_all = "camelCase")]
278pub struct ClientCapabilities {
279    #[serde(skip_serializing_if = "Option::is_none")]
280    pub experimental: Option<HashMap<String, serde_json::Value>>,
281    #[serde(skip_serializing_if = "Option::is_none")]
282    pub sampling: Option<serde_json::Value>,
283    #[serde(skip_serializing_if = "Option::is_none")]
284    pub roots: Option<RootsCapabilities>,
285}
286
287#[derive(Debug, Serialize, Deserialize)]
288#[serde(rename_all = "camelCase")]
289pub struct ServerCapabilities {
290    #[serde(skip_serializing_if = "Option::is_none")]
291    pub experimental: Option<HashMap<String, serde_json::Value>>,
292    #[serde(skip_serializing_if = "Option::is_none")]
293    pub logging: Option<serde_json::Value>,
294    #[serde(skip_serializing_if = "Option::is_none")]
295    pub prompts: Option<PromptsCapabilities>,
296    #[serde(skip_serializing_if = "Option::is_none")]
297    pub resources: Option<ResourcesCapabilities>,
298    #[serde(skip_serializing_if = "Option::is_none")]
299    pub tools: Option<ToolsCapabilities>,
300}
301
302#[derive(Debug, Serialize, Deserialize)]
303#[serde(rename_all = "camelCase")]
304pub struct PromptsCapabilities {
305    #[serde(skip_serializing_if = "Option::is_none")]
306    pub list_changed: Option<bool>,
307}
308
309#[derive(Debug, Serialize, Deserialize)]
310#[serde(rename_all = "camelCase")]
311pub struct ResourcesCapabilities {
312    #[serde(skip_serializing_if = "Option::is_none")]
313    pub subscribe: Option<bool>,
314    #[serde(skip_serializing_if = "Option::is_none")]
315    pub list_changed: Option<bool>,
316}
317
318#[derive(Debug, Serialize, Deserialize)]
319#[serde(rename_all = "camelCase")]
320pub struct ToolsCapabilities {
321    #[serde(skip_serializing_if = "Option::is_none")]
322    pub list_changed: Option<bool>,
323}
324
325#[derive(Debug, Serialize, Deserialize)]
326#[serde(rename_all = "camelCase")]
327pub struct RootsCapabilities {
328    #[serde(skip_serializing_if = "Option::is_none")]
329    pub list_changed: Option<bool>,
330}
331
332#[derive(Debug, Serialize, Deserialize)]
333#[serde(rename_all = "camelCase")]
334pub struct Tool {
335    pub name: String,
336    #[serde(skip_serializing_if = "Option::is_none")]
337    pub description: Option<String>,
338    pub input_schema: serde_json::Value,
339}
340
341#[derive(Debug, Serialize, Deserialize)]
342#[serde(rename_all = "camelCase")]
343pub struct Implementation {
344    pub name: String,
345    pub version: String,
346}
347
348#[derive(Debug, Serialize, Deserialize)]
349#[serde(rename_all = "camelCase")]
350pub struct Resource {
351    pub uri: Url,
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 mime_type: Option<String>,
357}
358
359#[derive(Debug, Serialize, Deserialize)]
360#[serde(rename_all = "camelCase")]
361pub struct ResourceContents {
362    pub uri: Url,
363    #[serde(skip_serializing_if = "Option::is_none")]
364    pub mime_type: Option<String>,
365}
366
367#[derive(Debug, Serialize, Deserialize)]
368#[serde(rename_all = "camelCase")]
369pub struct TextResourceContents {
370    pub uri: Url,
371    #[serde(skip_serializing_if = "Option::is_none")]
372    pub mime_type: Option<String>,
373    pub text: String,
374}
375
376#[derive(Debug, Serialize, Deserialize)]
377#[serde(rename_all = "camelCase")]
378pub struct BlobResourceContents {
379    pub uri: Url,
380    #[serde(skip_serializing_if = "Option::is_none")]
381    pub mime_type: Option<String>,
382    pub blob: String,
383}
384
385#[derive(Debug, Serialize, Deserialize)]
386#[serde(rename_all = "camelCase")]
387pub struct ResourceTemplate {
388    pub uri_template: String,
389    pub name: String,
390    #[serde(skip_serializing_if = "Option::is_none")]
391    pub description: Option<String>,
392    #[serde(skip_serializing_if = "Option::is_none")]
393    pub mime_type: Option<String>,
394}
395
396#[derive(Debug, Serialize, Deserialize)]
397#[serde(rename_all = "lowercase")]
398pub enum LoggingLevel {
399    Debug,
400    Info,
401    Notice,
402    Warning,
403    Error,
404    Critical,
405    Alert,
406    Emergency,
407}
408
409#[derive(Debug, Serialize, Deserialize)]
410#[serde(rename_all = "camelCase")]
411pub struct ModelPreferences {
412    #[serde(skip_serializing_if = "Option::is_none")]
413    pub hints: Option<Vec<ModelHint>>,
414    #[serde(skip_serializing_if = "Option::is_none")]
415    pub cost_priority: Option<f64>,
416    #[serde(skip_serializing_if = "Option::is_none")]
417    pub speed_priority: Option<f64>,
418    #[serde(skip_serializing_if = "Option::is_none")]
419    pub intelligence_priority: Option<f64>,
420}
421
422#[derive(Debug, Serialize, Deserialize)]
423#[serde(rename_all = "camelCase")]
424pub struct ModelHint {
425    #[serde(skip_serializing_if = "Option::is_none")]
426    pub name: Option<String>,
427}
428
429#[derive(Debug, Serialize)]
430#[serde(rename_all = "camelCase")]
431pub enum NotificationType {
432    Initialized,
433    Progress,
434    Message,
435    ResourcesUpdated,
436    ResourcesListChanged,
437    ToolsListChanged,
438    PromptsListChanged,
439    RootsListChanged,
440}
441
442impl NotificationType {
443    pub fn as_str(&self) -> &'static str {
444        match self {
445            NotificationType::Initialized => "notifications/initialized",
446            NotificationType::Progress => "notifications/progress",
447            NotificationType::Message => "notifications/message",
448            NotificationType::ResourcesUpdated => "notifications/resources/updated",
449            NotificationType::ResourcesListChanged => "notifications/resources/list_changed",
450            NotificationType::ToolsListChanged => "notifications/tools/list_changed",
451            NotificationType::PromptsListChanged => "notifications/prompts/list_changed",
452            NotificationType::RootsListChanged => "notifications/roots/list_changed",
453        }
454    }
455}
456
457#[derive(Debug, Serialize)]
458#[serde(untagged)]
459pub enum ClientNotification {
460    Initialized,
461    Progress(ProgressParams),
462    RootsListChanged,
463}
464
465#[derive(Debug, Serialize, Deserialize)]
466#[serde(untagged)]
467pub enum ProgressToken {
468    String(String),
469    Number(f64),
470}
471
472#[derive(Debug, Serialize)]
473#[serde(rename_all = "camelCase")]
474pub struct ProgressParams {
475    pub progress_token: ProgressToken,
476    pub progress: f64,
477    #[serde(skip_serializing_if = "Option::is_none")]
478    pub total: Option<f64>,
479    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
480    pub meta: Option<HashMap<String, serde_json::Value>>,
481}
482
483pub enum CompletionTotal {
484    Exact(u32),
485    HasMore,
486    Unknown,
487}
488
489impl CompletionTotal {
490    pub fn from_options(has_more: Option<bool>, total: Option<u32>) -> Self {
491        match (has_more, total) {
492            (_, Some(count)) => CompletionTotal::Exact(count),
493            (Some(true), _) => CompletionTotal::HasMore,
494            _ => CompletionTotal::Unknown,
495        }
496    }
497}
498
499pub struct Completion {
500    pub values: Vec<String>,
501    pub total: CompletionTotal,
502}
503
504#[derive(Debug, Deserialize)]
505#[serde(rename_all = "camelCase")]
506pub struct CallToolResponse {
507    pub content: Vec<ToolResponseContent>,
508    #[serde(skip_serializing_if = "Option::is_none")]
509    pub is_error: Option<bool>,
510    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
511    pub meta: Option<HashMap<String, serde_json::Value>>,
512}
513
514#[derive(Debug, Serialize, Deserialize)]
515#[serde(tag = "type")]
516pub enum ToolResponseContent {
517    #[serde(rename = "text")]
518    Text { text: String },
519    #[serde(rename = "image")]
520    Image { data: String, mime_type: String },
521    #[serde(rename = "resource")]
522    Resource { resource: ResourceContents },
523}
524
525#[derive(Debug, Deserialize)]
526#[serde(rename_all = "camelCase")]
527pub struct ListToolsResponse {
528    pub tools: Vec<Tool>,
529    #[serde(skip_serializing_if = "Option::is_none")]
530    pub next_cursor: Option<String>,
531    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
532    pub meta: Option<HashMap<String, serde_json::Value>>,
533}
534
535#[derive(Debug, Deserialize)]
536#[serde(rename_all = "camelCase")]
537pub struct ListRootsResponse {
538    pub roots: Vec<Root>,
539    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
540    pub meta: Option<HashMap<String, serde_json::Value>>,
541}
542
543#[derive(Debug, Serialize, Deserialize)]
544#[serde(rename_all = "camelCase")]
545pub struct Root {
546    pub uri: Url,
547    #[serde(skip_serializing_if = "Option::is_none")]
548    pub name: Option<String>,
549}