UNPKG

@codervisor/devlog-mcp

Version:

MCP server for managing development logs and working notes

112 lines (111 loc) 4.15 kB
/** * Zod to JSON Schema converter for MCP tools * * This module converts Zod schemas to JSON Schema format * required by MCP tool definitions. */ /** * Convert a Zod schema to JSON Schema format for MCP tool inputSchema */ export function zodToJsonSchema(schema) { return zodToJsonSchemaRecursive(schema._def); } function zodToJsonSchemaRecursive(def) { switch (def.typeName) { case 'ZodString': const stringSchema = { type: 'string' }; // Handle string validations if (def.checks) { for (const check of def.checks) { switch (check.kind) { case 'min': stringSchema.minLength = check.value; break; case 'max': stringSchema.maxLength = check.value; break; case 'regex': stringSchema.pattern = check.regex.source; break; } } } return stringSchema; case 'ZodNumber': const numberSchema = { type: 'number' }; // Handle number validations if (def.checks) { for (const check of def.checks) { switch (check.kind) { case 'min': numberSchema.minimum = check.value; break; case 'max': numberSchema.maximum = check.value; break; case 'int': numberSchema.type = 'integer'; break; } } } return numberSchema; case 'ZodBoolean': return { type: 'boolean' }; case 'ZodEnum': return { type: 'string', enum: def.values, }; case 'ZodArray': return { type: 'array', items: zodToJsonSchemaRecursive(def.type._def), }; case 'ZodObject': const properties = {}; const required = []; for (const [key, value] of Object.entries(def.shape())) { const fieldDef = value._def; properties[key] = zodToJsonSchemaRecursive(fieldDef); // Check if field is optional if (fieldDef.typeName !== 'ZodOptional' && fieldDef.typeName !== 'ZodDefault') { required.push(key); } } const objectSchema = { type: 'object', properties, }; if (required.length > 0) { objectSchema.required = required; } return objectSchema; case 'ZodOptional': return zodToJsonSchemaRecursive(def.innerType._def); case 'ZodDefault': const defaultSchema = zodToJsonSchemaRecursive(def.innerType._def); defaultSchema.default = def.defaultValue(); return defaultSchema; case 'ZodTransform': // For transforms, just use the input schema return zodToJsonSchemaRecursive(def.schema._def); case 'ZodEffects': // For effects (including transforms), use the underlying schema return zodToJsonSchemaRecursive(def.schema._def); case 'ZodNullable': // Handle nullable types const nullableSchema = zodToJsonSchemaRecursive(def.innerType._def); if (Array.isArray(nullableSchema.type)) { nullableSchema.type.push('null'); } else { nullableSchema.type = [nullableSchema.type, 'null']; } return nullableSchema; default: // Fallback for unsupported types console.warn(`Unsupported Zod type: ${def.typeName}, falling back to any`); return {}; } }