Skip to content

Commit 751ffcb

Browse files
chore: sync schemas.ts to spec @d494db5c; segregate pre-2026 wire schemas
schemas.ts: - Result/Notification _meta now use plain MetaObject (not RequestMetaSchema) - ResultTypeSchema, resultType optional on ResultSchema (BC: pre-2026 omits it) - RequestMetaSchema kept simple {progressToken?}; namespaced io.modelcontextprotocol/* keys validated by parseClientMeta in P2, not here (TS2589 depth budget) - DiscoverRequest/Result, UnsupportedProtocolVersionErrorData, MissingRequiredClientCapabilityErrorData - DiscoverRequest/PaginatedRequest params: .default({}) — spec @d494db5c marks params required; .default keeps inferred type required while server-side parse stays tolerant of pre-2026 clients (Client._send populates params._meta in P2) - SubscriptionFilter, SubscriptionsListenRequest/Params, SubscriptionsAcknowledgedNotification/Params - subscriptions/listen has no result type per spec — omitted from resultSchemas runtime map; ResultTypeMap['subscriptions/listen'] = never - InputRequest/Response/s, InputRequiredResult, InputResponseRequestParams - CacheableResult/CacheScope (SEP-2243), PaginatedResult extends CacheableResult, ReadResourceResult extends CacheableResult - structuredContent: unknown (was Record<string,unknown>) - Tool inputSchema/outputSchema loosened to match spec (open record + type:object on input) - ToolExecution removed (only had taskSupport) - ClientRequest/ServerNotification/etc unions = 2026 spec methods only - registerLegacySchemas() lets legacyWireSchemas merge into runtime lookup maps - Dropped Initialize*/Ping/SetLevel/Subscribe/Unsubscribe/RootsListChanged NEW legacyWireSchemas.ts: - LegacyRequestParams/Result/RequestMetaObject base types (no namespaced keys, no resultType) - TS interfaces + zod for Initialize/Ping/SetLevel/Subscribe/Unsubscribe/RootsListChanged - legacyRequest/Result/NotificationSchemas maps; registerLegacySchemas() side-effect on import types.ts: re-exports legacy types; RequestTypeMap/NotificationTypeMap/ResultTypeMap merge legacy methods. Adds Discover*/InputRequired*/Subscriptions*/Cache* types. guards.ts: isInitializeRequest/isInitializedNotification import from legacyWireSchemas. specTypeSchema.ts: allowlist updated (drop legacy, add 2026). spec.types.test.ts: Relax<T> helper makes spec-required PermissiveKeys (_meta/resultType/ttlMs/cacheScope/inputResponses/requestState/io.modelcontextprotocol/*) optional so mutual assignability holds for everything else. Dropped checks for removed types; added 17 checks for 2026 types. Count 176→150. types.capabilities.test.ts: import InitializeRequestParamsSchema from legacyWireSchemas. types.test.ts: outputSchema no longer requires type:object. mcp.ts: drop ToolExecution/execution (removed from spec). client.ts: assertCapabilityForMethod switches on RequestMethod (includes legacy).
1 parent 5d8ac72 commit 751ffcb

13 files changed

Lines changed: 883 additions & 470 deletions

File tree

.changeset/spec-types-d494db5c.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
'@modelcontextprotocol/core': major
3+
---
4+
Regenerate spec.types.ts and sync schemas to spec @d494db5c. Pre-2026 wire schemas (Initialize/Ping/SetLevel/Subscribe/Unsubscribe) moved to legacyWireSchemas.ts.

packages/client/src/client/client.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import type {
44
CallToolRequest,
55
ClientCapabilities,
66
ClientContext,
7-
ClientNotification,
8-
ClientRequest,
97
CompleteRequest,
108
GetPromptRequest,
119
Implementation,
@@ -498,7 +496,7 @@ export class Client extends Protocol<ClientContext> {
498496
}
499497

500498
protected assertCapabilityForMethod(method: RequestMethod | string): void {
501-
switch (method as ClientRequest['method']) {
499+
switch (method as RequestMethod) {
502500
case 'logging/setLevel': {
503501
if (!this._serverCapabilities?.logging) {
504502
throw new SdkError(SdkErrorCode.CapabilityNotSupported, `Server does not support logging (required for ${method})`);
@@ -561,7 +559,7 @@ export class Client extends Protocol<ClientContext> {
561559
}
562560

563561
protected assertNotificationCapability(method: NotificationMethod | string): void {
564-
switch (method as ClientNotification['method']) {
562+
switch (method as NotificationMethod) {
565563
case 'notifications/roots/list_changed': {
566564
if (!this._capabilities.roots?.listChanged) {
567565
throw new SdkError(

packages/core/src/types/guards.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1+
import type { InitializedNotification, InitializeRequest } from './legacyWireSchemas.js';
2+
import { InitializedNotificationSchema, InitializeRequestSchema } from './legacyWireSchemas.js';
13
import {
24
CallToolResultSchema,
3-
InitializedNotificationSchema,
4-
InitializeRequestSchema,
55
JSONRPCErrorResponseSchema,
66
JSONRPCMessageSchema,
77
JSONRPCNotificationSchema,
@@ -14,8 +14,6 @@ import type {
1414
CompleteRequest,
1515
CompleteRequestPrompt,
1616
CompleteRequestResourceTemplate,
17-
InitializedNotification,
18-
InitializeRequest,
1917
JSONRPCErrorResponse,
2018
JSONRPCMessage,
2119
JSONRPCNotification,

packages/core/src/types/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ export * from './constants.js';
44
export * from './enums.js';
55
export * from './errors.js';
66
export * from './guards.js';
7+
/* eslint-disable import/export -- legacy type names overlap with types.ts re-exports; TS resolves deterministically. */
8+
export * from './legacyWireSchemas.js';
79
export * from './schemas.js';
810
export * from './specTypeSchema.js';
911
export * from './types.js';
12+
/* eslint-enable import/export */
Lines changed: 268 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
/**
2+
* Pre-2026 wire types and schemas.
3+
*
4+
* These types represent JSON-RPC methods and notifications that were part of
5+
* MCP up to and including 2025-11-25 but are removed from the 2026-06 draft
6+
* spec. They are NOT in the current `spec.types.ts` (regenerated from the
7+
* spec repo) and are SDK-maintained here so `LegacyServer` / `LegacyClient`
8+
* can continue to speak the pre-2026 wire protocol.
9+
*
10+
* Deleted when pre-2026 protocol support is dropped.
11+
*/
12+
import * as z from 'zod/v4';
13+
14+
import {
15+
ClientCapabilitiesSchema,
16+
ImplementationSchema,
17+
LoggingLevelSchema,
18+
NotificationSchema,
19+
ProgressTokenSchema,
20+
registerLegacySchemas,
21+
ServerCapabilitiesSchema
22+
} from './schemas.js';
23+
import type {
24+
ClientCapabilities,
25+
Implementation,
26+
JSONRPCNotification,
27+
JSONRPCRequest,
28+
LoggingLevel,
29+
MetaObject,
30+
NotificationParams,
31+
ProgressToken,
32+
ServerCapabilities
33+
} from './spec.types.js';
34+
35+
/* ────────────────────────────────────────────────────────────────────────── */
36+
/* Legacy base shapes */
37+
/* */
38+
/* The 2026-06 spec's `RequestParams._meta` is required and carries */
39+
/* namespaced `io.modelcontextprotocol/*` keys. Pre-2026 requests have an */
40+
/* optional `_meta` with only `progressToken`. These local base types let */
41+
/* the legacy interfaces below avoid the strict 2026 shape. */
42+
/* ────────────────────────────────────────────────────────────────────────── */
43+
44+
/** Pre-2026 `_meta` shape: only `progressToken`, no namespaced keys. */
45+
export interface LegacyRequestMetaObject extends MetaObject {
46+
progressToken?: ProgressToken;
47+
}
48+
49+
/** Pre-2026 request params: `_meta` is optional. */
50+
export interface LegacyRequestParams {
51+
_meta?: LegacyRequestMetaObject;
52+
[key: string]: unknown;
53+
}
54+
55+
/** Pre-2026 result: no `resultType`. */
56+
export interface LegacyResult {
57+
_meta?: MetaObject;
58+
[key: string]: unknown;
59+
}
60+
61+
/* Zod base shapes for legacy schemas. Kept separate from `schemas.ts` so the
62+
* 2026 file is spec-only at the source level. The shapes here are the pre-2026
63+
* wire format (no namespaced `_meta` keys, no `resultType`). */
64+
65+
const LegacyRequestMetaSchema = z.looseObject({
66+
progressToken: ProgressTokenSchema.optional()
67+
});
68+
69+
const LegacyBaseRequestParamsSchema = z.object({
70+
_meta: LegacyRequestMetaSchema.optional()
71+
});
72+
73+
const LegacyRequestSchema = z.object({
74+
method: z.string(),
75+
params: LegacyBaseRequestParamsSchema.loose().optional()
76+
});
77+
78+
const LegacyResultSchema = z.looseObject({
79+
_meta: z.record(z.string(), z.unknown()).optional()
80+
});
81+
82+
/* ────────────────────────────────────────────────────────────────────────── */
83+
/* `initialize` / `notifications/initialized` */
84+
/* ────────────────────────────────────────────────────────────────────────── */
85+
86+
export interface InitializeRequestParams extends LegacyRequestParams {
87+
/**
88+
* The latest version of the Model Context Protocol that the client
89+
* supports. The client MAY decide to support older versions as well.
90+
*/
91+
protocolVersion: string;
92+
capabilities: ClientCapabilities;
93+
clientInfo: Implementation;
94+
}
95+
96+
export interface InitializeRequest extends JSONRPCRequest {
97+
method: 'initialize';
98+
params: InitializeRequestParams;
99+
}
100+
101+
export interface InitializeResult extends LegacyResult {
102+
/**
103+
* The version of the Model Context Protocol that the server wants to use.
104+
* This may not match the version that the client requested. If the client
105+
* cannot support this version, it MUST disconnect.
106+
*/
107+
protocolVersion: string;
108+
capabilities: ServerCapabilities;
109+
serverInfo: Implementation;
110+
/**
111+
* Instructions describing how to use the server and its features.
112+
*/
113+
instructions?: string;
114+
}
115+
116+
export interface InitializedNotification extends JSONRPCNotification {
117+
method: 'notifications/initialized';
118+
params?: NotificationParams;
119+
}
120+
121+
export const InitializeRequestParamsSchema = LegacyBaseRequestParamsSchema.extend({
122+
protocolVersion: z.string(),
123+
capabilities: ClientCapabilitiesSchema,
124+
clientInfo: ImplementationSchema
125+
});
126+
127+
export const InitializeRequestSchema = LegacyRequestSchema.extend({
128+
method: z.literal('initialize'),
129+
params: InitializeRequestParamsSchema
130+
});
131+
132+
export const InitializeResultSchema = LegacyResultSchema.extend({
133+
protocolVersion: z.string(),
134+
capabilities: ServerCapabilitiesSchema,
135+
serverInfo: ImplementationSchema,
136+
instructions: z.string().optional()
137+
});
138+
139+
export const InitializedNotificationSchema = NotificationSchema.extend({
140+
method: z.literal('notifications/initialized')
141+
});
142+
143+
/* ────────────────────────────────────────────────────────────────────────── */
144+
/* `ping` */
145+
/* ────────────────────────────────────────────────────────────────────────── */
146+
147+
export interface PingRequest extends JSONRPCRequest {
148+
method: 'ping';
149+
params?: LegacyRequestParams;
150+
}
151+
152+
export const PingRequestSchema = LegacyRequestSchema.extend({
153+
method: z.literal('ping')
154+
});
155+
156+
/* ────────────────────────────────────────────────────────────────────────── */
157+
/* `logging/setLevel` */
158+
/* ────────────────────────────────────────────────────────────────────────── */
159+
160+
export interface SetLevelRequestParams extends LegacyRequestParams {
161+
/**
162+
* The level of logging that the client wants to receive from the server.
163+
*/
164+
level: LoggingLevel;
165+
}
166+
167+
export interface SetLevelRequest extends JSONRPCRequest {
168+
method: 'logging/setLevel';
169+
params: SetLevelRequestParams;
170+
}
171+
172+
export const SetLevelRequestParamsSchema = LegacyBaseRequestParamsSchema.extend({
173+
level: LoggingLevelSchema
174+
});
175+
176+
export const SetLevelRequestSchema = LegacyRequestSchema.extend({
177+
method: z.literal('logging/setLevel'),
178+
params: SetLevelRequestParamsSchema
179+
});
180+
181+
/* ────────────────────────────────────────────────────────────────────────── */
182+
/* `resources/subscribe` / `resources/unsubscribe` */
183+
/* ────────────────────────────────────────────────────────────────────────── */
184+
185+
export interface SubscribeRequestParams extends LegacyRequestParams {
186+
/** The URI of the resource to subscribe to. */
187+
uri: string;
188+
}
189+
190+
export interface SubscribeRequest extends JSONRPCRequest {
191+
method: 'resources/subscribe';
192+
params: SubscribeRequestParams;
193+
}
194+
195+
export type UnsubscribeRequestParams = SubscribeRequestParams;
196+
197+
export interface UnsubscribeRequest extends JSONRPCRequest {
198+
method: 'resources/unsubscribe';
199+
params: UnsubscribeRequestParams;
200+
}
201+
202+
export const SubscribeRequestParamsSchema = LegacyBaseRequestParamsSchema.extend({
203+
uri: z.string()
204+
});
205+
206+
export const SubscribeRequestSchema = LegacyRequestSchema.extend({
207+
method: z.literal('resources/subscribe'),
208+
params: SubscribeRequestParamsSchema
209+
});
210+
211+
export const UnsubscribeRequestParamsSchema = SubscribeRequestParamsSchema;
212+
213+
export const UnsubscribeRequestSchema = LegacyRequestSchema.extend({
214+
method: z.literal('resources/unsubscribe'),
215+
params: UnsubscribeRequestParamsSchema
216+
});
217+
218+
/* ────────────────────────────────────────────────────────────────────────── */
219+
/* `notifications/roots/list_changed` (client → server) */
220+
/* ────────────────────────────────────────────────────────────────────────── */
221+
222+
export interface RootsListChangedNotification extends JSONRPCNotification {
223+
method: 'notifications/roots/list_changed';
224+
params?: NotificationParams;
225+
}
226+
227+
export const RootsListChangedNotificationSchema = NotificationSchema.extend({
228+
method: z.literal('notifications/roots/list_changed')
229+
});
230+
231+
/* ────────────────────────────────────────────────────────────────────────── */
232+
/* Maps for legacy method/result/notification dispatch */
233+
/* ────────────────────────────────────────────────────────────────────────── */
234+
235+
/** Legacy request methods that are not in the 2026-06 `RequestTypeMap`. */
236+
export const legacyRequestSchemas = {
237+
initialize: InitializeRequestSchema,
238+
ping: PingRequestSchema,
239+
'logging/setLevel': SetLevelRequestSchema,
240+
'resources/subscribe': SubscribeRequestSchema,
241+
'resources/unsubscribe': UnsubscribeRequestSchema
242+
} as const;
243+
244+
/** Legacy result schemas keyed by request method. */
245+
export const legacyResultSchemas = {
246+
initialize: InitializeResultSchema,
247+
ping: LegacyResultSchema,
248+
'logging/setLevel': LegacyResultSchema,
249+
'resources/subscribe': LegacyResultSchema,
250+
'resources/unsubscribe': LegacyResultSchema
251+
} as const;
252+
253+
/** Legacy notification methods that are not in the 2026-06 `NotificationTypeMap`. */
254+
export const legacyNotificationSchemas = {
255+
'notifications/initialized': InitializedNotificationSchema,
256+
'notifications/roots/list_changed': RootsListChangedNotificationSchema
257+
} as const;
258+
259+
export type LegacyRequestMethod = keyof typeof legacyRequestSchemas;
260+
export type LegacyNotificationMethod = keyof typeof legacyNotificationSchemas;
261+
262+
// Merge into the runtime lookup maps so `getRequestSchema('initialize')` etc.
263+
// continue to work. Runs at module load (this file is barrel-imported).
264+
registerLegacySchemas({
265+
requests: legacyRequestSchemas,
266+
results: legacyResultSchemas,
267+
notifications: legacyNotificationSchemas
268+
});

0 commit comments

Comments
 (0)