Skip to content

Commit cdff982

Browse files
committed
fix: align zod object schemas with stripped properties
1 parent db83829 commit cdff982

3 files changed

Lines changed: 30 additions & 1 deletion

File tree

packages/core/src/util/standardSchema.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,11 @@ export function standardSchemaToJsonSchema(schema: StandardJSONSchemaV1, io: 'in
188188
`Wrap your schema in z.object({...}) or equivalent.`
189189
);
190190
}
191-
return { type: 'object', ...result };
191+
const jsonSchema: Record<string, unknown> = { type: 'object', ...result };
192+
if (jsonSchema.properties !== undefined && !('additionalProperties' in jsonSchema) && !('unevaluatedProperties' in jsonSchema)) {
193+
jsonSchema.additionalProperties = false;
194+
}
195+
return jsonSchema;
192196
}
193197

194198
// Validation

packages/core/test/util/standardSchema.test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,28 @@ describe('standardSchemaToJsonSchema', () => {
3939
expect(keys.filter(k => k === 'type')).toHaveLength(1);
4040
expect(result.type).toBe('object');
4141
});
42+
43+
test('marks default z.object schemas as not accepting additional properties', () => {
44+
const schema = z.object({ message: z.string() });
45+
const result = standardSchemaToJsonSchema(schema, 'input');
46+
47+
expect(result.additionalProperties).toBe(false);
48+
});
49+
50+
test('preserves schemas that explicitly allow additional properties', () => {
51+
const schema = z.object({ message: z.string() }).passthrough();
52+
const result = standardSchemaToJsonSchema(schema, 'input');
53+
54+
expect(result.additionalProperties).toEqual({});
55+
});
56+
57+
test('does not add root additionalProperties to union schemas', () => {
58+
const schema = z.discriminatedUnion('action', [
59+
z.object({ action: z.literal('create'), name: z.string() }),
60+
z.object({ action: z.literal('delete'), id: z.string() })
61+
]);
62+
const result = standardSchemaToJsonSchema(schema, 'input');
63+
64+
expect(result.additionalProperties).toBeUndefined();
65+
});
4266
});

test/integration/test/server/mcp.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -934,6 +934,7 @@ describe('Zod v4', () => {
934934
expect(result.tools[0]!.name).toBe('test');
935935
expect(result.tools[0]!.inputSchema).toMatchObject({
936936
type: 'object',
937+
additionalProperties: false,
937938
properties: {
938939
name: { type: 'string' },
939940
value: { type: 'number' }

0 commit comments

Comments
 (0)