1- import { mergeCapabilities , Protocol , type ProtocolOptions , type RequestOptions } from '../shared/protocol.js' ;
1+ import { mergeCapabilities , Protocol , type ProtocolOptions , type RequestOptions , type RequestHandlerExtra } from '../shared/protocol.js' ;
22import type { Transport } from '../shared/transport.js' ;
33import {
44 type CallToolRequest ,
@@ -10,6 +10,8 @@ import {
1010 type CompatibilityCallToolResultSchema ,
1111 type CompleteRequest ,
1212 CompleteResultSchema ,
13+ ElicitRequestSchema ,
14+ type ElicitResult ,
1315 EmptyResultSchema ,
1416 ErrorCode ,
1517 type GetPromptRequest ,
@@ -40,6 +42,7 @@ import {
4042} from '../types.js' ;
4143import { AjvJsonSchemaValidator } from '../validation/ajv-provider.js' ;
4244import type { JsonSchemaType , JsonSchemaValidator , jsonSchemaValidator } from '../validation/types.js' ;
45+ import { ZodObject , ZodLiteral , z } from 'zod' ;
4346
4447export type ClientOptions = ProtocolOptions & {
4548 /**
@@ -437,4 +440,71 @@ export class Client<
437440 async sendRootsListChanged ( ) {
438441 return this . notification ( { method : 'notifications/roots/list_changed' } ) ;
439442 }
443+
444+ /**
445+ * Override setRequestHandler to automatically apply defaults for elicitation responses.
446+ * When a handler is registered for ElicitRequestSchema, it wraps the handler to apply
447+ * defaults from the schema before returning the response.
448+ */
449+ override setRequestHandler <
450+ T extends ZodObject < {
451+ method : ZodLiteral < string > ;
452+ } >
453+ > (
454+ requestSchema : T ,
455+ handler : (
456+ request : z . infer < T > ,
457+ extra : RequestHandlerExtra < ClientRequest | RequestT , ClientNotification | NotificationT >
458+ ) => ClientResult | ResultT | Promise < ClientResult | ResultT >
459+ ) : void {
460+ const method = requestSchema . shape . method . value ;
461+
462+ // Special handling for elicitation requests to apply defaults
463+ if ( method === 'elicitation/create' ) {
464+ const wrappedHandler = async (
465+ request : z . infer < typeof ElicitRequestSchema > ,
466+ extra : RequestHandlerExtra < ClientRequest | RequestT , ClientNotification | NotificationT >
467+ ) : Promise < ElicitResult > => {
468+ // Call the original handler
469+ const result = ( await handler ( request as z . infer < T > , extra ) ) as ElicitResult ;
470+
471+ // Only apply defaults if action is 'accept' and content exists
472+ if ( result . action === 'accept' && result . content ) {
473+ // Convert requestedSchema to JSON Schema format for validation
474+ const jsonSchema = {
475+ type : 'object' as const ,
476+ properties : request . params . requestedSchema . properties ,
477+ required : request . params . requestedSchema . required
478+ } ;
479+
480+ try {
481+ // Get validator which will apply defaults during validation
482+ const validator = this . _jsonSchemaValidator . getValidator ( jsonSchema ) ;
483+ const validationResult = validator ( result . content ) ;
484+
485+ if ( ! validationResult . valid ) {
486+ throw new McpError (
487+ ErrorCode . InvalidParams ,
488+ `Elicitation response content does not match requested schema: ${ validationResult . errorMessage } `
489+ ) ;
490+ }
491+ } catch ( error ) {
492+ if ( error instanceof McpError ) {
493+ throw error ;
494+ }
495+ // If validation fails, log but don't block - defaults were applied in-place
496+ // This handles edge cases where schema might not perfectly match
497+ }
498+ }
499+
500+ return result ;
501+ } ;
502+
503+ // Register the wrapped handler using the parent's setRequestHandler
504+ super . setRequestHandler ( ElicitRequestSchema , wrappedHandler ) ;
505+ } else {
506+ // For all other request types, use default behavior
507+ super . setRequestHandler ( requestSchema , handler ) ;
508+ }
509+ }
440510}
0 commit comments