Skip to content

Commit f8e37c7

Browse files
ochafikclaude
andcommitted
feat: remap generated schemas to SDK-compatible hierarchy
Post-process generated schemas to use SDK-compatible type hierarchy: - XxxNotificationSchema extends NotificationSchema (not JSONRPCNotificationSchema) - XxxRequestSchema extends RequestSchema (not JSONRPCRequestSchema) This makes generated schemas drop-in compatible with the existing types.ts hierarchy where jsonrpc/id fields are handled at the transport layer. Updated comparison tests to verify notification schemas now work correctly. 97 tests passing. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent a230db5 commit f8e37c7

File tree

4 files changed

+131
-60
lines changed

4 files changed

+131
-60
lines changed

scripts/generate-schemas.ts

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,11 @@ function postProcess(content: string): string {
116116
// ts-to-zod can't translate `typeof CONST` and falls back to z.any()
117117
content = fixTypeOfExpressions(content);
118118

119-
// 4. Add header comment
119+
// 4. Remap notification/request schemas to SDK-compatible hierarchy
120+
// (extend Notification/Request instead of JSONRPCNotification/JSONRPCRequest)
121+
content = remapToSdkHierarchy(content);
122+
123+
// 5. Add header comment
120124
content = content.replace(
121125
'// Generated by ts-to-zod',
122126
`// Generated by ts-to-zod
@@ -150,6 +154,78 @@ function fixTypeOfExpressions(content: string): string {
150154
return content;
151155
}
152156

157+
/**
158+
* Remap notification and request schemas to use SDK-compatible hierarchy.
159+
*
160+
* The spec defines:
161+
* - XxxNotification extends JSONRPCNotification (includes jsonrpc field)
162+
* - XxxRequest extends JSONRPCRequest (includes jsonrpc, id fields)
163+
*
164+
* The SDK types.ts uses:
165+
* - XxxNotification extends Notification (no jsonrpc field)
166+
* - XxxRequest extends Request (no jsonrpc, id fields)
167+
*
168+
* This allows the jsonrpc/id fields to be handled at the transport layer.
169+
*/
170+
function remapToSdkHierarchy(content: string): string {
171+
// List of notifications that should extend NotificationSchema instead of JSONRPCNotificationSchema
172+
const notifications = [
173+
'CancelledNotification',
174+
'InitializedNotification',
175+
'ProgressNotification',
176+
'ResourceListChangedNotification',
177+
'ResourceUpdatedNotification',
178+
'PromptListChangedNotification',
179+
'ToolListChangedNotification',
180+
'TaskStatusNotification',
181+
'LoggingMessageNotification',
182+
'RootsListChangedNotification',
183+
'ElicitationCompleteNotification',
184+
];
185+
186+
// List of requests that should extend RequestSchema instead of JSONRPCRequestSchema
187+
const requests = [
188+
'InitializeRequest',
189+
'PingRequest',
190+
'ListResourcesRequest',
191+
'ListResourceTemplatesRequest',
192+
'ReadResourceRequest',
193+
'SubscribeRequest',
194+
'UnsubscribeRequest',
195+
'ListPromptsRequest',
196+
'GetPromptRequest',
197+
'ListToolsRequest',
198+
'CallToolRequest',
199+
'GetTaskRequest',
200+
'ListTasksRequest',
201+
'GetTaskPayloadRequest',
202+
'CancelTaskRequest',
203+
'SetLevelRequest',
204+
'CreateMessageRequest',
205+
'CompleteRequest',
206+
'ListRootsRequest',
207+
'ElicitRequest',
208+
];
209+
210+
// Replace JSONRPCNotificationSchema.extend with NotificationSchema.extend for specific schemas
211+
for (const name of notifications) {
212+
content = content.replace(
213+
new RegExp(`export const ${name}Schema = JSONRPCNotificationSchema\\.extend\\(`),
214+
`export const ${name}Schema = NotificationSchema.extend(`
215+
);
216+
}
217+
218+
// Replace JSONRPCRequestSchema.extend with RequestSchema.extend for specific schemas
219+
for (const name of requests) {
220+
content = content.replace(
221+
new RegExp(`export const ${name}Schema = JSONRPCRequestSchema\\.extend\\(`),
222+
`export const ${name}Schema = RequestSchema.extend(`
223+
);
224+
}
225+
226+
return content;
227+
}
228+
153229
/**
154230
* Replace z.record(z.string(), z.unknown()).and(z.object({...})) with z.looseObject({...})
155231
* Uses brace-counting to handle nested objects correctly.

src/generated/index.ts

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,23 @@
11
/**
2-
* Generated Zod Schemas from MCP Specification
2+
* Generated Zod Schemas for MCP SDK
33
*
44
* This module provides auto-generated Zod schemas from spec.types.ts,
5-
* plus SDK version constants.
5+
* post-processed for SDK compatibility (extends Notification/Request
6+
* instead of JSONRPCNotification/JSONRPCRequest).
67
*
7-
* For production use with SDK-specific refinements and extras,
8-
* import from '@modelcontextprotocol/sdk/types.js'.
8+
* The schemas here are designed to be drop-in replacements for the
9+
* manually-defined schemas in types.ts.
910
*
10-
* @see spec.types.ts - Source TypeScript interfaces from MCP spec
11-
* @see spec.schemas.ts - Auto-generated Zod schemas
12-
* @see ../types.ts - Production schemas with SDK refinements
11+
* @see spec.types.ts - MCP specification types
12+
* @see spec.schemas.ts - Auto-generated Zod schemas (SDK-compatible)
13+
* @see ../types.ts - Production schemas with SDK extras
1314
*/
1415

15-
// Re-export all generated schemas
16+
// Re-export all generated schemas (SDK-compatible hierarchy via post-processing)
1617
export * from './spec.schemas.js';
1718

18-
// Re-export spec types (interfaces/types from MCP specification)
19+
// Re-export spec types
1920
export * from '../spec.types.js';
2021

21-
// Re-export SDK version constants (these differ from spec's DRAFT version)
22-
export {
23-
LATEST_PROTOCOL_VERSION,
24-
DEFAULT_NEGOTIATED_PROTOCOL_VERSION,
25-
SUPPORTED_PROTOCOL_VERSIONS,
26-
JSONRPC_VERSION,
27-
} from '../types.js';
22+
// Re-export SDK version constants
23+
export { LATEST_PROTOCOL_VERSION, DEFAULT_NEGOTIATED_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, JSONRPC_VERSION } from '../types.js';

src/generated/spec.schemas.ts

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ export const CancelledNotificationParamsSchema = NotificationParamsSchema.extend
242242
*
243243
* @category `notifications/cancelled`
244244
*/
245-
export const CancelledNotificationSchema = JSONRPCNotificationSchema.extend({
245+
export const CancelledNotificationSchema = NotificationSchema.extend({
246246
method: z.literal('notifications/cancelled'),
247247
params: CancelledNotificationParamsSchema
248248
});
@@ -504,7 +504,7 @@ export const ServerCapabilitiesSchema = z.object({
504504
*
505505
* @category `notifications/initialized`
506506
*/
507-
export const InitializedNotificationSchema = JSONRPCNotificationSchema.extend({
507+
export const InitializedNotificationSchema = NotificationSchema.extend({
508508
method: z.literal('notifications/initialized'),
509509
params: NotificationParamsSchema.optional()
510510
});
@@ -672,7 +672,7 @@ export const ImplementationSchema = BaseMetadataSchema.extend(IconsSchema.shape)
672672
*
673673
* @category `ping`
674674
*/
675-
export const PingRequestSchema = JSONRPCRequestSchema.extend({
675+
export const PingRequestSchema = RequestSchema.extend({
676676
method: z.literal('ping'),
677677
params: RequestParamsSchema.optional()
678678
});
@@ -719,7 +719,7 @@ export const ProgressNotificationParamsSchema = NotificationParamsSchema.extend(
719719
*
720720
* @category `notifications/progress`
721721
*/
722-
export const ProgressNotificationSchema = JSONRPCNotificationSchema.extend({
722+
export const ProgressNotificationSchema = NotificationSchema.extend({
723723
method: z.literal('notifications/progress'),
724724
params: ProgressNotificationParamsSchema
725725
});
@@ -811,7 +811,7 @@ export const ReadResourceRequestParamsSchema = ResourceRequestParamsSchema;
811811
*
812812
* @category `resources/read`
813813
*/
814-
export const ReadResourceRequestSchema = JSONRPCRequestSchema.extend({
814+
export const ReadResourceRequestSchema = RequestSchema.extend({
815815
method: z.literal('resources/read'),
816816
params: ReadResourceRequestParamsSchema
817817
});
@@ -822,7 +822,7 @@ export const ReadResourceRequestSchema = JSONRPCRequestSchema.extend({
822822
*
823823
* @category `notifications/resources/list_changed`
824824
*/
825-
export const ResourceListChangedNotificationSchema = JSONRPCNotificationSchema.extend({
825+
export const ResourceListChangedNotificationSchema = NotificationSchema.extend({
826826
method: z.literal('notifications/resources/list_changed'),
827827
params: NotificationParamsSchema.optional()
828828
});
@@ -842,7 +842,7 @@ export const SubscribeRequestParamsSchema = ResourceRequestParamsSchema;
842842
*
843843
* @category `resources/subscribe`
844844
*/
845-
export const SubscribeRequestSchema = JSONRPCRequestSchema.extend({
845+
export const SubscribeRequestSchema = RequestSchema.extend({
846846
method: z.literal('resources/subscribe'),
847847
params: SubscribeRequestParamsSchema
848848
});
@@ -862,7 +862,7 @@ export const UnsubscribeRequestParamsSchema = ResourceRequestParamsSchema;
862862
*
863863
* @category `resources/unsubscribe`
864864
*/
865-
export const UnsubscribeRequestSchema = JSONRPCRequestSchema.extend({
865+
export const UnsubscribeRequestSchema = RequestSchema.extend({
866866
method: z.literal('resources/unsubscribe'),
867867
params: UnsubscribeRequestParamsSchema
868868
});
@@ -893,7 +893,7 @@ export const ResourceUpdatedNotificationParamsSchema = NotificationParamsSchema.
893893
*
894894
* @category `notifications/resources/updated`
895895
*/
896-
export const ResourceUpdatedNotificationSchema = JSONRPCNotificationSchema.extend({
896+
export const ResourceUpdatedNotificationSchema = NotificationSchema.extend({
897897
method: z.literal('notifications/resources/updated'),
898898
params: ResourceUpdatedNotificationParamsSchema
899899
});
@@ -989,7 +989,7 @@ export const GetPromptRequestParamsSchema = RequestParamsSchema.extend({
989989
*
990990
* @category `prompts/get`
991991
*/
992-
export const GetPromptRequestSchema = JSONRPCRequestSchema.extend({
992+
export const GetPromptRequestSchema = RequestSchema.extend({
993993
method: z.literal('prompts/get'),
994994
params: GetPromptRequestParamsSchema
995995
});
@@ -1085,7 +1085,7 @@ export const AnnotationsSchema = z.object({
10851085
*
10861086
* @category `notifications/prompts/list_changed`
10871087
*/
1088-
export const PromptListChangedNotificationSchema = JSONRPCNotificationSchema.extend({
1088+
export const PromptListChangedNotificationSchema = NotificationSchema.extend({
10891089
method: z.literal('notifications/prompts/list_changed'),
10901090
params: NotificationParamsSchema.optional()
10911091
});
@@ -1147,7 +1147,7 @@ export const CallToolRequestParamsSchema = TaskAugmentedRequestParamsSchema.exte
11471147
*
11481148
* @category `notifications/tools/list_changed`
11491149
*/
1150-
export const ToolListChangedNotificationSchema = JSONRPCNotificationSchema.extend({
1150+
export const ToolListChangedNotificationSchema = NotificationSchema.extend({
11511151
method: z.literal('notifications/tools/list_changed'),
11521152
params: NotificationParamsSchema.optional()
11531153
});
@@ -1421,7 +1421,7 @@ export const CreateTaskResultSchema = ResultSchema.extend({
14211421
*
14221422
* @category `tasks/get`
14231423
*/
1424-
export const GetTaskRequestSchema = JSONRPCRequestSchema.extend({
1424+
export const GetTaskRequestSchema = RequestSchema.extend({
14251425
method: z.literal('tasks/get'),
14261426
params: z.object({
14271427
/**
@@ -1446,7 +1446,7 @@ export const GetTaskResultSchema = ResultSchema.and(TaskSchema).describe('The re
14461446
*
14471447
* @category `tasks/result`
14481448
*/
1449-
export const GetTaskPayloadRequestSchema = JSONRPCRequestSchema.extend({
1449+
export const GetTaskPayloadRequestSchema = RequestSchema.extend({
14501450
method: z.literal('tasks/result'),
14511451
params: z.object({
14521452
/**
@@ -1473,7 +1473,7 @@ export const GetTaskPayloadResultSchema = ResultSchema.and(z.record(z.string(),
14731473
*
14741474
* @category `tasks/cancel`
14751475
*/
1476-
export const CancelTaskRequestSchema = JSONRPCRequestSchema.extend({
1476+
export const CancelTaskRequestSchema = RequestSchema.extend({
14771477
method: z.literal('tasks/cancel'),
14781478
params: z.object({
14791479
/**
@@ -1528,7 +1528,7 @@ export const TaskStatusNotificationParamsSchema = NotificationParamsSchema.and(T
15281528
*
15291529
* @category `notifications/tasks/status`
15301530
*/
1531-
export const TaskStatusNotificationSchema = JSONRPCNotificationSchema.extend({
1531+
export const TaskStatusNotificationSchema = NotificationSchema.extend({
15321532
method: z.literal('notifications/tasks/status'),
15331533
params: TaskStatusNotificationParamsSchema
15341534
});
@@ -1604,7 +1604,7 @@ export const LoggingMessageNotificationParamsSchema = NotificationParamsSchema.e
16041604
*
16051605
* @category `notifications/message`
16061606
*/
1607-
export const LoggingMessageNotificationSchema = JSONRPCNotificationSchema.extend({
1607+
export const LoggingMessageNotificationSchema = NotificationSchema.extend({
16081608
method: z.literal('notifications/message'),
16091609
params: LoggingMessageNotificationParamsSchema
16101610
});
@@ -1947,7 +1947,7 @@ export const CompleteResultSchema = ResultSchema.extend({
19471947
*
19481948
* @category `roots/list`
19491949
*/
1950-
export const ListRootsRequestSchema = JSONRPCRequestSchema.extend({
1950+
export const ListRootsRequestSchema = RequestSchema.extend({
19511951
method: z.literal('roots/list'),
19521952
params: RequestParamsSchema.optional()
19531953
});
@@ -2002,7 +2002,7 @@ export const RootSchema = z.object({
20022002
*
20032003
* @category `notifications/roots/list_changed`
20042004
*/
2005-
export const RootsListChangedNotificationSchema = JSONRPCNotificationSchema.extend({
2005+
export const RootsListChangedNotificationSchema = NotificationSchema.extend({
20062006
method: z.literal('notifications/roots/list_changed'),
20072007
params: NotificationParamsSchema.optional()
20082008
});
@@ -2346,7 +2346,7 @@ export const ElicitResultSchema = ResultSchema.extend({
23462346
*
23472347
* @category `notifications/elicitation/complete`
23482348
*/
2349-
export const ElicitationCompleteNotificationSchema = JSONRPCNotificationSchema.extend({
2349+
export const ElicitationCompleteNotificationSchema = NotificationSchema.extend({
23502350
method: z.literal('notifications/elicitation/complete'),
23512351
params: z.object({
23522352
/**
@@ -2363,7 +2363,7 @@ export const ElicitationCompleteNotificationSchema = JSONRPCNotificationSchema.e
23632363
*
23642364
* @category `completion/complete`
23652365
*/
2366-
export const CompleteRequestSchema = JSONRPCRequestSchema.extend({
2366+
export const CompleteRequestSchema = RequestSchema.extend({
23672367
method: z.literal('completion/complete'),
23682368
params: CompleteRequestParamsSchema
23692369
});
@@ -2374,7 +2374,7 @@ export const CompleteRequestSchema = JSONRPCRequestSchema.extend({
23742374
*
23752375
* @category `logging/setLevel`
23762376
*/
2377-
export const SetLevelRequestSchema = JSONRPCRequestSchema.extend({
2377+
export const SetLevelRequestSchema = RequestSchema.extend({
23782378
method: z.literal('logging/setLevel'),
23792379
params: SetLevelRequestParamsSchema
23802380
});
@@ -2385,7 +2385,7 @@ export const SetLevelRequestSchema = JSONRPCRequestSchema.extend({
23852385
*
23862386
* @category `tools/call`
23872387
*/
2388-
export const CallToolRequestSchema = JSONRPCRequestSchema.extend({
2388+
export const CallToolRequestSchema = RequestSchema.extend({
23892389
method: z.literal('tools/call'),
23902390
params: CallToolRequestParamsSchema
23912391
});
@@ -2543,7 +2543,7 @@ export const InitializeRequestParamsSchema = RequestParamsSchema.extend({
25432543
*
25442544
* @category `initialize`
25452545
*/
2546-
export const InitializeRequestSchema = JSONRPCRequestSchema.extend({
2546+
export const InitializeRequestSchema = RequestSchema.extend({
25472547
method: z.literal('initialize'),
25482548
params: InitializeRequestParamsSchema
25492549
});
@@ -2944,7 +2944,7 @@ export const ClientRequestSchema = z.union([
29442944
*
29452945
* @category `elicitation/create`
29462946
*/
2947-
export const ElicitRequestSchema = JSONRPCRequestSchema.extend({
2947+
export const ElicitRequestSchema = RequestSchema.extend({
29482948
method: z.literal('elicitation/create'),
29492949
params: ElicitRequestParamsSchema
29502950
});
@@ -3214,7 +3214,7 @@ export const ClientResultSchema = z.union([
32143214
*
32153215
* @category `sampling/createMessage`
32163216
*/
3217-
export const CreateMessageRequestSchema = JSONRPCRequestSchema.extend({
3217+
export const CreateMessageRequestSchema = RequestSchema.extend({
32183218
method: z.literal('sampling/createMessage'),
32193219
params: CreateMessageRequestParamsSchema
32203220
});

0 commit comments

Comments
 (0)