Skip to content

Output

OutputFormat, encoders, and the ToolResult builder.

A tool's result has two halves and they are toggled independently: structuredContent on the call result, and outputSchema on the tools/list entry. The MCP spec imposes one asymmetric rule between them — a tool that advertises outputSchema must return conforming structuredContent, while the reverse is allowed — so they are not a single switch.

Both are on by default, server-wide via REST_FRAMEWORK_MCP["INCLUDE_STRUCTURED_CONTENT"] and ["INCLUDE_OUTPUT_SCHEMA"], and per tool via include_structured_content= and include_output_schema= at registration. The asymmetric rule is enforced: include_output_schema=True with include_structured_content=False raises at registration rather than advertising a schema nothing will satisfy.

That is a check on the settings, not on a response. To assert that a real result satisfies the schema its tool advertised — types and formats, not only the property names — see assert_tool_result_conforms.

See Omitting structuredContent and outputSchema for when to turn either off, and Hide plumbing from the model for what shapes the schema an agent sees — field markings project the payload and the advertised outputSchema from the same declaration.

OutputFormat

Bases: str, Enum

Encoding of a ToolResult's human-readable text block.

Only content[0] varies; structuredContent is always JSON.

Attributes:

Name Type Description
JSON

Pretty-printed JSON. The safe default.

TOON

Token-oriented object notation, compact for large uniform arrays. Falls back to JSON when the optional toon extra is absent.

AUTO

Per-payload choice — TOON for a uniform list of objects, JSON otherwise.

coerce classmethod

coerce(value: OutputFormat | str | None) -> OutputFormat

Accept either an enum member or its string value; default to JSON.

encode_json

encode_json(payload: Any) -> str

Encode payload as a stable, pretty JSON string.

default=str renders DRF outputs containing Decimal, UUID or datetime without raising; keys are sorted so the output is deterministic.

encode_toon

encode_toon(payload: Any) -> str

Encode payload as TOON (token-oriented object notation).

TOON is an optional dependency. Without python-toon installed this warns and falls back to JSON, so a tool call never breaks because the extra is absent. The warning fires every time — silence it with warnings.filterwarnings or install the extra.

The return value alone cannot say which encoder produced it, so a caller that labels the text — build_tool_result stamps a # format: toon marker — must ask toon_encoder rather than assume.

build_tool_result

build_tool_result(
    payload: Any,
    *,
    output_format: OutputFormat = OutputFormat.JSON,
    is_error: bool = False,
    include_structured_content: bool = True,
    meta: dict[str, Any] | None = None,
    content_kind: ToolContentKind = ToolContentKind.TEXT,
    content_mime_type: str | None = None,
    binding_name: str | None = None,
) -> ToolResult

Build a ToolResult for a successful (or tool-level error) call.

Parameters:

Name Type Description Default
payload Any

The JSON-shaped tool output. Becomes structuredContent verbatim and is also rendered as the first content block.

required
output_format OutputFormat

How content[0] renders the payload. TOON output is wrapped in a fenced toon block with a leading marker line so clients that don't parse TOON natively can still display it. On a deployment without the optional [toon] extra the encoder falls back to JSON, and the marker is left off with it — the label always names the format the bytes are actually in.

JSON
is_error bool

Stamped onto the result as isError.

False
include_structured_content bool

False omits structuredContent entirely — the key is absent, distinct from a True call whose payload happens to be null, which is emitted as "structuredContent": null. The text block still carries the full payload, so a client that doesn't consume the structured field loses nothing.

True
meta dict[str, Any] | None

The base protocol's _meta bundle on the result envelope — per-call, unlike the static _meta already advertised on the tools/list entry. Omitted from the payload when empty.

None
content_kind ToolContentKind

The block type the binding declared. Anything other than TEXT bypasses output_format entirely — there is no TOON rendering of a PNG — and a payload that doesn't match the declared kind comes back as an isError result naming the binding.

TEXT
content_mime_type str | None

Media type for a non-TEXT block.

None
binding_name str | None

Names the binding in that mismatch message.

None