types.rs

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