Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,8 @@ context.peer.notify_prompt_list_changed().await?;

## Sampling

> **Deprecated (SEP-2577):** Sampling is deprecated and will be removed in a future release. It remains fully functional for now. See [SEP-2577](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577).

Sampling flips the usual direction: the server asks the client to run an LLM completion. The server sends a `create_message` request, the client processes it through its LLM, and returns the result.

**MCP Spec:** [Sampling](https://modelcontextprotocol.io/specification/2025-11-25/client/sampling)
Expand Down Expand Up @@ -544,6 +546,8 @@ impl ClientHandler for MyClient {

## Roots

> **Deprecated (SEP-2577):** Roots is deprecated and will be removed in a future release. It remains fully functional for now. See [SEP-2577](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577).

Roots tell servers which directories or projects the client is working in. A root is a URI (typically `file://`) pointing to a workspace or repository. Servers can query roots to know where to look for files and how to scope their work.

**MCP Spec:** [Roots](https://modelcontextprotocol.io/specification/2025-11-25/client/roots)
Expand Down Expand Up @@ -612,6 +616,8 @@ client.notify_roots_list_changed().await?;

## Logging

> **Deprecated (SEP-2577):** Logging is deprecated and will be removed in a future release. It remains fully functional for now. See [SEP-2577](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577).

Servers can send structured log messages to clients. The client sets a minimum severity level, and the server sends messages through the peer notification interface.

**MCP Spec:** [Logging](https://modelcontextprotocol.io/specification/2025-11-25/server/utilities/logging)
Expand Down
1 change: 1 addition & 0 deletions conformance/src/bin/server.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![allow(deprecated)]
use std::{collections::HashSet, sync::Arc};

use rmcp::{
Expand Down
65 changes: 51 additions & 14 deletions crates/rmcp/src/model/capabilities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ pub struct ToolsCapability {
pub list_changed: Option<bool>,
}

/// Roots capability. Deprecated by SEP-2577; remains functional and will be
/// removed in a future release.
/// See <https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577>.
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
Expand Down Expand Up @@ -97,6 +100,9 @@ pub struct TaskRequestsCapability {
pub tools: Option<ToolsTaskCapability>,
}

/// Sampling task capability. Deprecated by SEP-2577; remains functional and
/// will be removed in a future release.
/// See <https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577>.
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
Expand Down Expand Up @@ -231,6 +237,10 @@ pub struct ElicitationCapability {
}

/// Sampling capability with optional sub-capabilities (SEP-1577).
///
/// Deprecated by SEP-2577; remains functional and will be removed in a future
/// release.
/// See <https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577>.
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
#[serde(rename_all = "camelCase")]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
Expand All @@ -250,8 +260,6 @@ pub struct SamplingCapability {
/// # use rmcp::model::ClientCapabilities;
/// let cap = ClientCapabilities::builder()
/// .enable_experimental()
/// .enable_roots()
/// .enable_roots_list_changed()
/// .build();
/// ```
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
Expand All @@ -266,9 +274,10 @@ pub struct ClientCapabilities {
/// support with no settings.
#[serde(skip_serializing_if = "Option::is_none")]
pub extensions: Option<ExtensionCapabilities>,
/// Capability for filesystem roots (deprecated by SEP-2577).
#[serde(skip_serializing_if = "Option::is_none")]
pub roots: Option<RootsCapabilities>,
/// Capability for LLM sampling requests (SEP-1577)
/// Capability for LLM sampling requests (SEP-1577, deprecated by SEP-2577).
#[serde(skip_serializing_if = "Option::is_none")]
pub sampling: Option<SamplingCapability>,
/// Capability to handle elicitation requests from servers for interactive user input
Expand All @@ -283,7 +292,6 @@ pub struct ClientCapabilities {
/// ```rust
/// # use rmcp::model::ServerCapabilities;
/// let cap = ServerCapabilities::builder()
/// .enable_logging()
/// .enable_experimental()
/// .enable_prompts()
/// .enable_resources()
Expand All @@ -304,6 +312,7 @@ pub struct ServerCapabilities {
/// support with no settings.
#[serde(skip_serializing_if = "Option::is_none")]
pub extensions: Option<ExtensionCapabilities>,
/// Capability for server log message notifications (deprecated by SEP-2577).
#[serde(skip_serializing_if = "Option::is_none")]
pub logging: Option<JsonObject>,
#[serde(skip_serializing_if = "Option::is_none")]
Expand All @@ -320,7 +329,7 @@ pub struct ServerCapabilities {

#[cfg(any(feature = "server", feature = "macros"))]
macro_rules! builder {
($Target: ident {$($f: ident: $T: ty),* $(,)?}) => {
($Target: ident {$($(#[$fa:meta])* $f: ident: $T: ty),* $(,)?}) => {
paste! {
#[derive(Default, Clone, Copy, Debug)]
#[expect(clippy::exhaustive_structs, reason = "intentionally exhaustive")]
Expand Down Expand Up @@ -352,20 +361,20 @@ macro_rules! builder {
}
}
}
builder!($Target @toggle $($f: $T,) *);
builder!($Target @toggle $($(#[$fa])* $f: $T,)*);

};
($Target: ident @toggle $f0: ident: $T0: ty, $($f: ident: $T: ty,)*) => {
builder!($Target @toggle [][$f0: $T0][$($f: $T,)*]);
($Target: ident @toggle $(#[$fa0:meta])* $f0: ident: $T0: ty, $($(#[$fa:meta])* $f: ident: $T: ty,)*) => {
builder!($Target @toggle [][$(#[$fa0])* $f0: $T0][$($(#[$fa])* $f: $T,)*]);
};
($Target: ident @toggle [$($ff: ident: $Tf: ty,)*][$fn: ident: $TN: ty][$fn_1: ident: $Tn_1: ty, $($ft: ident: $Tt: ty,)*]) => {
builder!($Target @impl_toggle [$($ff: $Tf,)*][$fn: $TN][$fn_1: $Tn_1, $($ft:$Tt,)*]);
builder!($Target @toggle [$($ff: $Tf,)* $fn: $TN,][$fn_1: $Tn_1][$($ft:$Tt,)*]);
($Target: ident @toggle [$($ff: ident: $Tf: ty,)*][$(#[$fna:meta])* $fn: ident: $TN: ty][$(#[$fn1a:meta])* $fn_1: ident: $Tn_1: ty, $($(#[$fta:meta])* $ft: ident: $Tt: ty,)*]) => {
builder!($Target @impl_toggle [$($ff: $Tf,)*][$(#[$fna])* $fn: $TN][$fn_1: $Tn_1, $($ft:$Tt,)*]);
builder!($Target @toggle [$($ff: $Tf,)* $fn: $TN,][$(#[$fn1a])* $fn_1: $Tn_1][$($(#[$fta])* $ft: $Tt,)*]);
};
($Target: ident @toggle [$($ff: ident: $Tf: ty,)*][$fn: ident: $TN: ty][]) => {
builder!($Target @impl_toggle [$($ff: $Tf,)*][$fn: $TN][]);
($Target: ident @toggle [$($ff: ident: $Tf: ty,)*][$(#[$fna:meta])* $fn: ident: $TN: ty][]) => {
builder!($Target @impl_toggle [$($ff: $Tf,)*][$(#[$fna])* $fn: $TN][]);
};
($Target: ident @impl_toggle [$($ff: ident: $Tf: ty,)*][$fn: ident: $TN: ty][$($ft: ident: $Tt: ty,)*]) => {
($Target: ident @impl_toggle [$($ff: ident: $Tf: ty,)*][$(#[$fna:meta])* $fn: ident: $TN: ty][$($ft: ident: $Tt: ty,)*]) => {
paste! {
impl<
$(const [<$ff:upper>]: bool,)*
Expand All @@ -375,6 +384,7 @@ macro_rules! builder {
false,
$([<$ft:upper>],)*
>> {
$(#[$fna])*
pub fn [<enable_ $fn>](self) -> [<$Target Builder>]<[<$Target BuilderState>]<
$([<$ff:upper>],)*
true,
Expand All @@ -387,6 +397,7 @@ macro_rules! builder {
state: PhantomData
}
}
$(#[$fna])*
pub fn [<enable_ $fn _with>](self, $fn: $TN) -> [<$Target Builder>]<[<$Target BuilderState>]<
$([<$ff:upper>],)*
true,
Expand Down Expand Up @@ -431,6 +442,10 @@ builder! {
ServerCapabilities {
experimental: ExperimentalCapabilities,
extensions: ExtensionCapabilities,
#[deprecated(
since = "1.8.0",
note = "Logging is deprecated by SEP-2577 and will be removed in a future release. See https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577"
)]
logging: JsonObject,
completions: JsonObject,
prompts: PromptsCapability,
Expand Down Expand Up @@ -509,7 +524,15 @@ builder! {
ClientCapabilities{
experimental: ExperimentalCapabilities,
extensions: ExtensionCapabilities,
#[deprecated(
since = "1.8.0",
note = "Roots is deprecated by SEP-2577 and will be removed in a future release. See https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577"
)]
roots: RootsCapabilities,
#[deprecated(
since = "1.8.0",
note = "Sampling is deprecated by SEP-2577 and will be removed in a future release. See https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577"
)]
sampling: SamplingCapability,
elicitation: ElicitationCapability,
tasks: TasksCapability,
Expand All @@ -520,6 +543,10 @@ builder! {
impl<const E: bool, const EXT: bool, const S: bool, const EL: bool, const TASKS: bool>
ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<E, EXT, true, S, EL, TASKS>>
{
#[deprecated(
since = "1.8.0",
note = "Roots is deprecated by SEP-2577 and will be removed in a future release. See https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577"
)]
pub fn enable_roots_list_changed(mut self) -> Self {
if let Some(c) = self.roots.as_mut() {
c.list_changed = Some(true);
Expand All @@ -533,6 +560,10 @@ impl<const E: bool, const EXT: bool, const R: bool, const EL: bool, const TASKS:
ClientCapabilitiesBuilder<ClientCapabilitiesBuilderState<E, EXT, R, true, EL, TASKS>>
{
/// Enable tool calling in sampling requests
#[deprecated(
since = "1.8.0",
note = "Sampling is deprecated by SEP-2577 and will be removed in a future release. See https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577"
)]
pub fn enable_sampling_tools(mut self) -> Self {
if let Some(c) = self.sampling.as_mut() {
c.tools = Some(JsonObject::default());
Expand All @@ -541,6 +572,10 @@ impl<const E: bool, const EXT: bool, const R: bool, const EL: bool, const TASKS:
}

/// Enable context inclusion in sampling (soft-deprecated)
#[deprecated(
since = "1.8.0",
note = "Sampling is deprecated by SEP-2577 and will be removed in a future release. See https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577"
)]
pub fn enable_sampling_context(mut self) -> Self {
if let Some(c) = self.sampling.as_mut() {
c.context = Some(JsonObject::default());
Expand Down Expand Up @@ -571,6 +606,7 @@ impl<const E: bool, const EXT: bool, const R: bool, const S: bool, const TASKS:
mod test {
use super::*;
#[test]
#[allow(deprecated)]
fn test_builder() {
let builder = <ServerCapabilitiesBuilder>::default()
.enable_logging()
Expand Down Expand Up @@ -673,6 +709,7 @@ mod test {
}

#[test]
#[allow(deprecated)]
fn test_client_extensions_capability() {
// Test building ClientCapabilities with extensions (MCP Apps support)
let mut extensions = ExtensionCapabilities::new();
Expand Down
26 changes: 19 additions & 7 deletions crates/rmcp/src/service/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,8 @@ where
}

macro_rules! method {
(peer_req $method:ident $Req:ident() => $Resp: ident ) => {
($(#[$meta:meta])* peer_req $method:ident $Req:ident() => $Resp: ident ) => {
$(#[$meta])*
pub async fn $method(&self) -> Result<$Resp, ServiceError> {
let result = self
.send_request(ClientRequest::$Req($Req {
Expand All @@ -283,7 +284,8 @@ macro_rules! method {
}
}
};
(peer_req $method:ident $Req:ident($Param: ident) => $Resp: ident ) => {
($(#[$meta:meta])* peer_req $method:ident $Req:ident($Param: ident) => $Resp: ident ) => {
$(#[$meta])*
pub async fn $method(&self, params: $Param) -> Result<$Resp, ServiceError> {
let result = self
.send_request(ClientRequest::$Req($Req {
Expand All @@ -298,7 +300,8 @@ macro_rules! method {
}
}
};
(peer_req $method:ident $Req:ident($Param: ident)? => $Resp: ident ) => {
($(#[$meta:meta])* peer_req $method:ident $Req:ident($Param: ident)? => $Resp: ident ) => {
$(#[$meta])*
pub async fn $method(&self, params: Option<$Param>) -> Result<$Resp, ServiceError> {
let result = self
.send_request(ClientRequest::$Req($Req {
Expand All @@ -313,7 +316,8 @@ macro_rules! method {
}
}
};
(peer_req $method:ident $Req:ident($Param: ident)) => {
($(#[$meta:meta])* peer_req $method:ident $Req:ident($Param: ident)) => {
$(#[$meta])*
pub async fn $method(&self, params: $Param) -> Result<(), ServiceError> {
let result = self
.send_request(ClientRequest::$Req($Req {
Expand All @@ -329,7 +333,8 @@ macro_rules! method {
}
};

(peer_not $method:ident $Not:ident($Param: ident)) => {
($(#[$meta:meta])* peer_not $method:ident $Not:ident($Param: ident)) => {
$(#[$meta])*
pub async fn $method(&self, params: $Param) -> Result<(), ServiceError> {
self.send_notification(ClientNotification::$Not($Not {
method: Default::default(),
Expand All @@ -340,7 +345,8 @@ macro_rules! method {
Ok(())
}
};
(peer_not $method:ident $Not:ident) => {
($(#[$meta:meta])* peer_not $method:ident $Not:ident) => {
$(#[$meta])*
pub async fn $method(&self) -> Result<(), ServiceError> {
self.send_notification(ClientNotification::$Not($Not {
method: Default::default(),
Expand All @@ -354,7 +360,13 @@ macro_rules! method {

impl Peer<RoleClient> {
method!(peer_req complete CompleteRequest(CompleteRequestParams) => CompleteResult);
method!(peer_req set_level SetLevelRequest(SetLevelRequestParams));
method!(
#[deprecated(
since = "1.8.0",
note = "Logging is deprecated by SEP-2577 and will be removed in a future release. See https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577"
)]
peer_req set_level SetLevelRequest(SetLevelRequestParams)
);
method!(peer_req get_prompt GetPromptRequest(GetPromptRequestParams) => GetPromptResult);
method!(peer_req list_prompts ListPromptsRequest(PaginatedRequestParams)? => ListPromptsResult);
method!(peer_req list_resources ListResourcesRequest(PaginatedRequestParams)? => ListResourcesResult);
Expand Down
Loading