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}