Skip to main content
Version: 1.1.0

Handler Traits

rust-mcp-sdk provides two pairs of handler traits - one standard (per-capability methods), one core (raw message methods). Choose based on how much control you need.

Server-side: ServerHandler vs ServerHandlerCoreโ€‹

ServerHandlerServerHandlerCore
Methods~30 fine-grained: handle_list_tools_request, handle_call_tool_request, handle_list_resources_request, etc.3 raw: handle_request, handle_notification, handle_error
DefaultsYes - ping, initialize, most notifications work out of the boxNo - you handle everything
Type safetyFully typed: method returns Result<ListToolsResult, RpcError>Generic: returns Result<ResultFromServer, RpcError> - you match on enum variants
Best for90% of serversFull control, custom protocol extensions, debugging
Runtime functionserver_runtime::create_server()server_runtime_core::create_server()
Conversion.to_mcp_server_handler().to_mcp_server_handler() (same method)

ServerHandler exampleโ€‹

async fn handle_call_tool_request(
&self, params: CallToolRequestParams, _runtime: Arc<dyn McpServer>,
) -> Result<CallToolResult, CallToolError> {
// params.name is "say_hello"
// params.arguments is the JSON args
Ok(CallToolResult::text_content(vec!["Hello!".into()]))
}

ServerHandlerCore exampleโ€‹

async fn handle_request(
&self, request: RequestFromClient, _runtime: Arc<dyn McpServer>,
) -> Result<ResultFromServer, RpcError> {
match request {
RequestFromClient::ListToolsRequest(_) => Ok(ListToolsResult { ... }.into()),
RequestFromClient::CallToolRequest(params) => Ok(CallToolResult::text_content(...).into()),
_ => Err(RpcError::method_not_found()),
}
}

Client-side: ClientHandler vs ClientHandlerCoreโ€‹

Same pattern, same decision:

ClientHandlerClientHandlerCore
Methods~20 per-message-type handlers3 raw methods
DefaultsYes - returns "not found" for unhandled requestsNo - you handle everything
Runtime functionclient_runtime::create_client()client_runtime_core::create_client()
Conversion.to_mcp_client_handler().to_mcp_client_handler() (same method)

Decision guideโ€‹

Do you need to intercept every raw JSON-RPC message?
โ”œโ”€โ”€ Yes โ†’ use Core
โ””โ”€โ”€ No โ†’ do you have a small fixed set of capabilities?
โ”œโ”€โ”€ Yes โ†’ ServerHandler / ClientHandler
โ””โ”€โ”€ No โ†’ ServerHandler / ClientHandler (override only what you need)

Start with the standard handler. Switch to Core only if you need access to the raw JSON-RPC envelope or want to implement custom protocol behavior.

Nextโ€‹