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);
});