Skip to content
Open
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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
```
</details>

For client-side TTL caching, configuration, and authorization partitioning, see [Client response caching](docs/CLIENT_CACHING.md).

### Build a Server

<details>
Expand Down
4 changes: 4 additions & 0 deletions crates/rmcp/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- add a configurable SEP-2549 client response cache with TTL, scope, pagination, and notification invalidation support

## [2.2.0](https://github.com/modelcontextprotocol/rust-sdk/compare/rmcp-v2.1.0...rmcp-v2.2.0) - 2026-07-08

### Added
Expand Down
7 changes: 7 additions & 0 deletions crates/rmcp/src/handler/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,22 @@ impl<H: ClientHandler> Service<RoleClient> for H {
self.on_logging_message(notification.params, context).await
}
ServerNotification::ResourceUpdatedNotification(notification) => {
context
.peer
.invalidate_resource_read_cache(&notification.params.uri)
.await;
self.on_resource_updated(notification.params, context).await
}
ServerNotification::ResourceListChangedNotification(_notification_no_param) => {
context.peer.invalidate_resource_list_cache().await;
self.on_resource_list_changed(context).await
}
ServerNotification::ToolListChangedNotification(_notification_no_param) => {
context.peer.invalidate_tool_cache().await;
self.on_tool_list_changed(context).await
}
ServerNotification::PromptListChangedNotification(_notification_no_param) => {
context.peer.invalidate_prompt_cache().await;
self.on_prompt_list_changed(context).await
}
ServerNotification::TaskStatusNotification(notification) => {
Expand Down
4 changes: 2 additions & 2 deletions crates/rmcp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ pub use handler::client::ClientHandler;
pub use handler::server::ServerHandler;
#[cfg(feature = "server")]
pub use handler::server::wrapper::Json;
#[cfg(feature = "client")]
pub use service::{ClientCacheConfig, MAX_CLIENT_CACHE_TTL, RoleClient, serve_client};
#[cfg(any(feature = "client", feature = "server"))]
pub use service::{Peer, Service, ServiceError, ServiceExt};
#[cfg(feature = "client")]
pub use service::{RoleClient, serve_client};
#[cfg(feature = "server")]
pub use service::{RoleServer, serve_server};

Expand Down
4 changes: 4 additions & 0 deletions crates/rmcp/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,8 @@ pub struct Peer<R: ServiceRole> {
progress_token_provider: Arc<dyn ProgressTokenProvider>,
progress_timeout_watchers: ProgressTimeoutWatchers,
info: Arc<std::sync::RwLock<Option<Arc<R::PeerInfo>>>>,
#[cfg(feature = "client")]
response_cache: client::cache::PeerResponseCache<R>,
}

impl<R: ServiceRole> std::fmt::Debug for Peer<R> {
Expand Down Expand Up @@ -588,6 +590,8 @@ impl<R: ServiceRole> Peer<R> {
progress_token_provider: Arc::new(AtomicU32ProgressTokenProvider::default()),
progress_timeout_watchers: Default::default(),
info: Arc::new(std::sync::RwLock::new(peer_info.map(Arc::new))),
#[cfg(feature = "client")]
response_cache: Default::default(),
},
rx,
)
Expand Down
Loading