* Override request handler registration to enforce server-side validation for tools/call.
(
requestSchema: T,
handler: (
request: SchemaOutput<T>,
extra: RequestHandlerExtra<ServerRequest | RequestT, ServerNotification | NotificationT>
) => ServerResult | ResultT | Promise<ServerResult | ResultT>
)
| 216 | * Override request handler registration to enforce server-side validation for tools/call. |
| 217 | */ |
| 218 | public override setRequestHandler<T extends AnyObjectSchema>( |
| 219 | requestSchema: T, |
| 220 | handler: ( |
| 221 | request: SchemaOutput<T>, |
| 222 | extra: RequestHandlerExtra<ServerRequest | RequestT, ServerNotification | NotificationT> |
| 223 | ) => ServerResult | ResultT | Promise<ServerResult | ResultT> |
| 224 | ): void { |
| 225 | const shape = getObjectShape(requestSchema); |
| 226 | const methodSchema = shape?.method; |
| 227 | if (!methodSchema) { |
| 228 | throw new Error('Schema is missing a method literal'); |
| 229 | } |
| 230 | |
| 231 | // Extract literal value using type-safe property access |
| 232 | let methodValue: unknown; |
| 233 | if (isZ4Schema(methodSchema)) { |
| 234 | const v4Schema = methodSchema as unknown as ZodV4Internal; |
| 235 | const v4Def = v4Schema._zod?.def; |
| 236 | methodValue = v4Def?.value ?? v4Schema.value; |
| 237 | } else { |
| 238 | const v3Schema = methodSchema as unknown as ZodV3Internal; |
| 239 | const legacyDef = v3Schema._def; |
| 240 | methodValue = legacyDef?.value ?? v3Schema.value; |
| 241 | } |
| 242 | |
| 243 | if (typeof methodValue !== 'string') { |
| 244 | throw new Error('Schema method literal must be a string'); |
| 245 | } |
| 246 | const method = methodValue; |
| 247 | |
| 248 | if (method === 'tools/call') { |
| 249 | const wrappedHandler = async ( |
| 250 | request: SchemaOutput<T>, |
| 251 | extra: RequestHandlerExtra<ServerRequest | RequestT, ServerNotification | NotificationT> |
| 252 | ): Promise<ServerResult | ResultT> => { |
| 253 | const validatedRequest = safeParse(CallToolRequestSchema, request); |
| 254 | if (!validatedRequest.success) { |
| 255 | const errorMessage = |
| 256 | validatedRequest.error instanceof Error ? validatedRequest.error.message : String(validatedRequest.error); |
| 257 | throw new McpError(ErrorCode.InvalidParams, `Invalid tools/call request: ${errorMessage}`); |
| 258 | } |
| 259 | |
| 260 | const { params } = validatedRequest.data; |
| 261 | |
| 262 | const result = await Promise.resolve(handler(request, extra)); |
| 263 | |
| 264 | // When task creation is requested, validate and return CreateTaskResult |
| 265 | if (params.task) { |
| 266 | const taskValidationResult = safeParse(CreateTaskResultSchema, result); |
| 267 | if (!taskValidationResult.success) { |
| 268 | const errorMessage = |
| 269 | taskValidationResult.error instanceof Error |
| 270 | ? taskValidationResult.error.message |
| 271 | : String(taskValidationResult.error); |
| 272 | throw new McpError(ErrorCode.InvalidParams, `Invalid task creation result: ${errorMessage}`); |
| 273 | } |
| 274 | return taskValidationResult.data; |
| 275 | } |
no test coverage detected