From 7b6900fb11f9d97be8c6786b45c5a2628adf0f4b Mon Sep 17 00:00:00 2001 From: Taylor Ninesling Date: Wed, 7 Jan 2026 15:56:51 -0600 Subject: [PATCH 1/4] feat!: implement ServerHandler for Box and Arc where H is a ServerHandler --- crates/rmcp/src/handler/server.rs | 390 +++++++++++++++++++++++ crates/rmcp/src/handler/server/router.rs | 2 +- 2 files changed, 391 insertions(+), 1 deletion(-) diff --git a/crates/rmcp/src/handler/server.rs b/crates/rmcp/src/handler/server.rs index f10cfa7c8..705496071 100644 --- a/crates/rmcp/src/handler/server.rs +++ b/crates/rmcp/src/handler/server.rs @@ -327,3 +327,393 @@ pub trait ServerHandler: Sized + Send + Sync + 'static { std::future::ready(Err(McpError::method_not_found::())) } } + +impl ServerHandler for Box { + fn enqueue_task( + &self, + request: CallToolRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).enqueue_task(request, context) + } + + fn ping( + &self, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).ping(context) + } + + fn initialize( + &self, + request: InitializeRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).initialize(request, context) + } + + fn complete( + &self, + request: CompleteRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).complete(request, context) + } + + fn set_level( + &self, + request: SetLevelRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).set_level(request, context) + } + + fn get_prompt( + &self, + request: GetPromptRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).get_prompt(request, context) + } + + fn list_prompts( + &self, + request: Option, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).list_prompts(request, context) + } + + fn list_resources( + &self, + request: Option, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).list_resources(request, context) + } + + fn list_resource_templates( + &self, + request: Option, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).list_resource_templates(request, context) + } + + fn read_resource( + &self, + request: ReadResourceRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).read_resource(request, context) + } + + fn subscribe( + &self, + request: SubscribeRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).subscribe(request, context) + } + + fn unsubscribe( + &self, + request: UnsubscribeRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).unsubscribe(request, context) + } + + fn call_tool( + &self, + request: CallToolRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).call_tool(request, context) + } + + fn list_tools( + &self, + request: Option, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).list_tools(request, context) + } + + fn on_custom_request( + &self, + request: CustomRequest, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).on_custom_request(request, context) + } + + fn on_cancelled( + &self, + notification: CancelledNotificationParam, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_cancelled(notification, context) + } + + fn on_progress( + &self, + notification: ProgressNotificationParam, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_progress(notification, context) + } + + fn on_initialized( + &self, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_initialized(context) + } + + fn on_roots_list_changed( + &self, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_roots_list_changed(context) + } + + fn on_custom_notification( + &self, + notification: CustomNotification, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_custom_notification(notification, context) + } + + fn get_info(&self) -> ServerInfo { + (**self).get_info() + } + + fn list_tasks( + &self, + request: Option, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).list_tasks(request, context) + } + + fn get_task_info( + &self, + request: GetTaskInfoParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).get_task_info(request, context) + } + + fn get_task_result( + &self, + request: GetTaskResultParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).get_task_result(request, context) + } + + fn cancel_task( + &self, + request: CancelTaskParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).cancel_task(request, context) + } +} + +impl ServerHandler for std::sync::Arc { + fn enqueue_task( + &self, + request: CallToolRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).enqueue_task(request, context) + } + + fn ping( + &self, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).ping(context) + } + + fn initialize( + &self, + request: InitializeRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).initialize(request, context) + } + + fn complete( + &self, + request: CompleteRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).complete(request, context) + } + + fn set_level( + &self, + request: SetLevelRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).set_level(request, context) + } + + fn get_prompt( + &self, + request: GetPromptRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).get_prompt(request, context) + } + + fn list_prompts( + &self, + request: Option, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).list_prompts(request, context) + } + + fn list_resources( + &self, + request: Option, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).list_resources(request, context) + } + + fn list_resource_templates( + &self, + request: Option, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).list_resource_templates(request, context) + } + + fn read_resource( + &self, + request: ReadResourceRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).read_resource(request, context) + } + + fn subscribe( + &self, + request: SubscribeRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).subscribe(request, context) + } + + fn unsubscribe( + &self, + request: UnsubscribeRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).unsubscribe(request, context) + } + + fn call_tool( + &self, + request: CallToolRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).call_tool(request, context) + } + + fn list_tools( + &self, + request: Option, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).list_tools(request, context) + } + + fn on_custom_request( + &self, + request: CustomRequest, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).on_custom_request(request, context) + } + + fn on_cancelled( + &self, + notification: CancelledNotificationParam, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_cancelled(notification, context) + } + + fn on_progress( + &self, + notification: ProgressNotificationParam, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_progress(notification, context) + } + + fn on_initialized( + &self, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_initialized(context) + } + + fn on_roots_list_changed( + &self, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_roots_list_changed(context) + } + + fn on_custom_notification( + &self, + notification: CustomNotification, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_custom_notification(notification, context) + } + + fn get_info(&self) -> ServerInfo { + (**self).get_info() + } + + fn list_tasks( + &self, + request: Option, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).list_tasks(request, context) + } + + fn get_task_info( + &self, + request: GetTaskInfoParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).get_task_info(request, context) + } + + fn get_task_result( + &self, + request: GetTaskResultParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).get_task_result(request, context) + } + + fn cancel_task( + &self, + request: CancelTaskParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).cancel_task(request, context) + } +} diff --git a/crates/rmcp/src/handler/server/router.rs b/crates/rmcp/src/handler/server/router.rs index 0b9080818..1f34ba5b2 100644 --- a/crates/rmcp/src/handler/server/router.rs +++ b/crates/rmcp/src/handler/server/router.rs @@ -133,6 +133,6 @@ where } fn get_info(&self) -> ::Info { - self.service.get_info() + ServerHandler::get_info(&self.service) } } From e0006bb7753785681e1b8562df88532894f0de06 Mon Sep 17 00:00:00 2001 From: Taylor Ninesling Date: Wed, 7 Jan 2026 16:08:20 -0600 Subject: [PATCH 2/4] feat!: implement ClientHandler for Box and Arc where H is a ClientHandler --- crates/rmcp/src/handler/client.rs | 210 ++++++++++++++++++++++++++++++ 1 file changed, 210 insertions(+) diff --git a/crates/rmcp/src/handler/client.rs b/crates/rmcp/src/handler/client.rs index 15b1c0c00..b9e79387f 100644 --- a/crates/rmcp/src/handler/client.rs +++ b/crates/rmcp/src/handler/client.rs @@ -210,3 +210,213 @@ impl ClientHandler for ClientInfo { self.clone() } } + +impl ClientHandler for Box { + fn ping( + &self, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).ping(context) + } + + fn create_message( + &self, + params: CreateMessageRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).create_message(params, context) + } + + fn list_roots( + &self, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).list_roots(context) + } + + fn create_elicitation( + &self, + request: CreateElicitationRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).create_elicitation(request, context) + } + + fn on_custom_request( + &self, + request: CustomRequest, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).on_custom_request(request, context) + } + + fn on_cancelled( + &self, + params: CancelledNotificationParam, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_cancelled(params, context) + } + + fn on_progress( + &self, + params: ProgressNotificationParam, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_progress(params, context) + } + + fn on_logging_message( + &self, + params: LoggingMessageNotificationParam, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_logging_message(params, context) + } + + fn on_resource_updated( + &self, + params: ResourceUpdatedNotificationParam, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_resource_updated(params, context) + } + + fn on_resource_list_changed( + &self, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_resource_list_changed(context) + } + + fn on_tool_list_changed( + &self, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_tool_list_changed(context) + } + + fn on_prompt_list_changed( + &self, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_prompt_list_changed(context) + } + + fn on_custom_notification( + &self, + notification: CustomNotification, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_custom_notification(notification, context) + } + + fn get_info(&self) -> ClientInfo { + (**self).get_info() + } +} + +impl ClientHandler for std::sync::Arc { + fn ping( + &self, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).ping(context) + } + + fn create_message( + &self, + params: CreateMessageRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).create_message(params, context) + } + + fn list_roots( + &self, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).list_roots(context) + } + + fn create_elicitation( + &self, + request: CreateElicitationRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).create_elicitation(request, context) + } + + fn on_custom_request( + &self, + request: CustomRequest, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).on_custom_request(request, context) + } + + fn on_cancelled( + &self, + params: CancelledNotificationParam, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_cancelled(params, context) + } + + fn on_progress( + &self, + params: ProgressNotificationParam, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_progress(params, context) + } + + fn on_logging_message( + &self, + params: LoggingMessageNotificationParam, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_logging_message(params, context) + } + + fn on_resource_updated( + &self, + params: ResourceUpdatedNotificationParam, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_resource_updated(params, context) + } + + fn on_resource_list_changed( + &self, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_resource_list_changed(context) + } + + fn on_tool_list_changed( + &self, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_tool_list_changed(context) + } + + fn on_prompt_list_changed( + &self, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_prompt_list_changed(context) + } + + fn on_custom_notification( + &self, + notification: CustomNotification, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_custom_notification(notification, context) + } + + fn get_info(&self) -> ClientInfo { + (**self).get_info() + } +} From af889fb7a3b6c3f4c22301ac0e6c1f3f154b0207 Mon Sep 17 00:00:00 2001 From: Taylor Ninesling Date: Wed, 7 Jan 2026 16:38:33 -0600 Subject: [PATCH 3/4] test: test Box and Arc have blanket implementations for handler traits --- crates/rmcp/src/handler/client.rs | 4 +-- crates/rmcp/src/handler/server.rs | 4 +-- crates/rmcp/tests/test_handler_wrappers.rs | 29 ++++++++++++++++++++++ 3 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 crates/rmcp/tests/test_handler_wrappers.rs diff --git a/crates/rmcp/src/handler/client.rs b/crates/rmcp/src/handler/client.rs index b9e79387f..73681894a 100644 --- a/crates/rmcp/src/handler/client.rs +++ b/crates/rmcp/src/handler/client.rs @@ -211,7 +211,7 @@ impl ClientHandler for ClientInfo { } } -impl ClientHandler for Box { +impl ClientHandler for Box { fn ping( &self, context: RequestContext, @@ -316,7 +316,7 @@ impl ClientHandler for Box { } } -impl ClientHandler for std::sync::Arc { +impl ClientHandler for std::sync::Arc { fn ping( &self, context: RequestContext, diff --git a/crates/rmcp/src/handler/server.rs b/crates/rmcp/src/handler/server.rs index 705496071..477172efa 100644 --- a/crates/rmcp/src/handler/server.rs +++ b/crates/rmcp/src/handler/server.rs @@ -328,7 +328,7 @@ pub trait ServerHandler: Sized + Send + Sync + 'static { } } -impl ServerHandler for Box { +impl ServerHandler for Box { fn enqueue_task( &self, request: CallToolRequestParam, @@ -523,7 +523,7 @@ impl ServerHandler for Box { } } -impl ServerHandler for std::sync::Arc { +impl ServerHandler for std::sync::Arc { fn enqueue_task( &self, request: CallToolRequestParam, diff --git a/crates/rmcp/tests/test_handler_wrappers.rs b/crates/rmcp/tests/test_handler_wrappers.rs new file mode 100644 index 000000000..06558cdfa --- /dev/null +++ b/crates/rmcp/tests/test_handler_wrappers.rs @@ -0,0 +1,29 @@ +// cargo test --test test_handler_wrappers --features "client server" + +mod common; + +use std::sync::Arc; + +use rmcp::{ClientHandler, ServerHandler}; + +use common::handlers::{TestClientHandler, TestServer}; + +#[test] +fn test_wrapped_server_handlers() { + // This test asserts that, when T: ServerHandler, both Box and Arc also implement ServerHandler. + fn accepts_server_handler(_handler: H) {} + + accepts_server_handler(Box::new(TestServer::new())); + accepts_server_handler(Arc::new(TestServer::new())); +} + +#[test] +fn test_wrapped_client_handlers() { + // This test asserts that, when T: ClientHandler, both Box and Arc also implement ClientHandler. + fn accepts_client_handler(_handler: H) {} + + let client = TestClientHandler::new(false, false); + + accepts_client_handler(Box::new(client.clone())); + accepts_client_handler(Arc::new(client)); +} From caf00d30a7c829660c22d0a57a3be0b4d046bdc2 Mon Sep 17 00:00:00 2001 From: Taylor Ninesling Date: Fri, 9 Jan 2026 17:01:53 -0600 Subject: [PATCH 4/4] refactor: deduplicate blanket implementations with macros --- crates/rmcp/src/handler/client.rs | 292 ++++------- crates/rmcp/src/handler/server.rs | 541 +++++++-------------- crates/rmcp/tests/test_handler_wrappers.rs | 3 +- 3 files changed, 277 insertions(+), 559 deletions(-) diff --git a/crates/rmcp/src/handler/client.rs b/crates/rmcp/src/handler/client.rs index 73681894a..cd238310f 100644 --- a/crates/rmcp/src/handler/client.rs +++ b/crates/rmcp/src/handler/client.rs @@ -1,4 +1,6 @@ pub mod progress; +use std::sync::Arc; + use crate::{ error::ErrorData as McpError, model::*, @@ -211,212 +213,114 @@ impl ClientHandler for ClientInfo { } } -impl ClientHandler for Box { - fn ping( - &self, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).ping(context) - } +macro_rules! impl_client_handler_for_wrapper { + ($wrapper:ident) => { + impl ClientHandler for $wrapper { + fn ping( + &self, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).ping(context) + } - fn create_message( - &self, - params: CreateMessageRequestParam, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).create_message(params, context) - } + fn create_message( + &self, + params: CreateMessageRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).create_message(params, context) + } - fn list_roots( - &self, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).list_roots(context) - } + fn list_roots( + &self, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).list_roots(context) + } - fn create_elicitation( - &self, - request: CreateElicitationRequestParam, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).create_elicitation(request, context) - } + fn create_elicitation( + &self, + request: CreateElicitationRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).create_elicitation(request, context) + } - fn on_custom_request( - &self, - request: CustomRequest, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).on_custom_request(request, context) - } + fn on_custom_request( + &self, + request: CustomRequest, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).on_custom_request(request, context) + } - fn on_cancelled( - &self, - params: CancelledNotificationParam, - context: NotificationContext, - ) -> impl Future + Send + '_ { - (**self).on_cancelled(params, context) - } + fn on_cancelled( + &self, + params: CancelledNotificationParam, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_cancelled(params, context) + } - fn on_progress( - &self, - params: ProgressNotificationParam, - context: NotificationContext, - ) -> impl Future + Send + '_ { - (**self).on_progress(params, context) - } + fn on_progress( + &self, + params: ProgressNotificationParam, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_progress(params, context) + } - fn on_logging_message( - &self, - params: LoggingMessageNotificationParam, - context: NotificationContext, - ) -> impl Future + Send + '_ { - (**self).on_logging_message(params, context) - } + fn on_logging_message( + &self, + params: LoggingMessageNotificationParam, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_logging_message(params, context) + } - fn on_resource_updated( - &self, - params: ResourceUpdatedNotificationParam, - context: NotificationContext, - ) -> impl Future + Send + '_ { - (**self).on_resource_updated(params, context) - } + fn on_resource_updated( + &self, + params: ResourceUpdatedNotificationParam, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_resource_updated(params, context) + } - fn on_resource_list_changed( - &self, - context: NotificationContext, - ) -> impl Future + Send + '_ { - (**self).on_resource_list_changed(context) - } + fn on_resource_list_changed( + &self, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_resource_list_changed(context) + } - fn on_tool_list_changed( - &self, - context: NotificationContext, - ) -> impl Future + Send + '_ { - (**self).on_tool_list_changed(context) - } + fn on_tool_list_changed( + &self, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_tool_list_changed(context) + } - fn on_prompt_list_changed( - &self, - context: NotificationContext, - ) -> impl Future + Send + '_ { - (**self).on_prompt_list_changed(context) - } + fn on_prompt_list_changed( + &self, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_prompt_list_changed(context) + } - fn on_custom_notification( - &self, - notification: CustomNotification, - context: NotificationContext, - ) -> impl Future + Send + '_ { - (**self).on_custom_notification(notification, context) - } + fn on_custom_notification( + &self, + notification: CustomNotification, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_custom_notification(notification, context) + } - fn get_info(&self) -> ClientInfo { - (**self).get_info() - } + fn get_info(&self) -> ClientInfo { + (**self).get_info() + } + } + }; } -impl ClientHandler for std::sync::Arc { - fn ping( - &self, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).ping(context) - } - - fn create_message( - &self, - params: CreateMessageRequestParam, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).create_message(params, context) - } - - fn list_roots( - &self, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).list_roots(context) - } - - fn create_elicitation( - &self, - request: CreateElicitationRequestParam, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).create_elicitation(request, context) - } - - fn on_custom_request( - &self, - request: CustomRequest, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).on_custom_request(request, context) - } - - fn on_cancelled( - &self, - params: CancelledNotificationParam, - context: NotificationContext, - ) -> impl Future + Send + '_ { - (**self).on_cancelled(params, context) - } - - fn on_progress( - &self, - params: ProgressNotificationParam, - context: NotificationContext, - ) -> impl Future + Send + '_ { - (**self).on_progress(params, context) - } - - fn on_logging_message( - &self, - params: LoggingMessageNotificationParam, - context: NotificationContext, - ) -> impl Future + Send + '_ { - (**self).on_logging_message(params, context) - } - - fn on_resource_updated( - &self, - params: ResourceUpdatedNotificationParam, - context: NotificationContext, - ) -> impl Future + Send + '_ { - (**self).on_resource_updated(params, context) - } - - fn on_resource_list_changed( - &self, - context: NotificationContext, - ) -> impl Future + Send + '_ { - (**self).on_resource_list_changed(context) - } - - fn on_tool_list_changed( - &self, - context: NotificationContext, - ) -> impl Future + Send + '_ { - (**self).on_tool_list_changed(context) - } - - fn on_prompt_list_changed( - &self, - context: NotificationContext, - ) -> impl Future + Send + '_ { - (**self).on_prompt_list_changed(context) - } - - fn on_custom_notification( - &self, - notification: CustomNotification, - context: NotificationContext, - ) -> impl Future + Send + '_ { - (**self).on_custom_notification(notification, context) - } - - fn get_info(&self) -> ClientInfo { - (**self).get_info() - } -} +impl_client_handler_for_wrapper!(Box); +impl_client_handler_for_wrapper!(Arc); diff --git a/crates/rmcp/src/handler/server.rs b/crates/rmcp/src/handler/server.rs index 477172efa..073ee1086 100644 --- a/crates/rmcp/src/handler/server.rs +++ b/crates/rmcp/src/handler/server.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use crate::{ error::ErrorData as McpError, model::*, @@ -328,392 +330,205 @@ pub trait ServerHandler: Sized + Send + Sync + 'static { } } -impl ServerHandler for Box { - fn enqueue_task( - &self, - request: CallToolRequestParam, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).enqueue_task(request, context) - } +macro_rules! impl_server_handler_for_wrapper { + ($wrapper:ident) => { + impl ServerHandler for $wrapper { + fn enqueue_task( + &self, + request: CallToolRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).enqueue_task(request, context) + } - fn ping( - &self, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).ping(context) - } + fn ping( + &self, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).ping(context) + } - fn initialize( - &self, - request: InitializeRequestParam, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).initialize(request, context) - } + fn initialize( + &self, + request: InitializeRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).initialize(request, context) + } - fn complete( - &self, - request: CompleteRequestParam, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).complete(request, context) - } + fn complete( + &self, + request: CompleteRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).complete(request, context) + } - fn set_level( - &self, - request: SetLevelRequestParam, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).set_level(request, context) - } + fn set_level( + &self, + request: SetLevelRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).set_level(request, context) + } - fn get_prompt( - &self, - request: GetPromptRequestParam, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).get_prompt(request, context) - } + fn get_prompt( + &self, + request: GetPromptRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).get_prompt(request, context) + } - fn list_prompts( - &self, - request: Option, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).list_prompts(request, context) - } + fn list_prompts( + &self, + request: Option, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).list_prompts(request, context) + } - fn list_resources( - &self, - request: Option, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).list_resources(request, context) - } + fn list_resources( + &self, + request: Option, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).list_resources(request, context) + } - fn list_resource_templates( - &self, - request: Option, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).list_resource_templates(request, context) - } + fn list_resource_templates( + &self, + request: Option, + context: RequestContext, + ) -> impl Future> + Send + '_ + { + (**self).list_resource_templates(request, context) + } - fn read_resource( - &self, - request: ReadResourceRequestParam, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).read_resource(request, context) - } + fn read_resource( + &self, + request: ReadResourceRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).read_resource(request, context) + } - fn subscribe( - &self, - request: SubscribeRequestParam, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).subscribe(request, context) - } + fn subscribe( + &self, + request: SubscribeRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).subscribe(request, context) + } - fn unsubscribe( - &self, - request: UnsubscribeRequestParam, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).unsubscribe(request, context) - } + fn unsubscribe( + &self, + request: UnsubscribeRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).unsubscribe(request, context) + } - fn call_tool( - &self, - request: CallToolRequestParam, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).call_tool(request, context) - } + fn call_tool( + &self, + request: CallToolRequestParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).call_tool(request, context) + } - fn list_tools( - &self, - request: Option, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).list_tools(request, context) - } + fn list_tools( + &self, + request: Option, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).list_tools(request, context) + } - fn on_custom_request( - &self, - request: CustomRequest, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).on_custom_request(request, context) - } + fn on_custom_request( + &self, + request: CustomRequest, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).on_custom_request(request, context) + } - fn on_cancelled( - &self, - notification: CancelledNotificationParam, - context: NotificationContext, - ) -> impl Future + Send + '_ { - (**self).on_cancelled(notification, context) - } + fn on_cancelled( + &self, + notification: CancelledNotificationParam, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_cancelled(notification, context) + } - fn on_progress( - &self, - notification: ProgressNotificationParam, - context: NotificationContext, - ) -> impl Future + Send + '_ { - (**self).on_progress(notification, context) - } + fn on_progress( + &self, + notification: ProgressNotificationParam, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_progress(notification, context) + } - fn on_initialized( - &self, - context: NotificationContext, - ) -> impl Future + Send + '_ { - (**self).on_initialized(context) - } + fn on_initialized( + &self, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_initialized(context) + } - fn on_roots_list_changed( - &self, - context: NotificationContext, - ) -> impl Future + Send + '_ { - (**self).on_roots_list_changed(context) - } + fn on_roots_list_changed( + &self, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_roots_list_changed(context) + } - fn on_custom_notification( - &self, - notification: CustomNotification, - context: NotificationContext, - ) -> impl Future + Send + '_ { - (**self).on_custom_notification(notification, context) - } + fn on_custom_notification( + &self, + notification: CustomNotification, + context: NotificationContext, + ) -> impl Future + Send + '_ { + (**self).on_custom_notification(notification, context) + } - fn get_info(&self) -> ServerInfo { - (**self).get_info() - } + fn get_info(&self) -> ServerInfo { + (**self).get_info() + } - fn list_tasks( - &self, - request: Option, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).list_tasks(request, context) - } + fn list_tasks( + &self, + request: Option, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).list_tasks(request, context) + } - fn get_task_info( - &self, - request: GetTaskInfoParam, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).get_task_info(request, context) - } + fn get_task_info( + &self, + request: GetTaskInfoParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).get_task_info(request, context) + } - fn get_task_result( - &self, - request: GetTaskResultParam, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).get_task_result(request, context) - } + fn get_task_result( + &self, + request: GetTaskResultParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).get_task_result(request, context) + } - fn cancel_task( - &self, - request: CancelTaskParam, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).cancel_task(request, context) - } + fn cancel_task( + &self, + request: CancelTaskParam, + context: RequestContext, + ) -> impl Future> + Send + '_ { + (**self).cancel_task(request, context) + } + } + }; } -impl ServerHandler for std::sync::Arc { - fn enqueue_task( - &self, - request: CallToolRequestParam, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).enqueue_task(request, context) - } - - fn ping( - &self, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).ping(context) - } - - fn initialize( - &self, - request: InitializeRequestParam, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).initialize(request, context) - } - - fn complete( - &self, - request: CompleteRequestParam, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).complete(request, context) - } - - fn set_level( - &self, - request: SetLevelRequestParam, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).set_level(request, context) - } - - fn get_prompt( - &self, - request: GetPromptRequestParam, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).get_prompt(request, context) - } - - fn list_prompts( - &self, - request: Option, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).list_prompts(request, context) - } - - fn list_resources( - &self, - request: Option, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).list_resources(request, context) - } - - fn list_resource_templates( - &self, - request: Option, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).list_resource_templates(request, context) - } - - fn read_resource( - &self, - request: ReadResourceRequestParam, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).read_resource(request, context) - } - - fn subscribe( - &self, - request: SubscribeRequestParam, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).subscribe(request, context) - } - - fn unsubscribe( - &self, - request: UnsubscribeRequestParam, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).unsubscribe(request, context) - } - - fn call_tool( - &self, - request: CallToolRequestParam, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).call_tool(request, context) - } - - fn list_tools( - &self, - request: Option, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).list_tools(request, context) - } - - fn on_custom_request( - &self, - request: CustomRequest, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).on_custom_request(request, context) - } - - fn on_cancelled( - &self, - notification: CancelledNotificationParam, - context: NotificationContext, - ) -> impl Future + Send + '_ { - (**self).on_cancelled(notification, context) - } - - fn on_progress( - &self, - notification: ProgressNotificationParam, - context: NotificationContext, - ) -> impl Future + Send + '_ { - (**self).on_progress(notification, context) - } - - fn on_initialized( - &self, - context: NotificationContext, - ) -> impl Future + Send + '_ { - (**self).on_initialized(context) - } - - fn on_roots_list_changed( - &self, - context: NotificationContext, - ) -> impl Future + Send + '_ { - (**self).on_roots_list_changed(context) - } - - fn on_custom_notification( - &self, - notification: CustomNotification, - context: NotificationContext, - ) -> impl Future + Send + '_ { - (**self).on_custom_notification(notification, context) - } - - fn get_info(&self) -> ServerInfo { - (**self).get_info() - } - - fn list_tasks( - &self, - request: Option, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).list_tasks(request, context) - } - - fn get_task_info( - &self, - request: GetTaskInfoParam, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).get_task_info(request, context) - } - - fn get_task_result( - &self, - request: GetTaskResultParam, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).get_task_result(request, context) - } - - fn cancel_task( - &self, - request: CancelTaskParam, - context: RequestContext, - ) -> impl Future> + Send + '_ { - (**self).cancel_task(request, context) - } -} +impl_server_handler_for_wrapper!(Box); +impl_server_handler_for_wrapper!(Arc); diff --git a/crates/rmcp/tests/test_handler_wrappers.rs b/crates/rmcp/tests/test_handler_wrappers.rs index 06558cdfa..e1faddc91 100644 --- a/crates/rmcp/tests/test_handler_wrappers.rs +++ b/crates/rmcp/tests/test_handler_wrappers.rs @@ -4,9 +4,8 @@ mod common; use std::sync::Arc; -use rmcp::{ClientHandler, ServerHandler}; - use common::handlers::{TestClientHandler, TestServer}; +use rmcp::{ClientHandler, ServerHandler}; #[test] fn test_wrapped_server_handlers() {