Design JSON Schema-compatible Zod schemas
mainSince schemas are converted to JSON Schema for the MCP interface, you must follow specific patterns to ensure compatibility:
- Use Discriminated Unions: For operations with different requirements (e.g., 'delete' vs 'edit'), use
z.discriminatedUnioninstead ofsuperRefine. This translates well to JSON Schema. - Avoid
superRefinefor logic: Do not use complex refinements that rely on parent context or cross-field logic that cannot be expressed in JSON Schema. - Be Explicit: Always use
.describe()on parameters to provide documentation for the LLM. - Strictness: Use
.strict()on objects to prevent unexpected inputs. - Standard Types: Stick to standard Zod types that have clear JSON Schema equivalents.
// ✅ DO: Use discriminated unions
const schema = z.discriminatedUnion('operation', [
z.object({ operation: z.literal('delete'), target: z.string() }),
z.object({ operation: z.literal('edit'), target: z.string(), content: z.string() })
]).strict();
// ❌ DON'T: Use complex refinements for conditional logic
const schema = z.object({
operation: z.enum(['delete', 'edit']),
content: z.string().superRefine((val, ctx) => { /* ... */ })
});