chore: import upstream snapshot with attribution
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) Waiting to run
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) Waiting to run
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
# 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).
|
||||
Reference in New Issue
Block a user