|
| 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