turbomcp_protocol/types/
capabilities.rs

1//! MCP capability negotiation types
2//!
3//! This module contains types for capability discovery and negotiation between
4//! MCP clients and servers. Capabilities define what features each side supports
5//! and are exchanged during the initialization handshake.
6//!
7//! # Capability Types
8//!
9//! - [`ClientCapabilities`] - Client-side capabilities
10//! - [`ServerCapabilities`] - Server-side capabilities
11//! - Feature-specific capability structures for each MCP feature
12
13use serde::{Deserialize, Serialize};
14use std::collections::HashMap;
15
16/// Client capabilities per MCP 2025-11-25 specification
17///
18/// ## Version Support
19/// - MCP 2025-11-25: roots, sampling, elicitation, experimental
20/// - MCP 2025-11-25 draft (SEP-1686): + tasks
21#[derive(Debug, Clone, Serialize, Deserialize, Default)]
22pub struct ClientCapabilities {
23    /// Experimental, non-standard capabilities that the client supports
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub experimental: Option<HashMap<String, serde_json::Value>>,
26
27    /// Present if the client supports listing roots
28    #[serde(skip_serializing_if = "Option::is_none")]
29    pub roots: Option<RootsCapabilities>,
30
31    /// Present if the client supports sampling from an LLM
32    #[serde(skip_serializing_if = "Option::is_none")]
33    pub sampling: Option<SamplingCapabilities>,
34
35    /// Present if the client supports elicitation from the server
36    #[serde(skip_serializing_if = "Option::is_none")]
37    pub elicitation: Option<ElicitationCapabilities>,
38
39    /// Present if the client supports the Tasks API (MCP 2025-11-25 draft, SEP-1686)
40    ///
41    /// When present, indicates the client can act as a receiver for task-augmented requests
42    /// from the server (e.g., sampling/createMessage, elicitation/create).
43    #[cfg(feature = "mcp-tasks")]
44    #[serde(skip_serializing_if = "Option::is_none")]
45    pub tasks: Option<ClientTasksCapabilities>,
46}
47
48/// Server capabilities per MCP 2025-11-25 specification
49///
50/// ## Version Support
51/// - MCP 2025-11-25: logging, completions, prompts, resources, tools, experimental
52/// - MCP 2025-11-25 draft (SEP-1686): + tasks
53#[derive(Debug, Clone, Serialize, Deserialize, Default)]
54pub struct ServerCapabilities {
55    /// Experimental, non-standard capabilities that the server supports
56    #[serde(skip_serializing_if = "Option::is_none")]
57    pub experimental: Option<HashMap<String, serde_json::Value>>,
58
59    /// Present if the server supports sending log messages to the client
60    #[serde(skip_serializing_if = "Option::is_none")]
61    pub logging: Option<LoggingCapabilities>,
62
63    /// Present if the server supports argument autocompletion suggestions
64    #[serde(skip_serializing_if = "Option::is_none")]
65    pub completions: Option<CompletionCapabilities>,
66
67    /// Present if the server offers any prompt templates
68    #[serde(skip_serializing_if = "Option::is_none")]
69    pub prompts: Option<PromptsCapabilities>,
70
71    /// Present if the server offers any resources to read
72    #[serde(skip_serializing_if = "Option::is_none")]
73    pub resources: Option<ResourcesCapabilities>,
74
75    /// Present if the server offers any tools to call
76    #[serde(skip_serializing_if = "Option::is_none")]
77    pub tools: Option<ToolsCapabilities>,
78
79    /// Present if the server supports the Tasks API (MCP 2025-11-25 draft, SEP-1686)
80    ///
81    /// When present, indicates the server can act as a receiver for task-augmented requests
82    /// from the client (e.g., tools/call).
83    #[cfg(feature = "mcp-tasks")]
84    #[serde(skip_serializing_if = "Option::is_none")]
85    pub tasks: Option<ServerTasksCapabilities>,
86}
87
88/// Sampling capabilities
89#[derive(Debug, Clone, Serialize, Deserialize, Default)]
90pub struct SamplingCapabilities;
91
92/// Elicitation capabilities per MCP 2025-11-25 specification
93#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
94pub struct ElicitationCapabilities {
95    /// Whether the client performs JSON schema validation on elicitation responses
96    /// If true, the client validates user input against the provided schema before sending
97    #[serde(rename = "schemaValidation", skip_serializing_if = "Option::is_none")]
98    pub schema_validation: Option<bool>,
99}
100
101impl ElicitationCapabilities {
102    /// Create elicitation capabilities with schema validation enabled
103    pub fn with_schema_validation(mut self) -> Self {
104        self.schema_validation = Some(true);
105        self
106    }
107
108    /// Create elicitation capabilities with schema validation disabled
109    pub fn without_schema_validation(mut self) -> Self {
110        self.schema_validation = Some(false);
111        self
112    }
113}
114
115/// Completion capabilities
116#[derive(Debug, Clone, Serialize, Deserialize, Default)]
117pub struct CompletionCapabilities;
118
119/// Roots capabilities
120#[derive(Debug, Clone, Serialize, Deserialize, Default)]
121pub struct RootsCapabilities {
122    /// Whether list can change
123    #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
124    pub list_changed: Option<bool>,
125}
126
127/// Logging capabilities
128#[derive(Debug, Clone, Serialize, Deserialize, Default)]
129pub struct LoggingCapabilities;
130
131/// Prompts capabilities
132#[derive(Debug, Clone, Serialize, Deserialize, Default)]
133pub struct PromptsCapabilities {
134    /// Whether list can change
135    #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
136    pub list_changed: Option<bool>,
137}
138
139/// Resources capabilities
140#[derive(Debug, Clone, Serialize, Deserialize, Default)]
141pub struct ResourcesCapabilities {
142    /// Whether subscribe is supported
143    #[serde(skip_serializing_if = "Option::is_none")]
144    pub subscribe: Option<bool>,
145
146    /// Whether list can change
147    #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
148    pub list_changed: Option<bool>,
149}
150
151/// Tools capabilities
152#[derive(Debug, Clone, Serialize, Deserialize, Default)]
153pub struct ToolsCapabilities {
154    /// Whether list can change
155    #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
156    pub list_changed: Option<bool>,
157}
158
159// ========== Tasks API Capabilities (MCP 2025-11-25 draft, SEP-1686) ==========
160
161/// Server tasks capabilities (MCP 2025-11-25 draft, SEP-1686)
162///
163/// Indicates which task operations and request types the server supports.
164///
165/// ## Example
166///
167/// ```rust,ignore
168/// use turbomcp_protocol::types::{
169///     ServerTasksCapabilities, TasksRequestsCapabilities, TasksToolsCapabilities
170/// };
171///
172/// let tasks_caps = ServerTasksCapabilities {
173///     list: Some(TasksListCapabilities {}),
174///     cancel: Some(TasksCancelCapabilities {}),
175///     requests: Some(TasksRequestsCapabilities {
176///         tools: Some(TasksToolsCapabilities {
177///             call: Some(TasksToolsCallCapabilities {}),
178///         }),
179///         ..Default::default()
180///     }),
181/// };
182/// ```
183#[derive(Debug, Clone, Serialize, Deserialize, Default)]
184#[cfg(feature = "mcp-tasks")]
185pub struct ServerTasksCapabilities {
186    /// Present if the server supports tasks/list
187    #[serde(skip_serializing_if = "Option::is_none")]
188    pub list: Option<TasksListCapabilities>,
189
190    /// Present if the server supports tasks/cancel
191    #[serde(skip_serializing_if = "Option::is_none")]
192    pub cancel: Option<TasksCancelCapabilities>,
193
194    /// Present if the server supports task-augmented requests
195    #[serde(skip_serializing_if = "Option::is_none")]
196    pub requests: Option<ServerTasksRequestsCapabilities>,
197}
198
199/// Client tasks capabilities (MCP 2025-11-25 draft, SEP-1686)
200///
201/// Indicates which task operations and request types the client supports.
202///
203/// ## Example
204///
205/// ```rust,ignore
206/// use turbomcp_protocol::types::{
207///     ClientTasksCapabilities, ClientTasksRequestsCapabilities,
208///     TasksSamplingCapabilities, TasksSamplingCreateMessageCapabilities
209/// };
210///
211/// let tasks_caps = ClientTasksCapabilities {
212///     list: Some(TasksListCapabilities {}),
213///     cancel: Some(TasksCancelCapabilities {}),
214///     requests: Some(ClientTasksRequestsCapabilities {
215///         sampling: Some(TasksSamplingCapabilities {
216///             create_message: Some(TasksSamplingCreateMessageCapabilities {}),
217///         }),
218///         elicitation: Some(TasksElicitationCapabilities {
219///             create: Some(TasksElicitationCreateCapabilities {}),
220///         }),
221///     }),
222/// };
223/// ```
224#[derive(Debug, Clone, Serialize, Deserialize, Default)]
225#[cfg(feature = "mcp-tasks")]
226pub struct ClientTasksCapabilities {
227    /// Present if the client supports tasks/list
228    #[serde(skip_serializing_if = "Option::is_none")]
229    pub list: Option<TasksListCapabilities>,
230
231    /// Present if the client supports tasks/cancel
232    #[serde(skip_serializing_if = "Option::is_none")]
233    pub cancel: Option<TasksCancelCapabilities>,
234
235    /// Present if the client supports task-augmented requests
236    #[serde(skip_serializing_if = "Option::is_none")]
237    pub requests: Option<ClientTasksRequestsCapabilities>,
238}
239
240/// Task list capability
241#[derive(Debug, Clone, Serialize, Deserialize, Default)]
242#[cfg(feature = "mcp-tasks")]
243pub struct TasksListCapabilities;
244
245/// Task cancel capability
246#[derive(Debug, Clone, Serialize, Deserialize, Default)]
247#[cfg(feature = "mcp-tasks")]
248pub struct TasksCancelCapabilities;
249
250/// Server-side task-augmented requests capabilities
251#[derive(Debug, Clone, Serialize, Deserialize, Default)]
252#[cfg(feature = "mcp-tasks")]
253pub struct ServerTasksRequestsCapabilities {
254    /// Present if the server supports task-augmented tools/call
255    #[serde(skip_serializing_if = "Option::is_none")]
256    pub tools: Option<TasksToolsCapabilities>,
257}
258
259/// Client-side task-augmented requests capabilities
260#[derive(Debug, Clone, Serialize, Deserialize, Default)]
261#[cfg(feature = "mcp-tasks")]
262pub struct ClientTasksRequestsCapabilities {
263    /// Present if the client supports task-augmented sampling/createMessage
264    #[serde(skip_serializing_if = "Option::is_none")]
265    pub sampling: Option<TasksSamplingCapabilities>,
266
267    /// Present if the client supports task-augmented elicitation/create
268    #[serde(skip_serializing_if = "Option::is_none")]
269    pub elicitation: Option<TasksElicitationCapabilities>,
270}
271
272/// Tools task capabilities
273#[derive(Debug, Clone, Serialize, Deserialize, Default)]
274#[cfg(feature = "mcp-tasks")]
275pub struct TasksToolsCapabilities {
276    /// Present if task-augmented tools/call is supported
277    #[serde(skip_serializing_if = "Option::is_none")]
278    pub call: Option<TasksToolsCallCapabilities>,
279}
280
281/// Tools call task capability
282#[derive(Debug, Clone, Serialize, Deserialize, Default)]
283#[cfg(feature = "mcp-tasks")]
284pub struct TasksToolsCallCapabilities;
285
286/// Sampling task capabilities
287#[derive(Debug, Clone, Serialize, Deserialize, Default)]
288#[cfg(feature = "mcp-tasks")]
289pub struct TasksSamplingCapabilities {
290    /// Present if task-augmented sampling/createMessage is supported
291    #[serde(rename = "createMessage", skip_serializing_if = "Option::is_none")]
292    pub create_message: Option<TasksSamplingCreateMessageCapabilities>,
293}
294
295/// Sampling create message task capability
296#[derive(Debug, Clone, Serialize, Deserialize, Default)]
297#[cfg(feature = "mcp-tasks")]
298pub struct TasksSamplingCreateMessageCapabilities;
299
300/// Elicitation task capabilities
301#[derive(Debug, Clone, Serialize, Deserialize, Default)]
302#[cfg(feature = "mcp-tasks")]
303pub struct TasksElicitationCapabilities {
304    /// Present if task-augmented elicitation/create is supported
305    #[serde(skip_serializing_if = "Option::is_none")]
306    pub create: Option<TasksElicitationCreateCapabilities>,
307}
308
309/// Elicitation create task capability
310#[derive(Debug, Clone, Serialize, Deserialize, Default)]
311#[cfg(feature = "mcp-tasks")]
312pub struct TasksElicitationCreateCapabilities;