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 registered_at: std::time::SystemTime,
221}
222
223impl ToolMetadata {
224 pub fn new(name: String, description: Option<String>, input_schema: Value) -> Self {
225 Self {
226 name,
227 description,
228 input_schema,
229 registered_at: std::time::SystemTime::now(),
230 }
231 }
232}
233
234#[derive(Debug, Clone, Serialize, Deserialize)]
236#[serde(rename_all = "camelCase")]
237pub struct ListToolsResult {
238 pub tools: Vec<McpTool>,
239 #[serde(default, skip_serializing_if = "Option::is_none")]
240 pub next_cursor: Option<String>,
241}
242
243#[derive(Debug, Clone, Serialize, Deserialize)]
245pub struct CallToolParams {
246 pub name: String,
247 #[serde(default)]
248 pub arguments: Value,
249}
250
251#[derive(Debug, Clone, Serialize, Deserialize)]
253#[serde(rename_all = "camelCase")]
254pub struct CallToolResult {
255 pub content: Vec<ToolContent>,
256 #[serde(default)]
257 pub is_error: bool,
258}
259
260#[derive(Debug, Clone, Serialize, Deserialize)]
261#[serde(tag = "type", rename_all = "snake_case")]
262pub enum ToolContent {
263 Text { text: String },
264 Image { data: String, mime_type: String },
265 Resource { resource: ResourceContents },
266}
267
268#[derive(Debug, Clone, Serialize, Deserialize)]
272#[serde(rename_all = "camelCase")]
273pub struct McpResource {
274 pub uri: String,
275 pub name: String,
276 #[serde(default, skip_serializing_if = "Option::is_none")]
277 pub description: Option<String>,
278 #[serde(default, skip_serializing_if = "Option::is_none")]
279 pub mime_type: Option<String>,
280}
281
282#[derive(Debug, Clone, Serialize, Deserialize)]
284pub struct ResourceMetadata {
285 pub uri: String,
286 pub name: String,
287 pub description: Option<String>,
288 pub mime_type: Option<String>,
289 pub registered_at: std::time::SystemTime,
290}
291
292impl ResourceMetadata {
293 pub fn new(
294 uri: String,
295 name: String,
296 description: Option<String>,
297 mime_type: Option<String>,
298 ) -> Self {
299 Self {
300 uri,
301 name,
302 description,
303 mime_type,
304 registered_at: std::time::SystemTime::now(),
305 }
306 }
307}
308
309#[derive(Debug, Clone, Serialize, Deserialize)]
311#[serde(rename_all = "camelCase")]
312pub struct ListResourcesResult {
313 pub resources: Vec<McpResource>,
314 #[serde(default, skip_serializing_if = "Option::is_none")]
315 pub next_cursor: Option<String>,
316}
317
318#[derive(Debug, Clone, Serialize, Deserialize)]
320pub struct ReadResourceParams {
321 pub uri: String,
322}
323
324#[derive(Debug, Clone, Serialize, Deserialize)]
326#[serde(rename_all = "camelCase")]
327pub struct ResourceContents {
328 pub uri: String,
329 #[serde(default, skip_serializing_if = "Option::is_none")]
330 pub mime_type: Option<String>,
331 #[serde(flatten)]
332 pub content: ResourceContent,
333}
334
335#[derive(Debug, Clone, Serialize, Deserialize)]
336#[serde(untagged)]
337pub enum ResourceContent {
338 Text { text: String },
339 Blob { blob: String }, }
341
342#[derive(Debug, Clone, Serialize, Deserialize)]
344pub struct ReadResourceResult {
345 pub contents: Vec<ResourceContents>,
346}
347
348#[derive(Debug, Clone, Serialize, Deserialize)]
352pub struct McpPrompt {
353 pub name: String,
354 #[serde(default, skip_serializing_if = "Option::is_none")]
355 pub description: Option<String>,
356 #[serde(default, skip_serializing_if = "Vec::is_empty")]
357 pub arguments: Vec<PromptArgument>,
358}
359
360#[derive(Debug, Clone, Serialize, Deserialize)]
361pub struct PromptArgument {
362 pub name: String,
363 #[serde(default, skip_serializing_if = "Option::is_none")]
364 pub description: Option<String>,
365 #[serde(default)]
366 pub required: bool,
367}
368
369#[derive(Debug, Clone, Serialize, Deserialize)]
371#[serde(rename_all = "camelCase")]
372pub struct ListPromptsResult {
373 pub prompts: Vec<McpPrompt>,
374 #[serde(default, skip_serializing_if = "Option::is_none")]
375 pub next_cursor: Option<String>,
376}
377
378#[derive(Debug, Clone, Serialize, Deserialize)]
380pub struct GetPromptParams {
381 pub name: String,
382 #[serde(default)]
383 pub arguments: Value,
384}
385
386#[derive(Debug, Clone, Serialize, Deserialize)]
388pub struct PromptMessage {
389 pub role: PromptRole,
390 pub content: PromptContent,
391}
392
393#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
394#[serde(rename_all = "lowercase")]
395pub enum PromptRole {
396 User,
397 Assistant,
398}
399
400#[derive(Debug, Clone, Serialize, Deserialize)]
401#[serde(tag = "type", rename_all = "snake_case")]
402pub enum PromptContent {
403 Text { text: String },
404 Image { data: String, mime_type: String },
405 Resource { resource: ResourceContents },
406}
407
408#[derive(Debug, Clone, Serialize, Deserialize)]
410pub struct GetPromptResult {
411 #[serde(default, skip_serializing_if = "Option::is_none")]
412 pub description: Option<String>,
413 pub messages: Vec<PromptMessage>,
414}
415
416#[derive(Debug, Clone, Serialize, Deserialize)]
420#[serde(rename_all = "camelCase")]
421pub struct CreateMessageParams {
422 pub messages: Vec<SamplingMessage>,
423 #[serde(default, skip_serializing_if = "Option::is_none")]
424 pub model_preferences: Option<ModelPreferences>,
425 #[serde(default, skip_serializing_if = "Option::is_none")]
426 pub system_prompt: Option<String>,
427 #[serde(default, skip_serializing_if = "Option::is_none")]
428 pub max_tokens: Option<i32>,
429}
430
431#[derive(Debug, Clone, Serialize, Deserialize)]
432pub struct SamplingMessage {
433 pub role: PromptRole,
434 pub content: SamplingContent,
435}
436
437#[derive(Debug, Clone, Serialize, Deserialize)]
438#[serde(tag = "type", rename_all = "snake_case")]
439pub enum SamplingContent {
440 Text { text: String },
441 Image { data: String, mime_type: String },
442}
443
444#[derive(Debug, Clone, Serialize, Deserialize)]
445#[serde(rename_all = "camelCase")]
446pub struct ModelPreferences {
447 #[serde(default, skip_serializing_if = "Vec::is_empty")]
448 pub hints: Vec<ModelHint>,
449 #[serde(default, skip_serializing_if = "Option::is_none")]
450 pub cost_priority: Option<f32>,
451 #[serde(default, skip_serializing_if = "Option::is_none")]
452 pub speed_priority: Option<f32>,
453 #[serde(default, skip_serializing_if = "Option::is_none")]
454 pub intelligence_priority: Option<f32>,
455}
456
457#[derive(Debug, Clone, Serialize, Deserialize)]
458pub struct ModelHint {
459 #[serde(default, skip_serializing_if = "Option::is_none")]
460 pub name: Option<String>,
461}
462
463#[derive(Debug, Clone, Serialize, Deserialize)]
465#[serde(rename_all = "camelCase")]
466pub struct CreateMessageResult {
467 pub role: PromptRole,
468 pub content: SamplingContent,
469 pub model: String,
470 #[serde(default, skip_serializing_if = "Option::is_none")]
471 pub stop_reason: Option<String>,
472}
473
474#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
477#[serde(rename_all = "lowercase")]
478pub enum LogLevel {
479 Debug,
480 Info,
481 Notice,
482 Warning,
483 Error,
484 Critical,
485 Alert,
486 Emergency,
487}
488
489#[derive(Debug, Clone, Serialize, Deserialize)]
490pub struct LoggingMessageParams {
491 pub level: LogLevel,
492 #[serde(default, skip_serializing_if = "Option::is_none")]
493 pub logger: Option<String>,
494 pub data: Value,
495}
496
497pub const PROTOCOL_VERSION: &str = "2024-11-05";
500pub const JSONRPC_VERSION: &str = "2.0";
501
502impl JsonRpcRequest {
503 pub fn new(id: impl Into<RequestId>, method: impl Into<String>, params: Option<Value>) -> Self {
504 Self {
505 jsonrpc: JSONRPC_VERSION.to_string(),
506 id: id.into(),
507 method: method.into(),
508 params,
509 }
510 }
511}
512
513impl JsonRpcResponse {
514 pub fn success(id: RequestId, result: Value) -> Self {
515 Self {
516 jsonrpc: JSONRPC_VERSION.to_string(),
517 id,
518 result: Some(result),
519 error: None,
520 }
521 }
522
523 pub fn error(id: RequestId, error: JsonRpcError) -> Self {
524 Self {
525 jsonrpc: JSONRPC_VERSION.to_string(),
526 id,
527 result: None,
528 error: Some(error),
529 }
530 }
531}
532
533impl JsonRpcNotification {
534 pub fn new(method: impl Into<String>, params: Option<Value>) -> Self {
535 Self {
536 jsonrpc: JSONRPC_VERSION.to_string(),
537 method: method.into(),
538 params,
539 }
540 }
541}