1use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6pub const MCP_VERSION: &str = "2024-11-05";
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct JsonRpcRequest {
12 pub jsonrpc: String,
13 pub id: Option<Value>,
14 pub method: String,
15 pub params: Option<Value>,
16}
17
18#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct JsonRpcResponse {
21 pub jsonrpc: String,
22 pub id: Option<Value>,
23 #[serde(skip_serializing_if = "Option::is_none")]
24 pub result: Option<Value>,
25 #[serde(skip_serializing_if = "Option::is_none")]
26 pub error: Option<JsonRpcError>,
27}
28
29#[derive(Debug, Clone, Serialize, Deserialize)]
31pub struct JsonRpcError {
32 pub code: i32,
33 pub message: String,
34 #[serde(skip_serializing_if = "Option::is_none")]
35 pub data: Option<Value>,
36}
37
38#[derive(Debug, Clone, Serialize, Deserialize)]
40pub struct InitializeParams {
41 #[serde(rename = "protocolVersion")]
42 pub protocol_version: String,
43 pub capabilities: ClientCapabilities,
44 #[serde(rename = "clientInfo")]
45 pub client_info: ClientInfo,
46}
47
48#[derive(Debug, Clone, Serialize, Deserialize)]
50pub struct ClientCapabilities {
51 #[serde(skip_serializing_if = "Option::is_none")]
52 pub experimental: Option<Value>,
53 #[serde(skip_serializing_if = "Option::is_none")]
54 pub sampling: Option<Value>,
55}
56
57#[derive(Debug, Clone, Serialize, Deserialize)]
59pub struct ClientInfo {
60 pub name: String,
61 pub version: String,
62}
63
64#[derive(Debug, Clone, Serialize, Deserialize)]
66pub struct InitializeResult {
67 #[serde(rename = "protocolVersion")]
68 pub protocol_version: String,
69 pub capabilities: ServerCapabilities,
70 #[serde(rename = "serverInfo")]
71 pub server_info: ServerInfo,
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize)]
76pub struct ServerCapabilities {
77 #[serde(skip_serializing_if = "Option::is_none")]
78 pub logging: Option<Value>,
79 #[serde(skip_serializing_if = "Option::is_none")]
80 pub prompts: Option<Value>,
81 #[serde(skip_serializing_if = "Option::is_none")]
82 pub resources: Option<ResourcesCapability>,
83 #[serde(skip_serializing_if = "Option::is_none")]
84 pub tools: Option<ToolsCapability>,
85 #[serde(skip_serializing_if = "Option::is_none")]
86 pub experimental: Option<Value>,
87}
88
89#[derive(Debug, Clone, Serialize, Deserialize)]
91pub struct ResourcesCapability {
92 #[serde(skip_serializing_if = "Option::is_none")]
93 pub subscribe: Option<bool>,
94 #[serde(skip_serializing_if = "Option::is_none")]
95 pub list_changed: Option<bool>,
96}
97
98#[derive(Debug, Clone, Serialize, Deserialize)]
100pub struct ToolsCapability {
101 #[serde(skip_serializing_if = "Option::is_none")]
102 pub list_changed: Option<bool>,
103}
104
105#[derive(Debug, Clone, Serialize, Deserialize)]
107pub struct ServerInfo {
108 pub name: String,
109 pub version: String,
110}
111
112#[derive(Debug, Clone, Serialize, Deserialize)]
114pub struct Tool {
115 pub name: String,
116 pub description: String,
117 #[serde(rename = "inputSchema")]
118 pub input_schema: Value,
119}
120
121#[derive(Debug, Clone, Serialize, Deserialize)]
123pub struct CallToolParams {
124 pub name: String,
125 #[serde(skip_serializing_if = "Option::is_none")]
126 pub arguments: Option<Value>,
127}
128
129#[derive(Debug, Clone, Serialize, Deserialize)]
131pub struct CallToolResult {
132 pub content: Vec<ToolContent>,
133 #[serde(rename = "isError", skip_serializing_if = "Option::is_none")]
134 pub is_error: Option<bool>,
135}
136
137#[derive(Debug, Clone, Serialize, Deserialize)]
139#[serde(tag = "type")]
140pub enum ToolContent {
141 #[serde(rename = "text")]
142 Text { text: String },
143 #[serde(rename = "image")]
144 Image { data: String, mime_type: String },
145 #[serde(rename = "resource")]
146 Resource { resource: ResourceContent },
147}
148
149#[derive(Debug, Clone, Serialize, Deserialize)]
151pub struct ResourceContent {
152 pub uri: String,
153 #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
154 pub mime_type: Option<String>,
155 #[serde(skip_serializing_if = "Option::is_none")]
156 pub text: Option<String>,
157 #[serde(skip_serializing_if = "Option::is_none")]
158 pub blob: Option<String>,
159}
160
161#[derive(Debug, Clone, Serialize, Deserialize)]
163pub struct Resource {
164 pub uri: String,
165 pub name: String,
166 pub description: String,
167 #[serde(rename = "mimeType", skip_serializing_if = "Option::is_none")]
168 pub mime_type: Option<String>,
169}
170
171#[allow(dead_code)]
173#[derive(Debug, Clone, Serialize, Deserialize)]
174pub struct ListResourcesParams {
175 #[serde(skip_serializing_if = "Option::is_none")]
176 pub cursor: Option<String>,
177}
178
179#[derive(Debug, Clone, Serialize, Deserialize)]
181pub struct ListResourcesResult {
182 pub resources: Vec<Resource>,
183 #[serde(rename = "nextCursor", skip_serializing_if = "Option::is_none")]
184 pub next_cursor: Option<String>,
185}
186
187#[derive(Debug, Clone, Serialize, Deserialize)]
189pub struct ReadResourceParams {
190 pub uri: String,
191}
192
193#[derive(Debug, Clone, Serialize, Deserialize)]
195pub struct ReadResourceResult {
196 pub contents: Vec<ResourceContent>,
197}
198
199#[derive(Debug, Clone, Serialize, Deserialize)]
201pub struct ListToolsResult {
202 pub tools: Vec<Tool>,
203 #[serde(rename = "nextCursor", skip_serializing_if = "Option::is_none")]
204 pub next_cursor: Option<String>,
205}
206
207pub mod error_codes {
209 pub const INVALID_REQUEST: i32 = -32600;
210 pub const METHOD_NOT_FOUND: i32 = -32601;
211 pub const INVALID_PARAMS: i32 = -32602;
212 pub const INTERNAL_ERROR: i32 = -32603;
213}
214
215impl JsonRpcResponse {
216 pub fn success(id: Option<Value>, result: Value) -> Self {
217 Self {
218 jsonrpc: "2.0".to_string(),
219 id,
220 result: Some(result),
221 error: None,
222 }
223 }
224
225 pub fn error(id: Option<Value>, error: JsonRpcError) -> Self {
226 Self {
227 jsonrpc: "2.0".to_string(),
228 id,
229 result: None,
230 error: Some(error),
231 }
232 }
233}
234
235impl JsonRpcError {
236 pub fn invalid_request(message: impl Into<String>) -> Self {
237 Self {
238 code: error_codes::INVALID_REQUEST,
239 message: message.into(),
240 data: None,
241 }
242 }
243
244 pub fn method_not_found(method: impl Into<String>) -> Self {
245 Self {
246 code: error_codes::METHOD_NOT_FOUND,
247 message: format!("Method not found: {}", method.into()),
248 data: None,
249 }
250 }
251
252 pub fn invalid_params(message: impl Into<String>) -> Self {
253 Self {
254 code: error_codes::INVALID_PARAMS,
255 message: message.into(),
256 data: None,
257 }
258 }
259
260 pub fn internal_error(message: impl Into<String>) -> Self {
261 Self {
262 code: error_codes::INTERNAL_ERROR,
263 message: message.into(),
264 data: None,
265 }
266 }
267}