#!/usr/bin/env node
// Handle CLI commands before importing MCP server
const args = process.argv.slice(2);
const command = args[0];
if (command === "install" && args.length === 1) {
    // Show help menu
    showHelpMenu();
    process.exit(0);
}
if (command === "install-skills" || command === "uninstall-skills") {
    // Delegate to skills installer
    const { execSync } = await import("child_process");
    const { fileURLToPath } = await import("url");
    const { dirname, join } = await import("path");
    const __filename = fileURLToPath(import.meta.url);
    const __dirname = dirname(__filename);
    const installerPath = join(__dirname, "..", "bin", "install-skills.js");
    try {
        execSync(`node "${installerPath}" ${command}`, {
            stdio: "inherit",
            cwd: process.cwd(),
        });
        process.exit(0);
    }
    catch {
        process.exit(1);
    }
}
if (command === "install-mcp") {
    await installMcpConfig();
    process.exit(0);
}
if (command === "uninstall-mcp") {
    await uninstallMcpConfig();
    process.exit(0);
}
function showHelpMenu() {
    console.log(`
╭─────────────────────────────────────────────────────────────────╮
│                                                                 │
│  Mozaic Design System MCP Server & Skills                      │
│  Self-contained Claude Code skills for Mozaic Design System    │
│                                                                 │
╰─────────────────────────────────────────────────────────────────╯

Usage:
  npx mozaic-mcp-server [command]

Commands:
  (no args)           Start MCP server for use in Claude Desktop
  install             Show this help menu
  install-skills      Install Claude Code skills and database
  uninstall-skills    Remove Claude Code skills and database
  install-mcp         Add MCP server to Claude Desktop config
  uninstall-mcp       Remove MCP server from Claude Desktop config

Examples:
  # Install skills (recommended for most users)
  npx mozaic-mcp-server install-skills

  # Install MCP server for Claude Desktop
  npx mozaic-mcp-server install-mcp

  # Start MCP server manually (for testing)
  npx mozaic-mcp-server

Documentation:
  Skills Guide:   https://github.com/MerzoukeMansouri/adeo-mozaic-mcp#skills
  MCP Guide:      https://github.com/MerzoukeMansouri/adeo-mozaic-mcp#mcp-server
  `);
}
async function installMcpConfig() {
    const { homedir } = await import("os");
    const { readFileSync, writeFileSync, existsSync, mkdirSync } = await import("fs");
    const { join } = await import("path");
    const { fileURLToPath } = await import("url");
    const { dirname } = await import("path");
    const configPath = join(homedir(), ".claude", "config.json");
    const __filename = fileURLToPath(import.meta.url);
    const __dirname = dirname(__filename);
    const serverPath = join(__dirname, "index.js");
    console.log("📦 Installing MCP server to Claude Desktop config...\n");
    // Ensure .claude directory exists
    const claudeDir = join(homedir(), ".claude");
    if (!existsSync(claudeDir)) {
        mkdirSync(claudeDir, { recursive: true });
    }
    // Read existing config or create new one
    let config = { mcpServers: {} };
    if (existsSync(configPath)) {
        try {
            const configContent = readFileSync(configPath, "utf-8");
            config = JSON.parse(configContent);
            if (!config.mcpServers) {
                config.mcpServers = {};
            }
        }
        catch {
            console.error("⚠️  Failed to parse existing config, creating new one");
            config = { mcpServers: {} };
        }
    }
    // Add Mozaic MCP server configuration
    config.mcpServers.mozaic = {
        command: "node",
        args: [serverPath],
    };
    // Write updated config
    try {
        writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
        console.log("✅ MCP server installed successfully!\n");
        console.log("Configuration added to:", configPath);
        console.log("\n📝 Next steps:");
        console.log("   1. Restart Claude Desktop");
        console.log("   2. Look for the 🔌 icon to verify MCP server is connected");
        console.log("   3. Use Mozaic tools in your conversations\n");
    }
    catch (error) {
        console.error("❌ Failed to write config:", error);
        process.exit(1);
    }
}
async function uninstallMcpConfig() {
    const { homedir } = await import("os");
    const { readFileSync, writeFileSync, existsSync } = await import("fs");
    const { join } = await import("path");
    const configPath = join(homedir(), ".claude", "config.json");
    console.log("🗑️  Removing MCP server from Claude Desktop config...\n");
    if (!existsSync(configPath)) {
        console.log("⚠️  No Claude Desktop config found");
        return;
    }
    try {
        const configContent = readFileSync(configPath, "utf-8");
        const config = JSON.parse(configContent);
        if (config.mcpServers && config.mcpServers.mozaic) {
            delete config.mcpServers.mozaic;
            writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
            console.log("✅ MCP server removed successfully!\n");
            console.log("   Restart Claude Desktop for changes to take effect\n");
        }
        else {
            console.log("ℹ️  Mozaic MCP server not found in config\n");
        }
    }
    catch (error) {
        console.error("❌ Failed to update config:", error);
        process.exit(1);
    }
}
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import Database from "better-sqlite3";
import { appendFileSync, existsSync } from "fs";
import { dirname, join } from "path";
import { fileURLToPath } from "url";
import { z } from "zod";
// Debug mode - enable with --debug flag
const DEBUG = process.argv.includes("--debug");
const LOG_FILE = join(dirname(fileURLToPath(import.meta.url)), "..", "mcp-server.log");
function log(message, data) {
    if (!DEBUG)
        return;
    const timestamp = new Date().toISOString();
    const logMessage = data
        ? `[${timestamp}] ${message}: ${JSON.stringify(data, null, 2)}\n`
        : `[${timestamp}] ${message}\n`;
    appendFileSync(LOG_FILE, logMessage);
}
// Import tool handlers
import { handleGenerateReactComponent, } from "./tools/generate-react-component.js";
import { handleGenerateVueComponent, } from "./tools/generate-vue-component.js";
import { handleGetComponentInfo } from "./tools/get-component-info.js";
import { handleGetCssUtility } from "./tools/get-css-utility.js";
import { handleGetDesignTokens } from "./tools/get-design-tokens.js";
import { handleListComponents } from "./tools/list-components.js";
import { handleListCssUtilities } from "./tools/list-css-utilities.js";
import { handleSearchDocumentation, } from "./tools/search-documentation.js";
import { handleSearchIcons } from "./tools/search-icons.js";
import { handleGetIcon } from "./tools/get-icon.js";
import { handleGetInstallInfo } from "./tools/get-install-info.js";
// Get database path
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const dbPath = join(__dirname, "..", "data", "mozaic.db");
// Initialize database
let db;
function initializeDatabase() {
    log("Initializing database", { path: dbPath });
    if (!existsSync(dbPath)) {
        const error = `Database not found at ${dbPath}. Run 'npm run build' to build the database first.`;
        log("Database error", { error });
        throw new Error(error);
    }
    const database = new Database(dbPath, { readonly: true });
    database.pragma("journal_mode = WAL");
    log("Database initialized successfully");
    return database;
}
// Create MCP server
const server = new McpServer({
    name: "mozaic-design-system",
    version: "1.0.0",
});
// Register tools using the new McpServer API
log("Registering MCP tools");
server.registerTool("get_design_tokens", {
    description: "Get Mozaic design tokens with CSS/SCSS variables. Categories: colors (brand, semantic, component), typography (font sizes, weights, line heights), spacing (magic unit scale), shadows, borders, screens (breakpoints), grid (gutters).",
    inputSchema: {
        category: z
            .enum(["colors", "typography", "spacing", "shadows", "borders", "screens", "grid", "all"])
            .describe("Token category: colors, typography, spacing, shadows, borders, screens, grid, or all"),
        format: z
            .enum(["json", "scss", "css", "js"])
            .default("json")
            .describe("Output format: json (structured), scss ($variables), css (--custom-properties), js (constants)"),
    },
}, async (args) => {
    log("Tool called: get_design_tokens", args);
    if (!db)
        db = initializeDatabase();
    const result = handleGetDesignTokens(db, args);
    log("Tool result: get_design_tokens", { contentLength: result.content.length });
    return result;
});
server.registerTool("get_component_info", {
    description: "Get Vue/React component details: props (types, defaults, required), slots, events, and code examples. For CSS-only utilities (Flexy, Margin, Padding), use get_css_utility instead.",
    inputSchema: {
        component: z
            .string()
            .describe("Component name (e.g., 'button', 'modal', 'accordion', 'text-input')"),
        framework: z
            .enum(["vue", "react"])
            .default("vue")
            .describe("Framework for code examples: vue (@mozaic-ds/vue-3) or react (@mozaic-ds/react)"),
    },
}, async (args) => {
    log("Tool called: get_component_info", args);
    if (!db)
        db = initializeDatabase();
    const result = handleGetComponentInfo(db, args);
    log("Tool result: get_component_info", { contentLength: result.content.length });
    return result;
});
server.registerTool("list_components", {
    description: "List Mozaic Vue/React components by category. Returns component names you can use with get_component_info. For CSS utilities (Flexy, Margin), use list_css_utilities instead.",
    inputSchema: {
        category: z
            .enum(["form", "navigation", "feedback", "layout", "data-display", "action", "all"])
            .default("all")
            .describe("Filter: form (inputs, selects), navigation (tabs, breadcrumb), feedback (modal, toast), layout, data-display, action (buttons), or all"),
    },
}, async (args) => {
    log("Tool called: list_components", args);
    if (!db)
        db = initializeDatabase();
    const result = handleListComponents(db, args);
    log("Tool result: list_components", { contentLength: result.content.length });
    return result;
});
server.registerTool("generate_vue_component", {
    description: "Generate ready-to-use Vue 3 code with Mozaic components (@mozaic-ds/vue-3). Returns <template> with proper imports. Use get_component_info first to see available props.",
    inputSchema: {
        component: z
            .string()
            .describe("Component to generate (e.g., 'button', 'text-input', 'modal', 'select')"),
        props: z
            .record(z.unknown())
            .optional()
            .describe("Props to apply (e.g., {theme: 'primary', size: 'm'})"),
        children: z.string().optional().describe("Slot content (text or HTML)"),
    },
}, async (args) => {
    log("Tool called: generate_vue_component", args);
    if (!db)
        db = initializeDatabase();
    const result = handleGenerateVueComponent(db, args);
    log("Tool result: generate_vue_component", { contentLength: result.content.length });
    return result;
});
server.registerTool("generate_react_component", {
    description: "Generate ready-to-use React/TSX code with Mozaic components (@mozaic-ds/react). Returns JSX with proper imports. Use get_component_info first to see available props.",
    inputSchema: {
        component: z
            .string()
            .describe("Component to generate (e.g., 'Button', 'TextInput', 'Modal', 'Select')"),
        props: z
            .record(z.unknown())
            .optional()
            .describe("Props to apply (e.g., {theme: 'primary', size: 'm'})"),
        children: z.string().optional().describe("Children content (text or JSX)"),
    },
}, async (args) => {
    log("Tool called: generate_react_component", args);
    if (!db)
        db = initializeDatabase();
    const result = handleGenerateReactComponent(db, args);
    log("Tool result: generate_react_component", { contentLength: result.content.length });
    return result;
});
server.registerTool("search_documentation", {
    description: "Search Mozaic Design System documentation for installation guides, component usage, configuration, styling, tokens, patterns, and best practices. Use this for any question about how to use Mozaic.",
    inputSchema: {
        query: z
            .string()
            .describe("Search query (e.g., 'installation', 'vue setup', 'button props', 'color tokens')"),
        limit: z.number().default(5).describe("Maximum number of results"),
    },
}, async (args) => {
    log("Tool called: search_documentation", args);
    if (!db)
        db = initializeDatabase();
    const result = handleSearchDocumentation(db, args);
    log("Tool result: search_documentation", {
        contentLength: result.content.length,
        resultText: result.content[0]?.text?.substring(0, 500),
    });
    return result;
});
server.registerTool("get_css_utility", {
    description: "Get CSS utility classes and examples for Mozaic layout and spacing utilities. These are CSS-only utilities (no framework component needed). Available: Flexy (flexbox grid), Container, Margin, Padding, Ratio, Scroll.",
    inputSchema: {
        name: z.string().describe("Utility name (e.g., 'flexy', 'margin', 'padding', 'container')"),
        includeClasses: z
            .boolean()
            .default(true)
            .describe("Include all CSS class names in the response"),
    },
}, async (args) => {
    log("Tool called: get_css_utility", args);
    if (!db)
        db = initializeDatabase();
    const result = handleGetCssUtility(db, args);
    log("Tool result: get_css_utility", { contentLength: result.content.length });
    return result;
});
server.registerTool("list_css_utilities", {
    description: "List Mozaic CSS-only utilities (no framework needed). Returns utility names to use with get_css_utility. Layout: Flexy (grid), Container. Utility: Margin, Padding, Ratio, Scroll.",
    inputSchema: {
        category: z
            .enum(["layout", "utility", "all"])
            .default("all")
            .describe("Filter: 'layout' (Flexy, Container) or 'utility' (Margin, Padding, Ratio, Scroll)"),
    },
}, async (args) => {
    log("Tool called: list_css_utilities", args);
    if (!db)
        db = initializeDatabase();
    const result = handleListCssUtilities(db, args);
    log("Tool result: list_css_utilities", { contentLength: result.content.length });
    return result;
});
server.registerTool("search_icons", {
    description: "Search Mozaic Design System icons by name or type. Returns icon names, types (navigation, media, social, payment), and available sizes (16, 24, 32, 48, 64). Use get_icon for detailed SVG/code output.",
    inputSchema: {
        query: z
            .string()
            .describe('Search query for icon name (e.g., "arrow", "cart", "user", "check")'),
        type: z
            .string()
            .optional()
            .describe('Filter by icon type/category (e.g., "navigation", "media", "social")'),
        size: z.number().optional().describe("Filter by icon size in pixels (16, 24, 32, 48, or 64)"),
        limit: z.number().default(20).describe("Maximum number of results"),
    },
}, async (args) => {
    log("Tool called: search_icons", args);
    if (!db)
        db = initializeDatabase();
    const result = handleSearchIcons(db, args);
    log("Tool result: search_icons", { contentLength: result.content.length });
    return result;
});
server.registerTool("get_icon", {
    description: "Get a specific Mozaic icon by name with SVG markup and ready-to-use code for React/Vue. Use search_icons first to find icon names.",
    inputSchema: {
        name: z.string().describe('The icon name (e.g., "ArrowArrowBottom16", "Cart24", "User32")'),
        format: z
            .enum(["svg", "react", "vue", "all"])
            .default("all")
            .describe("Output format: svg (raw SVG), react (import code), vue (component code), or all"),
    },
}, async (args) => {
    log("Tool called: get_icon", args);
    if (!db)
        db = initializeDatabase();
    const result = handleGetIcon(db, args);
    log("Tool result: get_icon", { contentLength: result.content.length });
    return result;
});
server.registerTool("get_install_info", {
    description: "Get installation commands and import statements for a Mozaic component. Returns package name, install command (npm/yarn/pnpm), import statements, peer dependencies, and quick start code.",
    inputSchema: {
        component: z.string().describe('Component name (e.g., "button", "modal", "text-input")'),
        framework: z
            .enum(["vue", "react"])
            .default("vue")
            .describe("Target framework: vue (@mozaic-ds/vue-3) or react (@mozaic-ds/react)"),
        packageManager: z
            .enum(["npm", "yarn", "pnpm"])
            .default("npm")
            .describe("Package manager for install commands"),
    },
}, async (args) => {
    log("Tool called: get_install_info", args);
    if (!db)
        db = initializeDatabase();
    const result = handleGetInstallInfo(db, args);
    log("Tool result: get_install_info", { contentLength: result.content.length });
    return result;
});
// Start server
async function main() {
    log("=== MCP Server Starting ===");
    log("Debug mode enabled", { DEBUG, argv: process.argv });
    log("Database path", { dbPath });
    // Initialize database on startup
    try {
        db = initializeDatabase();
    }
    catch (error) {
        log("Failed to initialize database on startup", { error: String(error) });
        // Continue anyway - will fail gracefully on tool calls
    }
    log("Connecting to stdio transport");
    const transport = new StdioServerTransport();
    await server.connect(transport);
    log("Server connected and ready");
}
main().catch((error) => {
    log("Fatal error", { error: String(error) });
    process.exit(1);
});
//# sourceMappingURL=index.js.map