Skip to main content
Glama
server.ts21.3 kB
import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from '@modelcontextprotocol/sdk/types.js'; import { z } from 'zod'; import type { InterfaceType, DesignStyle, ColorMood, AnimationIntensity } from './utils/types.js'; import { refineUIPrompt } from './tools/refine-prompt.js'; import { analyzeInterface, generateAnalysisOutput } from './tools/analyzer.js'; import { composeAnimations } from './tools/animations.js'; import { generateUXFlow } from './tools/ux-flow.js'; import { suggestTechStack } from './tools/tech-stack.js'; import { getDesignPrinciplePrompt, DESIGN_PRINCIPLES, VISUAL_TECHNIQUES } from './resources/design-principles.js'; import { ENTRY_ANIMATIONS, SCROLL_ANIMATIONS, HOVER_ANIMATIONS, EASING_FUNCTIONS } from './resources/animation-patterns.js'; import { UX_PATTERNS, ACCESSIBILITY_PATTERNS } from './resources/ux-patterns.js'; import { INTERFACE_TEMPLATES, getTemplatePrompt } from './resources/templates.js'; import { INTERFACE_PROMPTS, listAvailablePrompts, fillPromptTemplate } from './prompts/interface-prompts.js'; const server = new Server( { name: 'ui-prompt-refiner', version: '1.0.0', }, { capabilities: { tools: {}, resources: {}, prompts: {}, }, } ); // Input schemas for tools const RefinePromptSchema = z.object({ rawPrompt: z.string().describe('Your basic interface idea or requirements'), interfaceType: z.enum([ 'website-landing', 'website-saas', 'website-portfolio', 'website-ecommerce', 'dashboard', 'mobile-app', 'desktop-app', 'cli-terminal', 'presentation', 'admin-panel', 'social-platform', 'custom' ]).optional().describe('Type of interface (auto-detected if not provided)'), style: z.enum([ 'minimalist', 'bold-experimental', 'corporate-professional', 'playful-creative', 'luxury-elegant', 'tech-futuristic', 'organic-natural', 'brutalist', 'retro-vintage', 'glassmorphic', 'neumorphic', 'custom' ]).optional().describe('Desired design style'), colorMood: z.enum([ 'energetic', 'calm', 'professional', 'playful', 'luxurious', 'trustworthy', 'innovative', 'natural', 'bold', 'neutral' ]).optional().describe('Color palette mood'), animationIntensity: z.enum(['subtle', 'moderate', 'dramatic', 'cinematic']) .optional().describe('Level of animation effects'), targetAudience: z.string().optional().describe('Who will use this interface'), brandKeywords: z.array(z.string()).optional().describe('Keywords describing the brand'), }); const AnalyzeInterfaceSchema = z.object({ rawPrompt: z.string().describe('Interface description to analyze'), interfaceType: z.enum([ 'website-landing', 'website-saas', 'website-portfolio', 'website-ecommerce', 'dashboard', 'mobile-app', 'desktop-app', 'cli-terminal', 'presentation', 'admin-panel', 'social-platform', 'custom' ]).optional().describe('Override detected interface type'), }); const ComposeAnimationsSchema = z.object({ interfaceType: z.enum([ 'website-landing', 'website-saas', 'website-portfolio', 'website-ecommerce', 'dashboard', 'mobile-app', 'desktop-app', 'cli-terminal', 'presentation', 'admin-panel', 'social-platform', 'custom' ]).describe('Type of interface'), intensity: z.enum(['subtle', 'moderate', 'dramatic', 'cinematic']) .describe('Animation intensity level'), sections: z.array(z.string()).optional().describe('Specific sections to animate'), customRequirements: z.string().optional().describe('Additional animation requirements'), }); const GenerateUXFlowSchema = z.object({ interfaceType: z.enum([ 'website-landing', 'website-saas', 'website-portfolio', 'website-ecommerce', 'dashboard', 'mobile-app', 'desktop-app', 'cli-terminal', 'presentation', 'admin-panel', 'social-platform', 'custom' ]).describe('Type of interface'), primaryGoal: z.string().describe('Main user goal (e.g., "sign up for newsletter")'), secondaryGoals: z.array(z.string()).optional().describe('Additional user goals'), userPersonas: z.array(z.string()).optional().describe('Target user types'), customFlows: z.array(z.string()).optional().describe('Custom user flows to include'), }); const SuggestTechStackSchema = z.object({ interfaceType: z.enum([ 'website-landing', 'website-saas', 'website-portfolio', 'website-ecommerce', 'dashboard', 'mobile-app', 'desktop-app', 'cli-terminal', 'presentation', 'admin-panel', 'social-platform', 'custom' ]).describe('Type of interface'), designStyle: z.enum([ 'minimalist', 'bold-experimental', 'corporate-professional', 'playful-creative', 'luxury-elegant', 'tech-futuristic', 'organic-natural', 'brutalist', 'retro-vintage', 'glassmorphic', 'neumorphic', 'custom' ]).optional().describe('Design style being used'), animationIntensity: z.enum(['subtle', 'moderate', 'dramatic', 'cinematic']) .optional().describe('Animation level'), requirements: z.array(z.string()).optional().describe('Special requirements'), }); // List available tools server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: 'refine_ui_prompt', description: 'Transform a basic interface idea into a comprehensive, world-class UI/UX design specification. This is the main tool that generates detailed design prompts covering visual design, typography, colors, animations, and user experience.', inputSchema: { type: 'object', properties: { rawPrompt: { type: 'string', description: 'Your basic interface idea or requirements' }, interfaceType: { type: 'string', enum: ['website-landing', 'website-saas', 'website-portfolio', 'website-ecommerce', 'dashboard', 'mobile-app', 'desktop-app', 'cli-terminal', 'presentation', 'admin-panel', 'social-platform', 'custom'], description: 'Type of interface (auto-detected if not provided)' }, style: { type: 'string', enum: ['minimalist', 'bold-experimental', 'corporate-professional', 'playful-creative', 'luxury-elegant', 'tech-futuristic', 'organic-natural', 'brutalist', 'retro-vintage', 'glassmorphic', 'neumorphic', 'custom'], description: 'Desired design style' }, colorMood: { type: 'string', enum: ['energetic', 'calm', 'professional', 'playful', 'luxurious', 'trustworthy', 'innovative', 'natural', 'bold', 'neutral'], description: 'Color palette mood' }, animationIntensity: { type: 'string', enum: ['subtle', 'moderate', 'dramatic', 'cinematic'], description: 'Level of animation effects' }, targetAudience: { type: 'string', description: 'Who will use this interface' }, brandKeywords: { type: 'array', items: { type: 'string' }, description: 'Keywords describing the brand' } }, required: ['rawPrompt'] } }, { name: 'analyze_interface', description: 'Analyze an interface request to detect the type, suggest styles, identify components, and understand the scope. Use this before refining to understand what you\'re working with.', inputSchema: { type: 'object', properties: { rawPrompt: { type: 'string', description: 'Interface description to analyze' }, interfaceType: { type: 'string', enum: ['website-landing', 'website-saas', 'website-portfolio', 'website-ecommerce', 'dashboard', 'mobile-app', 'desktop-app', 'cli-terminal', 'presentation', 'admin-panel', 'social-platform', 'custom'], description: 'Override detected interface type' } }, required: ['rawPrompt'] } }, { name: 'compose_animations', description: 'Generate detailed animation specifications including entry animations, scroll effects, hover states, loading animations, and transition choreography with CSS code examples.', inputSchema: { type: 'object', properties: { interfaceType: { type: 'string', enum: ['website-landing', 'website-saas', 'website-portfolio', 'website-ecommerce', 'dashboard', 'mobile-app', 'desktop-app', 'cli-terminal', 'presentation', 'admin-panel', 'social-platform', 'custom'], description: 'Type of interface' }, intensity: { type: 'string', enum: ['subtle', 'moderate', 'dramatic', 'cinematic'], description: 'Animation intensity level' }, sections: { type: 'array', items: { type: 'string' }, description: 'Specific sections to animate' }, customRequirements: { type: 'string', description: 'Additional animation requirements' } }, required: ['interfaceType', 'intensity'] } }, { name: 'generate_ux_flow', description: 'Create detailed user experience flows including user journeys, interaction patterns, state management, error handling, and accessibility requirements.', inputSchema: { type: 'object', properties: { interfaceType: { type: 'string', enum: ['website-landing', 'website-saas', 'website-portfolio', 'website-ecommerce', 'dashboard', 'mobile-app', 'desktop-app', 'cli-terminal', 'presentation', 'admin-panel', 'social-platform', 'custom'], description: 'Type of interface' }, primaryGoal: { type: 'string', description: 'Main user goal' }, secondaryGoals: { type: 'array', items: { type: 'string' }, description: 'Additional user goals' }, userPersonas: { type: 'array', items: { type: 'string' }, description: 'Target user types' }, customFlows: { type: 'array', items: { type: 'string' }, description: 'Custom user flows to include' } }, required: ['interfaceType', 'primaryGoal'] } }, { name: 'suggest_tech_stack', description: 'Get technology stack recommendations including frameworks, styling approaches, animation libraries, and deployment options based on your interface type and design requirements.', inputSchema: { type: 'object', properties: { interfaceType: { type: 'string', enum: ['website-landing', 'website-saas', 'website-portfolio', 'website-ecommerce', 'dashboard', 'mobile-app', 'desktop-app', 'cli-terminal', 'presentation', 'admin-panel', 'social-platform', 'custom'], description: 'Type of interface' }, designStyle: { type: 'string', enum: ['minimalist', 'bold-experimental', 'corporate-professional', 'playful-creative', 'luxury-elegant', 'tech-futuristic', 'organic-natural', 'brutalist', 'retro-vintage', 'glassmorphic', 'neumorphic', 'custom'], description: 'Design style being used' }, animationIntensity: { type: 'string', enum: ['subtle', 'moderate', 'dramatic', 'cinematic'], description: 'Animation level' }, requirements: { type: 'array', items: { type: 'string' }, description: 'Special requirements' } }, required: ['interfaceType'] } } ] }; }); // Handle tool calls server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { switch (name) { case 'refine_ui_prompt': { const parsed = RefinePromptSchema.parse(args); const result = refineUIPrompt({ rawPrompt: parsed.rawPrompt, interfaceType: parsed.interfaceType as InterfaceType | undefined, style: parsed.style as DesignStyle | undefined, colorMood: parsed.colorMood as ColorMood | undefined, animationIntensity: parsed.animationIntensity as AnimationIntensity | undefined, targetAudience: parsed.targetAudience, brandKeywords: parsed.brandKeywords, }); return { content: [{ type: 'text', text: result }] }; } case 'analyze_interface': { const parsed = AnalyzeInterfaceSchema.parse(args); const analysis = analyzeInterface(parsed.rawPrompt, parsed.interfaceType as InterfaceType | undefined); const result = generateAnalysisOutput(analysis, parsed.rawPrompt); return { content: [{ type: 'text', text: result }] }; } case 'compose_animations': { const parsed = ComposeAnimationsSchema.parse(args); const result = composeAnimations({ interfaceType: parsed.interfaceType as InterfaceType, intensity: parsed.intensity as AnimationIntensity, sections: parsed.sections, customRequirements: parsed.customRequirements, }); return { content: [{ type: 'text', text: result }] }; } case 'generate_ux_flow': { const parsed = GenerateUXFlowSchema.parse(args); const result = generateUXFlow({ interfaceType: parsed.interfaceType as InterfaceType, primaryGoal: parsed.primaryGoal, secondaryGoals: parsed.secondaryGoals, userPersonas: parsed.userPersonas, customFlows: parsed.customFlows, }); return { content: [{ type: 'text', text: result }] }; } case 'suggest_tech_stack': { const parsed = SuggestTechStackSchema.parse(args); const result = suggestTechStack({ interfaceType: parsed.interfaceType as InterfaceType, designStyle: parsed.designStyle as DesignStyle | undefined, animationIntensity: parsed.animationIntensity as AnimationIntensity | undefined, requirements: parsed.requirements, }); return { content: [{ type: 'text', text: result }] }; } default: throw new Error(`Unknown tool: ${name}`); } } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; return { content: [{ type: 'text', text: `Error: ${errorMessage}` }], isError: true, }; } }); // List available resources server.setRequestHandler(ListResourcesRequestSchema, async () => { return { resources: [ { uri: 'design://principles', name: 'Design Principles', description: 'Core design principles including Gestalt, visual hierarchy, and color theory', mimeType: 'text/markdown', }, { uri: 'design://animation-patterns', name: 'Animation Patterns', description: 'Library of animation patterns, easing functions, and timing guidelines', mimeType: 'text/markdown', }, { uri: 'design://ux-patterns', name: 'UX Patterns', description: 'Common UX patterns for navigation, feedback, forms, and more', mimeType: 'text/markdown', }, { uri: 'design://interface-templates', name: 'Interface Templates', description: 'Templates and guidelines for different interface types', mimeType: 'text/markdown', }, ], }; }); // Read resources server.setRequestHandler(ReadResourceRequestSchema, async (request) => { const { uri } = request.params; switch (uri) { case 'design://principles': return { contents: [ { uri, mimeType: 'text/markdown', text: `# Design Principles Reference ${getDesignPrinciplePrompt()} ## Visual Techniques ### Depth Creation ${VISUAL_TECHNIQUES.depthCreation.map(t => `- ${t}`).join('\n')} ### Texture & Pattern ${VISUAL_TECHNIQUES.textureAndPattern.map(t => `- ${t}`).join('\n')} ### Dynamic Elements ${VISUAL_TECHNIQUES.dynamicElements.map(t => `- ${t}`).join('\n')} ### Typographic Effects ${VISUAL_TECHNIQUES.typographicEffects.map(t => `- ${t}`).join('\n')} `, }, ], }; case 'design://animation-patterns': return { contents: [ { uri, mimeType: 'text/markdown', text: `# Animation Patterns Reference ## Easing Functions ${Object.entries(EASING_FUNCTIONS).map(([key, easing]) => ` ### ${easing.name} - CSS: \`${easing.css}\` - Feel: ${easing.description} - Use: ${easing.useCase} `).join('\n')} ## Entry Animations ${Object.entries(ENTRY_ANIMATIONS).map(([key, anim]) => ` ### ${anim.name} - Duration: ${anim.duration} - Stagger: ${anim.stagger} - Description: ${anim.description} `).join('\n')} ## Scroll Animations ${Object.entries(SCROLL_ANIMATIONS).map(([key, anim]) => ` ### ${anim.name} - Description: ${anim.description} - Use: ${anim.useCase} `).join('\n')} ## Hover Effects ${Object.entries(HOVER_ANIMATIONS).map(([key, anim]) => ` ### ${anim.name} - Effect: \`${anim.effect}\` - Duration: ${anim.duration} - Use: ${anim.useCase} `).join('\n')} `, }, ], }; case 'design://ux-patterns': return { contents: [ { uri, mimeType: 'text/markdown', text: `# UX Patterns Reference ## Onboarding Patterns ${Object.entries(UX_PATTERNS.onboarding).map(([key, pattern]) => ` ### ${pattern.name} ${pattern.description} - Implementation: ${pattern.implementation} - Best for: ${pattern.bestFor} `).join('\n')} ## Navigation Patterns ${Object.entries(UX_PATTERNS.navigation).map(([key, pattern]) => ` ### ${pattern.name} ${pattern.description} - Micro-interaction: ${pattern.microInteraction} - Best for: ${pattern.bestFor} `).join('\n')} ## Feedback Patterns ${Object.entries(UX_PATTERNS.feedback).map(([key, pattern]) => ` ### ${pattern.name} ${pattern.description} `).join('\n')} ## Accessibility Requirements ${Object.entries(ACCESSIBILITY_PATTERNS).map(([category, items]) => ` ### ${category.replace(/([A-Z])/g, ' $1').trim()} ${Object.entries(items).map(([key, value]) => `- **${key}**: ${value}`).join('\n')} `).join('\n')} `, }, ], }; case 'design://interface-templates': return { contents: [ { uri, mimeType: 'text/markdown', text: `# Interface Templates Reference ${Object.entries(INTERFACE_TEMPLATES).map(([type, template]) => ` ## ${template.name} **Type**: ${type} **Description**: ${template.description} ### Recommended Sections ${template.sections.map((s, i) => `${i + 1}. ${s}`).join('\n')} ### Key Components ${template.keyComponents.map(c => `- ${c}`).join('\n')} ### Suggested Styles ${template.suggestedStyles.join(', ')} ### Animation Focus ${template.animationFocus.map(a => `- ${a}`).join('\n')} ### UX Priorities ${template.uxPriorities.map(p => `- ${p}`).join('\n')} --- `).join('\n')} `, }, ], }; default: throw new Error(`Unknown resource: ${uri}`); } }); // List available prompts server.setRequestHandler(ListPromptsRequestSchema, async () => { const prompts = listAvailablePrompts(); return { prompts: prompts.map(p => ({ name: p.type, description: p.description, arguments: [ { name: 'purpose', description: 'What is the purpose of this interface?', required: true, }, { name: 'audience', description: 'Who is the target audience?', required: false, }, { name: 'style', description: 'Preferred design style', required: false, }, { name: 'animationLevel', description: 'Animation intensity (subtle, moderate, dramatic, cinematic)', required: false, }, ], })), }; }); // Get prompt server.setRequestHandler(GetPromptRequestSchema, async (request) => { const { name, arguments: promptArgs } = request.params; const template = INTERFACE_PROMPTS[name]; if (!template) { throw new Error(`Unknown prompt: ${name}`); } const variables = promptArgs || {}; const filledPrompt = fillPromptTemplate(name, variables as Record<string, string>); return { description: template.description, messages: [ { role: 'user', content: { type: 'text', text: filledPrompt, }, }, ], }; }); // Start the server async function main() { const transport = new StdioServerTransport(); await server.connect(transport); console.error('UI Prompt Refiner MCP server running on stdio'); } main().catch((error) => { console.error('Fatal error:', error); process.exit(1); });

Implementation Reference

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/Nwabukin/mcp-ui-prompt-refiner'

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