Skip to content

Commit 2dfda9c

Browse files
committed
feat(client): add SEP-2549 response caching
1 parent 3662d20 commit 2dfda9c

9 files changed

Lines changed: 1135 additions & 24 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
7474
```
7575
</details>
7676

77+
For client-side TTL caching, configuration, and authorization partitioning, see [Client response caching](docs/CLIENT_CACHING.md).
78+
7779
### Build a Server
7880

7981
<details>

crates/rmcp/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- add a configurable SEP-2549 client response cache with TTL, scope, pagination, and notification invalidation support
13+
1014
## [2.2.0](https://github.com/modelcontextprotocol/rust-sdk/compare/rmcp-v2.1.0...rmcp-v2.2.0) - 2026-07-08
1115

1216
### Added

crates/rmcp/src/handler/client.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,22 @@ impl<H: ClientHandler> Service<RoleClient> for H {
5555
self.on_logging_message(notification.params, context).await
5656
}
5757
ServerNotification::ResourceUpdatedNotification(notification) => {
58+
context
59+
.peer
60+
.invalidate_resource_read_cache(&notification.params.uri)
61+
.await;
5862
self.on_resource_updated(notification.params, context).await
5963
}
6064
ServerNotification::ResourceListChangedNotification(_notification_no_param) => {
65+
context.peer.invalidate_resource_list_cache().await;
6166
self.on_resource_list_changed(context).await
6267
}
6368
ServerNotification::ToolListChangedNotification(_notification_no_param) => {
69+
context.peer.invalidate_tool_cache().await;
6470
self.on_tool_list_changed(context).await
6571
}
6672
ServerNotification::PromptListChangedNotification(_notification_no_param) => {
73+
context.peer.invalidate_prompt_cache().await;
6774
self.on_prompt_list_changed(context).await
6875
}
6976
ServerNotification::TaskStatusNotification(notification) => {

crates/rmcp/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ pub use handler::client::ClientHandler;
1616
pub use handler::server::ServerHandler;
1717
#[cfg(feature = "server")]
1818
pub use handler::server::wrapper::Json;
19+
#[cfg(feature = "client")]
20+
pub use service::{ClientCacheConfig, MAX_CLIENT_CACHE_TTL, RoleClient, serve_client};
1921
#[cfg(any(feature = "client", feature = "server"))]
2022
pub use service::{Peer, Service, ServiceError, ServiceExt};
21-
#[cfg(feature = "client")]
22-
pub use service::{RoleClient, serve_client};
2323
#[cfg(feature = "server")]
2424
pub use service::{RoleServer, serve_server};
2525

crates/rmcp/src/service.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,8 @@ pub struct Peer<R: ServiceRole> {
527527
progress_token_provider: Arc<dyn ProgressTokenProvider>,
528528
progress_timeout_watchers: ProgressTimeoutWatchers,
529529
info: Arc<std::sync::RwLock<Option<Arc<R::PeerInfo>>>>,
530+
#[cfg(feature = "client")]
531+
response_cache: client::cache::PeerResponseCache<R>,
530532
}
531533

532534
impl<R: ServiceRole> std::fmt::Debug for Peer<R> {
@@ -588,6 +590,8 @@ impl<R: ServiceRole> Peer<R> {
588590
progress_token_provider: Arc::new(AtomicU32ProgressTokenProvider::default()),
589591
progress_timeout_watchers: Default::default(),
590592
info: Arc::new(std::sync::RwLock::new(peer_info.map(Arc::new))),
593+
#[cfg(feature = "client")]
594+
response_cache: Default::default(),
591595
},
592596
rx,
593597
)

0 commit comments

Comments
 (0)