Skip to content

Commit ab70a36

Browse files
authored
Merge pull request #159 from QuantGeekDev/fix/118-optional-fields-legacy-schema
fix: optional fields marked as required in legacy schema format
2 parents 298799f + 5fcd54d commit ab70a36

File tree

1 file changed

+24
-5
lines changed

1 file changed

+24
-5
lines changed

src/tools/BaseTool.ts

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -832,8 +832,8 @@ export abstract class MCPTool<TInput extends Record<string, any> = any, TSchema
832832
description: fieldSchema.description,
833833
};
834834

835-
// If the field is not an optional, add it to the required array.
836-
if (!(fieldSchema.type instanceof z.ZodOptional)) {
835+
// If the field is not optional/nullable/defaulted, add it to the required array.
836+
if (!this.isFieldOptional(fieldSchema.type)) {
837837
required.push(key);
838838
}
839839
});
@@ -947,10 +947,18 @@ export abstract class MCPTool<TInput extends Record<string, any> = any, TSchema
947947
}
948948

949949
private getJsonSchemaType(zodType: z.ZodType<any>): string {
950-
// Unwrap optional types to correctly determine the JSON schema type.
950+
// Unwrap optional/nullable/default types to correctly determine the JSON schema type.
951951
let currentType = zodType;
952-
if (currentType instanceof z.ZodOptional) {
953-
currentType = currentType.unwrap();
952+
while (true) {
953+
if (currentType instanceof z.ZodOptional) {
954+
currentType = currentType.unwrap();
955+
} else if (currentType instanceof z.ZodNullable) {
956+
currentType = currentType.unwrap();
957+
} else if (currentType instanceof z.ZodDefault) {
958+
currentType = (currentType as any)._def.innerType;
959+
} else {
960+
break;
961+
}
954962
}
955963

956964
if (currentType instanceof z.ZodString) return 'string';
@@ -961,6 +969,17 @@ export abstract class MCPTool<TInput extends Record<string, any> = any, TSchema
961969
return 'string';
962970
}
963971

972+
private isFieldOptional(zodType: z.ZodType<any>): boolean {
973+
let current = zodType;
974+
while (true) {
975+
if (current instanceof z.ZodOptional) return true;
976+
if (current instanceof z.ZodNullable) return true;
977+
if (current instanceof z.ZodDefault) return true;
978+
break;
979+
}
980+
return false;
981+
}
982+
964983
protected createSuccessResponse(data: unknown): ToolResponse {
965984
if (this.isImageContent(data) || this.isAudioContent(data) ||
966985
this.isResourceLinkContent(data) || this.isEmbeddedResourceContent(data)) {

0 commit comments

Comments
 (0)