Commit Graph

13 Commits

Author SHA1 Message Date
Max Isbey a0d793154a Let a 2025-11-25 tools/call answer with a CreateTaskResult
SEP-1686 makes a task-augmented `tools/call` answer with a `CreateTaskResult`,
but `SERVER_RESULTS[("tools/call", "2025-11-25")]` held `CallToolResult` alone.
The request half shipped and the response half did not, so a server returning
a task got `-32603 "Handler returned an invalid result"`, a server returning
both shapes had `task` silently sieved away, and a client receiving one raised
`ValidationError` before its caller saw anything. The v1.x line could express
that response; v2 cannot, on a revision the SDK still negotiates and still lets
a server advertise `capabilities.tasks` for.

Give the row its second arm as a generated `AnyCallToolResult`, alongside the
2026 aliases, and widen the lowlevel `Server`'s `on_call_tool` to match. Return
types are covariant, so a handler that only returns `CallToolResult` is
unaffected. Only the 2025-11-25 row gets the arm. The earlier handshake
revisions share `_v2025.CallToolRequest` and so already parse `params.task`, but
that is an artifact of the shared schema era, not a licence to answer: they
predate SEP-1686, and a clean INTERNAL_ERROR serves an off-spec client better
than a result shape its revision never defined. `MONOLITH_RESULTS["tools/call"]`
gains the arm too, so `parse_server_result` covers everything the surface admits.

`Task.ttl` is required and nullable ("null for unlimited"), and every dump path
passes `exclude_none=True`, which cannot tell a required null from an unset
optional and dropped it, leaving a body that fails the surface it was just
validated against. Rather than patch the 27 dump sites, models carrying such a
field now take a `KeepRequiredNullable` base that puts it back, and only that:
a field the caller filtered out with `include`/`exclude`, or one that was never
set, stays absent. The generator derives which classes need it from the schema
and a test asserts the same rule against the built models, so a nullable-required
field in a future revision is covered without anyone remembering. The field set
resolves on first dump rather than at class creation, because the generated
modules defer annotations and finish with `model_rebuild()`, so resolving early
would silently see nothing for a forward-referenced field.

That rule also reaches two live bugs of the same shape.
`LoggingMessageNotificationParams.data` is required and untyped, so
`ctx.log("info", None)` dropped the key and the receiving session rejected the
notification before dispatch: the message vanished with no error to either side,
at every protocol version. And `JSONRPCError.id` is required-and-nullable per
JSON-RPC 2.0, which the streamable-HTTP writer worked around by hand at one call
site; that patch is deleted and the base covers every writer.

The base is applied per model rather than to `MCPModel`/`WireModel`: a wrap
serializer costs per dump and pushes pydantic off its fast path for every model
in the tree, which measured 5x on a 20-tool `tools/list`. Its return is
deliberately unannotated, because an annotation there collapses the model's
serialization JSON schema to an opaque object.

The `tasks/*` lifecycle methods are left where they already work. They are
absent from `SPEC_CLIENT_METHODS`, so `Server.add_request_handler` serves them
today; adding registry rows would put those names into that version-flattened
set, which would make it illegal for an extension to bind `tasks/get` and would
gate the 2026 tasks extension's own calls to METHOD_NOT_FOUND. 2026-07-28 keeps
rejecting a `CreateTaskResult` on `tools/call`, which is correct: tasks left the
core protocol there.
2026-07-29 15:38:27 +00:00
Max b9422f1c9b Make the per-version wire packages private (mcp_types._v*) (#3191) 2026-07-27 22:16:48 +01:00
Max 837ef904f8 Align with spec #3002: optional clientInfo, serverInfo in result _meta (#3143)
Deploy Docs / deploy-docs (push) Has been cancelled
CI / checks (push) Failing after 24m23s
CI / all-green (push) Has been cancelled
Conformance Tests / server-conformance (push) Has been cancelled
Conformance Tests / client-conformance (push) Has been cancelled
GitHub Actions Security Analysis / zizmor (push) Has been cancelled
2026-07-23 12:00:36 +01:00
Max 4df609119f Add a client extension API (#3034) 2026-06-30 21:31:02 +01:00
Max 7322ca56f4 Require integrity protection for MRTR requestState (#3032) 2026-06-30 21:30:32 +01:00
Max b15b1d5f07 Add a client-side response cache honoring SEP-2549 caching hints (#3023) 2026-06-30 11:31:06 +01:00
Max e942d00b98 Re-vendor 2026-07-28 schema at spec ead35b59 (SubscriptionsListenResult) (#3006) 2026-06-27 10:15:34 +02:00
Max 3a8da8c0c3 Fix docs/release follow-ups from the mcp-types package split (#2977) 2026-06-26 13:16:09 +02:00
Marcelo Trylesinski 0ee7f1b293 Split protocol types into a standalone mcp-types package (#2973) 2026-06-25 19:18:38 +02:00
Max 84bf9bde05 First end-to-end 2026-07-28 stateless tools/call (experimental entry + ClientSession pin) (#2917) 2026-06-20 14:55:59 +01:00
Max 1cec2d60f4 Relax monolith ElicitRequestURLParams.elicitation_id for 2026-07-28 (#2913) 2026-06-19 16:06:08 +01:00
Max 510832aa45 Re-vendor 2026-07-28 schema and absorb spec #2907 error-code renumber (#2912) 2026-06-19 15:46:15 +01:00
Max 65be5a7147 Protocol types for 2026-07-28: superset monolith, committed per-version packages, and wire-method maps (#2849) 2026-06-16 17:40:14 +01:00