Skip to content

Commit 46e6af3

Browse files
ochafikclaude
andcommitted
docs: add types.ts.draft showing thin re-export layer
Draft of what types.ts could look like as a thin re-export layer: - 337 lines vs 2556 lines (87% reduction) - Re-exports from generated/sdk.schemas.js and sdk.types.js - Keeps SDK-specific extras (ErrorCode, McpError, type guards, etc.) NOT MERGED: Build errors reveal type mismatches that need resolution: - ClientCapabilities.applyDefaults property missing - Task vs GetTaskResult shape differences - SamplingMessageContentBlock array handling - Zod enum type compatibility This draft documents the target state for future work. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 63e0210 commit 46e6af3

File tree

1 file changed

+337
-0
lines changed

1 file changed

+337
-0
lines changed

src/types.ts.draft

Lines changed: 337 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,337 @@
1+
/**
2+
* MCP SDK Types and Schemas
3+
*
4+
* This file re-exports generated types and schemas, then adds SDK-specific
5+
* extras: constants, error classes, type guards, and utility schemas/types.
6+
*
7+
* Generated files:
8+
* - generated/sdk.types.ts: Pre-processed types (SDK hierarchy)
9+
* - generated/sdk.schemas.ts: Zod schemas from sdk.types.ts
10+
*
11+
* @see scripts/generate-schemas.ts for the generation pipeline
12+
*/
13+
import { z } from 'zod/v4';
14+
import type { AuthInfo } from './server/auth/types.js';
15+
16+
// =============================================================================
17+
// Re-export generated schemas and types
18+
// =============================================================================
19+
20+
export * from './generated/sdk.schemas.js';
21+
export type * from './generated/sdk.types.js';
22+
23+
// =============================================================================
24+
// SDK Constants
25+
// =============================================================================
26+
27+
export const LATEST_PROTOCOL_VERSION = '2025-11-25';
28+
export const DEFAULT_NEGOTIATED_PROTOCOL_VERSION = '2025-03-26';
29+
export const SUPPORTED_PROTOCOL_VERSIONS = [
30+
LATEST_PROTOCOL_VERSION,
31+
'2025-06-18',
32+
'2025-03-26',
33+
'2024-11-05',
34+
'2024-10-07',
35+
];
36+
export const RELATED_TASK_META_KEY = 'io.modelcontextprotocol/related-task';
37+
export const JSONRPC_VERSION = '2.0';
38+
39+
// =============================================================================
40+
// SDK Error Types
41+
// =============================================================================
42+
43+
export enum ErrorCode {
44+
// SDK error codes
45+
ConnectionClosed = -32000,
46+
RequestTimeout = -32001,
47+
48+
// Standard JSON-RPC error codes
49+
ParseError = -32700,
50+
InvalidRequest = -32600,
51+
MethodNotFound = -32601,
52+
InvalidParams = -32602,
53+
InternalError = -32603,
54+
55+
// MCP-specific error codes
56+
UrlElicitationRequired = -32042,
57+
}
58+
59+
export class McpError extends Error {
60+
constructor(
61+
public readonly code: number,
62+
message: string,
63+
public readonly data?: unknown
64+
) {
65+
super(`MCP error ${code}: ${message}`);
66+
this.name = 'McpError';
67+
}
68+
69+
static fromError(code: number, message: string, data?: unknown): McpError {
70+
if (code === ErrorCode.UrlElicitationRequired && data) {
71+
const errorData = data as { elicitations?: unknown[] };
72+
if (errorData.elicitations) {
73+
return new UrlElicitationRequiredError(
74+
errorData.elicitations as ElicitRequestURLParams[],
75+
message
76+
);
77+
}
78+
}
79+
return new McpError(code, message, data);
80+
}
81+
}
82+
83+
import type { ElicitRequestURLParams } from './generated/sdk.types.js';
84+
85+
export class UrlElicitationRequiredError extends McpError {
86+
constructor(
87+
elicitations: ElicitRequestURLParams[],
88+
message: string = `URL elicitation${elicitations.length > 1 ? 's' : ''} required`
89+
) {
90+
super(ErrorCode.UrlElicitationRequired, message, { elicitations });
91+
}
92+
93+
get elicitations(): ElicitRequestURLParams[] {
94+
return (this.data as { elicitations: ElicitRequestURLParams[] })?.elicitations ?? [];
95+
}
96+
}
97+
98+
// =============================================================================
99+
// SDK-Specific Schemas (not in spec)
100+
// =============================================================================
101+
102+
import {
103+
ResultSchema,
104+
CallToolResultSchema,
105+
TextContentSchema,
106+
ImageContentSchema,
107+
AudioContentSchema,
108+
RoleSchema,
109+
} from './generated/sdk.schemas.js';
110+
111+
/** Task creation parameters */
112+
export const TaskCreationParamsSchema = z.looseObject({
113+
ttl: z.union([z.number(), z.null()]).optional(),
114+
pollInterval: z.number().optional(),
115+
});
116+
117+
/** Client-side task capability */
118+
export const ClientTasksCapabilitySchema = z.looseObject({
119+
list: z.object({}).passthrough().optional(),
120+
cancel: z.object({}).passthrough().optional(),
121+
requests: z
122+
.looseObject({
123+
sampling: z.looseObject({ createMessage: z.object({}).passthrough().optional() }).optional(),
124+
elicitation: z.looseObject({ create: z.object({}).passthrough().optional() }).optional(),
125+
})
126+
.optional(),
127+
});
128+
129+
/** Server-side task capability */
130+
export const ServerTasksCapabilitySchema = z.looseObject({
131+
list: z.object({}).passthrough().optional(),
132+
cancel: z.object({}).passthrough().optional(),
133+
requests: z
134+
.looseObject({
135+
tools: z.looseObject({ call: z.object({}).passthrough().optional() }).optional(),
136+
})
137+
.optional(),
138+
});
139+
140+
/** Backwards-compatible CallToolResult (accepts legacy `toolResult` field) */
141+
export const CompatibilityCallToolResultSchema = CallToolResultSchema.or(
142+
ResultSchema.extend({ toolResult: z.unknown() })
143+
);
144+
145+
/** Progress information for long-running operations */
146+
export const ProgressSchema = z.object({
147+
progress: z.number(),
148+
total: z.optional(z.number()),
149+
message: z.optional(z.string()),
150+
});
151+
152+
/** Content types for sampling messages */
153+
export const SamplingContentSchema = z.discriminatedUnion('type', [
154+
TextContentSchema,
155+
ImageContentSchema,
156+
AudioContentSchema,
157+
]);
158+
159+
/** CreateMessageResult with tools support */
160+
export const CreateMessageResultWithToolsSchema = ResultSchema.extend({
161+
model: z.string(),
162+
stopReason: z.optional(z.enum(['endTurn', 'stopSequence', 'maxTokens', 'toolUse']).or(z.string())),
163+
role: RoleSchema,
164+
content: z.union([
165+
SamplingContentSchema,
166+
z.array(SamplingContentSchema),
167+
]),
168+
});
169+
170+
/** Elicitation complete notification params */
171+
export const ElicitationCompleteNotificationParamsSchema = z.object({
172+
_meta: z.looseObject({ progressToken: z.union([z.string(), z.number()]).optional() }).optional(),
173+
elicitationId: z.string(),
174+
});
175+
176+
/** Base schema for list changed options */
177+
export const ListChangedOptionsBaseSchema = z.object({
178+
autoRefresh: z.boolean().default(true),
179+
debounceMs: z.number().int().nonnegative().default(300),
180+
});
181+
182+
/** @deprecated Use ResourceTemplateReferenceSchema */
183+
import { ResourceTemplateReferenceSchema } from './generated/sdk.schemas.js';
184+
export const ResourceReferenceSchema = ResourceTemplateReferenceSchema;
185+
186+
// =============================================================================
187+
// Type Guards
188+
// =============================================================================
189+
190+
import {
191+
JSONRPCRequestSchema,
192+
JSONRPCNotificationSchema,
193+
JSONRPCResultResponseSchema,
194+
JSONRPCErrorResponseSchema,
195+
InitializeRequestSchema,
196+
InitializedNotificationSchema,
197+
TaskAugmentedRequestParamsSchema,
198+
} from './generated/sdk.schemas.js';
199+
200+
import type {
201+
JSONRPCRequest,
202+
JSONRPCNotification,
203+
JSONRPCResultResponse,
204+
JSONRPCErrorResponse,
205+
InitializeRequest,
206+
InitializedNotification,
207+
TaskAugmentedRequestParams,
208+
CompleteRequest,
209+
PromptReference,
210+
ResourceTemplateReference,
211+
Tool,
212+
Prompt,
213+
Resource,
214+
} from './generated/sdk.types.js';
215+
216+
export const isTaskAugmentedRequestParams = (value: unknown): value is TaskAugmentedRequestParams =>
217+
TaskAugmentedRequestParamsSchema.safeParse(value).success &&
218+
typeof (value as TaskAugmentedRequestParams)?.task !== 'undefined';
219+
220+
export const isJSONRPCRequest = (value: unknown): value is JSONRPCRequest =>
221+
JSONRPCRequestSchema.safeParse(value).success;
222+
223+
export const isJSONRPCNotification = (value: unknown): value is JSONRPCNotification =>
224+
JSONRPCNotificationSchema.safeParse(value).success;
225+
226+
export const isJSONRPCResultResponse = (value: unknown): value is JSONRPCResultResponse =>
227+
JSONRPCResultResponseSchema.safeParse(value).success;
228+
229+
export const isJSONRPCErrorResponse = (value: unknown): value is JSONRPCErrorResponse =>
230+
JSONRPCErrorResponseSchema.safeParse(value).success;
231+
232+
export const isInitializeRequest = (value: unknown): value is InitializeRequest =>
233+
InitializeRequestSchema.safeParse(value).success;
234+
235+
export const isInitializedNotification = (value: unknown): value is InitializedNotification =>
236+
InitializedNotificationSchema.safeParse(value).success;
237+
238+
// =============================================================================
239+
// Assertion Functions
240+
// =============================================================================
241+
242+
import type { CompleteRequestParams } from './generated/sdk.types.js';
243+
244+
type ExpandRecursively<T> = T extends object
245+
? T extends infer O
246+
? { [K in keyof O]: ExpandRecursively<O[K]> }
247+
: never
248+
: T;
249+
250+
export type CompleteRequestResourceTemplate = ExpandRecursively<
251+
CompleteRequest & { params: CompleteRequestParams & { ref: ResourceTemplateReference } }
252+
>;
253+
254+
export type CompleteRequestPrompt = ExpandRecursively<
255+
CompleteRequest & { params: CompleteRequestParams & { ref: PromptReference } }
256+
>;
257+
258+
export function assertCompleteRequestPrompt(request: CompleteRequest): asserts request is CompleteRequestPrompt {
259+
if (request.params.ref.type !== 'ref/prompt') {
260+
throw new TypeError(`Expected CompleteRequestPrompt, but got ${request.params.ref.type}`);
261+
}
262+
}
263+
264+
export function assertCompleteRequestResourceTemplate(
265+
request: CompleteRequest
266+
): asserts request is CompleteRequestResourceTemplate {
267+
if (request.params.ref.type !== 'ref/resource') {
268+
throw new TypeError(`Expected CompleteRequestResourceTemplate, but got ${request.params.ref.type}`);
269+
}
270+
}
271+
272+
// =============================================================================
273+
// SDK-Specific Types
274+
// =============================================================================
275+
276+
// Utility type for inferring from Zod schemas
277+
type Infer<Schema extends z.ZodTypeAny> = z.infer<Schema>;
278+
279+
/** Headers compatible with Node.js and browser */
280+
export type IsomorphicHeaders = Record<string, string | string[] | undefined>;
281+
282+
/** Information about the incoming request */
283+
export interface RequestInfo {
284+
headers: IsomorphicHeaders;
285+
}
286+
287+
/** Extra information about a message */
288+
export interface MessageExtraInfo {
289+
requestInfo?: RequestInfo;
290+
authInfo?: AuthInfo;
291+
closeSSEStream?: () => void;
292+
closeStandaloneSSEStream?: () => void;
293+
}
294+
295+
/** Callback for list changed notifications */
296+
export type ListChangedCallback<T> = (error: Error | null, items: T[] | null) => void;
297+
298+
/** Options for subscribing to list changed notifications */
299+
export type ListChangedOptions<T> = {
300+
autoRefresh?: boolean;
301+
debounceMs?: number;
302+
onChanged: ListChangedCallback<T>;
303+
};
304+
305+
/** Configuration for list changed notification handlers */
306+
export type ListChangedHandlers = {
307+
tools?: ListChangedOptions<Tool>;
308+
prompts?: ListChangedOptions<Prompt>;
309+
resources?: ListChangedOptions<Resource>;
310+
};
311+
312+
import type { CreateMessageRequestParams } from './generated/sdk.types.js';
313+
314+
/** CreateMessageRequestParams without tools */
315+
export type CreateMessageRequestParamsBase = Omit<CreateMessageRequestParams, 'tools' | 'toolChoice'>;
316+
317+
/** CreateMessageRequestParams with required tools */
318+
export interface CreateMessageRequestParamsWithTools extends CreateMessageRequestParams {
319+
tools: Tool[];
320+
}
321+
322+
/** @deprecated Use ResourceTemplateReference */
323+
export type ResourceReference = ResourceTemplateReference;
324+
325+
// SDK-specific inferred types
326+
export type TaskCreationParams = Infer<typeof TaskCreationParamsSchema>;
327+
export type Progress = Infer<typeof ProgressSchema>;
328+
export type SamplingContent = Infer<typeof SamplingContentSchema>;
329+
export type CreateMessageResultWithTools = Infer<typeof CreateMessageResultWithToolsSchema>;
330+
export type CompatibilityCallToolResult = Infer<typeof CompatibilityCallToolResultSchema>;
331+
export type ElicitationCompleteNotificationParams = Infer<typeof ElicitationCompleteNotificationParamsSchema>;
332+
333+
// SDK-specific type (not in spec) - used internally for request metadata
334+
export type RequestMeta = {
335+
progressToken?: string | number;
336+
[key: string]: unknown;
337+
};

0 commit comments

Comments
 (0)