#[non_exhaustive]pub struct ClientCapabilities {
pub sampling: Option<SamplingCapabilities>,
pub elicitation: Option<ElicitationCapabilities>,
pub roots: Option<RootsCapabilities>,
pub tasks: Option<ClientTasksCapability>,
pub experimental: Option<HashMap<String, Value>>,
pub extensions: Option<HashMap<String, Value>>,
}Expand description
Client capabilities advertised during initialization.
§Examples
use pmcp::types::ClientCapabilities;
let mut capabilities = ClientCapabilities::default();
capabilities.experimental = Some([("custom-feature".to_string(), serde_json::json!(true))]
.into_iter()
.collect());Fields (Non-exhaustive)§
This struct is marked as non-exhaustive
Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.sampling: Option<SamplingCapabilities>Sampling capabilities (for LLM providers)
elicitation: Option<ElicitationCapabilities>Elicitation capabilities (for user input)
roots: Option<RootsCapabilities>Roots capabilities
tasks: Option<ClientTasksCapability>Task capabilities (MCP 2025-11-25)
experimental: Option<HashMap<String, Value>>Experimental capabilities
extensions: Option<HashMap<String, Value>>Extension capabilities — reverse-domain-keyed protocol extensions.
This is the wire-correct home for declarations from the Extensions Track
of MCP (SEPs that ship as extensions rather than as core protocol
changes), and is the client-side twin of
ServerCapabilities::extensions.
Use experimental only for pre-SEP, pre-namespaced flags. New
extensions belong here.
§On MCP 2026-07-28 this travels PER REQUEST, not in a handshake
MCP 2026-07-28 is stateless and has no initialize handshake, so a v2
client’s declaration rides inside every request’s
_meta["io.modelcontextprotocol/clientCapabilities"] rather than being
exchanged once at connection setup. This field is therefore both:
- the typed source that a client’s per-request
_metaemission serializes FROM, and - the type that the server’s already-resolved
ProtocolContext::client_capabilities(resolved once at ingress) deserializes INTO.
On MCP 2025-11-25 the same field travels once, inside the initialize
request’s capabilities.
§This is a DECLARATION, never an authorization
The map is client-supplied, self-reported and trivially forgeable. It
says only what the client SUPPORTS — never who the caller IS. It may be
read to decide whether a capability may be served; it must never be read
as identity. Owner binding and every access decision read the
authenticated context (OAuth sub / the resolved principal), never this
map.
§Examples
use pmcp::types::ClientCapabilities;
use std::collections::HashMap;
let mut caps = ClientCapabilities::default();
let mut ext = HashMap::new();
ext.insert(
"io.modelcontextprotocol/tasks".to_string(),
serde_json::json!({}),
);
caps.extensions = Some(ext);Implementations§
Source§impl ClientCapabilities
impl ClientCapabilities
Sourcepub fn minimal() -> Self
pub fn minimal() -> Self
Create a minimal set of client capabilities.
§Examples
use pmcp::ClientCapabilities;
// Create minimal capabilities (no features advertised)
let capabilities = ClientCapabilities::minimal();
assert!(!capabilities.supports_sampling());
assert!(!capabilities.supports_elicitation());
// Use in client initialization
let transport = StdioTransport::new();
let mut client = Client::new(transport);
let server_info = client.initialize(ClientCapabilities::minimal()).await?;Sourcepub fn full() -> Self
pub fn full() -> Self
Create a full set of client capabilities.
Advertises all standard client capabilities defined in the MCP specification. Note: Client capabilities indicate what the CLIENT can do (e.g., handle sampling requests, provide user input). Server capabilities (tools, prompts, resources) are advertised by servers, not clients.
§Examples
use pmcp::ClientCapabilities;
// Create full capabilities (all client features supported)
let capabilities = ClientCapabilities::full();
assert!(capabilities.supports_sampling());
assert!(capabilities.supports_elicitation());
// Inspect specific capabilities
assert!(capabilities.roots.unwrap().list_changed);
// Use in client that supports all MCP client features
let transport = StdioTransport::new();
let mut client = Client::new(transport);
let server_info = client.initialize(ClientCapabilities::full()).await?;Sourcepub fn supports_elicitation(&self) -> bool
pub fn supports_elicitation(&self) -> bool
Check if the client supports elicitation (user input requests).
§Examples
use pmcp::{ClientCapabilities, types::capabilities::ElicitationCapabilities};
// Check elicitation support
let caps = ClientCapabilities::full();
assert!(caps.supports_elicitation());
// Build capabilities with elicitation
let mut interactive_client = ClientCapabilities::default();
interactive_client.elicitation = Some(ElicitationCapabilities::default());
assert!(interactive_client.supports_elicitation());
// Use for interactive tools
let caps = ClientCapabilities::full();
if caps.supports_elicitation() {
println!("Client can handle user input requests");
}Sourcepub fn supports_sampling(&self) -> bool
pub fn supports_sampling(&self) -> bool
Check if the client supports sampling.
§Examples
use pmcp::{ClientCapabilities, types::capabilities::SamplingCapabilities};
// Check sampling support for LLM operations
let caps = ClientCapabilities::full();
assert!(caps.supports_sampling());
// Build LLM client capabilities
let mut llm_client = ClientCapabilities::default();
llm_client.sampling = Some(SamplingCapabilities {
models: Some(vec![
"gpt-4".to_string(),
"claude-3".to_string(),
"llama-2".to_string(),
]),
..SamplingCapabilities::default()
});
assert!(llm_client.supports_sampling());
// List supported models
if let Some(sampling) = &llm_client.sampling {
if let Some(models) = &sampling.models {
println!("Supported models: {:?}", models);
}
}