// SPEC-597-EXEMPT: canonical mapping (npm-package↔framework, keyword catalogue)
// — must enumerate framework names by design; no detection logic to migrate.
// tools/suggest-mcps.ts — Recommend relevant third-party MCPs
// Uses config/mcp-catalog.json + project knowledge
// SPEC-027: generates install instructions per MCP and supports catalog auto-extension
import { readFile } from 'node:fs/promises';
import { t, ti } from '../i18n/index.js';
import { knowledgeStore, specStore } from '../storage/index.js';
// === MCP Catalog ===
let catalogCache = null;
async function loadCatalog() {
    if (catalogCache) {
        return catalogCache;
    }
    try {
        const configPath = new URL('../config/mcp-catalog.json', import.meta.url);
        const content = await readFile(configPath, 'utf-8');
        const raw = JSON.parse(content);
        // Remove _description
        const mcps = raw.mcps;
        catalogCache = { mcps };
        return catalogCache;
    }
    catch {
        /* v8 ignore next -- catalog always bundled; unreachable in production */
        return { mcps: {} };
    }
}
/**
 * SPEC-027: Generate detailed installation instructions for an MCP server.
 * Produces Claude Code, Cursor, and Cline config snippets where applicable.
 */
export function generateInstallInstructions(mcpName, installCommand, source) {
    const lines = [
        `### Installing ${mcpName}`,
        '',
        `**Package source:** ${source}`,
        '',
        '**Quick install:**',
        '```bash',
        installCommand,
        '```',
        '',
    ];
    // Claude Code config snippet
    if (installCommand.includes('npx') || installCommand.includes('npm')) {
        const pkg = installCommand.split(/\s+/).find((p) => p.startsWith('@') || /^\w/.test(p));
        if (pkg) {
            lines.push('**Claude Code (claude_desktop_config.json):**', '```json', `{`, `  "mcpServers": {`, `    "${mcpName.toLowerCase().replace(/\s+/g, '-')}": {`, `      "command": "npx",`, `      "args": ["-y", "${pkg}"]`, `    }`, `  }`, `}`, '```', '');
        }
    }
    lines.push('> The MCP server will be available immediately after adding to your config.');
    return lines.join('\n');
}
/**
 * SPEC-027: Build an extended catalog entry from a web-discovered MCP.
 * Used when catalog auto-extension is triggered.
 */
export function buildCatalogExtensionEntry(key, name, description, installCommand, services) {
    return {
        name,
        description,
        type: 'community',
        source: 'community',
        services,
        installCommand,
        capabilities: [description],
        docsUrl: `https://npmjs.com/package/${key}`,
        autoDiscovered: true,
        discoveredAt: new Date().toISOString(),
    };
}
export async function handleSuggestMcps(args) {
    const { projectId, specId } = args;
    const knowledge = await knowledgeStore.getKnowledge(projectId);
    if (!knowledge) {
        return {
            content: [
                {
                    type: 'text',
                    text: ti('errors.projectNotFound', { projectId }),
                },
            ],
            isError: true,
        };
    }
    const catalog = await loadCatalog();
    // Get installed MCPs
    const installed = knowledge.availableMcps;
    const installedNames = installed.map((m) => m.name.toLowerCase());
    // Build project context for matching
    const stackLower = knowledge.stack.map((s) => s.toLowerCase());
    const dbEngine = knowledge.database.toLowerCase();
    const conventions = JSON.stringify(knowledge.conventions).toLowerCase();
    // Optionally get spec context
    let specContext = [];
    if (specId) {
        const spec = await specStore.getSpec(projectId, specId);
        if (spec) {
            specContext = [spec.target, spec.type, ...spec.tags];
        }
    }
    // Score and recommend MCPs from catalog
    const recommended = [];
    for (const [key, entry] of Object.entries(catalog.mcps)) {
        // Skip if already installed
        if (installedNames.some((n) => n.includes(key))) {
            continue;
        }
        // Score relevance
        let score = 0;
        const reasons = [];
        // Check if any services match the project stack or database
        for (const service of entry.services) {
            if (stackLower.includes(service) ||
                dbEngine.includes(service) ||
                conventions.includes(service)) {
                score += 3;
                reasons.push(`Project uses ${service}`);
            }
        }
        // Check type relevance
        const typeRelevance = {
            database: ['postgresql', 'supabase', 'mysql', 'sqlite', 'mongodb', 'firebase'],
            deployment: ['vercel', 'railway', 'docker', 'fly.io', 'netlify'],
            'project-management': ['linear', 'jira', 'github'],
            monitoring: ['sentry', 'datadog'],
            payments: ['stripe', 'paddle'],
            design: ['figma'],
            testing: ['playwright', 'puppeteer', 'cypress'],
            communication: ['slack'],
        };
        const typeMatches = typeRelevance[entry.type] ?? [];
        for (const match of typeMatches) {
            if (stackLower.includes(match) || dbEngine.includes(match)) {
                score += 2;
                reasons.push(`${entry.type} tools complement ${match}`);
            }
        }
        // Spec context boost
        for (const ctx of specContext) {
            if (entry.type.includes(ctx) || entry.services.some((s) => s.includes(ctx))) {
                score += 1;
                reasons.push(`Relevant to spec context: ${ctx}`);
            }
        }
        // General MCPs that benefit most projects
        if (key === 'github' && stackLower.some((s) => s.includes('git'))) {
            score += 2;
            reasons.push('GitHub integration benefits most projects');
        }
        if (key === 'puppeteer' && knowledge.apps.some((a) => a.type === 'frontend')) {
            score += 1;
            reasons.push('Browser automation for frontend testing');
        }
        if (score > 0) {
            const relevance = score >= 4 ? 'high' : score >= 2 ? 'medium' : 'low';
            recommended.push({
                name: entry.name,
                source: entry.source,
                relevance,
                reason: reasons.join('; '),
                installCommand: entry.installCommand,
                capabilities: entry.capabilities,
                docsUrl: entry.docsUrl,
            });
        }
    }
    // Sort by relevance
    const relevanceOrder = { high: 0, medium: 1, low: 2 };
    recommended.sort((a, b) => relevanceOrder[a.relevance] - relevanceOrder[b.relevance]);
    const result = {
        installed,
        recommended,
        message: recommended.length > 0
            ? `Found ${recommended.length} recommended MCP(s) for your project.`
            : 'No additional MCPs recommended. Your project is well covered.',
    };
    // Format output
    const lines = [
        `## ${t('tools.suggest_mcps.description')}`,
        '',
        `**${result.message}**`,
        '',
    ];
    if (installed.length > 0) {
        lines.push('### Installed MCPs');
        lines.push('');
        for (const mcp of installed) {
            lines.push(`- **${mcp.name}** (\`${mcp.command}\`)`);
        }
        lines.push('');
    }
    if (recommended.length > 0) {
        lines.push('### Recommended MCPs');
        lines.push('');
        lines.push('| MCP | Relevance | Install |');
        lines.push('|-----|-----------|---------|');
        for (const rec of recommended) {
            lines.push(`| **${rec.name}** | ${rec.relevance} | \`${rec.installCommand}\` |`);
        }
        lines.push('');
        for (const rec of recommended) {
            lines.push(`#### ${rec.name} (${rec.relevance} relevance)`);
            lines.push('');
            lines.push(`**Reason:** ${rec.reason}`);
            lines.push('');
            lines.push(`**Capabilities:** ${rec.capabilities.join(', ')}`);
            lines.push('');
            lines.push(`**Docs:** [${rec.docsUrl}](${rec.docsUrl})`);
            lines.push('');
            // SPEC-027: include detailed installation instructions
            lines.push(generateInstallInstructions(rec.name, rec.installCommand, rec.source));
            lines.push('');
        }
    }
    return {
        content: [{ type: 'text', text: lines.join('\n') }],
    };
}
//# sourceMappingURL=suggest-mcps.js.map