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-06-18 specification
17#[derive(Debug, Clone, Serialize, Deserialize, Default)]
18pub struct ClientCapabilities {
19    /// Experimental, non-standard capabilities that the client supports
20    #[serde(skip_serializing_if = "Option::is_none")]
21    pub experimental: Option<HashMap<String, serde_json::Value>>,
22
23    /// Present if the client supports listing roots
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub roots: Option<RootsCapabilities>,
26
27    /// Present if the client supports sampling from an LLM
28    #[serde(skip_serializing_if = "Option::is_none")]
29    pub sampling: Option<SamplingCapabilities>,
30
31    /// Present if the client supports elicitation from the server
32    #[serde(skip_serializing_if = "Option::is_none")]
33    pub elicitation: Option<ElicitationCapabilities>,
34}
35
36/// Server capabilities per MCP 2025-06-18 specification
37#[derive(Debug, Clone, Serialize, Deserialize, Default)]
38pub struct ServerCapabilities {
39    /// Experimental, non-standard capabilities that the server supports
40    #[serde(skip_serializing_if = "Option::is_none")]
41    pub experimental: Option<HashMap<String, serde_json::Value>>,
42
43    /// Present if the server supports sending log messages to the client
44    #[serde(skip_serializing_if = "Option::is_none")]
45    pub logging: Option<LoggingCapabilities>,
46
47    /// Present if the server supports argument autocompletion suggestions
48    #[serde(skip_serializing_if = "Option::is_none")]
49    pub completions: Option<CompletionCapabilities>,
50
51    /// Present if the server offers any prompt templates
52    #[serde(skip_serializing_if = "Option::is_none")]
53    pub prompts: Option<PromptsCapabilities>,
54
55    /// Present if the server offers any resources to read
56    #[serde(skip_serializing_if = "Option::is_none")]
57    pub resources: Option<ResourcesCapabilities>,
58
59    /// Present if the server offers any tools to call
60    #[serde(skip_serializing_if = "Option::is_none")]
61    pub tools: Option<ToolsCapabilities>,
62}
63
64/// Sampling capabilities
65#[derive(Debug, Clone, Serialize, Deserialize, Default)]
66pub struct SamplingCapabilities;
67
68/// Elicitation capabilities per MCP 2025-06-18 specification
69#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
70pub struct ElicitationCapabilities {
71    /// Whether the client performs JSON schema validation on elicitation responses
72    /// If true, the client validates user input against the provided schema before sending
73    #[serde(rename = "schemaValidation", skip_serializing_if = "Option::is_none")]
74    pub schema_validation: Option<bool>,
75}
76
77impl ElicitationCapabilities {
78    /// Create elicitation capabilities with schema validation enabled
79    pub fn with_schema_validation(mut self) -> Self {
80        self.schema_validation = Some(true);
81        self
82    }
83
84    /// Create elicitation capabilities with schema validation disabled
85    pub fn without_schema_validation(mut self) -> Self {
86        self.schema_validation = Some(false);
87        self
88    }
89}
90
91/// Completion capabilities
92#[derive(Debug, Clone, Serialize, Deserialize, Default)]
93pub struct CompletionCapabilities;
94
95/// Roots capabilities
96#[derive(Debug, Clone, Serialize, Deserialize, Default)]
97pub struct RootsCapabilities {
98    /// Whether list can change
99    #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
100    pub list_changed: Option<bool>,
101}
102
103/// Logging capabilities
104#[derive(Debug, Clone, Serialize, Deserialize, Default)]
105pub struct LoggingCapabilities;
106
107/// Prompts capabilities
108#[derive(Debug, Clone, Serialize, Deserialize, Default)]
109pub struct PromptsCapabilities {
110    /// Whether list can change
111    #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
112    pub list_changed: Option<bool>,
113}
114
115/// Resources capabilities
116#[derive(Debug, Clone, Serialize, Deserialize, Default)]
117pub struct ResourcesCapabilities {
118    /// Whether subscribe is supported
119    #[serde(skip_serializing_if = "Option::is_none")]
120    pub subscribe: Option<bool>,
121
122    /// Whether list can change
123    #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
124    pub list_changed: Option<bool>,
125}
126
127/// Tools capabilities
128#[derive(Debug, Clone, Serialize, Deserialize, Default)]
129pub struct ToolsCapabilities {
130    /// Whether list can change
131    #[serde(rename = "listChanged", skip_serializing_if = "Option::is_none")]
132    pub list_changed: Option<bool>,
133}