// tools/design-schema/mcp-schema.ts
// SPEC-016b: Generates TypeScript interfaces for MCP tool inputs and outputs.
// Criterion 3: design_schema generates TypeScript interfaces for each MCP tool.
import { isMcpServerProject } from '../../engine/detectors/mcp-server-detector.js';
// === Detection ===
export function isMcpSchema(knowledge) {
    return isMcpServerProject(knowledge);
}
// === TypeScript interface generators ===
/* v8 ignore start */
function jsonSchemaTypeToTs(schema, indent = 0) {
    const pad = ' '.repeat(indent);
    if (schema === null || schema === undefined) {
        return 'unknown';
    }
    if (typeof schema !== 'object') {
        return 'unknown';
    }
    const s = schema;
    const type = s.type;
    if (type === 'string') {
        return 'string';
    }
    if (type === 'number' || type === 'integer') {
        return 'number';
    }
    if (type === 'boolean') {
        return 'boolean';
    }
    if (type === 'array') {
        const items = s.items;
        return `Array<${jsonSchemaTypeToTs(items, indent)}>`;
    }
    if (type === 'object') {
        const props = s.properties;
        const required = s.required ?? [];
        if (!props || Object.keys(props).length === 0) {
            return 'Record<string, unknown>';
        }
        const innerPad = ' '.repeat(indent + 2);
        const fieldLines = Object.entries(props).map(([key, val]) => {
            const optional = !required.includes(key) ? '?' : '';
            return `${innerPad}${key}${optional}: ${jsonSchemaTypeToTs(val, indent + 2)};`;
        });
        return `{\n${fieldLines.join('\n')}\n${pad}}`;
    }
    return 'unknown';
}
/* v8 ignore stop */
function toPascalCase(name) {
    return name
        .split('_')
        .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
        .join('');
}
function buildToolInterface(tool) {
    const lines = [];
    const pascal = toPascalCase(tool.name);
    lines.push(`/** Input schema for MCP tool: ${tool.name} */`);
    lines.push(`export interface ${pascal}Input ${jsonSchemaTypeToTs(tool.inputSchema)}`);
    lines.push('');
    lines.push(`/** Output contract for MCP tool: ${tool.name} */`);
    lines.push(`export interface ${pascal}Output {`);
    lines.push('  content: Array<{');
    lines.push("    type: 'text' | 'image' | 'embedded_resource';");
    lines.push('    text?: string;');
    lines.push('    data?: string;');
    lines.push('    mimeType?: string;');
    lines.push('  }>;');
    lines.push('  isError?: boolean;');
    lines.push('}');
    lines.push('');
    return lines;
}
function buildDefaultMcpTools(entities) {
    return entities.map((name) => ({
        name: name.toLowerCase().replace(/\s+/g, '_'),
        description: `MCP tool for ${name}`,
        inputSchema: {
            type: 'object',
            properties: {
                input: { type: 'string', description: `Input for ${name}` },
            },
            required: ['input'],
            additionalProperties: false,
        },
        outputFormat: 'text',
        errorCases: ['Invalid input', 'Operation failed'],
    }));
}
// === Main schema generator ===
export function generateMcpSchema(entityNames, knowledge, tools) {
    const resolvedTools = tools ?? buildDefaultMcpTools(entityNames);
    const lines = [
        '// Auto-generated MCP tool TypeScript interfaces',
        '// Generated by Planu — SPEC-016b',
        `// Server language: ${knowledge.language} | framework: ${knowledge.framework ?? 'MCP'}`,
        '',
        "import type { ErrorCode } from '@modelcontextprotocol/sdk/types.js';",
        '',
        '// === MCP Error helper ===',
        '',
        'export class McpError extends Error {',
        '  constructor(',
        '    public readonly code: ErrorCode,',
        '    message: string,',
        '  ) {',
        '    super(message);',
        "    this.name = 'McpError';",
        '  }',
        '}',
        '',
        '// === Tool Input/Output interfaces ===',
        '',
    ];
    for (const tool of resolvedTools) {
        lines.push(...buildToolInterface(tool));
    }
    lines.push('// === Tool registry union ===');
    lines.push('');
    const inputUnion = resolvedTools.map((t) => `${toPascalCase(t.name)}Input`).join(' | ');
    const outputUnion = resolvedTools.map((t) => `${toPascalCase(t.name)}Output`).join(' | ');
    lines.push(`export type AnyToolInput = ${inputUnion || 'Record<string, unknown>'};`);
    lines.push(`export type AnyToolOutput = ${outputUnion || 'Record<string, unknown>'};`);
    lines.push('');
    lines.push('// === Zod schema stubs (implement with full Zod validation) ===');
    lines.push('// import { z } from "zod";');
    for (const tool of resolvedTools) {
        const pascal = toPascalCase(tool.name);
        const props = tool.inputSchema.properties ?? {};
        const required = tool.inputSchema.required ?? [];
        const fields = Object.keys(props)
            .map((f) => `  ${f}: z.string()${required.includes(f) ? '' : '.optional()'},`)
            .join('\n');
        lines.push(`// export const ${tool.name}Schema = z.object({`);
        if (fields) {
            lines.push(`// ${fields}`);
        }
        lines.push('// });');
        lines.push(`// export type ${pascal}Input = z.infer<typeof ${tool.name}Schema>;`);
        lines.push('');
    }
    return lines.join('\n');
}
//# sourceMappingURL=mcp-schema.js.map