pub struct McpServer { /* private fields */ }Expand description
MCP server backed by the rmcp framework.
The struct is cloned per request by rmcp’s handler dispatch; the expensive bits (provider closure) are behind an Arc so cloning is cheap.
Implementations§
Source§impl McpServer
impl McpServer
pub fn new(options: ServerOptions) -> Self
Sourcepub fn builtins(&self) -> &BuiltinsConfig
pub fn builtins(&self) -> &BuiltinsConfig
Read the manifest-declared builtins: config. Downstream
consumers (e.g. a graph_overview tool that wipes a temp/
directory when temp_cleanup: on_overview is set) call this
to discover what flags the operator asked for. The framework
itself does not act on this — that would force it to interpret
graph-specific semantics it shouldn’t know about.
Sourcepub fn tool_router_mut(&mut self) -> &mut ToolRouter<McpServer>
pub fn tool_router_mut(&mut self) -> &mut ToolRouter<McpServer>
Mutable access to the tool router for dynamic tool registration.
Use only at server-construction time (before serve).
Once dispatching starts, the router is cloned per request and
mutation would race.
Sourcepub fn prompt_router_mut(&mut self) -> &mut PromptRouter<McpServer>
pub fn prompt_router_mut(&mut self) -> &mut PromptRouter<McpServer>
Mutable access to the prompt router for dynamic skill / prompt
registration. Same lifecycle contract as [tool_router_mut]:
boot-time only. Most operators reach prompts via
serve_prompts rather than touching the router directly.
Sourcepub fn register_typed_tool<T, F>(
&mut self,
name: &'static str,
description: &'static str,
handler: F,
)where
T: for<'de> Deserialize<'de> + JsonSchema + Default + Send + Sync + 'static,
F: Fn(T) -> String + Send + Sync + 'static,
pub fn register_typed_tool<T, F>(
&mut self,
name: &'static str,
description: &'static str,
handler: F,
)where
T: for<'de> Deserialize<'de> + JsonSchema + Default + Send + Sync + 'static,
F: Fn(T) -> String + Send + Sync + 'static,
Register a typed dynamic tool with an infallible handler. Compresses the boilerplate of:
- Generating a JSON Schema for the args type via
schemars. - Building a
rmcp::model::Toolattr from the schema + name + description. - Deserialising the per-call JSON arguments via serde.
- Wrapping the handler in a
rmcp::handler::server::router::tool::ToolRoute::new_dynclosure suitable fortool_router_mut.
The handler is Fn(T) -> String; it owns whatever state it
needs through the closure environment (typically an Arc-clone
of a domain-specific state handle). A String is the only
outcome the handler can produce, so every call that reaches
it reports a success envelope (isError: false). That makes
this the entry point for tools that genuinely cannot fail, and
for tools that
deliberately render their own failures as ordinary prose the
agent reads and moves on from — the “errors as values” shape
the source / GitHub builtins use.
A tool whose failure the client should be able to branch on
wants register_typed_tool_fallible
instead: it takes Fn(T) -> Result<String, String> and routes
the Err body through the MCP error envelope, so a caller sees
isError: true rather than having to pattern-match the text.
Arguments that fail to deserialise are an error envelope on either method — a call the framework could not even hand to the handler is not a result the agent should read as one.
Sourcepub fn register_typed_tool_fallible<T, F>(
&mut self,
name: &'static str,
description: &'static str,
handler: F,
)
pub fn register_typed_tool_fallible<T, F>( &mut self, name: &'static str, description: &'static str, handler: F, )
Register a typed dynamic tool whose handler can fail.
Same shape as register_typed_tool
— same schema generation, same argument deserialisation, same
dyn route — except the handler is
Fn(T) -> Result<String, String>. Ok(body) produces the
usual success envelope; Err(body) produces an MCP error
envelope (isError: true) carrying the error text verbatim.
That string is what the agent reads, so write it for that
reader rather than dumping a Debug of some internal type
into it.
The consumer’s ResultPostprocessHook runs on both arms,
with the same ResultCtx, and its footer is appended to the
error text exactly as it is to a success body. A downstream
server that stamps identity or rebuild state onto every result
keeps that stamp on the failure path, where an unplaceable
error would otherwise send the agent hunting in the wrong
graph.
Sourcepub fn ping_tool_attr() -> Tool
pub fn ping_tool_attr() -> Tool
Generated tool metadata function for ping
Sourcepub fn read_source_tool_attr() -> Tool
pub fn read_source_tool_attr() -> Tool
Generated tool metadata function for read_source
Sourcepub fn grep_tool_attr() -> Tool
pub fn grep_tool_attr() -> Tool
Generated tool metadata function for grep
Sourcepub fn list_source_tool_attr() -> Tool
pub fn list_source_tool_attr() -> Tool
Generated tool metadata function for list_source
Sourcepub fn repo_management_tool_attr() -> Tool
pub fn repo_management_tool_attr() -> Tool
Generated tool metadata function for repo_management
Trait Implementations§
Source§impl ServerHandler for McpServer
impl ServerHandler for McpServer
Source§async fn on_initialized(&self, context: NotificationContext<RoleServer>)
async fn on_initialized(&self, context: NotificationContext<RoleServer>)
notifications/initialized — the one point at which a
client-advertised root can be adopted (see crate::server::roots).
rmcp dispatches every peer notification on a task it spawns
(spawn_service_task, which is tokio::spawn unless rmcp’s local
feature is enabled), and the response router lives in the same select
loop, so awaiting a server→client roots/list request here cannot
deadlock and cannot delay the client’s session. If rmcp’s local
feature is ever enabled that becomes spawn_local and this reasoning
must be re-checked.
Everything about adoption is opt-in and guarded inside the roots
module: with no workspace.adopt_client_roots this returns after two
field reads, having sent nothing.
Source§async fn on_roots_list_changed(&self, context: NotificationContext<RoleServer>)
async fn on_roots_list_changed(&self, context: NotificationContext<RoleServer>)
notifications/roots/list_changed — re-run adoption, unless the
operator has claimed the root in the meantime.
fn get_info(&self) -> ServerInfo
async fn list_prompts( &self, _request: Option<PaginatedRequestParams>, _context: RequestContext<RoleServer>, ) -> Result<ListPromptsResult, McpError>
async fn get_prompt( &self, request: GetPromptRequestParams, context: RequestContext<RoleServer>, ) -> Result<GetPromptResponse, McpError>
Source§async fn call_tool(
&self,
request: CallToolRequestParams,
context: RequestContext<RoleServer>,
) -> Result<CallToolResponse, ErrorData>
async fn call_tool( &self, request: CallToolRequestParams, context: RequestContext<RoleServer>, ) -> Result<CallToolResponse, ErrorData>
tools/call request from a client. Read moreasync fn list_tools( &self, _request: Option<PaginatedRequestParams>, context: RequestContext<RoleServer>, ) -> Result<ListToolsResult, ErrorData>
fn ping( &self, context: RequestContext<RoleServer>, ) -> impl Future<Output = Result<(), ErrorData>> + MaybeSendFuture
fn initialize( &self, request: InitializeRequestParams, context: RequestContext<RoleServer>, ) -> impl Future<Output = Result<InitializeResult, ErrorData>> + MaybeSendFuture
Source§fn supported_protocol_versions(&self) -> Cow<'static, [ProtocolVersion]>
fn supported_protocol_versions(&self) -> Cow<'static, [ProtocolVersion]>
Source§fn discover(
&self,
context: RequestContext<RoleServer>,
) -> impl Future<Output = Result<DiscoverResult, ErrorData>> + MaybeSendFuture
fn discover( &self, context: RequestContext<RoleServer>, ) -> impl Future<Output = Result<DiscoverResult, ErrorData>> + MaybeSendFuture
fn complete( &self, request: CompleteRequestParams, context: RequestContext<RoleServer>, ) -> impl Future<Output = Result<CompleteResult, ErrorData>> + MaybeSendFuture
fn set_level( &self, request: SetLevelRequestParams, context: RequestContext<RoleServer>, ) -> impl Future<Output = Result<(), ErrorData>> + MaybeSendFuture
fn list_resources( &self, request: Option<PaginatedRequestParams>, context: RequestContext<RoleServer>, ) -> impl Future<Output = Result<ListResourcesResult, ErrorData>> + MaybeSendFuture
fn list_resource_templates( &self, request: Option<PaginatedRequestParams>, context: RequestContext<RoleServer>, ) -> impl Future<Output = Result<ListResourceTemplatesResult, ErrorData>> + MaybeSendFuture
fn read_resource( &self, request: ReadResourceRequestParams, context: RequestContext<RoleServer>, ) -> impl Future<Output = Result<ReadResourceResponse, ErrorData>> + MaybeSendFuture
Source§fn accepted_subscription_filter(
&self,
requested: &SubscriptionFilter,
) -> Option<SubscriptionFilter>
fn accepted_subscription_filter( &self, requested: &SubscriptionFilter, ) -> Option<SubscriptionFilter>
Source§fn listen(
&self,
context: SubscriptionContext,
) -> impl Future<Output = Result<(), ErrorData>> + MaybeSendFuture
fn listen( &self, context: SubscriptionContext, ) -> impl Future<Output = Result<(), ErrorData>> + MaybeSendFuture
Source§fn subscribe(
&self,
request: SubscribeRequestParams,
context: RequestContext<RoleServer>,
) -> impl Future<Output = Result<(), ErrorData>> + MaybeSendFuture
fn subscribe( &self, request: SubscribeRequestParams, context: RequestContext<RoleServer>, ) -> impl Future<Output = Result<(), ErrorData>> + MaybeSendFuture
resources/subscribe is legacy-only; implement accepted_subscription_filter and listen for protocol version 2026-07-28
Source§fn unsubscribe(
&self,
request: UnsubscribeRequestParams,
context: RequestContext<RoleServer>,
) -> impl Future<Output = Result<(), ErrorData>> + MaybeSendFuture
fn unsubscribe( &self, request: UnsubscribeRequestParams, context: RequestContext<RoleServer>, ) -> impl Future<Output = Result<(), ErrorData>> + MaybeSendFuture
resources/unsubscribe is legacy-only; subscriptions/listen is cancelled through its request lifecycle
fn on_custom_request( &self, request: CustomRequest, context: RequestContext<RoleServer>, ) -> impl Future<Output = Result<CustomResult, ErrorData>> + MaybeSendFuture
fn on_cancelled( &self, notification: CancelledNotificationParam, context: NotificationContext<RoleServer>, ) -> impl Future<Output = ()> + MaybeSendFuture
fn on_progress( &self, notification: ProgressNotificationParam, context: NotificationContext<RoleServer>, ) -> impl Future<Output = ()> + MaybeSendFuture
fn on_custom_notification( &self, notification: CustomNotification, context: NotificationContext<RoleServer>, ) -> impl Future<Output = ()> + MaybeSendFuture
Source§fn get_task(
&self,
request: GetTaskParams,
context: RequestContext<RoleServer>,
) -> impl Future<Output = Result<GetTaskResult, ErrorData>> + MaybeSendFuture
fn get_task( &self, request: GetTaskParams, context: RequestContext<RoleServer>, ) -> impl Future<Output = Result<GetTaskResult, ErrorData>> + MaybeSendFuture
tasks/get: return the current DetailedTask state.Source§fn update_task(
&self,
request: UpdateTaskParams,
context: RequestContext<RoleServer>,
) -> impl Future<Output = Result<(), ErrorData>> + MaybeSendFuture
fn update_task( &self, request: UpdateTaskParams, context: RequestContext<RoleServer>, ) -> impl Future<Output = Result<(), ErrorData>> + MaybeSendFuture
tasks/update: accept responses to outstanding in-task
input requests. Returns an empty acknowledgement on success.Source§fn cancel_task(
&self,
request: CancelTaskParams,
context: RequestContext<RoleServer>,
) -> impl Future<Output = Result<(), ErrorData>> + MaybeSendFuture
fn cancel_task( &self, request: CancelTaskParams, context: RequestContext<RoleServer>, ) -> impl Future<Output = Result<(), ErrorData>> + MaybeSendFuture
tasks/cancel: cooperative cancellation. Returns an empty
acknowledgement; the task’s observable status may lag.Auto Trait Implementations§
impl !RefUnwindSafe for McpServer
impl !UnwindSafe for McpServer
impl Freeze for McpServer
impl Send for McpServer
impl Sync for McpServer
impl Unpin for McpServer
impl UnsafeUnpin for McpServer
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<R, S> DynService<R> for Swhere
R: ServiceRole,
S: Service<R>,
impl<R, S> DynService<R> for Swhere
R: ServiceRole,
S: Service<R>,
fn handle_request( &self, request: <R as ServiceRole>::PeerReq, context: RequestContext<R>, ) -> Pin<Box<dyn Future<Output = Result<<R as ServiceRole>::Resp, ErrorData>> + Send + '_>>
fn handle_notification( &self, notification: <R as ServiceRole>::PeerNot, context: NotificationContext<R>, ) -> Pin<Box<dyn Future<Output = Result<(), ErrorData>> + Send + '_>>
fn get_info(&self) -> <R as ServiceRole>::Info
Source§fn supported_protocol_versions(&self) -> Cow<'static, [ProtocolVersion]>
fn supported_protocol_versions(&self) -> Cow<'static, [ProtocolVersion]>
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<H> Service<RoleServer> for Hwhere
H: ServerHandler,
impl<H> Service<RoleServer> for Hwhere
H: ServerHandler,
async fn handle_request( &self, request: <RoleServer as ServiceRole>::PeerReq, context: RequestContext<RoleServer>, ) -> Result<<RoleServer as ServiceRole>::Resp, ErrorData>
async fn handle_notification( &self, notification: <RoleServer as ServiceRole>::PeerNot, context: NotificationContext<RoleServer>, ) -> Result<(), ErrorData>
fn get_info(&self) -> <RoleServer as ServiceRole>::Info
Source§fn supported_protocol_versions(&self) -> Cow<'static, [ProtocolVersion]>
fn supported_protocol_versions(&self) -> Cow<'static, [ProtocolVersion]>
initialize
negotiation may agree to. Read more