2.8 KiB
| @modelcontextprotocol/server | @modelcontextprotocol/core-internal |
|---|---|
| minor | minor |
Serve input_required handlers on 2025-era connections: the legacy shim (on by default) converts each embedded request of an input_required return into a real server→client request (elicitation/create, sampling/createMessage, roots/list) over the live session — stamped with the originating request's id for stream association — and re-enters the handler with the collected inputResponses until a final result. Handlers are written once in the 2026 inputRequired(...) style and serve both eras; the previous loud -32603 failure remains available via ServerOptions.inputRequired.legacyShim: false. Knobs: inputRequired.maxRounds (default 8) and inputRequired.roundTimeoutMs (default 600 000 ms per leg; legs carry a progressToken so a client reporting progress mid-leg resets the leg timeout). Semantics mirror the modern client driver exactly: per-round replaced inputResponses, byte-exact requestState echo with the verify hook running every round, paced requestState-only rounds, and elicitation accepted content passed through UNVALIDATED (the handler validates via the schema-aware acceptedContent overload, exactly as on the 2026 era). URL-mode legs synthesize the elicitationId the 2025-11-25 wire requires. Failures surface per family (tools/call → isError tool result; prompts/get / resources/read → JSON-RPC error); stateless legacy HTTP degrades to a clean capability refusal; the shim emits no progress of its own (the originating progressToken is the handler's single must-increase stream — the shim never adds a second author to it).
ctx.mcpReq.requestState is now a typed accessor: ctx.mcpReq.requestState<T>() returns the payload the configured requestState.verify hook resolved with (e.g. createRequestStateCodec.verify — the hook's return value is now load-bearing; verifiers that are not also decoders should resolve undefined), the raw wire string when no hook is configured, or undefined when the round carried no state. Code that read the property directly becomes a call: ctx.mcpReq.requestState → ctx.mcpReq.requestState<string>(). Note the member is now always present (a function), so truthiness no longer means "has state", and it is dropped by JSON serialization of the context.
New typed readers for inputResponses, exported from @modelcontextprotocol/server: a schema-aware acceptedContent(responses, key, schema) overload (validates untrusted accepted content against any synchronous Standard Schema) and inputResponse(responses, key) (discriminated missing | elicit | sampling | roots view, for decline/cancel detection and the non-elicitation kinds). Content conveniences like text extraction stay in application code as one-liners over the discriminated view.