Skip to main content

ToolHandler

Trait ToolHandler 

Source
pub trait ToolHandler: Send + Sync {
Show 26 methods // Required methods fn definition(&self) -> Tool; fn call( &self, ctx: &McpContext, arguments: Value, ) -> McpResult<Vec<Content>>; // Provided methods fn icon(&self) -> Option<&Icon> { ... } fn version(&self) -> Option<&str> { ... } fn tags(&self) -> &[String] { ... } fn annotations(&self) -> Option<&ToolAnnotations> { ... } fn output_schema(&self) -> Option<Value> { ... } fn final_title(&self) -> Option<&str> { ... } fn final_icons(&self) -> Option<&[RawIcon]> { ... } fn final_metadata(&self) -> Option<&OpenMetadata> { ... } fn final_definition(&self) -> Option<FinalTool> { ... } fn final_tool_schema_authority(&self) -> FinalToolSchemaAuthority { ... } fn upstream_final_tool_schema_registration( &self, ) -> Option<UpstreamFinalToolSchemaRegistration> { ... } fn final_tool_error_structured_content( &self, _kind: ToolErrorKind, ) -> Option<Value> { ... } fn timeout(&self) -> Option<Duration> { ... } fn call_async<'a>( &'a self, ctx: &'a McpContext, arguments: Value, ) -> BoxFuture<'a, McpOutcome<Vec<Content>>> { ... } fn call_final( &self, ctx: &McpContext, arguments: Value, ) -> McpResult<CompleteResult<FinalCallToolResult>> { ... } fn call_final_async<'a>( &'a self, ctx: &'a McpContext, arguments: Value, ) -> BoxFuture<'a, McpOutcome<CompleteResult<FinalCallToolResult>>> { ... } fn call_async_in_request<'a>( &'a self, ctx: &'a McpContext, _request_cx: &'a Cx, arguments: Value, ) -> BoxFuture<'a, McpOutcome<Vec<Content>>> { ... } fn call_final_async_in_request<'a>( &'a self, ctx: &'a McpContext, _request_cx: &'a Cx, arguments: Value, ) -> BoxFuture<'a, McpOutcome<CompleteResult<FinalCallToolResult>>> { ... } fn declares_final_tasks(&self) -> bool { ... } fn declares_final_mrtr(&self) -> bool { ... } fn call_final_outcome( &self, ctx: &McpContext, arguments: Value, ) -> McpResult<FinalToolOutcome> { ... } fn call_final_outcome_async<'a>( &'a self, ctx: &'a McpContext, arguments: Value, ) -> BoxFuture<'a, McpOutcome<FinalToolOutcome>> { ... } fn call_final_outcome_async_in_request<'a>( &'a self, ctx: &'a McpContext, _request_cx: &'a Cx, arguments: Value, ) -> BoxFuture<'a, McpOutcome<FinalToolOutcome>> { ... } fn call_final_outcome_async_resuming_in_request<'a>( &'a self, ctx: &'a McpContext, request_cx: &'a Cx, arguments: Value, _resume_inputs: Option<&'a MrtrCompletedInputs>, ) -> BoxFuture<'a, McpOutcome<FinalToolOutcome>> { ... }
}
Expand description

Handler for a tool.

This trait is typically implemented via the #[tool] macro.

§Sync vs Async

By default, implement call() for synchronous execution. For async tools, override call_async() instead. The router always calls call_async(), which defaults to running call() in an async block.

§Return Type

Async handlers return McpOutcome<Vec<Content>>, a 4-valued type supporting:

  • Ok(content) - Successful result
  • Err(McpError) - Recoverable error
  • Cancelled - Request was cancelled
  • Panicked - Unrecoverable failure

Required Methods§

Source

fn definition(&self) -> Tool

Returns the tool definition.

Source

fn call(&self, ctx: &McpContext, arguments: Value) -> McpResult<Vec<Content>>

Calls the tool synchronously with the given arguments.

This is the default implementation point. Override this for simple synchronous tools. Returns McpResult which is converted to McpOutcome by the async wrapper.

Provided Methods§

Source

fn icon(&self) -> Option<&Icon>

Returns the tool’s icon, if any.

Default implementation returns None. Override to provide an icon. Note: Icons can also be set directly in definition().

Source

fn version(&self) -> Option<&str>

Returns the tool’s version, if any.

Default implementation returns None. Override to provide a version. Note: Version can also be set directly in definition().

Source

fn tags(&self) -> &[String]

Returns the tool’s tags for filtering and organization.

Default implementation returns an empty slice. Override to provide tags. Note: Tags can also be set directly in definition().

Source

fn annotations(&self) -> Option<&ToolAnnotations>

Returns the tool’s annotations providing behavioral hints.

Default implementation returns None. Override to provide annotations like destructive, idempotent, read_only, or open_world_hint. Note: Annotations can also be set directly in definition().

Source

fn output_schema(&self) -> Option<Value>

Returns the tool’s output schema (JSON Schema).

Default implementation returns None. Override to provide a schema that describes the structure of the tool’s output. Note: Output schema can also be set directly in definition().

Source

fn final_title(&self) -> Option<&str>

Returns the final display title for this tool.

This final-only field is deliberately separate from the legacy tool definition so modern catalog projection never synthesizes or leaks a legacy version/tag field.

Source

fn final_icons(&self) -> Option<&[RawIcon]>

Returns the validated final icon set for this tool.

A legacy singular icon is not projected automatically because its optional source and scalar size hint do not form an exact final icon.

Source

fn final_metadata(&self) -> Option<&OpenMetadata>

Returns final open metadata for this tool’s catalog entry.

Source

fn final_definition(&self) -> Option<FinalTool>

Returns an exact final catalog definition when this handler owns one.

Legacy-first handlers normally leave this as None; the router then freezes the ordinary Self::definition plus the individual final metadata hooks into a final definition. A native final handler or proxy should override this hook so title-bearing annotations, the complete icon collection, and open metadata are never projected through the narrower legacy Tool model.

Source

fn final_tool_schema_authority(&self) -> FinalToolSchemaAuthority

Returns the legacy diagnostic label for this handler’s exact-final schemas.

Ordinary and legacy-backed handlers keep local schema admission. The router does not use this forgeable label for admission; exact proxy registration supplies a sealed token through Self::upstream_final_tool_schema_registration instead.

Source

fn upstream_final_tool_schema_registration( &self, ) -> Option<UpstreamFinalToolSchemaRegistration>

Returns a sealed upstream-schema registration for an exact proxy.

Ordinary handlers must use the default. The token has no public constructor, so only server-owned proxy registration can opt out of local input/output validation and framework-error synthesis.

Source

fn final_tool_error_structured_content( &self, _kind: ToolErrorKind, ) -> Option<Value>

Maps a framework-authored tool error into this tool’s structured output.

A handler that declares outputSchema must return a truthful value for both closed error kinds. Registration invokes this hook once for each kind, bounds and validates the returned JSON, and stores immutable copies beside the admitted schemas. Returning None, an over-limit value, or a value rejected by outputSchema rejects registration before any catalog mutation.

Source

fn timeout(&self) -> Option<Duration>

Returns the tool’s custom timeout duration.

Default implementation returns None, meaning no additional handler ceiling is added. Override to specify a per-handler timeout.

A non-zero value tightens the ambient/request/server budget. It never replaces or relaxes an earlier absolute deadline. A zero value is treated like None and therefore cannot disable an outer timeout. Pending async work is dropped when the legacy synchronous dispatcher’s timer observes a comparable deadline, and a late completion is rejected. The dispatcher does not drive a caller’s foreign virtual clock. This cannot preempt a blocking synchronous call() or guarantee child-work drain; handlers must still cooperate with McpContext::checkpoint.

Source

fn call_async<'a>( &'a self, ctx: &'a McpContext, arguments: Value, ) -> BoxFuture<'a, McpOutcome<Vec<Content>>>

Calls the tool asynchronously with the given arguments.

Override this for tools that need true async execution (e.g., I/O-bound operations, database queries, HTTP requests).

Returns McpOutcome to properly represent all four states: success, error, cancellation, and panic.

The default implementation delegates to the sync call() method and converts the McpResult to McpOutcome.

Source

fn call_final( &self, ctx: &McpContext, arguments: Value, ) -> McpResult<CompleteResult<FinalCallToolResult>>

Calls the tool through the final MCP 2026-07-28 result surface.

Legacy-only handlers retain their exact Self::call result and are promoted without loss into a complete final result. Handlers that author final-only metadata, annotations, resource links, or a tool error result should override this method (or its async counterpart) so the router can preserve the supplied final result algebra exactly.

Source

fn call_final_async<'a>( &'a self, ctx: &'a McpContext, arguments: Value, ) -> BoxFuture<'a, McpOutcome<CompleteResult<FinalCallToolResult>>>

Asynchronously calls the tool through the final result surface.

The default delegates to Self::call_final.

Source

fn call_async_in_request<'a>( &'a self, ctx: &'a McpContext, _request_cx: &'a Cx, arguments: Value, ) -> BoxFuture<'a, McpOutcome<Vec<Content>>>

Calls the tool from a request-owned structured child.

Modern router dispatch supplies the child Cx that owns this handler invocation. Implementations that spawn or otherwise coordinate nested work must use this context so cancellation and completion remain within the request’s structured lifetime. Existing handlers keep their exact behavior through the default delegation to Self::call_async.

Source

fn call_final_async_in_request<'a>( &'a self, ctx: &'a McpContext, _request_cx: &'a Cx, arguments: Value, ) -> BoxFuture<'a, McpOutcome<CompleteResult<FinalCallToolResult>>>

Calls the tool’s final result hook from a request-owned child.

Existing final async handlers keep their behavior through the default delegation to Self::call_final_async.

Source

fn declares_final_tasks(&self) -> bool

Declares whether this handler can return a final Tasks CreateTask outcome.

The router verifies this declaration only if the handler actually returns [FinalToolOutcome::CreateTask], then admits negotiated Tasks capability and runtime readiness before mutating task state. Handlers that return [FinalToolOutcome::CreateTask] must override this to return true.

Source

fn declares_final_mrtr(&self) -> bool

Declares whether this handler can use final MRTR continuations.

This is an immutable handler capability, rather than an inference from a runtime outcome. A declared-capable handler requires a modern connection partition before the router invokes it, so an InputRequired outcome can never be produced without durable continuation ownership.

Source

fn call_final_outcome( &self, ctx: &McpContext, arguments: Value, ) -> McpResult<FinalToolOutcome>

Calls the tool through the final complete, input-required, or task-creation surface.

Existing handlers remain complete-only. A task-capable handler overrides this method, or its async/request-owned counterpart, and returns [FinalToolOutcome::CreateTask] without mutating task state.

Source

fn call_final_outcome_async<'a>( &'a self, ctx: &'a McpContext, arguments: Value, ) -> BoxFuture<'a, McpOutcome<FinalToolOutcome>>

Asynchronously calls the final complete, input-required, or task-creation surface.

Source

fn call_final_outcome_async_in_request<'a>( &'a self, ctx: &'a McpContext, _request_cx: &'a Cx, arguments: Value, ) -> BoxFuture<'a, McpOutcome<FinalToolOutcome>>

Calls the disjoint final outcome from a request-owned structured child.

Source

fn call_final_outcome_async_resuming_in_request<'a>( &'a self, ctx: &'a McpContext, request_cx: &'a Cx, arguments: Value, _resume_inputs: Option<&'a MrtrCompletedInputs>, ) -> BoxFuture<'a, McpOutcome<FinalToolOutcome>>

Resumes a final tool invocation after framework-admitted MRTR input.

resume_inputs exists only after the router consumed a framework-minted request state bound to the original modern operation. Handlers inspect its typed accessors rather than decoding client wire values. #[tool] exposes this as an Option<&MrtrCompletedInputs> user-function parameter: initial calls receive None and admitted retries receive Some. Existing handlers preserve their normal final hook by default.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§