Files
modelcontextprotocol--pytho…/examples/stories/schema_validators/README.md
T
wehub-resource-sync 49b9bb6724
Deploy Docs / deploy-docs (push) Failing after 1s
Conformance Tests / client-conformance (push) Failing after 3s
Conformance Tests / server-conformance (push) Failing after 1s
GitHub Actions Security Analysis / zizmor (push) Failing after 1s
CI / checks (push) Failing after 59m20s
CI / all-green (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:10:27 +08:00

53 lines
2.2 KiB
Markdown

# schema-validators
Four ways to type a tool parameter so `MCPServer` derives the JSON-Schema
`inputSchema` and validates arguments before your handler runs: a pydantic
`BaseModel`, a `TypedDict`, a `@dataclass`, and a bare `dict[str, Any]`. The
client lists the tools, resolves each `who` schema, and round-trips a call.
## Run it
```bash
# stdio (default — the client spawns the server as a subprocess)
uv run python -m stories.schema_validators.client
# HTTP — the client self-hosts the server on a free port, runs, then tears it down
uv run python -m stories.schema_validators.client --http
# same, against the lowlevel-API server variant
uv run python -m stories.schema_validators.client --http --server server_lowlevel
```
## What to look at
- `client.py` `main` — the body opens with `async with Client(target, mode=mode)
as client:`. `target` is anything `Client` accepts (an in-process server, a
transport, or an HTTP URL); the entry point picks it, the story constructs it.
- `server.py` — `who.name` vs `who["name"]`: pydantic and dataclass parameters
arrive as **instances** (attribute access); TypedDict and `dict[str, Any]`
arrive as plain dicts.
- `client.py` — the listed `inputSchema` for the three typed variants nests a
`$defs`/`$ref` object with a `name` property; `greet_dict` publishes only
`{"type": "object", "additionalProperties": true}` — no field validation.
- `server_lowlevel.py` — the same schemas written by hand. There is no
reflection layer at this tier; you author JSON Schema and unpack
`params.arguments` yourself.
## Caveats
- Pydantic emits local `#/$defs/` references for nested models. The SDK does
not dereference network `$ref`s (SEP-2106 MUST NOT); only same-document refs
are resolved during validation.
- `PersonTD` is `total=True`, so its nested schema requires both `name` and
`title`; the `BaseModel` and `@dataclass` variants default `title="friend"`,
so only `name` is required there. Use `typing.NotRequired[...]` to mark
optional TypedDict fields.
## Spec
[Tools — input schema](https://modelcontextprotocol.io/specification/2025-11-25/server/tools#input-schema)
## See also
`tools/` (output schema → `structuredContent`), `error_handling/` (what
happens when validation fails).