# The tool presentation schema is not a parser

> Source: https://github.com/max-listov/stitchkit/blob/master/docs/decisions/0050-presentation-schema-is-not-a-parser.md

---

# 0050 — The tool presentation schema is not a parser

## Status

Accepted. Supersedes the executable-advertised-schema premise of ADR 0034 and
the Zod-rebuilding mechanism of ADRs 0031, 0033 and 0044. Their model-facing
flattening guarantees remain in force.

## Context

MCP and AI SDKs parsed the Zod schema Stitchkit supplied for advertisement,
then `executeToolMethod` parsed the SDK result with the original contract. A
transform could therefore run twice; protected native MCP inputs ran three
times. Making the derived flattened Zod schema preserve every runtime semantic
created a large coupling to Zod internals without removing the duplicate parse.

## Decision

- Original contract `params` and `input` Zod schemas are the only executable
  parsers for handler-bound contract data.
- Tool preparation creates one immutable presentation JSON Schema shared by
  MCP, agent tools, manifests, validation and prepared-surface caching.
- `flattenUnionInput` is a pure, conservative JSON Schema projection. It may
  widen branch-specific constraints but cannot transform runtime values. The
  flattened document is a superset of the unflattened presentation document.
- Presentation describes the nominal values a caller should send. Runtime-only
  tolerance such as `z.coerce.number()` accepting `"7"` or `.catch()` recovering
  invalid input stays in the executable parser and is deliberately not widened
  to `{}` in the advertised schema; advertising every tolerated fallback would
  erase useful model guidance.
- MCP receives the document as metadata on an identity `z.looseObject({})`
  carrier. AI SDK receives it through `jsonSchema()` with an identity validator.
- `ToolExtend.schema` remains executable: Stitchkit parses only its own keys
  once inside the shared runner, resolves context, then removes those keys
  before contract parsing.
- Protected native tools use the same carrier and runner. Raw registration
  remains an explicit opt-out.

## Consequences

Strict failures now occur inside Stitchkit and reach tool hooks/audit instead of
being rejected by an SDK before the callback. Loose keys, defaults, coercions,
refinements and transforms reach exactly the original parser. Presentation
flattening no longer depends on private Zod check internals. Identity adapters
also let the runtime parser accept tolerated coercion/catch inputs even when the
nominal presentation tells generated callers to send the canonical type.

`flattenDiscriminatedUnion` and `flattenUnionsDeep` are removed: returning an
executable derived parser would reintroduce the architecture this decision
forbids. `flattenToolJsonSchema` is the presentation-only replacement.
