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}
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<HashMap<String, 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, Clone, Serialize, Deserialize)]
129#[serde(rename_all = "camelCase")]
130pub struct ReadResourceRequest {
131 pub uri: Url,
132}
133
134#[derive(Debug, Clone, Serialize, Deserialize)]
135#[serde(rename_all = "camelCase")]
136pub struct ListRequest {
137 #[serde(skip_serializing_if = "Option::is_none")]
138 pub cursor: Option<String>,
139 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
140 pub meta: Option<serde_json::Value>,
141}
142
143#[derive(Debug, Clone, Serialize, Deserialize)]
144#[serde(rename_all = "camelCase")]
145pub struct ToolsListResponse {
146 pub tools: Vec<Tool>,
147 #[serde(skip_serializing_if = "Option::is_none")]
148 pub next_cursor: Option<String>,
149 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
150 pub meta: Option<serde_json::Value>,
151}
152#[derive(Debug, Clone, Deserialize, Serialize)]
153#[serde(rename_all = "camelCase")]
154pub struct PromptsListResponse {
155 pub prompts: Vec<Prompt>,
156 #[serde(skip_serializing_if = "Option::is_none")]
157 pub next_cursor: Option<String>,
158 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
159 pub meta: Option<HashMap<String, serde_json::Value>>,
160}
161
162#[derive(Debug, Clone, Deserialize, Serialize)]
163#[serde(rename_all = "camelCase")]
164pub struct Prompt {
165 pub name: String,
166 #[serde(skip_serializing_if = "Option::is_none")]
167 pub description: Option<String>,
168 #[serde(skip_serializing_if = "Option::is_none")]
169 pub arguments: Option<Vec<PromptArgument>>,
170}
171
172#[derive(Debug, Clone, Deserialize, Serialize)]
173#[serde(rename_all = "camelCase")]
174pub struct PromptArgument {
175 pub name: String,
176 #[serde(skip_serializing_if = "Option::is_none")]
177 pub description: Option<String>,
178 #[serde(skip_serializing_if = "Option::is_none")]
179 pub required: Option<bool>,
180}
181
182#[derive(Debug, Clone, Deserialize, Serialize)]
183#[serde(rename_all = "camelCase")]
184pub struct ResourcesListResponse {
185 pub resources: Vec<Resource>,
186 #[serde(skip_serializing_if = "Option::is_none")]
187 pub next_cursor: Option<String>,
188 #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
189 pub meta: Option<HashMap<String, serde_json::Value>>,
190}
191
192#[derive(Debug, Clone, Serialize, Deserialize)]
193#[serde(rename_all = "camelCase")]
194pub struct Resource {
195 pub uri: Url,
196 pub name: String,
197 #[serde(skip_serializing_if = "Option::is_none")]
198 pub description: Option<String>,
199 #[serde(skip_serializing_if = "Option::is_none")]
200 pub mime_type: Option<String>,
201}
202
203#[derive(Debug, Clone, Copy, PartialEq, Eq)]
204pub enum ErrorCode {
205 ConnectionClosed = -1,
207 RequestTimeout = -2,
208
209 ParseError = -32700,
211 InvalidRequest = -32600,
212 MethodNotFound = -32601,
213 InvalidParams = -32602,
214 InternalError = -32603,
215}
216
217#[cfg(test)]
218mod tests {
219 use super::*;
220
221 #[test]
222 fn test_server_capabilities() {
223 let capabilities = ServerCapabilities::default();
224 let json = serde_json::to_string(&capabilities).unwrap();
225 assert_eq!(json, "{}");
226 }
227}