1use serde::{Deserialize, Serialize};
7use serde_json::Value;
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct JsonRpcRequest {
12 pub jsonrpc: String,
13 pub id: RequestId,
14 pub method: String,
15 #[serde(default, skip_serializing_if = "Option::is_none")]
16 pub params: Option<Value>,
17}
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct JsonRpcNotification {
22 pub jsonrpc: String,
23 pub method: String,
24 #[serde(default, skip_serializing_if = "Option::is_none")]
25 pub params: Option<Value>,
26}
27
28#[derive(Debug, Clone, Serialize, Deserialize)]
30pub struct JsonRpcResponse {
31 pub jsonrpc: String,
32 pub id: RequestId,
33 #[serde(skip_serializing_if = "Option::is_none")]
34 pub result: Option<Value>,
35 #[serde(skip_serializing_if = "Option::is_none")]
36 pub error: Option<JsonRpcError>,
37}
38
39#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
41#[serde(untagged)]
42pub enum RequestId {
43 String(String),
44 Number(i64),
45}
46
47impl From<i64> for RequestId {
48 fn from(n: i64) -> Self {
49 RequestId::Number(n)
50 }
51}
52
53impl From<String> for RequestId {
54 fn from(s: String) -> Self {
55 RequestId::String(s)
56 }
57}
58
59#[derive(Debug, Clone, Serialize, Deserialize)]
61pub struct JsonRpcError {
62 pub code: i32,
63 pub message: String,
64 #[serde(skip_serializing_if = "Option::is_none")]
65 pub data: Option<Value>,
66}
67
68impl JsonRpcError {
69 pub fn parse_error(msg: impl Into<String>) -> Self {
70 Self {
71 code: -32700,
72 message: msg.into(),
73 data: None,
74 }
75 }
76
77 pub fn invalid_request(msg: impl Into<String>) -> Self {
78 Self {
79 code: -32600,
80 message: msg.into(),
81 data: None,
82 }
83 }
84
85 pub fn method_not_found(method: &str) -> Self {
86 Self {
87 code: -32601,
88 message: format!("Method not found: {}", method),
89 data: None,
90 }
91 }
92
93 pub fn invalid_params(msg: impl Into<String>) -> Self {
94 Self {
95 code: -32602,
96 message: msg.into(),
97 data: None,
98 }
99 }
100
101 pub fn internal_error(msg: impl Into<String>) -> Self {
102 Self {
103 code: -32603,
104 message: msg.into(),
105 data: None,
106 }
107 }
108}
109
110#[derive(Debug, Clone, Default, Serialize, Deserialize)]
114pub struct ClientCapabilities {
115 #[serde(default, skip_serializing_if = "Option::is_none")]
116 pub roots: Option<RootsCapability>,
117 #[serde(default, skip_serializing_if = "Option::is_none")]
118 pub sampling: Option<SamplingCapability>,
119 #[serde(default, skip_serializing_if = "Option::is_none")]
120 pub experimental: Option<Value>,
121}
122
123#[derive(Debug, Clone, Default, Serialize, Deserialize)]
124pub struct RootsCapability {
125 #[serde(default)]
126 pub list_changed: bool,
127}
128
129#[derive(Debug, Clone, Default, Serialize, Deserialize)]
130pub struct SamplingCapability {}
131
132#[derive(Debug, Clone, Default, Serialize, Deserialize)]
134pub struct ServerCapabilities {
135 #[serde(default, skip_serializing_if = "Option::is_none")]
136 pub tools: Option<ToolsCapability>,
137 #[serde(default, skip_serializing_if = "Option::is_none")]
138 pub resources: Option<ResourcesCapability>,
139 #[serde(default, skip_serializing_if = "Option::is_none")]
140 pub prompts: Option<PromptsCapability>,
141 #[serde(default, skip_serializing_if = "Option::is_none")]
142 pub logging: Option<LoggingCapability>,
143 #[serde(default, skip_serializing_if = "Option::is_none")]
144 pub experimental: Option<Value>,
145}
146
147#[derive(Debug, Clone, Default, Serialize, Deserialize)]
148pub struct ToolsCapability {
149 #[serde(default)]
150 pub list_changed: bool,
151}
152
153#[derive(Debug, Clone, Default, Serialize, Deserialize)]
154pub struct ResourcesCapability {
155 #[serde(default)]
156 pub subscribe: bool,
157 #[serde(default)]
158 pub list_changed: bool,
159}
160
161#[derive(Debug, Clone, Default, Serialize, Deserialize)]
162pub struct PromptsCapability {
163 #[serde(default)]
164 pub list_changed: bool,
165}
166
167#[derive(Debug, Clone, Default, Serialize, Deserialize)]
168pub struct LoggingCapability {}
169
170#[derive(Debug, Clone, Serialize, Deserialize)]
172#[serde(rename_all = "camelCase")]
173pub struct InitializeParams {
174 pub protocol_version: String,
175 pub capabilities: ClientCapabilities,
176 pub client_info: ClientInfo,
177}
178
179#[derive(Debug, Clone, Serialize, Deserialize)]
180pub struct ClientInfo {
181 pub name: String,
182 pub version: String,
183}
184
185#[derive(Debug, Clone, Serialize, Deserialize)]
187#[serde(rename_all = "camelCase")]
188pub struct InitializeResult {
189 pub protocol_version: String,
190 pub capabilities: ServerCapabilities,
191 pub server_info: ServerInfo,
192 #[serde(default, skip_serializing_if = "Option::is_none")]
193 pub instructions: Option<String>,
194}
195
196#[derive(Debug, Clone, Serialize, Deserialize)]
197pub struct ServerInfo {
198 pub name: String,
199 pub version: String,
200}
201
202#[derive(Debug, Clone, Serialize, Deserialize)]
206#[serde(rename_all = "camelCase")]
207pub struct McpTool {
208 pub name: String,
209 #[serde(default, skip_serializing_if = "Option::is_none")]
210 pub description: Option<String>,
211 pub input_schema: Value, }
213
214#[derive(Debug, Clone, Serialize, Deserialize)]
216pub struct ToolMetadata {
217 pub name: String,
218 pub description: Option<String>,
219 pub input_schema: Value,
220 pub endpoint: Option<String>,
222 pub metadata: Option<Value>,
224 pub registered_at: std::time::SystemTime,
225}
226
227impl ToolMetadata {
228 pub fn new(name: String, description: Option<String>, input_schema: Value) -> Self {
229 Self {
230 name,
231 description,
232 input_schema,
233 endpoint: None,
234 metadata: None,
235 registered_at: std::time::SystemTime::now(),
236 }
237 }
238
239 pub fn with_endpoint(mut self, endpoint: String) -> Self {
240 self.endpoint = Some(endpoint);
241 self
242 }
243
244 pub fn with_metadata(mut self, metadata: Value) -> Self {
245 self.metadata = Some(metadata);
246 self
247 }
248}
249
250#[derive(Debug, Clone, Serialize, Deserialize)]
252#[serde(rename_all = "camelCase")]
253pub struct ListToolsResult {
254 pub tools: Vec<McpTool>,
255 #[serde(default, skip_serializing_if = "Option::is_none")]
256 pub next_cursor: Option<String>,
257}
258
259#[derive(Debug, Clone, Serialize, Deserialize)]
261pub struct CallToolParams {
262 pub name: String,
263 #[serde(default)]
264 pub arguments: Value,
265}
266
267#[derive(Debug, Clone, Serialize, Deserialize)]
269#[serde(rename_all = "camelCase")]
270pub struct CallToolResult {
271 pub content: Vec<ToolContent>,
272 #[serde(default)]
273 pub is_error: bool,
274}
275
276#[derive(Debug, Clone, Serialize, Deserialize)]
277#[serde(tag = "type", rename_all = "snake_case")]
278pub enum ToolContent {
279 Text { text: String },
280 Image { data: String, mime_type: String },
281 Resource { resource: ResourceContents },
282}
283
284#[derive(Debug, Clone, Serialize, Deserialize)]
288#[serde(rename_all = "camelCase")]
289pub struct McpResource {
290 pub uri: String,
291 pub name: String,
292 #[serde(default, skip_serializing_if = "Option::is_none")]
293 pub description: Option<String>,
294 #[serde(default, skip_serializing_if = "Option::is_none")]
295 pub mime_type: Option<String>,
296}
297
298#[derive(Debug, Clone, Serialize, Deserialize)]
300pub struct ResourceMetadata {
301 pub uri: String,
302 pub name: String,
303 pub description: Option<String>,
304 pub mime_type: Option<String>,
305 pub registered_at: std::time::SystemTime,
306}
307
308impl ResourceMetadata {
309 pub fn new(
310 uri: String,
311 name: String,
312 description: Option<String>,
313 mime_type: Option<String>,
314 ) -> Self {
315 Self {
316 uri,
317 name,
318 description,
319 mime_type,
320 registered_at: std::time::SystemTime::now(),
321 }
322 }
323}
324
325#[derive(Debug, Clone, Serialize, Deserialize)]
327#[serde(rename_all = "camelCase")]
328pub struct ListResourcesResult {
329 pub resources: Vec<McpResource>,
330 #[serde(default, skip_serializing_if = "Option::is_none")]
331 pub next_cursor: Option<String>,
332}
333
334#[derive(Debug, Clone, Serialize, Deserialize)]
336pub struct ReadResourceParams {
337 pub uri: String,
338}
339
340#[derive(Debug, Clone, Serialize, Deserialize)]
342#[serde(rename_all = "camelCase")]
343pub struct ResourceContents {
344 pub uri: String,
345 #[serde(default, skip_serializing_if = "Option::is_none")]
346 pub mime_type: Option<String>,
347 #[serde(flatten)]
348 pub content: ResourceContent,
349}
350
351#[derive(Debug, Clone, Serialize, Deserialize)]
352#[serde(untagged)]
353pub enum ResourceContent {
354 Text { text: String },
355 Blob { blob: String }, }
357
358#[derive(Debug, Clone, Serialize, Deserialize)]
360pub struct ReadResourceResult {
361 pub contents: Vec<ResourceContents>,
362}
363
364#[derive(Debug, Clone, Serialize, Deserialize)]
368pub struct McpPrompt {
369 pub name: String,
370 #[serde(default, skip_serializing_if = "Option::is_none")]
371 pub description: Option<String>,
372 #[serde(default, skip_serializing_if = "Vec::is_empty")]
373 pub arguments: Vec<PromptArgument>,
374}
375
376#[derive(Debug, Clone, Serialize, Deserialize)]
377pub struct PromptArgument {
378 pub name: String,
379 #[serde(default, skip_serializing_if = "Option::is_none")]
380 pub description: Option<String>,
381 #[serde(default)]
382 pub required: bool,
383}
384
385#[derive(Debug, Clone, Serialize, Deserialize)]
387#[serde(rename_all = "camelCase")]
388pub struct ListPromptsResult {
389 pub prompts: Vec<McpPrompt>,
390 #[serde(default, skip_serializing_if = "Option::is_none")]
391 pub next_cursor: Option<String>,
392}
393
394#[derive(Debug, Clone, Serialize, Deserialize)]
396pub struct GetPromptParams {
397 pub name: String,
398 #[serde(default)]
399 pub arguments: Value,
400}
401
402#[derive(Debug, Clone, Serialize, Deserialize)]
404pub struct PromptMessage {
405 pub role: PromptRole,
406 pub content: PromptContent,
407}
408
409#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
410#[serde(rename_all = "lowercase")]
411pub enum PromptRole {
412 User,
413 Assistant,
414}
415
416#[derive(Debug, Clone, Serialize, Deserialize)]
417#[serde(tag = "type", rename_all = "snake_case")]
418pub enum PromptContent {
419 Text { text: String },
420 Image { data: String, mime_type: String },
421 Resource { resource: ResourceContents },
422}
423
424#[derive(Debug, Clone, Serialize, Deserialize)]
426pub struct GetPromptResult {
427 #[serde(default, skip_serializing_if = "Option::is_none")]
428 pub description: Option<String>,
429 pub messages: Vec<PromptMessage>,
430}
431
432#[derive(Debug, Clone, Serialize, Deserialize)]
436#[serde(rename_all = "camelCase")]
437pub struct CreateMessageParams {
438 pub messages: Vec<SamplingMessage>,
439 #[serde(default, skip_serializing_if = "Option::is_none")]
440 pub model_preferences: Option<ModelPreferences>,
441 #[serde(default, skip_serializing_if = "Option::is_none")]
442 pub system_prompt: Option<String>,
443 #[serde(default, skip_serializing_if = "Option::is_none")]
444 pub max_tokens: Option<i32>,
445}
446
447#[derive(Debug, Clone, Serialize, Deserialize)]
448pub struct SamplingMessage {
449 pub role: PromptRole,
450 pub content: SamplingContent,
451}
452
453#[derive(Debug, Clone, Serialize, Deserialize)]
454#[serde(tag = "type", rename_all = "snake_case")]
455pub enum SamplingContent {
456 Text { text: String },
457 Image { data: String, mime_type: String },
458}
459
460#[derive(Debug, Clone, Serialize, Deserialize)]
461#[serde(rename_all = "camelCase")]
462pub struct ModelPreferences {
463 #[serde(default, skip_serializing_if = "Vec::is_empty")]
464 pub hints: Vec<ModelHint>,
465 #[serde(default, skip_serializing_if = "Option::is_none")]
466 pub cost_priority: Option<f32>,
467 #[serde(default, skip_serializing_if = "Option::is_none")]
468 pub speed_priority: Option<f32>,
469 #[serde(default, skip_serializing_if = "Option::is_none")]
470 pub intelligence_priority: Option<f32>,
471}
472
473#[derive(Debug, Clone, Serialize, Deserialize)]
474pub struct ModelHint {
475 #[serde(default, skip_serializing_if = "Option::is_none")]
476 pub name: Option<String>,
477}
478
479#[derive(Debug, Clone, Serialize, Deserialize)]
481#[serde(rename_all = "camelCase")]
482pub struct CreateMessageResult {
483 pub role: PromptRole,
484 pub content: SamplingContent,
485 pub model: String,
486 #[serde(default, skip_serializing_if = "Option::is_none")]
487 pub stop_reason: Option<String>,
488}
489
490#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
493#[serde(rename_all = "lowercase")]
494pub enum LogLevel {
495 Debug,
496 Info,
497 Notice,
498 Warning,
499 Error,
500 Critical,
501 Alert,
502 Emergency,
503}
504
505#[derive(Debug, Clone, Serialize, Deserialize)]
506pub struct LoggingMessageParams {
507 pub level: LogLevel,
508 #[serde(default, skip_serializing_if = "Option::is_none")]
509 pub logger: Option<String>,
510 pub data: Value,
511}
512
513pub const PROTOCOL_VERSION: &str = "2024-11-05";
516pub const JSONRPC_VERSION: &str = "2.0";
517
518impl JsonRpcRequest {
519 pub fn new(id: impl Into<RequestId>, method: impl Into<String>, params: Option<Value>) -> Self {
520 Self {
521 jsonrpc: JSONRPC_VERSION.to_string(),
522 id: id.into(),
523 method: method.into(),
524 params,
525 }
526 }
527}
528
529impl JsonRpcResponse {
530 pub fn success(id: RequestId, result: Value) -> Self {
531 Self {
532 jsonrpc: JSONRPC_VERSION.to_string(),
533 id,
534 result: Some(result),
535 error: None,
536 }
537 }
538
539 pub fn error(id: RequestId, error: JsonRpcError) -> Self {
540 Self {
541 jsonrpc: JSONRPC_VERSION.to_string(),
542 id,
543 result: None,
544 error: Some(error),
545 }
546 }
547}
548
549impl JsonRpcNotification {
550 pub fn new(method: impl Into<String>, params: Option<Value>) -> Self {
551 Self {
552 jsonrpc: JSONRPC_VERSION.to_string(),
553 method: method.into(),
554 params,
555 }
556 }
557}