#[non_exhaustive]pub enum ToolOutput {
Payload(Value),
Result(CallToolResult),
}Expand description
Output of a ToolHandler call: either a plain value the server wraps into a
CallToolResult, or a fully-formed CallToolResult the handler owns end-to-end.
A handler that implements only ToolHandler::handle (the common case) never
constructs this enum — the default ToolHandler::handle_output wraps the
returned value in ToolOutput::Payload, preserving today’s behavior exactly.
This is a control enum consumed inside the server dispatch tail, NOT a wire
type — it deliberately does not derive Serialize/Deserialize.
Marked #[non_exhaustive]: additional output modes may be added in a
backwards-compatible way, so downstream matches must include a wildcard arm.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
Payload(Value)
A plain value. The server runs it through the existing tail: response
middleware (redaction/sanitization), the Phase 102 task create-path gate,
and text-wrap / widget enrichment — byte-identical to returning a Value
from ToolHandler::handle today.
Result(CallToolResult)
A fully-formed CallToolResult the handler owns.
§⚠️ BYPASS WARNING — this variant is sent to the wire VERBATIM
The contained CallToolResult is
serialized and returned to the client exactly as provided. It
BYPASSES:
- response middleware — redaction, sanitization, and audit hooks
(
ToolMiddleware::on_response) DO NOT run for this variant; - text-wrapping —
contentis not synthesized from a stringified value; - widget enrichment —
structured_content/_metaare not injected.
The handler is therefore responsible for its OWN redaction and
sanitization of both content and _meta, at the same trust level as
returning a raw Value today. This is a deliberate, user-approved design
choice (D-04a): a handler that needs to own the full envelope (e.g. to set
_meta[relatedTask]) opts into owning its security posture too.
What is NOT bypassed: request middleware
(ToolMiddleware::on_request) still runs before the handler executes, and
handler errors still route through the normal error path. Only the
successful Result arm skips response middleware.
See the phase migration guide for how to move a hand-written handler onto this variant safely.