Skip to content

Commit e526ee6

Browse files
ochafikclaude
andcommitted
feat: inject proper params typing into Request and Notification interfaces
Update pre-processing to transform Request.params and Notification.params: - Request.params: { [key: string]: any } → RequestParams & { [key: string]: any } - Notification.params: { [key: string]: any } → NotificationParams & { [key: string]: any } This allows RequestSchema, NotificationSchema, and ResultSchema to be re-exported from generated schemas with proper _meta typing. Total schemas re-exported: 36 Lines saved: ~368 (2600 → 2232) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 4ddcf2b commit e526ee6

File tree

4 files changed

+102
-77
lines changed

4 files changed

+102
-77
lines changed

scripts/generate-schemas.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ const RELATED_TASK_META_KEY = 'io.modelcontextprotocol/related-task';
106106
* 1. `extends JSONRPCRequest` → `extends Request`
107107
* 2. `extends JSONRPCNotification` → `extends Notification`
108108
* 3. Add RELATED_TASK_META_KEY to RequestParams._meta
109+
* 4. Change Request.params type to use RequestParams (for proper _meta typing)
109110
*/
110111
function preProcessTypes(content: string): string {
111112
const project = new Project({ useInMemoryFileSystem: true });
@@ -120,6 +121,9 @@ function preProcessTypes(content: string): string {
120121
// Transform 3: Add RELATED_TASK_META_KEY to RequestParams._meta
121122
injectRelatedTaskMetaKey(sourceFile);
122123

124+
// Transform 4: Update Request.params to use RequestParams
125+
updateRequestParamsType(sourceFile);
126+
123127
return sourceFile.getFullText();
124128
}
125129

@@ -208,6 +212,39 @@ function injectRelatedTaskMetaKey(sourceFile: SourceFile): void {
208212
console.log(' ✓ Injected RELATED_TASK_META_KEY into RequestParams._meta');
209213
}
210214

215+
/**
216+
* Update Request.params and Notification.params to use proper param types.
217+
*
218+
* Before:
219+
* interface Request { params?: { [key: string]: any }; }
220+
* interface Notification { params?: { [key: string]: any }; }
221+
*
222+
* After:
223+
* interface Request { params?: RequestParams & { [key: string]: any }; }
224+
* interface Notification { params?: NotificationParams & { [key: string]: any }; }
225+
*/
226+
function updateRequestParamsType(sourceFile: SourceFile): void {
227+
// Update Request.params
228+
const requestInterface = sourceFile.getInterface('Request');
229+
if (requestInterface) {
230+
const paramsProp = requestInterface.getProperty('params');
231+
if (paramsProp) {
232+
paramsProp.setType('RequestParams & { [key: string]: any }');
233+
console.log(' ✓ Updated Request.params to include RequestParams');
234+
}
235+
}
236+
237+
// Update Notification.params
238+
const notificationInterface = sourceFile.getInterface('Notification');
239+
if (notificationInterface) {
240+
const paramsProp = notificationInterface.getProperty('params');
241+
if (paramsProp) {
242+
paramsProp.setType('NotificationParams & { [key: string]: any }');
243+
console.log(' ✓ Updated Notification.params to include NotificationParams');
244+
}
245+
}
246+
}
247+
211248
// =============================================================================
212249
// Post-processing: AST-based transforms using ts-morph
213250
// =============================================================================

src/generated/sdk.schemas.ts

Lines changed: 50 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,27 @@ export const RelatedTaskMetadataSchema = z.object({
4343
taskId: z.string()
4444
});
4545

46-
/** @internal */
47-
export const RequestSchema = z.object({
48-
method: z.string(),
49-
// Allow unofficial extensions of `Request.params` without impacting `RequestParams`.
50-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
51-
params: z.record(z.string(), z.any()).optional()
46+
/**
47+
* Common params for any request.
48+
*
49+
* @internal
50+
*/
51+
export const RequestParamsSchema = z.object({
52+
/**
53+
* See [General fields: `_meta`](/specification/draft/basic/index#meta) for notes on `_meta` usage.
54+
*/
55+
_meta: z
56+
.looseObject({
57+
/**
58+
* If specified, the caller is requesting out-of-band progress notifications for this request (as represented by notifications/progress). The value of this parameter is an opaque token that will be attached to any subsequent notifications. The receiver is not obligated to provide these notifications.
59+
*/
60+
progressToken: ProgressTokenSchema.optional(),
61+
/**
62+
* If specified, this request is related to the provided task.
63+
*/
64+
'io.modelcontextprotocol/related-task': RelatedTaskMetadataSchema.optional()
65+
})
66+
.optional()
5267
});
5368

5469
/** @internal */
@@ -64,7 +79,7 @@ export const NotificationSchema = z.object({
6479
method: z.string(),
6580
// Allow unofficial extensions of `Notification.params` without impacting `NotificationParams`.
6681
// eslint-disable-next-line @typescript-eslint/no-explicit-any
67-
params: z.record(z.string(), z.any()).optional()
82+
params: NotificationParamsSchema.and(z.record(z.string(), z.any())).optional()
6883
});
6984

7085
/**
@@ -102,14 +117,12 @@ export const ErrorSchema = z.object({
102117
*/
103118
export const RequestIdSchema = z.union([z.string(), z.number().int()]);
104119

105-
/**
106-
* A request that expects a response.
107-
*
108-
* @category JSON-RPC
109-
*/
110-
export const JSONRPCRequestSchema = RequestSchema.extend({
111-
jsonrpc: z.literal('2.0'),
112-
id: RequestIdSchema
120+
/** @internal */
121+
export const RequestSchema = z.object({
122+
method: z.string(),
123+
// Allow unofficial extensions of `Request.params` without impacting `RequestParams`.
124+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
125+
params: RequestParamsSchema.and(z.record(z.string(), z.any())).optional()
113126
});
114127

115128
/**
@@ -195,29 +208,6 @@ export const CancelledNotificationSchema = NotificationSchema.extend({
195208
params: CancelledNotificationParamsSchema
196209
});
197210

198-
/**
199-
* Common params for any request.
200-
*
201-
* @internal
202-
*/
203-
export const RequestParamsSchema = z.object({
204-
/**
205-
* See [General fields: `_meta`](/specification/draft/basic/index#meta) for notes on `_meta` usage.
206-
*/
207-
_meta: z
208-
.looseObject({
209-
/**
210-
* If specified, the caller is requesting out-of-band progress notifications for this request (as represented by notifications/progress). The value of this parameter is an opaque token that will be attached to any subsequent notifications. The receiver is not obligated to provide these notifications.
211-
*/
212-
progressToken: ProgressTokenSchema.optional(),
213-
/**
214-
* If specified, this request is related to the provided task.
215-
*/
216-
'io.modelcontextprotocol/related-task': RelatedTaskMetadataSchema.optional()
217-
})
218-
.optional()
219-
});
220-
221211
/**
222212
* Capabilities a client may support. Known capabilities are defined here, in this schema, but this is not a closed set: any client can define its own, additional capabilities.
223213
*
@@ -1967,21 +1957,14 @@ export const ListToolsResultSchema = PaginatedResultSchema.extend({
19671957
});
19681958

19691959
/**
1970-
* This file is automatically generated from the Model Context Protocol specification.
1971-
*
1972-
* Source: https://github.com/modelcontextprotocol/modelcontextprotocol
1973-
* Pulled from: https://raw.githubusercontent.com/modelcontextprotocol/modelcontextprotocol/main/schema/draft/schema.ts
1974-
* Last updated from commit: 35fa160caf287a9c48696e3ae452c0645c713669
1975-
*
1976-
* DO NOT EDIT THIS FILE MANUALLY. Changes will be overwritten by automated updates.
1977-
* To update this file, run: npm run fetch:spec-types
1978-
*/ /* JSON-RPC types */
1979-
/**
1980-
* Refers to any valid JSON-RPC object that can be decoded off the wire, or encoded to be sent.
1960+
* A request that expects a response.
19811961
*
19821962
* @category JSON-RPC
19831963
*/
1984-
export const JSONRPCMessageSchema = z.union([JSONRPCRequestSchema, JSONRPCNotificationSchema, JSONRPCResponseSchema]);
1964+
export const JSONRPCRequestSchema = RequestSchema.extend({
1965+
jsonrpc: z.literal('2.0'),
1966+
id: RequestIdSchema
1967+
});
19851968

19861969
/**
19871970
* An error response that indicates that the server requires the client to provide additional information via an elicitation request.
@@ -2367,6 +2350,23 @@ export const CallToolResultSchema = ResultSchema.extend({
23672350
isError: z.boolean().optional()
23682351
});
23692352

2353+
/**
2354+
* This file is automatically generated from the Model Context Protocol specification.
2355+
*
2356+
* Source: https://github.com/modelcontextprotocol/modelcontextprotocol
2357+
* Pulled from: https://raw.githubusercontent.com/modelcontextprotocol/modelcontextprotocol/main/schema/draft/schema.ts
2358+
* Last updated from commit: 35fa160caf287a9c48696e3ae452c0645c713669
2359+
*
2360+
* DO NOT EDIT THIS FILE MANUALLY. Changes will be overwritten by automated updates.
2361+
* To update this file, run: npm run fetch:spec-types
2362+
*/ /* JSON-RPC types */
2363+
/**
2364+
* Refers to any valid JSON-RPC object that can be decoded off the wire, or encoded to be sent.
2365+
*
2366+
* @category JSON-RPC
2367+
*/
2368+
export const JSONRPCMessageSchema = z.union([JSONRPCRequestSchema, JSONRPCNotificationSchema, JSONRPCResponseSchema]);
2369+
23702370
/**
23712371
* Describes a message returned as part of a prompt.
23722372
*

src/generated/sdk.types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ export interface Request {
8181
method: string;
8282
// Allow unofficial extensions of `Request.params` without impacting `RequestParams`.
8383
// eslint-disable-next-line @typescript-eslint/no-explicit-any
84-
params?: { [key: string]: any };
84+
params?: RequestParams & { [key: string]: any };
8585
}
8686

8787
/** @internal */
@@ -97,7 +97,7 @@ export interface Notification {
9797
method: string;
9898
// Allow unofficial extensions of `Notification.params` without impacting `NotificationParams`.
9999
// eslint-disable-next-line @typescript-eslint/no-explicit-any
100-
params?: { [key: string]: any };
100+
params?: NotificationParams & { [key: string]: any };
101101
}
102102

103103
/**

src/types.ts

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,17 @@ import {
5454
// Request/notification base schemas (with RELATED_TASK_META_KEY injected)
5555
RequestParamsSchema,
5656
TaskAugmentedRequestParamsSchema,
57+
NotificationParamsSchema,
58+
// Core request/notification schemas (params include proper _meta typing)
59+
RequestSchema,
60+
NotificationSchema,
61+
ResultSchema,
5762
} from './generated/sdk.schemas.js';
5863

5964
// Alias RequestParamsSchema to BaseRequestParamsSchema for internal use
6065
const BaseRequestParamsSchema = RequestParamsSchema;
66+
// Alias NotificationParamsSchema to NotificationsParamsSchema (plural) for backwards compat
67+
const NotificationsParamsSchema = NotificationParamsSchema;
6168

6269
export {
6370
ProgressTokenSchema,
@@ -91,6 +98,10 @@ export {
9198
ResourceContentsSchema,
9299
TextResourceContentsSchema,
93100
BlobResourceContentsSchema,
101+
// Core protocol schemas
102+
RequestSchema,
103+
NotificationSchema,
104+
ResultSchema,
94105
};
95106

96107
export const LATEST_PROTOCOL_VERSION = '2025-11-25';
@@ -151,31 +162,8 @@ const RequestMetaSchema = z.looseObject({
151162
export const isTaskAugmentedRequestParams = (value: unknown): value is TaskAugmentedRequestParams =>
152163
TaskAugmentedRequestParamsSchema.safeParse(value).success;
153164

154-
export const RequestSchema = z.object({
155-
method: z.string(),
156-
params: BaseRequestParamsSchema.loose().optional()
157-
});
158-
159-
const NotificationsParamsSchema = z.object({
160-
/**
161-
* See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields)
162-
* for notes on _meta usage.
163-
*/
164-
_meta: RequestMetaSchema.optional()
165-
});
166-
167-
export const NotificationSchema = z.object({
168-
method: z.string(),
169-
params: NotificationsParamsSchema.loose().optional()
170-
});
171-
172-
export const ResultSchema = z.looseObject({
173-
/**
174-
* See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields)
175-
* for notes on _meta usage.
176-
*/
177-
_meta: RequestMetaSchema.optional()
178-
});
165+
// Note: RequestSchema, NotificationSchema, ResultSchema are re-exported from generated.
166+
// They include proper _meta typing with RELATED_TASK_META_KEY.
179167

180168
/**
181169
* A request that expects a response.

0 commit comments

Comments
 (0)