Skip to content

chore: update spec.types.ts from upstream#2027

Open
github-actions[bot] wants to merge 1 commit intomainfrom
update-spec-types
Open

chore: update spec.types.ts from upstream#2027
github-actions[bot] wants to merge 1 commit intomainfrom
update-spec-types

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot commented May 7, 2026

This PR updates packages/core/src/types/spec.types.ts from the Model Context Protocol specification.

Source file: https://github.com/modelcontextprotocol/modelcontextprotocol/blob/de6d76fba3078eda957dadb3cec51ca8ab851b5c/schema/draft/schema.ts

This is an automated update triggered by the nightly cron job.

@github-actions github-actions Bot requested a review from a team as a code owner May 7, 2026 05:08
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 7, 2026

⚠️ No Changeset found

Latest commit: 5f450ff

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@github-actions github-actions Bot force-pushed the update-spec-types branch from fe613a8 to 5f450ff Compare May 8, 2026 05:01
Comment on lines 3284 to +3291
| TaskStatusNotification;

/** @internal */
export type ClientResult =
| EmptyResult
| CreateMessageResult
| ListRootsResult
| ElicitResult
| GetTaskResult
| GetTaskPayloadResult
| ListTasksResult
| CancelTaskResult;
export type ClientResult = EmptyResult | GetTaskResult | GetTaskPayloadResult | ListTasksResult | CancelTaskResult;

/* Server messages */
/** @internal */
export type ServerRequest =
| PingRequest
| CreateMessageRequest
| ListRootsRequest
| ElicitRequest
| GetTaskRequest
| GetTaskPayloadRequest
| ListTasksRequest
| CancelTaskRequest;
export type ServerRequest = PingRequest | GetTaskRequest | GetTaskPayloadRequest | ListTasksRequest | CancelTaskRequest;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 The spec has restructured sampling/elicitation/roots out of the JSON-RPC request/response model: CreateMessageRequest/ElicitRequest/ListRootsRequest no longer extend JSONRPCRequest, their results no longer extend Result, the *ResultResponse wrappers are deleted, and all six are dropped from ServerRequest/ClientResult — they are now payloads embedded inside the new InputRequiredResult flow. The SDK still models these as standalone server→client wire requests (ServerRequestSchema/ClientResultSchema in schemas.ts:2107-2123, plus the server.createMessage()/elicitInput()/listRoots() APIs), so beyond the immediate spec.types.test.ts compile failures (lines 156/160/168/172/225/301/476/499 and hard references to the deleted SpecTypes.*ResultResponse types at 745-763 & 1019-1024), this sync leaves the SDK architecturally divergent from the protocol. Unlike the new-type additions, this isn't a mechanical "add schemas" fix — it requires redesigning the SDK's server-initiated-request APIs around InputRequiredResult/inputResponses, so this PR should be held until that companion work is ready.

Extended reasoning...

What changed

The upstream spec has fundamentally changed how a server obtains sampling, elicitation, and roots from the client. Previously these were ordinary server→client JSON-RPC requests: CreateMessageRequest, ElicitRequest, and ListRootsRequest each extended JSONRPCRequest, their results extended Result, each had a *ResultResponse envelope, and they were members of the ServerRequest / ClientResult unions. In this diff:

  • CreateMessageRequest / ElicitRequest / ListRootsRequest drop extends JSONRPCRequest (and their *Params drop TaskAugmentedRequestParams/RequestParams).
  • CreateMessageResult / ElicitResult / ListRootsResult drop extends Result.
  • CreateMessageResultResponse, ElicitResultResponse, ListRootsResultResponse are deleted.
  • All six are removed from the ServerRequest and ClientResult unions (lines 3284-3291).
  • They are now referenced only via the new InputRequest / InputResponse aliases, which are carried inside InputRequiredResult.inputRequests and echoed back via InputResponseRequestParams.inputResponses (or tasks/input_response).

In other words, the spec no longer models "server asks client for sampling" as a standalone JSON-RPC request — it is now an embedded sub-request inside a resultType: 'input_required' result that the client must fulfill and replay on the next call.

Immediate breakage in this PR

packages/core/test/spec.types.test.ts fails to compile in two distinct ways:

  1. Bidirectional assignability checks at lines 155-172, 223-225, 301, 476, 499 fail because the spec types no longer carry jsonrpc/id (requests) or the Result index signature (results), and the ServerRequest/ClientResult unions no longer line up with the SDK's.
  2. Hard references to deleted types: lines 745-763 and 1019-1024 reference SpecTypes.CreateMessageResultResponse, SpecTypes.ListRootsResultResponse, and SpecTypes.ElicitResultResponse, which no longer exist — these are unconditional TS2694/TS2339-class errors, not just assignability mismatches.

So the package will not build / CI will be red on merge.

Architectural divergence (why this isn't just a test fix)

The SDK runtime does not import spec.types.ts (only the test does), so src/ still typechecks — but that is precisely the problem the drift guard exists to surface. schemas.ts:2107 (ClientResultSchema) and schemas.ts:2119 (ServerRequestSchema) still include CreateMessageRequestSchema / ElicitRequestSchema / ListRootsRequestSchema and their results, and the public SDK surface (server.createMessage(), ctx.elicitInput(), roots listing) still issues these as wire-level JSON-RPC requests. After this sync, an SDK server speaking to a spec-compliant client would send a sampling/createMessage JSON-RPC request that the client is no longer obligated to handle as a top-level request; conversely, the SDK has no machinery to emit InputRequiredResult from a tool/prompt/resource handler or to accept inputResponses on the retry.

Step-by-step proof

  1. Before: spec.types.ts had interface CreateMessageRequest extends JSONRPCRequest { method: 'sampling/createMessage'; ... } and ServerRequest = PingRequest | CreateMessageRequest | ListRootsRequest | ElicitRequest | ....
  2. After (this diff, ~line 2311): interface CreateMessageRequest { method: 'sampling/createMessage'; params: ... } — no jsonrpc, no id. ServerRequest (line 3291) is now PingRequest | GetTaskRequest | GetTaskPayloadRequest | ListTasksRequest | CancelTaskRequest only.
  3. spec.types.test.ts:476 does (sdk: WithJSONRPCRequest<SDKTypes.CreateMessageRequest>, spec: SpecTypes.CreateMessageRequest) => { sdk = spec; }. spec has no jsonrpc/id, so sdk = spec fails: Type 'CreateMessageRequest' is missing the following properties: jsonrpc, id.
  4. spec.types.test.ts:756 does spec: SpecTypes.ListRootsResultResponse — that export no longer exists → Namespace has no exported member 'ListRootsResultResponse'.
  5. Meanwhile schemas.ts:2119-2123 still builds ServerRequestSchema from CreateMessageRequestSchema | ElicitRequestSchema | ListRootsRequestSchema | ..., so SDKTypes.ServerRequestSpecTypes.ServerRequest and the union check at ~499 fails too.

Why this is distinct from the "new types need schemas" comment

A separate comment notes that ResultType, InputRequiredResult, InputResponseRequestParams, TaskInputResponseRequest, etc. need new Zod schemas and specTypeSchema allowlist entries. That is additive, mechanical work. This finding is about the removal/restructuring of existing types and unions, whose remediation is not mechanical: you cannot simply add a schema — you have to (a) decide whether the SDK keeps server.createMessage()/elicitInput()/listRoots() as a compatibility shim or replaces them with an InputRequiredResult-returning API, (b) remove these from ServerRequestSchema/ClientResultSchema, and (c) rewrite the bidirectional test entries (drop the WithJSONRPCRequest<...> wrapper for these three, delete the *ResultResponse checks). The refutation that this is "the same finding" conflates detection mechanism (both trip spec.types.test.ts) with root cause and fix; reviewers need to see this called out separately because it is the part that requires API design, not a 10-line schema patch.

Recommended action

Hold this automated sync until a companion PR implements the InputRequiredResult flow in the SDK (new result/param schemas, updated ServerRequestSchema/ClientResultSchema, reworked createMessage/elicitInput/listRoots plumbing, and updated spec.types.test.ts entries for these six types plus removal of the three deleted *ResultResponse checks). Merging this alone breaks the build and publishes a spec snapshot the SDK cannot honor.

Comment on lines +393 to +418
export interface InputRequiredResult extends Result {
/* Requests issued by the server that must be complete before the
* client can retry the original request.
*/
inputRequests?: InputRequests;
/* Request state to be passed back to the server when the client
* retries the original request.
* Note: The client must treat this as an opaque blob; it must not
* interpret it in any way.
*/
requestState?: string;
}

/* Request parameter type that includes input responses and request state.
* These parameters may be included in any client-initiated request.
*/
export interface InputResponseRequestParams extends RequestParams {
/* New field to carry the responses for the server's requests from the
* InputRequiredResult message. For each key in the response's inputRequests
* field, the same key must appear here with the associated response.
*/
inputResponses?: InputResponses;
/* Request state passed back to the server from the client.
*/
requestState?: string;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 This spec sync adds 10 new Multi Round-Trip types (ResultType, InputRequest/InputResponse/InputRequests/InputResponses, InputRequiredResult, InputResponseRequestParams, TaskInputResponseRequest/TaskInputResponseRequestParams/TaskInputResponseResultResponse) and adds tasks/input_response to ClientRequest, but none of these have corresponding entries in schemas.ts, types.ts, or the sdkTypeChecks map — so spec.types.test.ts fails on the hardcoded type count (176 vs 182), the "comprehensive compatibility tests" coverage check, and the ClientRequest bidirectional assignability check. This automated cron PR needs companion SDK schema/type/test updates before it can land.

Extended reasoning...

What the bug is

This PR is the nightly automated sync of spec.types.ts from upstream. The upstream commit it pulls in introduces the new Multi Round-Trip machinery: ResultType, InputRequest, InputResponse, InputRequests, InputResponses, InputRequiredResult, InputResponseRequestParams, TaskInputResponseRequest, TaskInputResponseRequestParams, and TaskInputResponseResultResponse, plus a new tasks/input_response member of the ClientRequest union. None of these names appear anywhere else in packages/core/srcschemas.ts has no Zod schemas for them, types.ts has no SDK-side type aliases, and test/spec.types.test.ts has no sdkTypeChecks entries for them. The repo's spec↔SDK drift guard catches exactly this situation and fails the build.

Code path that triggers it

packages/core/test/spec.types.test.ts enforces three invariants that all break:

  1. Type count — line ~1089 hardcodes expect(specTypes).toHaveLength(176). After this sync the file exports 182 types (10 added, 4 removed: URLElicitationRequiredError, CreateMessageResultResponse, ListRootsResultResponse, ElicitResultResponse), so this assertion fails.
  2. Coverage check — the should have comprehensive compatibility tests test (lines ~1098-1108) parses every exported name from spec.types.ts, skips the MISSING_SDK_TYPES allowlist (currently only ['Error', 'URLElicitationRequiredError']), and asserts each remaining name has an entry in sdkTypeChecks. The 10 new types have no entry, so 10 assertions fail. Additionally, URLElicitationRequiredError was removed from the spec but is still in MISSING_SDK_TYPES, which will fail the "Missing SDK Types" suite that asserts every allowlisted name actually exists in the spec file.
  3. ClientRequest bidirectional checktsc shows the assignability check at ~line 496 failing because the spec ClientRequest union now contains TaskInputResponseRequest while the SDK ClientRequest union does not.

Why existing code doesn't prevent it

That's by design — spec.types.test.ts is the guard that turns an automated spec pull into a forcing function for SDK updates. The cron job only updates spec.types.ts; it does not (and cannot) generate the matching Zod schemas, SDK type aliases, or sdkTypeChecks entries. Note: the specTypeSchemas allowlist drift guard from #1993 (specTypeSchema.test.ts:162) does not trip here — that guard compares schemas.ts exports against the SPEC_SCHEMA_KEYS allowlist, not against spec.types.ts. The guard that trips is the runtime coverage check in spec.types.test.ts.

Step-by-step proof

Running cd packages/core && pnpm vitest run test/spec.types.test.ts on this branch:

  • should define some expected typesFAIL: expected 182 to be 176
  • should have comprehensive compatibility testsFAIL: ResultType, InputRequest, InputResponse, InputRequests, InputResponses, InputRequiredResult, InputResponseRequestParams, TaskInputResponseRequest, TaskInputResponseRequestParams, TaskInputResponseResultResponse each produce expected undefined to be defined

And tsc --noEmit on packages/core fails because spec.types.test.ts still references the now-removed CreateMessageResultResponse / ListRootsResultResponse / ElicitResultResponse / URLElicitationRequiredError (lines ~745-760, ~1019-1024, ~1069), and because spec.ClientRequest is no longer assignable to sdk.ClientRequest once TaskInputResponseRequest is in the union.

Impact

CI is red on this PR. Merging it as-is would break main. Beyond the test failures, downstream consumers using isSpecType / specTypeSchemas (#1887) would have no runtime validators for any of the new Multi Round-Trip messages, and the SDK ClientRequest union would be out of sync with the wire protocol.

How to fix

This needs a companion commit on top of the cron sync:

  • Add Zod schemas for ResultType, InputRequests, InputResponses, InputRequiredResult, InputResponseRequestParams, TaskInputResponseRequest, TaskInputResponseRequestParams, TaskInputResponseResultResponse (and InputRequest/InputResponse aliases) in schemas.ts, and register them in specTypeSchemas.
  • Add the corresponding SDK types in types.ts and add TaskInputResponseRequest to the SDK ClientRequest union.
  • In spec.types.test.ts: bump the toHaveLength(176) count, add sdkTypeChecks entries for all 10 new types, remove the entries/references for CreateMessageResultResponse / ListRootsResultResponse / ElicitResultResponse / URLElicitationRequiredError, and drop URLElicitationRequiredError from MISSING_SDK_TYPES.

(This is separate from the resultType required-field assignability breakage tracked elsewhere — even if resultType is made optional upstream, every failure listed here still occurs.)

Comment on lines 156 to 165
export interface Result {
_meta?: MetaObject;
/**
* Indicates the type of the result, which allows the client to determine
* how to parse the result object.
*
* @default "complete"
*/
resultType: ResultType;
[key: string]: unknown;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 The new resultType: ResultType field on the base Result interface is declared as required even though the JSDoc says @default "complete" — this makes every Result subtype (InitializeResult, CallToolResult, ReadResourceResult, GetPromptResult, EmptyResult, all the Paginated/Task results, etc.) require resultType. The SDK's ResultSchema in schemas.ts does not produce this field, so tsc --noEmit on @modelcontextprotocol/core now fails with 30+ TS2741 errors in spec.types.test.ts and CI will not pass. Given the @default annotation, the upstream spec almost certainly intended resultType?: ResultType; either the upstream schema.ts needs to be fixed before this is re-pulled, or this PR needs an accompanying SDK-side ResultSchema change before it can land.

Extended reasoning...

What the bug is

This automated spec sync adds a new field to the base Result interface in packages/core/src/types/spec.types.ts:

export interface Result {
    _meta?: MetaObject;
    /**
     * Indicates the type of the result, which allows the client to determine
     * how to parse the result object.
     *
     * @default "complete"
     */
    resultType: ResultType;
    [key: string]: unknown;
}

The field is declared without a ?, making it required on Result and on every interface that extends Result. The @default "complete" JSDoc strongly implies the spec author intended it to be optional and defaulted server-side, but the TypeScript declaration does not reflect that.

How it manifests / proof

The SDK maintains bidirectional-assignability checks between the spec types and the SDK's Zod-inferred types in packages/core/test/spec.types.test.ts (e.g. Result: (sdk, spec) => { sdk = spec; spec = sdk; }). The SDK's ResultSchema is defined in packages/core/src/types/schemas.ts:111 as:

export const ResultSchema = z.looseObject({
    _meta: ...
});

It has no resultType field, and a grep for resultType under packages/core/src finds it only in spec.types.ts — no SDK schema, handler, or result-construction site sets it.

Running pnpm tsc --noEmit -p packages/core/tsconfig.json on this branch produces 30+ errors of the form:

test/spec.types.test.ts: error TS2741: Property 'resultType' is missing in type
'{ _meta?: ...; }' but required in type 'Result'.

repeated for Result, EmptyResult, PaginatedResult, CompleteResult, ListToolsResult, CallToolResult, ListResourcesResult, ListResourceTemplatesResult, ReadResourceResult, ListPromptsResult, GetPromptResult, InitializeResult, CreateTaskResult, GetTaskResult, ListTasksResult, CancelTaskResult, GetTaskPayloadResult, JSONRPCResultResponse, JSONRPCMessage, ServerResult, ClientResult, and more.

Step-by-step

  1. spec.types.ts now says Result requires resultType: 'complete' | 'input_required'.
  2. schemas.ts infers the SDK Result type from ResultSchema = z.looseObject({ _meta: ... }), which has no resultType key.
  3. spec.types.test.ts does spec = sdk; for Result and every derived result type.
  4. TypeScript rejects the assignment because { _meta?: ... } lacks the required resultType property → TS2741.
  5. The same failure cascades to every extends Result interface and to JSONRPCResultResponse (whose result: Result field inherits the requirement).

Why existing code doesn't prevent it

Result has an index signature [key: string]: unknown, but index signatures do not satisfy explicitly-declared required properties — TypeScript still demands resultType be present by name. Nothing in this PR touches schemas.ts or any handler to add the field on the SDK side.

Impact

  • CI typecheck fails, so this PR cannot merge as-is.
  • Even if the typecheck were bypassed, every SDK consumer constructing a result literal (e.g. return { content: [...] } from a tool handler) would no longer satisfy Spec.CallToolResult, and downstream consumers typing against the spec types would see the same breakage.

How to fix

The cleanest fix is upstream: change the spec's schema.ts to resultType?: ResultType; (matching the @default "complete" semantics) and re-run pnpm run fetch:spec-types. If the spec genuinely intends the field to be required on the wire, then this PR must be accompanied by an SDK change that adds resultType: z.enum(['complete', 'input_required']).default('complete') (or equivalent) to ResultSchema and updates all result-construction sites — but that is a much larger, non-mechanical change that should not land in an automated nightly sync.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants