pub struct RequestRouter { /* private fields */ }Expand description
Request router for dispatching MCP requests to appropriate handlers
Implementations§
Source§impl RequestRouter
impl RequestRouter
Sourcepub fn new(
registry: Arc<HandlerRegistry>,
_metrics: Arc<ServerMetrics>,
server_config: ServerConfig,
) -> Self
pub fn new( registry: Arc<HandlerRegistry>, _metrics: Arc<ServerMetrics>, server_config: ServerConfig, ) -> Self
Create a new request router
Sourcepub fn with_config(
registry: Arc<HandlerRegistry>,
config: RouterConfig,
_metrics: Arc<ServerMetrics>,
server_config: ServerConfig,
) -> Self
pub fn with_config( registry: Arc<HandlerRegistry>, config: RouterConfig, _metrics: Arc<ServerMetrics>, server_config: ServerConfig, ) -> Self
Create a router with configuration
Sourcepub fn set_server_request_dispatcher<D>(&mut self, dispatcher: D)where
D: ServerRequestDispatcher + 'static,
pub fn set_server_request_dispatcher<D>(&mut self, dispatcher: D)where
D: ServerRequestDispatcher + 'static,
Set the server request dispatcher for bidirectional communication
CRITICAL: This also refreshes the server_to_client adapter so it sees the new dispatcher. Without this refresh, the adapter would still point to the old (empty) bidirectional router.
Sourcepub fn get_server_request_dispatcher(
&self,
) -> Option<&Arc<dyn ServerRequestDispatcher>>
pub fn get_server_request_dispatcher( &self, ) -> Option<&Arc<dyn ServerRequestDispatcher>>
Get the server request dispatcher
Sourcepub fn supports_bidirectional(&self) -> bool
pub fn supports_bidirectional(&self) -> bool
Check if bidirectional routing is enabled and supported
Sourcepub fn add_route<H>(&mut self, handler: H) -> ServerResult<()>where
H: RouteHandler + 'static,
pub fn add_route<H>(&mut self, handler: H) -> ServerResult<()>where
H: RouteHandler + 'static,
Add a custom route handler
§Errors
Returns ServerError::Routing if a route for the same method already exists.
Sourcepub fn create_context(
&self,
headers: Option<HashMap<String, String>>,
transport: Option<&str>,
) -> RequestContext
pub fn create_context( &self, headers: Option<HashMap<String, String>>, transport: Option<&str>, ) -> RequestContext
Create a properly configured RequestContext for this router
This factory method creates a RequestContext with all necessary capabilities pre-configured, including server-to-client communication for bidirectional features (sampling, elicitation, roots).
Design Pattern: Explicit Factory
- Context is valid from creation (no broken intermediate state)
- Router provides factory but doesn’t modify contexts
- Follows Single Responsibility Principle
HTTP Header Propagation: Pass headers from HTTP/WebSocket transports to include them in context metadata as “http_headers”.
§Arguments
headers- Optional HTTP headers from the transport layertransport- Optional transport type (“http”, “websocket”, etc.). Defaults to “http” if headers are provided.
§Example
// HTTP transport
let ctx = router.create_context(Some(headers), None);
// WebSocket transport
let ctx = router.create_context(Some(headers), Some("websocket"));
let response = router.route(request, ctx).await;Sourcepub async fn route(
&self,
request: JsonRpcRequest,
ctx: RequestContext,
) -> JsonRpcResponse
pub async fn route( &self, request: JsonRpcRequest, ctx: RequestContext, ) -> JsonRpcResponse
Route a JSON-RPC request to the appropriate handler
IMPORTANT: The context should be created using create_context() to ensure
it has all necessary capabilities configured. This method does NOT modify the
context - it only routes the request.
§Design Pattern
This follows the Single Responsibility Principle:
create_context(): Creates properly configured contextsroute(): Routes requests to handlers
Previously, route() was modifying the context (adding server_to_client),
which violated SRP and created invalid intermediate states.
Sourcepub async fn route_batch(
&self,
requests: Vec<JsonRpcRequest>,
ctx: RequestContext,
) -> Vec<JsonRpcResponse>
pub async fn route_batch( &self, requests: Vec<JsonRpcRequest>, ctx: RequestContext, ) -> Vec<JsonRpcResponse>
Handle batch requests
Sourcepub async fn send_elicitation_to_client(
&self,
request: ElicitRequest,
ctx: RequestContext,
) -> ServerResult<ElicitResult>
pub async fn send_elicitation_to_client( &self, request: ElicitRequest, ctx: RequestContext, ) -> ServerResult<ElicitResult>
Send an elicitation request to the client (server-initiated)
§Errors
Returns ServerError::Transport if:
- The bidirectional dispatcher is not configured
- The client request fails
- The client does not respond
Sourcepub async fn send_ping_to_client(
&self,
request: PingRequest,
ctx: RequestContext,
) -> ServerResult<PingResult>
pub async fn send_ping_to_client( &self, request: PingRequest, ctx: RequestContext, ) -> ServerResult<PingResult>
Send a ping request to the client (server-initiated)
§Errors
Returns ServerError::Transport if:
- The bidirectional dispatcher is not configured
- The client request fails
- The client does not respond
Sourcepub async fn send_create_message_to_client(
&self,
request: CreateMessageRequest,
ctx: RequestContext,
) -> ServerResult<CreateMessageResult>
pub async fn send_create_message_to_client( &self, request: CreateMessageRequest, ctx: RequestContext, ) -> ServerResult<CreateMessageResult>
Send a create message request to the client (server-initiated)
§Errors
Returns ServerError::Transport if:
- The bidirectional dispatcher is not configured
- The client request fails
- The client does not support sampling
Sourcepub async fn send_list_roots_to_client(
&self,
request: ListRootsRequest,
ctx: RequestContext,
) -> ServerResult<ListRootsResult>
pub async fn send_list_roots_to_client( &self, request: ListRootsRequest, ctx: RequestContext, ) -> ServerResult<ListRootsResult>
Send a list roots request to the client (server-initiated)
§Errors
Returns ServerError::Transport if:
- The bidirectional dispatcher is not configured
- The client request fails
- The client does not support roots
Trait Implementations§
Source§impl Clone for RequestRouter
impl Clone for RequestRouter
Source§impl Debug for RequestRouter
impl Debug for RequestRouter
Source§impl JsonRpcHandler for RequestRouter
impl JsonRpcHandler for RequestRouter
Source§fn handle_request<'life0, 'async_trait>(
&'life0 self,
req_value: Value,
) -> Pin<Box<dyn Future<Output = Value> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn handle_request<'life0, 'async_trait>(
&'life0 self,
req_value: Value,
) -> Pin<Box<dyn Future<Output = Value> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Handle a JSON-RPC request via the HTTP transport
This implementation enables RequestRouter to be used directly with
the HTTP transport layer (run_server), supporting the builder pattern
for programmatic server construction.
§Architecture
- Parses raw JSON into
JsonRpcRequest - Creates default
RequestContext(no auth/session for HTTP) - Routes through the existing
route()method - Serializes
JsonRpcResponseback to JSON
This provides the same request handling as the macro pattern but
allows runtime handler registration via ServerBuilder.