fix(mcp): retain fallback for unsupported array items

This commit is contained in:
moesnow authored and digua committed 2026-10-21 21:05:50 +08:00
1 parent 47129958dd
commit faed80c898
2 files changed
+34 -6

No files matched your search

+25
View File
@@ -30,6 +30,31 @@ test('keeps optional arrays optional and does not apply JSON Schema defaults', (
assert.deepEqual(schema.parse({ values: ['beta'] }), { values: ['beta'] })
})
for (const items of [{ type: 'object' }, { type: 'array' }, { type: 'integer' }, undefined]) {
test(`preserves the string/enum fallback for arrays with ${items?.type ?? 'missing'} items`, () => {
const shape = jsonSchemaToZod(
{
required: { type: 'array', items, description: 'Unsupported array' },
optional: { type: 'array', items, default: ['alpha'] },
choice: { type: 'array', items, enum: ['alpha', 'beta'] },
},
['required']
)
const schema = z.object(shape)
assert.deepEqual(schema.parse({ required: 'alpha' }), { required: 'alpha' })
const values = { required: 'alpha', optional: 'beta', choice: 'alpha' }
assert.deepEqual(schema.parse(values), values)
assert.equal(schema.safeParse({}).success, false)
assert.equal(schema.safeParse({ ...values, choice: 'gamma' }).success, false)
for (const value of [[], ['alpha'], [{ name: 'Alice', count: 4 }]]) {
assert.equal(schema.safeParse({ ...values, required: value }).success, false)
assert.equal(schema.safeParse({ ...values, optional: value }).success, false)
}
assert.equal(shape.required.description, 'Unsupported array')
})
}
test('preserves scalar, enum, fallback, required and default conversion behavior', () => {
const shape = jsonSchemaToZod(
{
+9 -6
View File
@@ -22,18 +22,21 @@ export function jsonSchemaToZod(
let zodType: z.ZodTypeAny
switch (prop.type) {
case 'array': {
const itemType = prop.items?.type
const itemSchema = itemType === 'number' ? z.number() : itemType === 'boolean' ? z.boolean() : z.string()
zodType = z.array(itemSchema).describe(prop.description ?? '')
break
}
case 'number':
zodType = z.number().describe(prop.description ?? '')
break
case 'boolean':
zodType = z.boolean().describe(prop.description ?? '')
break
case 'array': {
const itemType = prop.items?.type
if (itemType === 'string' || itemType === 'number' || itemType === 'boolean') {
const itemSchema = itemType === 'number' ? z.number() : itemType === 'boolean' ? z.boolean() : z.string()
zodType = z.array(itemSchema).describe(prop.description ?? '')
break
}
}
// Fall through to the existing string/enum fallback for unsupported item types.
case 'string':
default:
if (prop.enum) {