#!/usr/bin/env node
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
import * as fs from "fs";
import * as path from "path";
import { fileURLToPath } from "url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// --- Load data ---
function loadJsonFile(relativePath) {
    const filePath = path.resolve(__dirname, relativePath);
    if (!fs.existsSync(filePath)) {
        throw new Error(`Data file not found: ${filePath}. Run the doc generator first.`);
    }
    return JSON.parse(fs.readFileSync(filePath, "utf-8"));
}
// Try multiple paths for storefront data (generated output or local data dir)
function loadStorefrontData() {
    const paths = [
        "../../storefront-docs/docs/storefront-api.json",
        "../data/storefront-api.json",
    ];
    for (const p of paths) {
        const filePath = path.resolve(__dirname, p);
        if (fs.existsSync(filePath)) {
            return JSON.parse(fs.readFileSync(filePath, "utf-8"));
        }
    }
    throw new Error(`Storefront API data not found. Looked in:\n${paths.map((p) => "  - " + path.resolve(__dirname, p)).join("\n")}\nRun 'npm run docs:generate' in the storefront-docs package first.`);
}
// Load storefront types (graceful degradation — returns null if not found)
function loadStorefrontTypes() {
    const paths = [
        "../../storefront-docs/docs/storefront-types.json",
        "../data/storefront-types.json",
    ];
    for (const p of paths) {
        const filePath = path.resolve(__dirname, p);
        if (fs.existsSync(filePath)) {
            return JSON.parse(fs.readFileSync(filePath, "utf-8"));
        }
    }
    return null;
}
const storefrontData = loadStorefrontData();
const frameworkData = loadJsonFile("../data/framework.json");
const typesData = loadStorefrontTypes();
function loadSectionTemplates() {
    try {
        return loadJsonFile("../data/section-templates.json");
    }
    catch {
        return null;
    }
}
const sectionTemplatesData = loadSectionTemplates();
// --- Search helpers ---
function matchScore(text, query) {
    const lower = text.toLowerCase();
    const queryLower = query.toLowerCase();
    const words = queryLower.split(/\s+/).filter(Boolean);
    let score = 0;
    // Exact substring match
    if (lower.includes(queryLower)) {
        score += 10;
    }
    // Word matches
    for (const word of words) {
        if (lower.includes(word)) {
            score += 3;
        }
    }
    // Name exact match bonus
    if (lower === queryLower) {
        score += 20;
    }
    return score;
}
function searchFunctions(query) {
    const scored = storefrontData.functions
        .map((fn) => {
        const nameScore = matchScore(fn.name, query) * 3;
        const descScore = matchScore(fn.description, query);
        const catScore = fn.categories.some((c) => matchScore(c, query) > 0) ? 5 : 0;
        const paramScore = fn.params.some((p) => matchScore(p.name, query) > 0 || matchScore(p.description, query) > 0)
            ? 2
            : 0;
        const sigScore = matchScore(fn.signature, query) * 2;
        const typeScore = fn.parameterTypes?.some((t) => matchScore(t, query) > 0) ? 8 : 0;
        return { fn, score: nameScore + descScore + catScore + paramScore + sigScore + typeScore };
    })
        .filter((item) => item.score > 0)
        .sort((a, b) => b.score - a.score);
    return scored.map((item) => item.fn);
}
function searchFrameworkTopics(query) {
    return Object.entries(frameworkData.topics)
        .map(([key, topic]) => {
        const titleScore = matchScore(topic.title, query) * 3;
        const descScore = matchScore(topic.description, query) * 2;
        const contentScore = matchScore(topic.content, query);
        const tagScore = topic.tags.some((t) => matchScore(t, query) > 0) ? 5 : 0;
        return { key, topic, score: titleScore + descScore + contentScore + tagScore };
    })
        .filter((item) => item.score > 0)
        .sort((a, b) => b.score - a.score);
}
function searchTypes(query) {
    if (!typesData)
        return [];
    const scored = typesData.types
        .map((td) => {
        const nameScore = matchScore(td.name, query) * 3;
        const domainScore = matchScore(td.domain, query) * 2;
        const propScore = td.properties?.some((p) => matchScore(p.name, query) > 0 || matchScore(p.type, query) > 0)
            ? 4
            : 0;
        const enumScore = td.enumValues?.some((v) => matchScore(v, query) > 0) ? 4 : 0;
        return { td, score: nameScore + domainScore + propScore + enumScore };
    })
        .filter((item) => item.score > 0)
        .sort((a, b) => b.score - a.score);
    return scored.map((item) => item.td);
}
// --- Format helpers ---
function formatFunctionDoc(fn) {
    const lines = [];
    lines.push(`## ${fn.name}`);
    if (fn.displayName && fn.displayName !== fn.name) {
        lines.push(`*Also known as: ${fn.displayName}*`);
    }
    if (fn.description) {
        lines.push("", fn.description);
    }
    lines.push("", "```typescript", fn.signature, "```");
    // Add import statement
    const importName = fn.isClass && fn.className ? fn.className : fn.name;
    lines.push("", `**Import:** \`import { ${importName} } from "@ikas/bp-storefront";\``);
    if (fn.params.length > 0) {
        lines.push("", "**Parameters:**");
        for (const p of fn.params) {
            const typeInfo = p.type ? ` (${p.type})` : "";
            lines.push(`- \`${p.name}\`${typeInfo} - ${p.description || "No description"}`);
        }
    }
    if (fn.returns || fn.returnType) {
        lines.push("", `**Returns:** \`${fn.returnType}\`${fn.returns ? ` - ${fn.returns}` : ""}`);
    }
    if (fn.example) {
        lines.push("", "**Example:**", "```typescript", fn.example, "```");
    }
    if (fn.related.length > 0) {
        lines.push("", `**Related:** ${fn.related.map((r) => `\`${r}\``).join(", ")}`);
    }
    if (fn.categories.length > 0) {
        lines.push("", `**Categories:** ${fn.categories.join(", ")}`);
    }
    return lines.join("\n");
}
function formatFunctionSummary(fn) {
    const desc = fn.description ? fn.description.split(".")[0] + "." : "No description.";
    const alias = fn.displayName && fn.displayName !== fn.name ? ` (alias: ${fn.displayName})` : "";
    return `- \`${fn.name}\`${alias} - ${desc}`;
}
function formatTypeDefinition(td) {
    const lines = [];
    lines.push(`## ${td.name}`);
    lines.push("", `**Kind:** ${td.kind} | **Domain:** ${td.domain}`);
    if (td.kind === "type") {
        lines.push("", "```typescript");
        const extendsStr = td.extends ? ` & ${td.extends.join(" & ")}` : "";
        lines.push(`type ${td.name} = {`);
        if (td.properties) {
            for (const p of td.properties) {
                const opt = p.optional ? "?" : "";
                lines.push(`  ${p.name}${opt}: ${p.type};`);
            }
        }
        lines.push(`}${extendsStr};`);
        lines.push("```");
    }
    else if (td.kind === "enum") {
        lines.push("", "```typescript");
        lines.push(`enum ${td.name} {`);
        if (td.enumValues) {
            for (const v of td.enumValues) {
                lines.push(`  ${v} = "${v}",`);
            }
        }
        lines.push("}");
        lines.push("```");
    }
    // Show related functions if available
    if (td.relatedFunctions && td.relatedFunctions.length > 0) {
        lines.push("", "### Related Functions", "");
        for (const fnName of td.relatedFunctions) {
            const fn = storefrontData.functions.find((f) => f.name === fnName);
            if (fn) {
                const desc = fn.description ? fn.description.split(".")[0] + "." : "";
                const alias = fn.displayName && fn.displayName !== fn.name ? ` (alias: ${fn.displayName})` : "";
                lines.push(`- **\`${fn.name}\`**${alias} — ${desc}`);
                lines.push(`  \`${fn.signature}\``);
            }
            else {
                lines.push(`- \`${fnName}\``);
            }
        }
        lines.push("");
        lines.push("Use `get_functions_for_type(\"" + td.name + "\")` for full documentation of these functions.");
    }
    return lines.join("\n");
}
function formatTypeSummary(td) {
    if (td.kind === "enum") {
        const count = td.enumValues?.length ?? 0;
        return `- \`${td.name}\` (enum, ${count} values) — domain: ${td.domain}`;
    }
    const count = td.properties?.length ?? 0;
    const ext = td.extends ? ` extends ${td.extends.join(", ")}` : "";
    return `- \`${td.name}\` (${count} properties${ext}) — domain: ${td.domain}`;
}
// --- MCP Server ---
const server = new McpServer({
    name: "ikas-code-components",
    version: "0.1.0",
}, {
    instructions: "You are an AI assistant helping developers build ikas storefront components. CRITICAL RULE: All code examples and section templates provided by this server are API REFERENCE ONLY. You MUST create completely original JSX layouts, CSS class names, and visual designs. Never copy the HTML structure, styling, or class names from examples — only reuse the API patterns (imports, function calls, data access, type handling, form flows, null safety).",
});
// Tool: search_docs
server.tool("search_docs", "Search across all ikas storefront API docs and framework guides. Returns matching functions and framework topics ranked by relevance.", { query: z.string().describe("Search keyword or phrase") }, async ({ query }) => {
    const functions = searchFunctions(query).slice(0, 10);
    const topics = searchFrameworkTopics(query).slice(0, 5);
    const types = searchTypes(query).slice(0, 5);
    const parts = [];
    if (functions.length > 0) {
        parts.push("## Matching Storefront Functions\n");
        for (const fn of functions) {
            parts.push(formatFunctionSummary(fn));
        }
        parts.push("");
        parts.push("Use `get_function_doc(name)` to get full details for any function.");
    }
    if (topics.length > 0) {
        parts.push("\n## Matching Framework Topics\n");
        for (const item of topics) {
            parts.push(`- **${item.topic.title}** (key: \`${item.key}\`) - ${item.topic.description}`);
        }
        parts.push("");
        parts.push("Use `get_framework_guide(topic)` to get full content for any topic.");
    }
    if (types.length > 0) {
        parts.push("\n## Matching Types\n");
        for (const td of types) {
            parts.push(formatTypeSummary(td));
        }
        parts.push("");
        parts.push("Use `get_type_definition(name)` to get full type details, or `search_types(query)` for more type results.");
    }
    if (functions.length === 0 && topics.length === 0 && types.length === 0) {
        parts.push(`No results found for "${query}". Try different keywords or use \`list_functions()\` to see all available functions.`);
    }
    return { content: [{ type: "text", text: parts.join("\n") }] };
});
// Tool: get_function_doc
server.tool("get_function_doc", "Get full documentation for a specific storefront API function including signature, parameters, return type, and example.", { name: z.string().describe("Function name (e.g. 'addItemToCart', 'Router.navigate')") }, async ({ name }) => {
    const nameLower = name.toLowerCase();
    const fn = storefrontData.functions.find((f) => f.name.toLowerCase() === nameLower ||
        (f.displayName && f.displayName.toLowerCase() === nameLower));
    if (!fn) {
        // Try fuzzy match
        const matches = storefrontData.functions.filter((f) => f.name.toLowerCase().includes(nameLower) ||
            (f.displayName && f.displayName.toLowerCase().includes(nameLower)));
        if (matches.length > 0) {
            const suggestions = matches.slice(0, 5).map((f) => {
                const alias = f.displayName && f.displayName !== f.name ? ` (alias: ${f.displayName})` : "";
                return `  - ${f.name}${alias}`;
            });
            return {
                content: [
                    {
                        type: "text",
                        text: `Function "${name}" not found. Did you mean:\n${suggestions.join("\n")}`,
                    },
                ],
            };
        }
        return {
            content: [{ type: "text", text: `Function "${name}" not found. Use \`list_functions()\` to see all available functions.` }],
        };
    }
    return { content: [{ type: "text", text: formatFunctionDoc(fn) }] };
});
// Tool: list_functions
server.tool("list_functions", "List all available storefront API functions, optionally filtered by category. Call without arguments to see all categories. Common categories include: ProductDetail, Cart, ProductList, Navigation, Customer, Order, Image, Blog, Brand, Category, Pricing, Form, Validation, Pagination, Filtering, and more.", { category: z.string().optional().describe("Optional category filter (e.g. 'ProductDetail', 'Cart', 'Image', 'Order', 'Blog', 'Brand')") }, async ({ category }) => {
    let functions = storefrontData.functions;
    if (category) {
        const catLower = category.toLowerCase();
        functions = functions.filter((f) => f.categories.some((c) => c.toLowerCase() === catLower));
        if (functions.length === 0) {
            const availableCategories = [...new Set(storefrontData.functions.flatMap((f) => f.categories))];
            return {
                content: [
                    {
                        type: "text",
                        text: `No functions found in category "${category}". Available categories: ${availableCategories.join(", ")}`,
                    },
                ],
            };
        }
    }
    const parts = [];
    if (category) {
        parts.push(`## ${category} Functions\n`);
    }
    else {
        parts.push(`## All Storefront Functions (${functions.length} total)\n`);
    }
    // Group by category if no filter
    if (!category) {
        const byCategory = new Map();
        const uncategorized = [];
        for (const fn of functions) {
            if (fn.categories.length === 0) {
                uncategorized.push(fn);
            }
            else {
                for (const cat of fn.categories) {
                    const list = byCategory.get(cat) || [];
                    list.push(fn);
                    byCategory.set(cat, list);
                }
            }
        }
        for (const [cat, fns] of byCategory) {
            parts.push(`### ${cat}\n`);
            for (const fn of fns) {
                parts.push(formatFunctionSummary(fn));
            }
            parts.push("");
        }
        if (uncategorized.length > 0) {
            parts.push("### Other\n");
            for (const fn of uncategorized) {
                parts.push(formatFunctionSummary(fn));
            }
        }
    }
    else {
        for (const fn of functions) {
            parts.push(formatFunctionSummary(fn));
        }
    }
    return { content: [{ type: "text", text: parts.join("\n") }] };
});
// Tool: get_code_example
server.tool("get_code_example", "Get an API usage reference for a specific task. The code shows correct function calls, imports, and data handling patterns from a real production theme. IMPORTANT: The JSX layout and CSS are illustrative only — create your own original visual design, HTML structure, and styling. Section examples include child components, sub-components, hooks, and utilities. Available examples: header-section, hero-slider-section, category-images-section, footer-section, login-section, register-section, forgot-password-section, recover-password-section, product-slider-section, account-info-section, category-list-section, product-detail-section, features-section, cart-section, blog-post-section, blog-home-section, email-verification-section, rich-text-section, product-reviews-section, not-found-section, add-to-cart, variant-selection, product-pricing, image-handling, navigation, component-renderer, favorites, bundle-products.", { task: z.string().describe("Task description or example ID (e.g. 'add to cart', 'product-detail-section', 'header-section', 'cart-section', 'login-section', 'variant-selection', 'navigation', 'component-renderer', 'bundle-products')") }, async ({ task }) => {
    const taskLower = task.toLowerCase();
    // Try exact ID match first
    let example = storefrontData.codeExamples.find((e) => e.id === taskLower);
    // Try keyword match
    if (!example) {
        const scored = storefrontData.codeExamples
            .map((e) => {
            const idScore = matchScore(e.id, task) * 3;
            const titleScore = matchScore(e.title, task) * 2;
            const descScore = matchScore(e.description, task);
            return { example: e, score: idScore + titleScore + descScore };
        })
            .filter((item) => item.score > 0)
            .sort((a, b) => b.score - a.score);
        if (scored.length > 0) {
            example = scored[0].example;
        }
    }
    if (!example) {
        const available = storefrontData.codeExamples.map((e) => `  - \`${e.id}\` - ${e.title}`).join("\n");
        return {
            content: [
                {
                    type: "text",
                    text: `No example found matching "${task}". Available examples:\n${available}`,
                },
            ],
        };
    }
    const parts = [
        `## ${example.title}`,
        "",
        example.description,
        "",
        "> **API REFERENCE ONLY — DO NOT COPY THIS LAYOUT OR STYLING.**",
        "> Study the API patterns (function calls, imports, data access, error handling) then create your OWN unique component with original JSX structure, CSS class names, and visual design.",
        "",
    ];
    // Multi-file examples: show each file in its own code block
    if (example.files && example.files.length > 0) {
        for (const file of example.files) {
            const ext = file.filename.split(".").pop() || "text";
            const lang = ext === "tsx" || ext === "ts" ? "typescript" : ext === "css" ? "css" : ext === "json" ? "json" : "text";
            // Add inline originality comments to CSS and TSX files
            let content = file.content;
            if (ext === "css") {
                content = "/* EXAMPLE STYLING — create your own original CSS with different class names and design */\n" + content;
            }
            else if (ext === "tsx") {
                content = "// EXAMPLE COMPONENT — use the API patterns but create your own JSX structure and layout\n" + content;
            }
            parts.push(`### ${file.filename}`, "", `\`\`\`${lang}`, content, "```", "");
        }
    }
    else {
        parts.push("```typescript", example.code, "```", "");
    }
    parts.push(`**Reminder:** Use the API patterns above (function calls, imports, type handling) but create your own original HTML structure and CSS.`);
    parts.push("");
    parts.push(`**Related functions:** ${example.relatedFunctions.map((f) => `\`${f}\``).join(", ")}`);
    return { content: [{ type: "text", text: parts.join("\n") }] };
});
// Tool: get_framework_guide
server.tool("get_framework_guide", "Get a framework guide on a specific topic. Topics: project-structure, ikas-config, prop-types, component-structure, build-system, css-scoping, global-css, dev-server, imports, sections-vs-components, common-pitfalls, sub-component-patterns, ai-workflow, form-handling, async-data-patterns, product-detail-patterns, product-list-patterns, cart-patterns, account-patterns, header-footer-patterns, review-patterns, slider-overlay-patterns, blog-patterns, navigation-patterns, real-world-architecture, component-renderer-patterns (IkasComponentRenderer slots, filteredComponentIds, parentProps), private-var-map (how sections pass data to children via privateVarMap), page-composition (which sections compose each page type), sub-component-catalog (35+ reusable sub-components: Button, Input, Modal, Toast, ProductCard, etc.), config-advanced-features (filteredComponentIds, privateVarMap, isHeader/isFooter, propGroups, custom enums).", { topic: z.string().describe("Topic key or keyword (e.g. 'ai-workflow', 'common-pitfalls', 'prop-types', 'css-scoping', 'global-css', 'form-handling', 'async-data-patterns', 'imports')") }, async ({ topic }) => {
    const topicLower = topic.toLowerCase().replace(/\s+/g, "-");
    // Alias mapping for common alternative topic names
    const topicAliases = {
        "form-handling": "form-patterns",
        "forms": "form-patterns",
        "data-fetching": "async-data-patterns",
        "async": "async-data-patterns",
        "loading": "async-data-patterns",
        "sub-components": "sub-component-patterns",
        "subcomponents": "sub-component-patterns",
        "routing": "navigation-patterns",
        "router": "navigation-patterns",
        "observer": "component-structure",
        "reactivity": "component-structure",
        "pitfalls": "common-pitfalls",
        "gotchas": "common-pitfalls",
        "mistakes": "common-pitfalls",
        "header": "header-footer-patterns",
        "footer": "header-footer-patterns",
        "blog": "blog-patterns",
        "cart": "cart-patterns",
        "account": "account-patterns",
        "product-detail": "product-detail-patterns",
        "product-list": "product-list-patterns",
        "filtering": "product-list-patterns",
        "reviews": "review-patterns",
        "slider": "slider-overlay-patterns",
        "overlay": "slider-overlay-patterns",
        "modal": "slider-overlay-patterns",
        "architecture": "real-world-architecture",
        "theme": "real-world-architecture",
        "global-styles": "global-css",
        "global": "global-css",
        "css-variables": "global-css",
        "custom-properties": "global-css",
    };
    const resolvedTopic = topicAliases[topicLower] || topicLower;
    // Topics that involve MobX store reads get a reminder about root reactivity
    const storeTopics = new Set([
        "product-detail-patterns", "product-list-patterns", "cart-patterns",
        "account-patterns", "header-footer-patterns", "review-patterns",
        "blog-patterns", "form-handling", "async-data-patterns",
        "component-structure", "imports",
    ]);
    const observerReminder = "> **IMPORTANT: Do NOT use `observer()` on root component exports.** The ikas runtime wraps root renders in MobX `autorun()`, making them automatically reactive. All store reads (`cartStore`, `customerStore`, etc.) in root components are tracked automatically. Only use `observer()` on extracted sub-components.\n\n";
    // Try exact key match (with alias resolution)
    if (frameworkData.topics[resolvedTopic]) {
        const t = frameworkData.topics[resolvedTopic];
        const prefix = storeTopics.has(resolvedTopic) ? observerReminder : "";
        return { content: [{ type: "text", text: `## ${t.title}\n\n${prefix}${t.content}` }] };
    }
    // Try original topic key (without alias) in case it's a direct key
    if (resolvedTopic !== topicLower && frameworkData.topics[topicLower]) {
        const t = frameworkData.topics[topicLower];
        const prefix = storeTopics.has(topicLower) ? observerReminder : "";
        return { content: [{ type: "text", text: `## ${t.title}\n\n${prefix}${t.content}` }] };
    }
    // Try keyword search
    const matches = searchFrameworkTopics(topic);
    if (matches.length > 0) {
        const best = matches[0];
        const prefix = storeTopics.has(best.key) ? observerReminder : "";
        return {
            content: [{ type: "text", text: `## ${best.topic.title}\n\n${prefix}${best.topic.content}` }],
        };
    }
    const available = Object.entries(frameworkData.topics)
        .map(([key, t]) => `  - \`${key}\` - ${t.title}`)
        .join("\n");
    return {
        content: [
            {
                type: "text",
                text: `Topic "${topic}" not found. Available topics:\n${available}`,
            },
        ],
    };
});
// Tool: get_type_definition
server.tool("get_type_definition", "Get the full definition of a storefront type or enum by name (e.g. 'IkasProduct', 'IkasOrderStatus'). Shows all properties with types, extends, or enum values.", { name: z.string().describe("Type or enum name (e.g. 'IkasProduct', 'IkasOrderStatus')") }, async ({ name }) => {
    if (!typesData) {
        return {
            content: [{ type: "text", text: "Type data not available. Run 'npm run docs:generate' in storefront-docs first." }],
        };
    }
    const nameLower = name.toLowerCase();
    const td = typesData.types.find((t) => t.name.toLowerCase() === nameLower);
    if (td) {
        return { content: [{ type: "text", text: formatTypeDefinition(td) }] };
    }
    // Fuzzy match
    const matches = typesData.types.filter((t) => t.name.toLowerCase().includes(nameLower));
    if (matches.length > 0) {
        const suggestions = matches.slice(0, 10).map((t) => formatTypeSummary(t));
        return {
            content: [
                {
                    type: "text",
                    text: `Type "${name}" not found. Did you mean:\n${suggestions.join("\n")}`,
                },
            ],
        };
    }
    return {
        content: [{ type: "text", text: `Type "${name}" not found. Use \`list_types()\` to see all available types.` }],
    };
});
// Tool: get_functions_for_type
server.tool("get_functions_for_type", "Get full documentation for all utility functions that operate on a given storefront type. For example, get_functions_for_type('IkasImage') returns getSrc, getDefaultSrc, getThumbnailSrc, createMediaSrcset with full signatures, descriptions, and examples.", { typeName: z.string().describe("Type name (e.g. 'IkasImage', 'IkasProduct', 'IkasOrder')") }, async ({ typeName }) => {
    if (!typesData) {
        return {
            content: [{ type: "text", text: "Type data not available. Run 'npm run docs:generate' in storefront-docs first." }],
        };
    }
    const nameLower = typeName.toLowerCase();
    const td = typesData.types.find((t) => t.name.toLowerCase() === nameLower);
    if (!td) {
        // Fuzzy match suggestions
        const matches = typesData.types.filter((t) => t.name.toLowerCase().includes(nameLower));
        if (matches.length > 0) {
            const suggestions = matches.slice(0, 10).map((t) => `  - ${t.name}`);
            return {
                content: [
                    {
                        type: "text",
                        text: `Type "${typeName}" not found. Did you mean:\n${suggestions.join("\n")}`,
                    },
                ],
            };
        }
        return {
            content: [{ type: "text", text: `Type "${typeName}" not found. Use \`list_types()\` to see all available types.` }],
        };
    }
    if (!td.relatedFunctions || td.relatedFunctions.length === 0) {
        return {
            content: [
                {
                    type: "text",
                    text: `No utility functions found for type "${td.name}". This type may be used as a data structure without dedicated helper functions.`,
                },
            ],
        };
    }
    const parts = [`# Functions for ${td.name}\n`];
    parts.push(`${td.relatedFunctions.length} utility function(s) operate on this type.\n`);
    for (const fnName of td.relatedFunctions) {
        const fn = storefrontData.functions.find((f) => f.name === fnName);
        if (fn) {
            parts.push(formatFunctionDoc(fn));
            parts.push("");
        }
        else {
            parts.push(`## ${fnName}\n\nDocumentation not available.\n`);
        }
    }
    parts.push("---");
    parts.push(`\n**Import:** \`import { ${td.relatedFunctions.join(", ")} } from "@ikas/bp-storefront";\``);
    return { content: [{ type: "text", text: parts.join("\n") }] };
});
// Tool: get_model_guide
server.tool("get_model_guide", "Get a comprehensive guide for working with a storefront model type. Returns the type definition, all utility functions, matching code examples, related types, and import patterns. This is the one-stop-shop tool when you need to work with a model.", {
    model: z.string().optional().describe("Model type name (e.g. 'IkasImage', 'IkasProduct', 'IkasOrder')"),
    name: z.string().optional().describe("Alias for 'model' — model type name (e.g. 'IkasImage', 'IkasProduct', 'IkasOrder')"),
}, async ({ model: modelParam, name: nameParam }) => {
    const model = modelParam || nameParam;
    if (!model) {
        return {
            content: [{ type: "text", text: "Please provide a model name (e.g. 'IkasProduct', 'IkasOrder'). Use the 'model' or 'name' parameter." }],
        };
    }
    if (!typesData) {
        return {
            content: [{ type: "text", text: "Type data not available. Run 'npm run docs:generate' in storefront-docs first." }],
        };
    }
    const modelLower = model.toLowerCase();
    const td = typesData.types.find((t) => t.name.toLowerCase() === modelLower);
    if (!td) {
        // Fuzzy match suggestions
        const matches = typesData.types
            .filter((t) => t.name.toLowerCase().includes(modelLower))
            .slice(0, 10);
        if (matches.length > 0) {
            const suggestions = matches.map((t) => `  - ${t.name}`);
            return {
                content: [
                    {
                        type: "text",
                        text: `Model "${model}" not found. Did you mean:\n${suggestions.join("\n")}`,
                    },
                ],
            };
        }
        return {
            content: [{ type: "text", text: `Model "${model}" not found. Use \`list_types()\` to see all available types.` }],
        };
    }
    const parts = [`# Model Guide: ${td.name}\n`];
    // Section 1: Type definition
    parts.push("## 1. Type Definition\n");
    parts.push(formatTypeDefinition(td));
    parts.push("");
    // Section 2: Utility functions
    const relatedFns = td.relatedFunctions || [];
    if (relatedFns.length > 0) {
        parts.push("## 2. Utility Functions\n");
        for (const fnName of relatedFns) {
            const fn = storefrontData.functions.find((f) => f.name === fnName);
            if (fn) {
                parts.push(formatFunctionDoc(fn));
                parts.push("");
            }
        }
    }
    else {
        parts.push("## 2. Utility Functions\n");
        parts.push("No dedicated utility functions found for this type.\n");
    }
    // Section 3: Code examples
    const matchingExamples = storefrontData.codeExamples.filter((ex) => ex.relatedFunctions.some((f) => relatedFns.includes(f)) ||
        ex.code.includes(td.name));
    if (matchingExamples.length > 0) {
        parts.push("## 3. Code Examples\n");
        for (const ex of matchingExamples) {
            parts.push(`### ${ex.title}\n`);
            parts.push(ex.description);
            parts.push("\n```typescript");
            parts.push(ex.code);
            parts.push("```\n");
        }
    }
    // Section 4: Related types (types referenced in properties)
    const relatedTypeNames = new Set();
    if (td.properties) {
        for (const p of td.properties) {
            const matches = p.type.match(/Ikas\w+/g);
            if (matches) {
                for (const m of matches) {
                    if (m !== td.name)
                        relatedTypeNames.add(m);
                }
            }
        }
    }
    if (td.extends) {
        for (const ext of td.extends) {
            const matches = ext.match(/Ikas\w+/g);
            if (matches) {
                for (const m of matches) {
                    if (m !== td.name)
                        relatedTypeNames.add(m);
                }
            }
        }
    }
    if (relatedTypeNames.size > 0) {
        parts.push("## 4. Related Types\n");
        for (const name of relatedTypeNames) {
            const relTd = typesData.types.find((t) => t.name === name);
            if (relTd) {
                parts.push(formatTypeSummary(relTd));
            }
            else {
                parts.push(`- \`${name}\``);
            }
        }
        parts.push("");
    }
    // Section 5: Import patterns
    parts.push("## 5. Import Patterns\n");
    parts.push("```typescript");
    parts.push(`import { ${td.name} } from "@ikas/bp-storefront";`);
    if (relatedFns.length > 0) {
        parts.push(`import { ${relatedFns.join(", ")} } from "@ikas/bp-storefront";`);
    }
    parts.push("```");
    return { content: [{ type: "text", text: parts.join("\n") }] };
});
// Tool: search_types
server.tool("search_types", "Search storefront types and enums by keyword (e.g. 'price', 'address', 'status'). Returns top matches ranked by relevance.", { query: z.string().describe("Search keyword or phrase") }, async ({ query }) => {
    if (!typesData) {
        return {
            content: [{ type: "text", text: "Type data not available. Run 'npm run docs:generate' in storefront-docs first." }],
        };
    }
    const results = searchTypes(query).slice(0, 15);
    if (results.length === 0) {
        return {
            content: [{ type: "text", text: `No types found matching "${query}". Use \`list_types()\` to see all available types.` }],
        };
    }
    const parts = [`## Type Search Results for "${query}"\n`];
    for (const td of results) {
        parts.push(formatTypeSummary(td));
    }
    parts.push("");
    parts.push("Use `get_type_definition(name)` to get full details for any type.");
    return { content: [{ type: "text", text: parts.join("\n") }] };
});
// Tool: list_types
server.tool("list_types", "List all storefront types and enums, optionally filtered by domain (product, cart, order, customer...) or kind (type, enum).", {
    domain: z.string().optional().describe("Optional domain filter (e.g. 'product', 'cart', 'order', 'customer')"),
    kind: z.enum(["type", "enum"]).optional().describe("Optional kind filter: 'type' or 'enum'"),
}, async ({ domain, kind }) => {
    if (!typesData) {
        return {
            content: [{ type: "text", text: "Type data not available. Run 'npm run docs:generate' in storefront-docs first." }],
        };
    }
    let types = typesData.types;
    if (domain) {
        const domainLower = domain.toLowerCase();
        types = types.filter((t) => t.domain.toLowerCase() === domainLower);
    }
    if (kind) {
        types = types.filter((t) => t.kind === kind);
    }
    if (types.length === 0) {
        const availableDomains = [...new Set(typesData.types.map((t) => t.domain))].sort();
        return {
            content: [
                {
                    type: "text",
                    text: `No types found${domain ? ` in domain "${domain}"` : ""}${kind ? ` of kind "${kind}"` : ""}. Available domains: ${availableDomains.join(", ")}`,
                },
            ],
        };
    }
    const parts = [];
    const filterDesc = [domain && `domain: ${domain}`, kind && `kind: ${kind}`].filter(Boolean).join(", ");
    parts.push(`## Storefront Types (${types.length} total${filterDesc ? ` — ${filterDesc}` : ""})\n`);
    if (!domain) {
        // Group by domain
        const byDomain = new Map();
        for (const td of types) {
            const list = byDomain.get(td.domain) || [];
            list.push(td);
            byDomain.set(td.domain, list);
        }
        for (const [d, tds] of [...byDomain.entries()].sort((a, b) => a[0].localeCompare(b[0]))) {
            parts.push(`### ${d}\n`);
            for (const td of tds) {
                parts.push(formatTypeSummary(td));
            }
            parts.push("");
        }
    }
    else {
        for (const td of types) {
            parts.push(formatTypeSummary(td));
        }
    }
    parts.push("\nUse `get_type_definition(name)` to get full details for any type.");
    return { content: [{ type: "text", text: parts.join("\n") }] };
});
// Tool: get_prop_types
server.tool("get_prop_types", "Get all available ikas.config.json prop types with descriptions, TypeScript types, and examples. Tip: Use `npx ikas-component config add-component --props '[...]'` to create a component with all props in one command, or `add-prop` to add props incrementally. NEVER manually edit types.ts — it is auto-generated by the CLI.", {}, async () => {
    const propTypesTopic = frameworkData.topics["prop-types"];
    if (propTypesTopic) {
        return {
            content: [{ type: "text", text: `## ${propTypesTopic.title}\n\n${propTypesTopic.content}` }],
        };
    }
    return {
        content: [{ type: "text", text: "Prop types documentation not available." }],
    };
});
// Tool: get_section_template
// Build the enum dynamically from the loaded section templates data
const sectionTemplateKeys = sectionTemplatesData
    ? Object.keys(sectionTemplatesData.templates)
    : null;
server.tool("get_section_template", `Get a starter template showing the correct API integration pattern for a common section type. IMPORTANT: Use the function calls and data access patterns, but create your own original JSX structure, CSS class names, and visual design — do not copy the template's layout or styling. Returns index.tsx, types.ts, styles.css, ikas-config snippet, AND a ready-to-run CLI command with \`--props\` flag.${sectionTemplateKeys ? ` Available section types: ${sectionTemplateKeys.join(", ")}.` : ""} Workflow: 1) Call this tool, 2) Run the CLI command (creates component + props + types.ts), 3) Write your OWN index.tsx and styles.css using the API patterns from the template. NEVER manually create or edit types.ts.`, {
    sectionType: (sectionTemplateKeys
        ? z.enum(sectionTemplateKeys)
        : z.string()).describe("The section type to generate a template for"),
}, async ({ sectionType }) => {
    if (!sectionTemplatesData) {
        return {
            content: [
                {
                    type: "text",
                    text: "Section templates data not available. Ensure section-templates.json is in the data directory.",
                },
            ],
        };
    }
    const template = sectionTemplatesData.templates[sectionType];
    if (!template) {
        const available = Object.keys(sectionTemplatesData.templates).join(", ");
        return {
            content: [
                {
                    type: "text",
                    text: `Section template "${sectionType}" not found. Available: ${available}`,
                },
            ],
        };
    }
    const parts = [
        `## ${template.title} — API Integration Pattern Reference`,
        "",
        "> **CRITICAL: Do NOT import or use `observer()` on the root component export.** The ikas runtime wraps root renders in MobX `autorun()`, so root components are automatically reactive. Use `export default function ComponentName(...)` — a plain named function export. Only use `observer()` on extracted sub-components that independently read MobX stores.",
        "",
        "> **DESIGN ORIGINALITY REQUIRED:** This template shows the correct API integration pattern.",
        "> You MUST create your own original:",
        "> - JSX structure — different HTML hierarchy and layout",
        "> - CSS class names — your own naming convention",
        "> - Visual design — unique spacing, typography, colors, responsive breakpoints",
        "> - UX patterns — your own loading states, empty states, transitions",
        ">",
        "> KEEP from the template: imports, function calls, data access patterns, form handling flow, type casts, null safety.",
        "> REPLACE entirely: all HTML/JSX structure, all CSS rules, all class names, all visual design.",
        "",
        template.description,
        "",
    ];
    for (const [filename, content] of Object.entries(template.files)) {
        const ext = filename.split(".").pop() || "text";
        const lang = ext === "tsx" || ext === "ts"
            ? "typescript"
            : ext === "css"
                ? "css"
                : ext === "json"
                    ? "json"
                    : "text";
        // Add inline originality comments to CSS and TSX files
        let fileContent = content;
        if (ext === "css") {
            fileContent = "/* EXAMPLE STYLING — create your own original CSS with different class names and design */\n" + content;
        }
        else if (ext === "tsx") {
            fileContent = "// EXAMPLE COMPONENT — use the API patterns but create your own JSX structure and layout\n" + content;
        }
        parts.push(`### ${filename}`, "", `\`\`\`${lang}`, fileContent, "```", "");
    }
    // Generate a ready-to-run CLI command from the config snippet
    const configSnippetStr = template.files["ikas-config-snippet.json"];
    if (configSnippetStr) {
        try {
            const configSnippet = JSON.parse(configSnippetStr);
            const compName = configSnippet.name || sectionType;
            const compType = configSnippet.type || "section";
            const propsArr = configSnippet.props || [];
            let cliCommand = `npx ikas-component config add-component --name "${compName}" --type ${compType}`;
            if (configSnippet.isHeader)
                cliCommand += " --isHeader";
            if (configSnippet.isFooter)
                cliCommand += " --isFooter";
            if (propsArr.length > 0) {
                const propsJson = JSON.stringify(propsArr.map((p) => {
                    const prop = { name: p.name, type: p.type };
                    if (p.displayName)
                        prop.displayName = p.displayName;
                    if (p.required)
                        prop.required = true;
                    return prop;
                }));
                cliCommand += ` --props '${propsJson}'`;
            }
            parts.push("---", "", "### CLI Command (run this first)", "", "```bash", cliCommand, "```", "", "**IMPORTANT: Do NOT manually create or edit `types.ts`** — the CLI command above generates it automatically.", "");
        }
        catch {
            // If config snippet parsing fails, skip the CLI command section
        }
    }
    parts.push("---", "", "**IMPORTANT:** Do NOT use this template's JSX structure, CSS, or class names. This template only demonstrates the correct API usage pattern. Create a completely original visual design.", "", `Use \`get_framework_guide("${sectionType.includes("product") ? "product-detail-patterns" : "component-structure"}")\` for more patterns and best practices.`);
    return { content: [{ type: "text", text: parts.join("\n") }] };
});
// --- Start server ---
async function main() {
    const transport = new StdioServerTransport();
    await server.connect(transport);
}
main().catch((err) => {
    console.error("MCP server error:", err);
    process.exit(1);
});
//# sourceMappingURL=index.js.map