Skip to main content

mcp_kit/types/
messages.rs

1/// All MCP request/response/notification message types
2use serde::{Deserialize, Serialize};
3
4use crate::types::{
5    prompt::Prompt, resource::Resource, tool::Tool, ClientCapabilities, ClientInfo, Cursor,
6    LoggingLevel, Root, ServerCapabilities, ServerInfo,
7};
8
9// ─── Initialize ───────────────────────────────────────────────────────────────
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
12#[serde(rename_all = "camelCase")]
13pub struct InitializeRequest {
14    pub protocol_version: String,
15    pub capabilities: ClientCapabilities,
16    pub client_info: ClientInfo,
17}
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
20#[serde(rename_all = "camelCase")]
21pub struct InitializeResult {
22    pub protocol_version: String,
23    pub capabilities: ServerCapabilities,
24    pub server_info: ServerInfo,
25    #[serde(skip_serializing_if = "Option::is_none")]
26    pub instructions: Option<String>,
27}
28
29// ─── Tools ───────────────────────────────────────────────────────────────────
30
31#[derive(Debug, Clone, Default, Serialize, Deserialize)]
32pub struct ListToolsRequest {
33    #[serde(skip_serializing_if = "Option::is_none")]
34    pub cursor: Option<Cursor>,
35}
36
37#[derive(Debug, Clone, Serialize, Deserialize)]
38#[serde(rename_all = "camelCase")]
39pub struct ListToolsResult {
40    pub tools: Vec<Tool>,
41    #[serde(skip_serializing_if = "Option::is_none")]
42    pub next_cursor: Option<Cursor>,
43}
44
45#[derive(Debug, Clone, Serialize, Deserialize)]
46pub struct CallToolRequest {
47    pub name: String,
48    #[serde(default)]
49    pub arguments: serde_json::Value,
50}
51
52// ─── Resources ───────────────────────────────────────────────────────────────
53
54#[derive(Debug, Clone, Default, Serialize, Deserialize)]
55pub struct ListResourcesRequest {
56    #[serde(skip_serializing_if = "Option::is_none")]
57    pub cursor: Option<Cursor>,
58}
59
60#[derive(Debug, Clone, Serialize, Deserialize)]
61#[serde(rename_all = "camelCase")]
62pub struct ListResourcesResult {
63    pub resources: Vec<Resource>,
64    #[serde(skip_serializing_if = "Option::is_none")]
65    pub next_cursor: Option<Cursor>,
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize)]
69pub struct ReadResourceRequest {
70    pub uri: String,
71}
72
73pub use crate::types::resource::ReadResourceResult;
74
75#[derive(Debug, Clone, Serialize, Deserialize)]
76pub struct SubscribeRequest {
77    pub uri: String,
78}
79
80#[derive(Debug, Clone, Serialize, Deserialize)]
81pub struct UnsubscribeRequest {
82    pub uri: String,
83}
84
85// ─── Prompts ─────────────────────────────────────────────────────────────────
86
87#[derive(Debug, Clone, Default, Serialize, Deserialize)]
88pub struct ListPromptsRequest {
89    #[serde(skip_serializing_if = "Option::is_none")]
90    pub cursor: Option<Cursor>,
91}
92
93#[derive(Debug, Clone, Serialize, Deserialize)]
94#[serde(rename_all = "camelCase")]
95pub struct ListPromptsResult {
96    pub prompts: Vec<Prompt>,
97    #[serde(skip_serializing_if = "Option::is_none")]
98    pub next_cursor: Option<Cursor>,
99}
100
101#[derive(Debug, Clone, Serialize, Deserialize)]
102pub struct GetPromptRequest {
103    pub name: String,
104    #[serde(default)]
105    pub arguments: std::collections::HashMap<String, String>,
106}
107
108pub use crate::types::prompt::GetPromptResult;
109
110// ─── Completion ───────────────────────────────────────────────────────────────
111
112#[derive(Debug, Clone, Serialize, Deserialize)]
113pub struct CompleteRequest {
114    #[serde(rename = "ref")]
115    pub reference: CompletionReference,
116    pub argument: CompletionArgument,
117}
118
119#[derive(Debug, Clone, Serialize, Deserialize)]
120#[serde(tag = "type", rename_all = "camelCase")]
121pub enum CompletionReference {
122    #[serde(rename = "ref/prompt")]
123    Prompt { name: String },
124    #[serde(rename = "ref/resource")]
125    Resource { uri: String },
126}
127
128impl CompletionReference {
129    /// Get the name/uri of the reference
130    pub fn name(&self) -> &str {
131        match self {
132            Self::Prompt { name } => name,
133            Self::Resource { uri } => uri,
134        }
135    }
136
137    /// Check if this is a prompt reference
138    pub fn is_prompt(&self) -> bool {
139        matches!(self, Self::Prompt { .. })
140    }
141
142    /// Check if this is a resource reference
143    pub fn is_resource(&self) -> bool {
144        matches!(self, Self::Resource { .. })
145    }
146}
147
148#[derive(Debug, Clone, Serialize, Deserialize)]
149pub struct CompletionArgument {
150    pub name: String,
151    pub value: String,
152}
153
154#[derive(Debug, Clone, Serialize, Deserialize)]
155pub struct CompleteResult {
156    pub completion: CompletionValues,
157}
158
159impl CompleteResult {
160    /// Create a new completion result with the given values
161    pub fn new(values: impl IntoIterator<Item = impl Into<String>>) -> Self {
162        let values: Vec<String> = values.into_iter().map(Into::into).collect();
163        Self {
164            completion: CompletionValues {
165                total: Some(values.len() as u32),
166                values,
167                has_more: Some(false),
168            },
169        }
170    }
171
172    /// Create an empty completion result
173    pub fn empty() -> Self {
174        Self {
175            completion: CompletionValues {
176                values: vec![],
177                total: Some(0),
178                has_more: Some(false),
179            },
180        }
181    }
182
183    /// Create a completion result with pagination info
184    pub fn with_pagination(values: Vec<String>, total: u32, has_more: bool) -> Self {
185        Self {
186            completion: CompletionValues {
187                values,
188                total: Some(total),
189                has_more: Some(has_more),
190            },
191        }
192    }
193}
194
195#[derive(Debug, Clone, Serialize, Deserialize)]
196pub struct CompletionValues {
197    pub values: Vec<String>,
198    #[serde(skip_serializing_if = "Option::is_none")]
199    pub total: Option<u32>,
200    #[serde(skip_serializing_if = "Option::is_none")]
201    pub has_more: Option<bool>,
202}
203
204// ─── Logging ─────────────────────────────────────────────────────────────────
205
206#[derive(Debug, Clone, Serialize, Deserialize)]
207pub struct SetLevelRequest {
208    pub level: LoggingLevel,
209}
210
211// ─── Roots ───────────────────────────────────────────────────────────────────
212
213#[derive(Debug, Clone, Serialize, Deserialize)]
214pub struct ListRootsResult {
215    pub roots: Vec<Root>,
216}
217
218// ─── Notifications ────────────────────────────────────────────────────────────
219
220#[derive(Debug, Clone, Serialize, Deserialize)]
221#[serde(rename_all = "camelCase")]
222pub struct ProgressNotification {
223    pub progress_token: crate::protocol::ProgressToken,
224    pub progress: f64,
225    #[serde(skip_serializing_if = "Option::is_none")]
226    pub total: Option<f64>,
227    #[serde(skip_serializing_if = "Option::is_none")]
228    pub message: Option<String>,
229}
230
231#[derive(Debug, Clone, Serialize, Deserialize)]
232pub struct CancelledNotification {
233    pub request_id: crate::protocol::RequestId,
234    #[serde(skip_serializing_if = "Option::is_none")]
235    pub reason: Option<String>,
236}
237
238#[derive(Debug, Clone, Serialize, Deserialize)]
239pub struct LogMessageNotification {
240    pub level: LoggingLevel,
241    #[serde(skip_serializing_if = "Option::is_none")]
242    pub logger: Option<String>,
243    pub data: serde_json::Value,
244}
245
246#[derive(Debug, Clone, Serialize, Deserialize)]
247pub struct ResourceUpdatedNotification {
248    pub uri: String,
249}
250
251// ─── Roots Notifications ──────────────────────────────────────────────────────
252
253/// Empty request to list roots (server → client)
254#[derive(Debug, Clone, Default, Serialize, Deserialize)]
255pub struct ListRootsRequest {}
256
257/// Notification that the roots list has changed
258#[derive(Debug, Clone, Default, Serialize, Deserialize)]
259pub struct RootsListChangedNotification {}