mcp_sdk/
types.rs

1use std::collections::HashMap;
2
3use serde::{Deserialize, Serialize};
4use url::Url;
5
6pub const LATEST_PROTOCOL_VERSION: &str = "2024-11-05";
7
8#[derive(Debug, Clone, Serialize, Deserialize, Default)]
9#[serde(rename_all = "camelCase")]
10#[serde(default)]
11pub struct Implementation {
12    pub name: String,
13    pub version: String,
14}
15
16#[derive(Debug, Clone, Serialize, Deserialize, Default)]
17#[serde(rename_all = "camelCase")]
18#[serde(default)]
19pub struct InitializeRequest {
20    pub protocol_version: String,
21    pub capabilities: ClientCapabilities,
22    pub client_info: Implementation,
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize, Default)]
26#[serde(rename_all = "camelCase")]
27#[serde(default)]
28pub struct InitializeResponse {
29    pub protocol_version: String,
30    pub capabilities: ServerCapabilities,
31    pub server_info: Implementation,
32}
33
34#[derive(Debug, Clone, Serialize, Deserialize, Default)]
35#[serde(rename_all = "camelCase")]
36#[serde(default)]
37pub struct ServerCapabilities {
38    #[serde(skip_serializing_if = "Option::is_none")]
39    pub tools: Option<serde_json::Value>,
40    #[serde(skip_serializing_if = "Option::is_none")]
41    pub experimental: Option<serde_json::Value>,
42    #[serde(skip_serializing_if = "Option::is_none")]
43    pub logging: Option<serde_json::Value>,
44    #[serde(skip_serializing_if = "Option::is_none")]
45    pub prompts: Option<PromptCapabilities>,
46    #[serde(skip_serializing_if = "Option::is_none")]
47    pub resources: Option<ResourceCapabilities>,
48}
49
50#[derive(Debug, Clone, Serialize, Deserialize, Default)]
51#[serde(rename_all = "camelCase")]
52#[serde(default)]
53pub struct PromptCapabilities {
54    pub list_changed: Option<bool>,
55}
56
57#[derive(Debug, Clone, Serialize, Deserialize, Default)]
58#[serde(rename_all = "camelCase")]
59#[serde(default)]
60pub struct ResourceCapabilities {
61    pub subscribe: Option<bool>,
62    pub list_changed: Option<bool>,
63}
64
65#[derive(Debug, Clone, Serialize, Deserialize, Default)]
66#[serde(rename_all = "camelCase")]
67#[serde(default)]
68pub struct ClientCapabilities {
69    pub experimental: Option<serde_json::Value>,
70    pub sampling: Option<serde_json::Value>,
71    pub roots: Option<RootCapabilities>,
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize, Default)]
75#[serde(rename_all = "camelCase")]
76#[serde(default)]
77pub struct RootCapabilities {
78    pub list_changed: Option<bool>,
79}
80
81#[derive(Debug, Clone, Serialize, Deserialize)]
82#[serde(rename_all = "camelCase")]
83pub struct ToolDefinition {
84    pub name: String,
85    #[serde(skip_serializing_if = "Option::is_none")]
86    pub description: Option<String>,
87    pub input_schema: serde_json::Value,
88}
89#[derive(Debug, Clone, Serialize, Deserialize)]
90#[serde(rename_all = "camelCase")]
91pub struct CallToolRequest {
92    pub name: String,
93    #[serde(skip_serializing_if = "Option::is_none")]
94    pub arguments: Option<serde_json::Value>,
95    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
96    pub meta: Option<serde_json::Value>,
97}
98
99#[derive(Debug, Clone, Serialize, Deserialize)]
100#[serde(rename_all = "camelCase")]
101pub struct CallToolResponse {
102    pub content: Vec<ToolResponseContent>,
103    #[serde(skip_serializing_if = "Option::is_none")]
104    pub is_error: Option<bool>,
105    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
106    pub meta: Option<serde_json::Value>,
107}
108
109#[derive(Debug, Clone, Serialize, Deserialize)]
110#[serde(tag = "type")]
111pub enum ToolResponseContent {
112    #[serde(rename = "text")]
113    Text { text: String },
114    #[serde(rename = "image")]
115    Image { data: String, mime_type: String },
116    #[serde(rename = "resource")]
117    Resource { resource: ResourceContents },
118}
119
120#[derive(Debug, Clone, Serialize, Deserialize)]
121#[serde(rename_all = "camelCase")]
122pub struct ResourceContents {
123    pub uri: Url,
124    #[serde(skip_serializing_if = "Option::is_none")]
125    pub mime_type: Option<String>,
126}
127
128#[derive(Debug, Serialize, Deserialize)]
129#[serde(rename_all = "camelCase")]
130pub struct ListRequest {
131    #[serde(skip_serializing_if = "Option::is_none")]
132    pub cursor: Option<String>,
133    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
134    pub meta: Option<serde_json::Value>,
135}
136
137#[derive(Debug, Clone, Serialize, Deserialize)]
138#[serde(rename_all = "camelCase")]
139pub struct ToolsListResponse {
140    pub tools: Vec<ToolDefinition>,
141    #[serde(skip_serializing_if = "Option::is_none")]
142    pub next_cursor: Option<String>,
143    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
144    pub meta: Option<serde_json::Value>,
145}
146#[derive(Debug, Deserialize, Serialize)]
147#[serde(rename_all = "camelCase")]
148pub struct PromptsListResponse {
149    pub prompts: Vec<Prompt>,
150    #[serde(skip_serializing_if = "Option::is_none")]
151    pub next_cursor: Option<String>,
152    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
153    pub meta: Option<HashMap<String, serde_json::Value>>,
154}
155
156#[derive(Debug, Deserialize, Serialize)]
157#[serde(rename_all = "camelCase")]
158pub struct Prompt {
159    pub name: String,
160    #[serde(skip_serializing_if = "Option::is_none")]
161    pub description: Option<String>,
162    #[serde(skip_serializing_if = "Option::is_none")]
163    pub arguments: Option<Vec<PromptArgument>>,
164}
165
166#[derive(Debug, Deserialize, Serialize)]
167#[serde(rename_all = "camelCase")]
168pub struct PromptArgument {
169    pub name: String,
170    #[serde(skip_serializing_if = "Option::is_none")]
171    pub description: Option<String>,
172    #[serde(skip_serializing_if = "Option::is_none")]
173    pub required: Option<bool>,
174}
175
176#[derive(Debug, Deserialize, Serialize)]
177#[serde(rename_all = "camelCase")]
178pub struct ResourcesListResponse {
179    pub resources: Vec<Resource>,
180    #[serde(skip_serializing_if = "Option::is_none")]
181    pub next_cursor: Option<String>,
182    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
183    pub meta: Option<HashMap<String, serde_json::Value>>,
184}
185
186#[derive(Debug, Serialize, Deserialize)]
187#[serde(rename_all = "camelCase")]
188pub struct Resource {
189    pub uri: Url,
190    pub name: String,
191    #[serde(skip_serializing_if = "Option::is_none")]
192    pub description: Option<String>,
193    #[serde(skip_serializing_if = "Option::is_none")]
194    pub mime_type: Option<String>,
195}
196
197#[derive(Debug, Clone, Copy, PartialEq, Eq)]
198pub enum ErrorCode {
199    // SDK error codes
200    ConnectionClosed = -1,
201    RequestTimeout = -2,
202
203    // Standard JSON-RPC error codes
204    ParseError = -32700,
205    InvalidRequest = -32600,
206    MethodNotFound = -32601,
207    InvalidParams = -32602,
208    InternalError = -32603,
209}
210
211#[cfg(test)]
212mod tests {
213    use super::*;
214
215    #[test]
216    fn test_server_capabilities() {
217        let capabilities = ServerCapabilities::default();
218        let json = serde_json::to_string(&capabilities).unwrap();
219        assert_eq!(json, "{}");
220    }
221}