Uh oh!
There was an error while loading. Please reload this page.
lowlevel Server: widen on_* return types for InputRequiredResult; add subscriptions/listen slot - #2967
Conversation
… subscriptions/listen slot - on_call_tool / on_get_prompt / on_read_resource return types widened to include InputRequiredResult, matching MONOLITH_RESULTS in types/methods.py. Covariant widening; existing handlers returning the concrete type still type-check. - on_subscriptions_listen kwarg + _spec_requests row added so the 2026 subscriptions/listen method has a dispatch slot. - InputRequiredResult: model_validator enforces at-least-one of input_requests / request_state (spec MUST).
…locate validator test The discriminator-dump test was building a bare InputRequiredResult(), which the at-least-one-of validator now (correctly) rejects. Construct the minimal valid instance instead. Move the validator test alongside it in tests/test_types.py and drop the separate file.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Looks good — the test conflict from my earlier comment is resolved, and the typing changes line up with MONOLITH_RESULTS.
Extended reasoning...
Overview
This PR is a small, type-focused change for the 2026-07-28 protocol revision: it widens three on_* handler return annotations in the lowlevel Server constructor to admit InputRequiredResult, adds an on_subscriptions_listen constructor kwarg plus its _spec_requests dispatch row, and adds a model_validator on InputRequiredResult enforcing the spec's at-least-one-of input_requests/request_state requirement, with accompanying tests in tests/test_types.py.
Consistency checks
The widened return types (tools/call, prompts/get, resources/read) match the unions already declared in MONOLITH_RESULTS in src/mcp/types/methods.py, and the new subscriptions/listen slot's EmptyResult return matches the surface and monolith result maps for that method. The widening is covariant, so existing handlers typed with the narrower result still type-check. I also checked for other call sites constructing a bare InputRequiredResult() that the new validator would break — the only one was the old discriminator test, which this revision updates (the issue I flagged in my earlier review), and tests/types/test_wire_frames.py constructs the model with both fields so it remains valid.
Security risks
None identified. The change does not touch auth, transport security, or input handling beyond adding a stricter validation rule on an outbound result model; it adds no new code paths that process untrusted data.
Level of scrutiny
Moderate. Constructor signatures and a dispatch-table row in the lowlevel server are visible API surface, but the changes are mechanical, follow the existing row/kwarg pattern exactly, and are runtime-inert except for the validator, which is spec-mandated and matches the typescript/csharp SDK behaviour. The previously broken test is now fixed and a new validator test is co-located alongside it. I could not execute the test suite in this environment (no project venv available), but the test changes are simple enough to verify by inspection.
This pull request is included in pre-release v2.0.0a3 |
Type-only changes to the lowlevel
Serverconstructor for the 2026-07-28 protocol revision.Changes
Return-type widening — three
on_*handlers can now returnInputRequiredResultin addition to their concrete result type, matchingMONOLITH_RESULTSinsrc/mcp/types/methods.py:on_call_tool→CallToolResult | InputRequiredResulton_get_prompt→GetPromptResult | InputRequiredResulton_read_resource→ReadResourceResult | InputRequiredResultThese are the three methods whose request params extend
InputResponseRequestParams. Widening is covariant, so existing handlers typed-> CallToolResultetc. still type-check unchanged.New dispatch slot —
on_subscriptions_listenkwarg +_spec_requestsrow, sosubscriptions/listen(the one new-in-2026 client→server request method) reaches a registered handler instead ofMETHOD_NOT_FOUND.InputRequiredResultvalidator —model_validator(mode="after")enforcing the spec's at-least-one-ofinput_requests/request_staterequirement (matches the typescript-sdk and csharp-sdk behaviour).Not in this PR
tasks/*— moved to theio.modelcontextprotocol/tasksextension; not core 2026-07-28.on_discoveroverride —server/discoverstays the auto-derived built-in.get_capabilities()—ServerCapabilitieshas nosubscriptionsfield; nothing to set.Part of #2891.
AI Disclaimer