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