1use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6#[derive(Debug, Deserialize)]
8pub struct McpRequest {
9 pub jsonrpc: String,
10 pub id: Value,
11 pub method: String,
12 #[serde(default)]
13 pub params: Option<Value>,
14}
15
16#[derive(Debug, Serialize)]
18pub struct McpResponse {
19 pub jsonrpc: String,
20 pub id: Value,
21 #[serde(skip_serializing_if = "Option::is_none")]
22 pub result: Option<Value>,
23 #[serde(skip_serializing_if = "Option::is_none")]
24 pub error: Option<McpError>,
25}
26
27impl McpResponse {
28 pub fn success(id: Value, result: Value) -> Self {
30 Self {
31 jsonrpc: "2.0".to_string(),
32 id,
33 result: Some(result),
34 error: None,
35 }
36 }
37
38 pub fn error(id: Value, error: McpError) -> Self {
40 Self {
41 jsonrpc: "2.0".to_string(),
42 id,
43 result: None,
44 error: Some(error),
45 }
46 }
47}
48
49#[derive(Debug, Serialize)]
51pub struct McpError {
52 pub code: i32,
53 pub message: String,
54 #[serde(skip_serializing_if = "Option::is_none")]
55 pub data: Option<Value>,
56}
57
58impl McpError {
59 pub const PARSE_ERROR: i32 = -32700;
61 pub const INVALID_REQUEST: i32 = -32600;
62 pub const METHOD_NOT_FOUND: i32 = -32601;
63 pub const INVALID_PARAMS: i32 = -32602;
64 pub const INTERNAL_ERROR: i32 = -32603;
65
66 pub fn parse_error(msg: impl Into<String>) -> Self {
67 Self {
68 code: Self::PARSE_ERROR,
69 message: msg.into(),
70 data: None,
71 }
72 }
73
74 pub fn method_not_found(method: &str) -> Self {
75 Self {
76 code: Self::METHOD_NOT_FOUND,
77 message: format!("Method not found: {}", method),
78 data: None,
79 }
80 }
81
82 pub fn invalid_params(msg: impl Into<String>) -> Self {
83 Self {
84 code: Self::INVALID_PARAMS,
85 message: msg.into(),
86 data: None,
87 }
88 }
89
90 pub fn internal_error(msg: impl Into<String>) -> Self {
91 Self {
92 code: Self::INTERNAL_ERROR,
93 message: msg.into(),
94 data: None,
95 }
96 }
97}
98
99#[derive(Debug, Clone, Serialize)]
101pub struct McpTool {
102 pub name: String,
103 pub description: String,
104 #[serde(rename = "inputSchema")]
105 pub input_schema: Value,
106}
107
108#[derive(Debug, Clone, Serialize)]
110pub struct McpResource {
111 pub uri: String,
112 pub name: String,
113 #[serde(skip_serializing_if = "Option::is_none")]
114 pub description: Option<String>,
115 #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
116 pub mime_type: Option<String>,
117}
118
119#[derive(Debug, Clone, Serialize)]
121pub struct McpResourceContents {
122 pub uri: String,
123 #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
124 pub mime_type: Option<String>,
125 #[serde(skip_serializing_if = "Option::is_none")]
126 pub text: Option<String>,
127 #[serde(skip_serializing_if = "Option::is_none")]
128 pub blob: Option<String>,
129}
130
131#[derive(Debug, Clone, Serialize)]
133pub struct McpToolContent {
134 #[serde(rename = "type")]
135 pub content_type: String,
136 pub text: String,
137}
138
139impl McpToolContent {
140 pub fn text(text: impl Into<String>) -> Self {
141 Self {
142 content_type: "text".to_string(),
143 text: text.into(),
144 }
145 }
146}
147
148#[derive(Debug, Clone, Serialize, Default)]
150pub struct McpCapabilities {
151 #[serde(skip_serializing_if = "Option::is_none")]
152 pub tools: Option<Value>,
153 #[serde(skip_serializing_if = "Option::is_none")]
154 pub resources: Option<Value>,
155 #[serde(skip_serializing_if = "Option::is_none")]
156 pub prompts: Option<Value>,
157}
158
159#[derive(Debug, Clone, Serialize)]
161pub struct McpServerInfo {
162 pub name: String,
163 pub version: String,
164}