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 Tool {
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 #[serde(skip_serializing_if = "Option::is_none")]
89 pub output_schema: Option<serde_json::Value>,
90}
91#[derive(Debug, Clone, Serialize, Deserialize)]
92#[serde(rename_all = "camelCase")]
93pub struct CallToolRequest {
94 pub name: String,
95 #[serde(skip_serializing_if = "Option::is_none")]
96 pub arguments: Option<HashMap<String, serde_json::Value>>,
97 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
98 pub meta: Option<serde_json::Value>,
99}
100
101#[derive(Debug, Clone, Serialize, Deserialize)]
102#[serde(rename_all = "camelCase")]
103pub struct CallToolResponse {
104 pub content: Vec<ToolResponseContent>,
105 #[serde(skip_serializing_if = "Option::is_none")]
106 pub is_error: Option<bool>,
107 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
108 pub meta: Option<serde_json::Value>,
109}
110
111#[derive(Debug, Clone, Serialize, Deserialize)]
112#[serde(tag = "type")]
113pub enum ToolResponseContent {
114 #[serde(rename = "text")]
115 Text { text: String },
116 #[serde(rename = "image")]
117 Image { data: String, mime_type: String },
118 #[serde(rename = "resource")]
119 Resource { resource: ResourceContents },
120}
121
122#[derive(Debug, Clone, Serialize, Deserialize)]
123#[serde(rename_all = "camelCase")]
124pub struct ResourceContents {
125 pub uri: Url,
126 #[serde(skip_serializing_if = "Option::is_none")]
127 pub mime_type: Option<String>,
128}
129
130#[derive(Debug, Clone, Serialize, Deserialize)]
131#[serde(rename_all = "camelCase")]
132pub struct ReadResourceRequest {
133 pub uri: Url,
134}
135
136#[derive(Debug, Clone, Serialize, Deserialize)]
137#[serde(rename_all = "camelCase")]
138pub struct ListRequest {
139 #[serde(skip_serializing_if = "Option::is_none")]
140 pub cursor: Option<String>,
141 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
142 pub meta: Option<serde_json::Value>,
143}
144
145#[derive(Debug, Clone, Serialize, Deserialize)]
146#[serde(rename_all = "camelCase")]
147pub struct ToolsListResponse {
148 pub tools: Vec<Tool>,
149 #[serde(skip_serializing_if = "Option::is_none")]
150 pub next_cursor: Option<String>,
151 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
152 pub meta: Option<serde_json::Value>,
153}
154#[derive(Debug, Clone, Deserialize, Serialize)]
155#[serde(rename_all = "camelCase")]
156pub struct PromptsListResponse {
157 pub prompts: Vec<Prompt>,
158 #[serde(skip_serializing_if = "Option::is_none")]
159 pub next_cursor: Option<String>,
160 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
161 pub meta: Option<HashMap<String, serde_json::Value>>,
162}
163
164#[derive(Debug, Clone, Deserialize, Serialize)]
165#[serde(rename_all = "camelCase")]
166pub struct Prompt {
167 pub name: String,
168 #[serde(skip_serializing_if = "Option::is_none")]
169 pub description: Option<String>,
170 #[serde(skip_serializing_if = "Option::is_none")]
171 pub arguments: Option<Vec<PromptArgument>>,
172}
173
174#[derive(Debug, Clone, Deserialize, Serialize)]
175#[serde(rename_all = "camelCase")]
176pub struct PromptArgument {
177 pub name: String,
178 #[serde(skip_serializing_if = "Option::is_none")]
179 pub description: Option<String>,
180 #[serde(skip_serializing_if = "Option::is_none")]
181 pub required: Option<bool>,
182}
183
184#[derive(Debug, Clone, Deserialize, Serialize)]
185#[serde(rename_all = "camelCase")]
186pub struct ResourcesListResponse {
187 pub resources: Vec<Resource>,
188 #[serde(skip_serializing_if = "Option::is_none")]
189 pub next_cursor: Option<String>,
190 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
191 pub meta: Option<HashMap<String, serde_json::Value>>,
192}
193
194#[derive(Debug, Clone, Serialize, Deserialize)]
195#[serde(rename_all = "camelCase")]
196pub struct Resource {
197 pub uri: Url,
198 pub name: String,
199 #[serde(skip_serializing_if = "Option::is_none")]
200 pub description: Option<String>,
201 #[serde(skip_serializing_if = "Option::is_none")]
202 pub mime_type: Option<String>,
203}
204
205#[derive(Debug, Clone, Copy, PartialEq, Eq)]
206pub enum ErrorCode {
207 ConnectionClosed = -1,
209 RequestTimeout = -2,
210
211 ParseError = -32700,
213 InvalidRequest = -32600,
214 MethodNotFound = -32601,
215 InvalidParams = -32602,
216 InternalError = -32603,
217}
218
219#[cfg(test)]
220mod tests {
221 use super::*;
222
223 #[test]
224 fn test_server_capabilities() {
225 let capabilities = ServerCapabilities::default();
226 let json = serde_json::to_string(&capabilities).unwrap();
227 assert_eq!(json, "{}");
228 }
229}