fix: use cfg-gated Send+Sync supertraits to avoid semver break (#757)

This commit is contained in:
Dale Seo 2026-03-18 11:37:32 -04:00 • committed by GitHub
commit d485249048
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 248 additions and 213 deletions

View file

@ -4,8 +4,7 @@ use crate::{
error::ErrorData as McpError, error::ErrorData as McpError,
model::{TaskSupport, *}, model::{TaskSupport, *},
service::{ service::{
MaybeSend, MaybeSendFuture, NotificationContext, RequestContext, RoleServer, Service, MaybeSendFuture, NotificationContext, RequestContext, RoleServer, Service, ServiceRole,
ServiceRole,
}, },
}; };
@ -161,12 +160,8 @@ impl<H: ServerHandler> Service<RoleServer> for H {
} }
} }
#[allow(unused_variables)] macro_rules! server_handler_methods {
#[allow( () => {
private_bounds,
reason = "MaybeSend is a sealed conditional Send + Sync alias"
)]
pub trait ServerHandler: Sized + MaybeSend + 'static {
fn enqueue_task( fn enqueue_task(
&self, &self,
_request: CallToolRequestParams, _request: CallToolRequestParams,
@ -233,8 +228,9 @@ pub trait ServerHandler: Sized + MaybeSend + 'static {
&self, &self,
request: Option<PaginatedRequestParams>, request: Option<PaginatedRequestParams>,
context: RequestContext<RoleServer>, context: RequestContext<RoleServer>,
) -> impl Future<Output = Result<ListResourceTemplatesResult, McpError>> + MaybeSendFuture + '_ ) -> impl Future<Output = Result<ListResourceTemplatesResult, McpError>>
{ + MaybeSendFuture
+ '_ {
std::future::ready(Ok(ListResourceTemplatesResult::default())) std::future::ready(Ok(ListResourceTemplatesResult::default()))
} }
fn read_resource( fn read_resource(
@ -258,7 +254,9 @@ pub trait ServerHandler: Sized + MaybeSend + 'static {
request: UnsubscribeRequestParams, request: UnsubscribeRequestParams,
context: RequestContext<RoleServer>, context: RequestContext<RoleServer>,
) -> impl Future<Output = Result<(), McpError>> + MaybeSendFuture + '_ { ) -> impl Future<Output = Result<(), McpError>> + MaybeSendFuture + '_ {
std::future::ready(Err(McpError::method_not_found::<UnsubscribeRequestMethod>())) std::future::ready(Err(
McpError::method_not_found::<UnsubscribeRequestMethod>(),
))
} }
fn call_tool( fn call_tool(
&self, &self,
@ -369,6 +367,19 @@ pub trait ServerHandler: Sized + MaybeSend + 'static {
let _ = (request, context); let _ = (request, context);
std::future::ready(Err(McpError::method_not_found::<CancelTaskMethod>())) std::future::ready(Err(McpError::method_not_found::<CancelTaskMethod>()))
} }
};
}
#[allow(unused_variables)]
#[cfg(not(feature = "local"))]
pub trait ServerHandler: Sized + Send + Sync + 'static {
server_handler_methods!();
}
#[allow(unused_variables)]
#[cfg(feature = "local")]
pub trait ServerHandler: Sized + 'static {
server_handler_methods!();
} }
macro_rules! impl_server_handler_for_wrapper { macro_rules! impl_server_handler_for_wrapper {

View file

@ -128,11 +128,23 @@ pub type RxJsonRpcMessage<R> = JsonRpcMessage<
<R as ServiceRole>::PeerNot, <R as ServiceRole>::PeerNot,
>; >;
#[allow( #[cfg(not(feature = "local"))]
private_bounds, pub trait Service<R: ServiceRole>: Send + Sync + 'static {
reason = "MaybeSend is a sealed conditional Send + Sync alias" fn handle_request(
)] &self,
pub trait Service<R: ServiceRole>: MaybeSend + 'static { request: R::PeerReq,
context: RequestContext<R>,
) -> impl Future<Output = Result<R::Resp, McpError>> + MaybeSendFuture + '_;
fn handle_notification(
&self,
notification: R::PeerNot,
context: NotificationContext<R>,
) -> impl Future<Output = Result<(), McpError>> + MaybeSendFuture + '_;
fn get_info(&self) -> R::Info;
}
#[cfg(feature = "local")]
pub trait Service<R: ServiceRole>: 'static {
fn handle_request( fn handle_request(
&self, &self,
request: R::PeerReq, request: R::PeerReq,
@ -197,11 +209,23 @@ impl<R: ServiceRole> Service<R> for Box<dyn DynService<R>> {
} }
} }
#[allow( #[cfg(not(feature = "local"))]
private_bounds, pub trait DynService<R: ServiceRole>: Send + Sync {
reason = "MaybeSend is a sealed conditional Send + Sync alias" fn handle_request(
)] &self,
pub trait DynService<R: ServiceRole>: MaybeSend { request: R::PeerReq,
context: RequestContext<R>,
) -> MaybeBoxFuture<'_, Result<R::Resp, McpError>>;
fn handle_notification(
&self,
notification: R::PeerNot,
context: NotificationContext<R>,
) -> MaybeBoxFuture<'_, Result<(), McpError>>;
fn get_info(&self) -> R::Info;
}
#[cfg(feature = "local")]
pub trait DynService<R: ServiceRole> {
fn handle_request( fn handle_request(
&self, &self,
request: R::PeerReq, request: R::PeerReq,