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 { code: -32700, message: msg.into(), data: None }
71 }
72
73 pub fn invalid_request(msg: impl Into<String>) -> Self {
74 Self { code: -32600, message: msg.into(), data: None }
75 }
76
77 pub fn method_not_found(method: &str) -> Self {
78 Self { code: -32601, message: format!("Method not found: {}", method), data: None }
79 }
80
81 pub fn invalid_params(msg: impl Into<String>) -> Self {
82 Self { code: -32602, message: msg.into(), data: None }
83 }
84
85 pub fn internal_error(msg: impl Into<String>) -> Self {
86 Self { code: -32603, message: msg.into(), data: None }
87 }
88}
89
90#[derive(Debug, Clone, Default, Serialize, Deserialize)]
94pub struct ClientCapabilities {
95 #[serde(default, skip_serializing_if = "Option::is_none")]
96 pub roots: Option<RootsCapability>,
97 #[serde(default, skip_serializing_if = "Option::is_none")]
98 pub sampling: Option<SamplingCapability>,
99 #[serde(default, skip_serializing_if = "Option::is_none")]
100 pub experimental: Option<Value>,
101}
102
103#[derive(Debug, Clone, Default, Serialize, Deserialize)]
104pub struct RootsCapability {
105 #[serde(default)]
106 pub list_changed: bool,
107}
108
109#[derive(Debug, Clone, Default, Serialize, Deserialize)]
110pub struct SamplingCapability {}
111
112#[derive(Debug, Clone, Default, Serialize, Deserialize)]
114pub struct ServerCapabilities {
115 #[serde(default, skip_serializing_if = "Option::is_none")]
116 pub tools: Option<ToolsCapability>,
117 #[serde(default, skip_serializing_if = "Option::is_none")]
118 pub resources: Option<ResourcesCapability>,
119 #[serde(default, skip_serializing_if = "Option::is_none")]
120 pub prompts: Option<PromptsCapability>,
121 #[serde(default, skip_serializing_if = "Option::is_none")]
122 pub logging: Option<LoggingCapability>,
123 #[serde(default, skip_serializing_if = "Option::is_none")]
124 pub experimental: Option<Value>,
125}
126
127#[derive(Debug, Clone, Default, Serialize, Deserialize)]
128pub struct ToolsCapability {
129 #[serde(default)]
130 pub list_changed: bool,
131}
132
133#[derive(Debug, Clone, Default, Serialize, Deserialize)]
134pub struct ResourcesCapability {
135 #[serde(default)]
136 pub subscribe: bool,
137 #[serde(default)]
138 pub list_changed: bool,
139}
140
141#[derive(Debug, Clone, Default, Serialize, Deserialize)]
142pub struct PromptsCapability {
143 #[serde(default)]
144 pub list_changed: bool,
145}
146
147#[derive(Debug, Clone, Default, Serialize, Deserialize)]
148pub struct LoggingCapability {}
149
150#[derive(Debug, Clone, Serialize, Deserialize)]
152#[serde(rename_all = "camelCase")]
153pub struct InitializeParams {
154 pub protocol_version: String,
155 pub capabilities: ClientCapabilities,
156 pub client_info: ClientInfo,
157}
158
159#[derive(Debug, Clone, Serialize, Deserialize)]
160pub struct ClientInfo {
161 pub name: String,
162 pub version: String,
163}
164
165#[derive(Debug, Clone, Serialize, Deserialize)]
167#[serde(rename_all = "camelCase")]
168pub struct InitializeResult {
169 pub protocol_version: String,
170 pub capabilities: ServerCapabilities,
171 pub server_info: ServerInfo,
172 #[serde(default, skip_serializing_if = "Option::is_none")]
173 pub instructions: Option<String>,
174}
175
176#[derive(Debug, Clone, Serialize, Deserialize)]
177pub struct ServerInfo {
178 pub name: String,
179 pub version: String,
180}
181
182#[derive(Debug, Clone, Serialize, Deserialize)]
186#[serde(rename_all = "camelCase")]
187pub struct McpTool {
188 pub name: String,
189 #[serde(default, skip_serializing_if = "Option::is_none")]
190 pub description: Option<String>,
191 pub input_schema: Value, }
193
194#[derive(Debug, Clone, Serialize, Deserialize)]
196pub struct ToolMetadata {
197 pub name: String,
198 pub description: Option<String>,
199 pub input_schema: Value,
200 pub registered_at: std::time::SystemTime,
201}
202
203impl ToolMetadata {
204 pub fn new(name: String, description: Option<String>, input_schema: Value) -> Self {
205 Self {
206 name,
207 description,
208 input_schema,
209 registered_at: std::time::SystemTime::now(),
210 }
211 }
212}
213
214#[derive(Debug, Clone, Serialize, Deserialize)]
216#[serde(rename_all = "camelCase")]
217pub struct ListToolsResult {
218 pub tools: Vec<McpTool>,
219 #[serde(default, skip_serializing_if = "Option::is_none")]
220 pub next_cursor: Option<String>,
221}
222
223#[derive(Debug, Clone, Serialize, Deserialize)]
225pub struct CallToolParams {
226 pub name: String,
227 #[serde(default)]
228 pub arguments: Value,
229}
230
231#[derive(Debug, Clone, Serialize, Deserialize)]
233#[serde(rename_all = "camelCase")]
234pub struct CallToolResult {
235 pub content: Vec<ToolContent>,
236 #[serde(default)]
237 pub is_error: bool,
238}
239
240#[derive(Debug, Clone, Serialize, Deserialize)]
241#[serde(tag = "type", rename_all = "snake_case")]
242pub enum ToolContent {
243 Text { text: String },
244 Image { data: String, mime_type: String },
245 Resource { resource: ResourceContents },
246}
247
248#[derive(Debug, Clone, Serialize, Deserialize)]
252#[serde(rename_all = "camelCase")]
253pub struct McpResource {
254 pub uri: String,
255 pub name: String,
256 #[serde(default, skip_serializing_if = "Option::is_none")]
257 pub description: Option<String>,
258 #[serde(default, skip_serializing_if = "Option::is_none")]
259 pub mime_type: Option<String>,
260}
261
262#[derive(Debug, Clone, Serialize, Deserialize)]
264pub struct ResourceMetadata {
265 pub uri: String,
266 pub name: String,
267 pub description: Option<String>,
268 pub mime_type: Option<String>,
269 pub registered_at: std::time::SystemTime,
270}
271
272impl ResourceMetadata {
273 pub fn new(uri: String, name: String, description: Option<String>, mime_type: Option<String>) -> Self {
274 Self {
275 uri,
276 name,
277 description,
278 mime_type,
279 registered_at: std::time::SystemTime::now(),
280 }
281 }
282}
283
284#[derive(Debug, Clone, Serialize, Deserialize)]
286#[serde(rename_all = "camelCase")]
287pub struct ListResourcesResult {
288 pub resources: Vec<McpResource>,
289 #[serde(default, skip_serializing_if = "Option::is_none")]
290 pub next_cursor: Option<String>,
291}
292
293#[derive(Debug, Clone, Serialize, Deserialize)]
295pub struct ReadResourceParams {
296 pub uri: String,
297}
298
299#[derive(Debug, Clone, Serialize, Deserialize)]
301#[serde(rename_all = "camelCase")]
302pub struct ResourceContents {
303 pub uri: String,
304 #[serde(default, skip_serializing_if = "Option::is_none")]
305 pub mime_type: Option<String>,
306 #[serde(flatten)]
307 pub content: ResourceContent,
308}
309
310#[derive(Debug, Clone, Serialize, Deserialize)]
311#[serde(untagged)]
312pub enum ResourceContent {
313 Text { text: String },
314 Blob { blob: String }, }
316
317#[derive(Debug, Clone, Serialize, Deserialize)]
319pub struct ReadResourceResult {
320 pub contents: Vec<ResourceContents>,
321}
322
323#[derive(Debug, Clone, Serialize, Deserialize)]
327pub struct McpPrompt {
328 pub name: String,
329 #[serde(default, skip_serializing_if = "Option::is_none")]
330 pub description: Option<String>,
331 #[serde(default, skip_serializing_if = "Vec::is_empty")]
332 pub arguments: Vec<PromptArgument>,
333}
334
335#[derive(Debug, Clone, Serialize, Deserialize)]
336pub struct PromptArgument {
337 pub name: String,
338 #[serde(default, skip_serializing_if = "Option::is_none")]
339 pub description: Option<String>,
340 #[serde(default)]
341 pub required: bool,
342}
343
344#[derive(Debug, Clone, Serialize, Deserialize)]
346#[serde(rename_all = "camelCase")]
347pub struct ListPromptsResult {
348 pub prompts: Vec<McpPrompt>,
349 #[serde(default, skip_serializing_if = "Option::is_none")]
350 pub next_cursor: Option<String>,
351}
352
353#[derive(Debug, Clone, Serialize, Deserialize)]
355pub struct GetPromptParams {
356 pub name: String,
357 #[serde(default)]
358 pub arguments: Value,
359}
360
361#[derive(Debug, Clone, Serialize, Deserialize)]
363pub struct PromptMessage {
364 pub role: PromptRole,
365 pub content: PromptContent,
366}
367
368#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
369#[serde(rename_all = "lowercase")]
370pub enum PromptRole {
371 User,
372 Assistant,
373}
374
375#[derive(Debug, Clone, Serialize, Deserialize)]
376#[serde(tag = "type", rename_all = "snake_case")]
377pub enum PromptContent {
378 Text { text: String },
379 Image { data: String, mime_type: String },
380 Resource { resource: ResourceContents },
381}
382
383#[derive(Debug, Clone, Serialize, Deserialize)]
385pub struct GetPromptResult {
386 #[serde(default, skip_serializing_if = "Option::is_none")]
387 pub description: Option<String>,
388 pub messages: Vec<PromptMessage>,
389}
390
391#[derive(Debug, Clone, Serialize, Deserialize)]
395#[serde(rename_all = "camelCase")]
396pub struct CreateMessageParams {
397 pub messages: Vec<SamplingMessage>,
398 #[serde(default, skip_serializing_if = "Option::is_none")]
399 pub model_preferences: Option<ModelPreferences>,
400 #[serde(default, skip_serializing_if = "Option::is_none")]
401 pub system_prompt: Option<String>,
402 #[serde(default, skip_serializing_if = "Option::is_none")]
403 pub max_tokens: Option<i32>,
404}
405
406#[derive(Debug, Clone, Serialize, Deserialize)]
407pub struct SamplingMessage {
408 pub role: PromptRole,
409 pub content: SamplingContent,
410}
411
412#[derive(Debug, Clone, Serialize, Deserialize)]
413#[serde(tag = "type", rename_all = "snake_case")]
414pub enum SamplingContent {
415 Text { text: String },
416 Image { data: String, mime_type: String },
417}
418
419#[derive(Debug, Clone, Serialize, Deserialize)]
420#[serde(rename_all = "camelCase")]
421pub struct ModelPreferences {
422 #[serde(default, skip_serializing_if = "Vec::is_empty")]
423 pub hints: Vec<ModelHint>,
424 #[serde(default, skip_serializing_if = "Option::is_none")]
425 pub cost_priority: Option<f32>,
426 #[serde(default, skip_serializing_if = "Option::is_none")]
427 pub speed_priority: Option<f32>,
428 #[serde(default, skip_serializing_if = "Option::is_none")]
429 pub intelligence_priority: Option<f32>,
430}
431
432#[derive(Debug, Clone, Serialize, Deserialize)]
433pub struct ModelHint {
434 #[serde(default, skip_serializing_if = "Option::is_none")]
435 pub name: Option<String>,
436}
437
438#[derive(Debug, Clone, Serialize, Deserialize)]
440#[serde(rename_all = "camelCase")]
441pub struct CreateMessageResult {
442 pub role: PromptRole,
443 pub content: SamplingContent,
444 pub model: String,
445 #[serde(default, skip_serializing_if = "Option::is_none")]
446 pub stop_reason: Option<String>,
447}
448
449#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
452#[serde(rename_all = "lowercase")]
453pub enum LogLevel {
454 Debug,
455 Info,
456 Notice,
457 Warning,
458 Error,
459 Critical,
460 Alert,
461 Emergency,
462}
463
464#[derive(Debug, Clone, Serialize, Deserialize)]
465pub struct LoggingMessageParams {
466 pub level: LogLevel,
467 #[serde(default, skip_serializing_if = "Option::is_none")]
468 pub logger: Option<String>,
469 pub data: Value,
470}
471
472pub const PROTOCOL_VERSION: &str = "2024-11-05";
475pub const JSONRPC_VERSION: &str = "2.0";
476
477impl JsonRpcRequest {
478 pub fn new(id: impl Into<RequestId>, method: impl Into<String>, params: Option<Value>) -> Self {
479 Self {
480 jsonrpc: JSONRPC_VERSION.to_string(),
481 id: id.into(),
482 method: method.into(),
483 params,
484 }
485 }
486}
487
488impl JsonRpcResponse {
489 pub fn success(id: RequestId, result: Value) -> Self {
490 Self {
491 jsonrpc: JSONRPC_VERSION.to_string(),
492 id,
493 result: Some(result),
494 error: None,
495 }
496 }
497
498 pub fn error(id: RequestId, error: JsonRpcError) -> Self {
499 Self {
500 jsonrpc: JSONRPC_VERSION.to_string(),
501 id,
502 result: None,
503 error: Some(error),
504 }
505 }
506}
507
508impl JsonRpcNotification {
509 pub fn new(method: impl Into<String>, params: Option<Value>) -> Self {
510 Self {
511 jsonrpc: JSONRPC_VERSION.to_string(),
512 method: method.into(),
513 params,
514 }
515 }
516}