Skip to main content
Glama
index.ts•13 kB
#!/usr/bin/env node import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js'; import { z } from 'zod'; // Import tools import { generateComponent, optimizeClasses, createTheme, analyzeDesign, generatePreview, convertToTailwind, suggestImprovements, createLayout, getComponent, createProject } from './utils/tool-functions.js'; // Import types import type { ComponentGenerationOptions, ClassOptimizationOptions, ThemeCreationOptions, DesignAnalysisOptions, PreviewOptions, ConversionOptions, SuggestionOptions, LayoutOptions, ShadcnComponentRequest, ProjectGenerationOptions } from './types.js'; // Enhanced tool definitions with shadcn/ui integration const TOOLS = [ { name: 'generate_component', description: 'Generate Tailwind CSS components with AI assistance using Gemini', inputSchema: { type: 'object', properties: { description: { type: 'string', description: 'Description of the component to generate' }, type: { type: 'string', enum: ['button', 'card', 'form', 'navigation', 'modal', 'table', 'custom'], description: 'Type of component' }, framework: { type: 'string', enum: ['html', 'react', 'vue', 'svelte', 'angular'], default: 'react', description: 'Target framework' }, variant: { type: 'string', enum: ['primary', 'secondary', 'outline', 'ghost', 'link'], default: 'primary', description: 'Component variant' }, size: { type: 'string', enum: ['xs', 'sm', 'md', 'lg', 'xl'], default: 'md', description: 'Component size' }, theme: { type: 'string', enum: ['light', 'dark', 'auto'], default: 'light', description: 'Theme preference' }, useShadcn: { type: 'boolean', default: true, description: 'Use shadcn/ui components as base' }, responsive: { type: 'boolean', default: true, description: 'Make component responsive' }, accessibility: { type: 'boolean', default: true, description: 'Include accessibility features' } }, required: ['description', 'type'] } }, { name: 'get_shadcn_component', description: 'Get shadcn/ui component source code and usage examples', inputSchema: { type: 'object', properties: { componentName: { type: 'string', description: 'Name of the shadcn/ui component (e.g., "button", "card", "form")' }, includeDemo: { type: 'boolean', default: true, description: 'Include usage examples' }, framework: { type: 'string', enum: ['react', 'svelte'], default: 'react', description: 'Framework to get component for' } }, required: ['componentName'] } }, { name: 'create_project', description: 'Create a complete project with Vite + Tailwind + shadcn/ui setup', inputSchema: { type: 'object', properties: { projectName: { type: 'string', description: 'Name of the project' }, framework: { type: 'string', enum: ['react', 'vue', 'svelte'], default: 'react', description: 'Framework to use' }, typescript: { type: 'boolean', default: true, description: 'Use TypeScript' }, components: { type: 'array', items: { type: 'string' }, description: 'Initial shadcn/ui components to include' }, template: { type: 'string', enum: ['basic', 'dashboard', 'landing', 'blog', 'auth'], default: 'basic', description: 'Project template' } }, required: ['projectName'] } }, { name: 'optimize_classes', description: 'Optimize and clean up Tailwind CSS classes', inputSchema: { type: 'object', properties: { html: { type: 'string', description: 'HTML with Tailwind classes to optimize' }, removeRedundant: { type: 'boolean', default: true, description: 'Remove redundant classes' }, mergeConflicts: { type: 'boolean', default: true, description: 'Resolve conflicting classes' }, suggestAlternatives: { type: 'boolean', default: true, description: 'Suggest better alternatives' } }, required: ['html'] } }, { name: 'create_theme', description: 'Generate custom Tailwind theme with AI assistance', inputSchema: { type: 'object', properties: { brandColor: { type: 'string', description: 'Primary brand color (hex, rgb, or color name)' }, style: { type: 'string', enum: ['minimal', 'modern', 'classic', 'bold', 'elegant'], default: 'modern', description: 'Design style' }, colorCount: { type: 'number', default: 9, minimum: 5, maximum: 11, description: 'Number of color shades to generate' }, includeConfig: { type: 'boolean', default: true, description: 'Generate tailwind.config.js' }, typography: { type: 'boolean', default: true, description: 'Include typography scale' }, spacing: { type: 'boolean', default: true, description: 'Include custom spacing scale' } }, required: ['brandColor'] } }, { name: 'analyze_design', description: 'Analyze design with AI for improvements and best practices', inputSchema: { type: 'object', properties: { html: { type: 'string', description: 'HTML code to analyze' }, css: { type: 'string', description: 'Additional CSS code (optional)' }, context: { type: 'string', description: 'Design context or purpose' }, checkAccessibility: { type: 'boolean', default: true, description: 'Check accessibility compliance' }, checkResponsive: { type: 'boolean', default: true, description: 'Check responsive design' }, checkPerformance: { type: 'boolean', default: true, description: 'Check performance implications' } }, required: ['html'] } }, { name: 'generate_preview', description: 'Generate visual preview of Tailwind components', inputSchema: { type: 'object', properties: { html: { type: 'string', description: 'HTML code to preview' }, width: { type: 'number', default: 800, description: 'Preview width in pixels' }, height: { type: 'number', default: 600, description: 'Preview height in pixels' }, darkMode: { type: 'boolean', default: false, description: 'Generate dark mode preview' }, responsive: { type: 'boolean', default: false, description: 'Generate responsive breakpoint previews' } }, required: ['html'] } }, { name: 'convert_to_tailwind', description: 'Convert CSS/SCSS to Tailwind classes', inputSchema: { type: 'object', properties: { code: { type: 'string', description: 'CSS, SCSS, or HTML with styles to convert' }, format: { type: 'string', enum: ['css', 'scss', 'html'], description: 'Input format' }, preserveCustom: { type: 'boolean', default: false, description: 'Preserve custom properties that cannot be converted' }, optimize: { type: 'boolean', default: true, description: 'Optimize the converted classes' } }, required: ['code', 'format'] } }, { name: 'suggest_improvements', description: 'Get AI-powered suggestions for design improvements', inputSchema: { type: 'object', properties: { html: { type: 'string', description: 'HTML code to analyze' }, context: { type: 'string', description: 'Context about the design goals' }, targetAudience: { type: 'string', description: 'Target audience for the design' }, focusAreas: { type: 'array', items: { type: 'string', enum: ['accessibility', 'performance', 'ux', 'aesthetics', 'responsiveness'] }, description: 'Areas to focus improvements on' } }, required: ['html'] } }, { name: 'create_layout', description: 'Generate responsive layouts with Tailwind CSS', inputSchema: { type: 'object', properties: { type: { type: 'string', enum: ['dashboard', 'landing', 'blog', 'ecommerce', 'portfolio', 'documentation'], description: 'Layout type' }, sections: { type: 'array', items: { type: 'string' }, description: 'Layout sections (header, sidebar, main, footer, etc.)' }, complexity: { type: 'string', enum: ['simple', 'medium', 'complex'], default: 'medium', description: 'Layout complexity' }, framework: { type: 'string', enum: ['html', 'react', 'vue', 'svelte'], default: 'html', description: 'Target framework' } }, required: ['type', 'sections'] } } ]; class TailwindGeminiServer { private server: Server; constructor() { this.server = new Server( { name: 'mcp-tailwind-gemini', version: '1.0.0', }, { capabilities: { tools: {}, }, } ); this.setupToolHandlers(); } private setupToolHandlers() { // List available tools this.server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS, })); // Handle tool calls this.server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; // Validate args exists if (!args) { throw new Error(`No arguments provided for tool: ${name}`); } try { switch (name) { case 'generate_component': return await generateComponent(args as unknown as ComponentGenerationOptions); case 'get_shadcn_component': return await getComponent(args as unknown as ShadcnComponentRequest); case 'create_project': return await createProject(args as unknown as ProjectGenerationOptions); case 'optimize_classes': return await optimizeClasses(args as unknown as ClassOptimizationOptions); case 'create_theme': return await createTheme(args as unknown as ThemeCreationOptions); case 'analyze_design': return await analyzeDesign(args as unknown as DesignAnalysisOptions); case 'generate_preview': return await generatePreview(args as unknown as PreviewOptions); case 'convert_to_tailwind': return await convertToTailwind(args as unknown as ConversionOptions); case 'suggest_improvements': return await suggestImprovements(args as unknown as SuggestionOptions); case 'create_layout': return await createLayout(args as unknown as LayoutOptions); default: throw new Error(`Unknown tool: ${name}`); } } catch (error) { return { content: [ { type: 'text', text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`, }, ], }; } }); } async run() { const transport = new StdioServerTransport(); await this.server.connect(transport); console.error('MCP Tailwind Gemini Server running on stdio'); } } const server = new TailwindGeminiServer(); server.run().catch(console.error);

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Tai-DT/mcp-tailwind-gemini'

If you have feedback or need assistance with the MCP directory API, please join our Discord server