UNPKG

ultimate-mcp-server

Version:

The definitive all-in-one Model Context Protocol server for AI-assisted coding across 30+ platforms

998 lines (989 loc) 35.5 kB
/** * UI Understanding MCP Tools * * These tools automatically analyze UI/UX from URLs or images * to provide comprehensive design insights and recommendations */ import { ScreenshotCapture } from '../ui-understanding/screenshot-capture.js'; import { UIAnalyzer } from '../ui-understanding/ui-analyzer.js'; const screenshotCapture = new ScreenshotCapture(); const uiAnalyzer = new UIAnalyzer(); /** * Main UI analysis tool - automatically captures and analyzes UI */ export const analyze_ui_design = { name: 'analyze_ui_design', description: `Automatically capture and analyze UI/UX design from any URL or image. This tool provides comprehensive design analysis including: - Visual design system extraction (colors, typography, spacing) - Component identification and consistency analysis - Accessibility assessment with WCAG compliance - Usability evaluation with actionable improvements - Navigation and information architecture analysis - Content structure and readability metrics - Performance indicators The AI will proactively use this tool when: - You share a URL or mention a website - You ask about design, UI, or UX - You need design feedback or improvements - You want to understand a site's design system`, inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'URL of the website to analyze' }, imagePath: { type: 'string', description: 'Path to local image file (alternative to URL)' }, fullPage: { type: 'boolean', description: 'Capture full page (default: false)', default: false }, viewport: { type: 'object', description: 'Viewport size for capture', properties: { width: { type: 'number', default: 1920 }, height: { type: 'number', default: 1080 } } }, focusAreas: { type: 'array', description: 'Specific areas to focus analysis on', items: { type: 'string', enum: ['design-system', 'accessibility', 'usability', 'components', 'navigation', 'content', 'performance'] } }, context: { type: 'string', description: 'Additional context about what to analyze' } }, required: ['url'] }, handler: async (args) => { try { // Capture screenshots const screenshots = await screenshotCapture.captureScreenshot({ url: args.url, filePath: args.imagePath, fullPage: args.fullPage || false, viewport: args.viewport, waitTime: 2000 }); // Analyze UI const analysis = await uiAnalyzer.analyzeUI(screenshots, args.url, args.context); // Generate improvement suggestions const improvements = await uiAnalyzer.generateImprovements(analysis); // Format response const response = { summary: { url: analysis.url, timestamp: analysis.timestamp, screenshotCount: screenshots.length, elementCount: analysis.elements.length, accessibilityScore: analysis.accessibility.score, usabilityScore: analysis.usability.score }, designSystem: { primaryColors: analysis.designSystem.colors.primary, fonts: analysis.designSystem.typography.fonts, spacingUnit: analysis.designSystem.spacing.unit }, components: analysis.components.map(c => ({ name: c.name, instances: c.instances, consistency: c.consistency })), accessibility: { score: analysis.accessibility.score, criticalIssues: analysis.accessibility.issues.filter(i => i.severity === 'critical').length, majorIssues: analysis.accessibility.issues.filter(i => i.severity === 'major').length, topIssues: analysis.accessibility.issues.slice(0, 5) }, usability: { score: analysis.usability.score, goodPatterns: analysis.usability.patterns.filter(p => p.type === 'good').length, improvementAreas: analysis.usability.improvements.slice(0, 5) }, navigation: { type: analysis.navigation.structure, hasBreadcrumbs: !!analysis.navigation.breadcrumbs, userFlowComplexity: analysis.navigation.userFlow.length }, topImprovements: improvements.slice(0, 5), fullAnalysis: analysis }; await screenshotCapture.cleanup(); return { content: [{ type: 'text', text: JSON.stringify(response, null, 2) }] }; } catch (error) { await screenshotCapture.cleanup(); throw error; } } }; /** * Extract design system - automatically extracts colors, typography, spacing */ export const extract_design_system = { name: 'extract_design_system', description: `Extract the complete design system from any website or UI. This tool identifies: - Complete color palette (primary, secondary, accent, semantic colors) - Typography system (fonts, sizes, weights, line heights) - Spacing and grid system - Component styles and patterns - Visual effects (shadows, borders, animations) Perfect for: - Creating style guides - Ensuring design consistency - Building component libraries - Design system documentation`, inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'URL to extract design system from' }, format: { type: 'string', enum: ['json', 'css', 'scss', 'tokens'], description: 'Output format for design system', default: 'json' }, includeComponents: { type: 'boolean', description: 'Include component-specific styles', default: true } }, required: ['url'] }, handler: async (args) => { const screenshots = await screenshotCapture.captureScreenshot({ url: args.url, fullPage: false }); const analysis = await uiAnalyzer.analyzeUI(screenshots, args.url); let output; if (args.format === 'css') { output = generateCSSVariables(analysis.designSystem); } else if (args.format === 'scss') { output = generateSCSSVariables(analysis.designSystem); } else if (args.format === 'tokens') { output = generateDesignTokens(analysis.designSystem); } else { output = analysis.designSystem; } await screenshotCapture.cleanup(); return { content: [{ type: 'text', text: typeof output === 'string' ? output : JSON.stringify(output, null, 2) }] }; } }; /** * Check accessibility - comprehensive WCAG compliance check */ export const check_ui_accessibility = { name: 'check_ui_accessibility', description: `Perform comprehensive accessibility analysis on any website. Checks for: - WCAG 2.1 AA/AAA compliance - Color contrast issues - Missing alt text and ARIA labels - Keyboard navigation problems - Screen reader compatibility - Touch target sizes - Focus indicators Returns detailed report with: - Accessibility score (0-100) - Categorized issues by severity - Specific fix recommendations - WCAG criteria references`, inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'URL to check accessibility' }, wcagLevel: { type: 'string', enum: ['A', 'AA', 'AAA'], description: 'WCAG compliance level to check', default: 'AA' }, focusAreas: { type: 'array', description: 'Specific accessibility areas to focus on', items: { type: 'string', enum: ['contrast', 'alt-text', 'aria', 'keyboard', 'structure', 'focus'] } } }, required: ['url'] }, handler: async (args) => { const screenshots = await screenshotCapture.captureScreenshot({ url: args.url, fullPage: true }); const analysis = await uiAnalyzer.analyzeUI(screenshots, args.url); const report = { url: args.url, wcagLevel: args.wcagLevel, overallScore: analysis.accessibility.score, compliance: analysis.accessibility.score >= 90 ? 'PASS' : 'NEEDS IMPROVEMENT', summary: { totalIssues: analysis.accessibility.issues.length, criticalIssues: analysis.accessibility.issues.filter(i => i.severity === 'critical').length, majorIssues: analysis.accessibility.issues.filter(i => i.severity === 'major').length, minorIssues: analysis.accessibility.issues.filter(i => i.severity === 'minor').length }, issuesByType: groupIssuesByType(analysis.accessibility.issues), detailedIssues: analysis.accessibility.issues.map(issue => ({ ...issue, howToFix: issue.recommendation, wcagReference: issue.wcagCriteria })), recommendations: analysis.accessibility.recommendations, nextSteps: generateAccessibilityNextSteps(analysis.accessibility) }; await screenshotCapture.cleanup(); return { content: [{ type: 'text', text: JSON.stringify(report, null, 2) }] }; } }; /** * Compare UI designs - analyze differences between designs */ export const compare_ui_designs = { name: 'compare_ui_designs', description: `Compare two UI designs to identify differences and improvements. Analyzes: - Visual design changes (colors, typography, spacing) - Layout and structure differences - Component modifications - Content updates - Functionality changes - Accessibility improvements - Performance impact Useful for: - A/B testing analysis - Before/after comparisons - Design iteration reviews - Competitive analysis`, inputSchema: { type: 'object', properties: { url1: { type: 'string', description: 'First URL to compare' }, url2: { type: 'string', description: 'Second URL to compare' }, aspects: { type: 'array', description: 'Specific aspects to compare', items: { type: 'string', enum: ['design', 'layout', 'content', 'functionality', 'accessibility', 'performance'] } } }, required: ['url1', 'url2'] }, handler: async (args) => { // Capture both UIs const [screenshots1, screenshots2] = await Promise.all([ screenshotCapture.captureScreenshot({ url: args.url1 }), screenshotCapture.captureScreenshot({ url: args.url2 }) ]); // Analyze both const [analysis1, analysis2] = await Promise.all([ uiAnalyzer.analyzeUI(screenshots1, args.url1), uiAnalyzer.analyzeUI(screenshots2, args.url2) ]); // Compare analyses const comparison = { summary: { url1: args.url1, url2: args.url2, overallSimilarity: calculateSimilarity(analysis1, analysis2), majorDifferences: [] }, design: compareDesignSystems(analysis1.designSystem, analysis2.designSystem), accessibility: { scoreChange: analysis2.accessibility.score - analysis1.accessibility.score, improvementsMade: analysis2.accessibility.score > analysis1.accessibility.score, newIssues: findNewIssues(analysis1.accessibility.issues, analysis2.accessibility.issues), resolvedIssues: findResolvedIssues(analysis1.accessibility.issues, analysis2.accessibility.issues) }, usability: { scoreChange: analysis2.usability.score - analysis1.usability.score, newPatterns: findNewPatterns(analysis1.usability.patterns, analysis2.usability.patterns) }, components: compareComponents(analysis1.components, analysis2.components), recommendations: generateComparisonRecommendations(analysis1, analysis2) }; await screenshotCapture.cleanup(); return { content: [{ type: 'text', text: JSON.stringify(comparison, null, 2) }] }; } }; /** * Suggest UI improvements - AI-powered improvement recommendations */ export const suggest_ui_improvements = { name: 'suggest_ui_improvements', description: `Get AI-powered UI/UX improvement suggestions for any website. Provides: - Prioritized improvement recommendations - Implementation difficulty estimates - Expected impact analysis - Step-by-step implementation guides - Best practice examples - Metrics to track success Suggestions cover: - Accessibility enhancements - Usability improvements - Performance optimizations - Visual design refinements - Conversion rate optimization`, inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'URL to analyze for improvements' }, goals: { type: 'array', description: 'Specific improvement goals', items: { type: 'string', enum: ['conversion', 'accessibility', 'performance', 'aesthetics', 'usability', 'mobile'] } }, maxSuggestions: { type: 'number', description: 'Maximum number of suggestions', default: 10 } }, required: ['url'] }, handler: async (args) => { const screenshots = await screenshotCapture.captureScreenshot({ url: args.url, fullPage: false }); const analysis = await uiAnalyzer.analyzeUI(screenshots, args.url); const improvements = await uiAnalyzer.generateImprovements(analysis); // Filter and prioritize based on goals let filtered = improvements; if (args.goals && args.goals.length > 0) { filtered = improvements.filter(imp => args.goals.includes(imp.category)); } // Sort by impact and effort const prioritized = filtered.sort((a, b) => { const scoreA = getImpactScore(a.impact) / getEffortScore(a.effort); const scoreB = getImpactScore(b.impact) / getEffortScore(b.effort); return scoreB - scoreA; }).slice(0, args.maxSuggestions); const response = { url: args.url, totalSuggestions: prioritized.length, currentScores: { accessibility: analysis.accessibility.score, usability: analysis.usability.score }, improvements: prioritized.map((imp, index) => ({ priority: index + 1, ...imp, estimatedImpact: `${getImpactScore(imp.impact) * 20}% improvement`, timeToImplement: getTimeEstimate(imp.effort) })), quickWins: prioritized.filter(imp => imp.effort === 'low' && imp.impact === 'high'), implementationPlan: generateImplementationPlan(prioritized) }; await screenshotCapture.cleanup(); return { content: [{ type: 'text', text: JSON.stringify(response, null, 2) }] }; } }; /** * Analyze UI components - identify and analyze reusable components */ export const analyze_ui_components = { name: 'analyze_ui_components', description: `Identify and analyze all UI components in a design. Discovers: - Component inventory (buttons, cards, forms, etc.) - Component variations and states - Consistency analysis - Reusability opportunities - Component hierarchy - Design patterns used Great for: - Building component libraries - Ensuring design consistency - Documentation - Design system audits`, inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'URL to analyze components' }, componentTypes: { type: 'array', description: 'Specific component types to focus on', items: { type: 'string' } }, generateCode: { type: 'boolean', description: 'Generate component code snippets', default: false } }, required: ['url'] }, handler: async (args) => { const screenshots = await screenshotCapture.captureScreenshot({ url: args.url, fullPage: true }); const analysis = await uiAnalyzer.analyzeUI(screenshots, args.url); const componentReport = { url: args.url, totalComponents: analysis.components.length, componentInventory: analysis.components.map(comp => ({ name: comp.name, type: comp.type, instances: comp.instances, consistencyScore: comp.consistency, variants: comp.variants.map(v => ({ name: v.name, usage: v.usage, properties: v.properties })), recommendations: generateComponentRecommendations(comp) })), designPatterns: identifyDesignPatterns(analysis.components), reusabilityScore: calculateReusabilityScore(analysis.components), suggestions: { componentsToCreate: findMissingComponents(analysis), componentsToConsolidate: findDuplicateComponents(analysis.components), consistencyImprovements: findInconsistentComponents(analysis.components) } }; if (args.generateCode) { componentReport.componentInventory.forEach((comp) => { comp.codeSnippet = generateComponentCode(comp); }); } await screenshotCapture.cleanup(); return { content: [{ type: 'text', text: JSON.stringify(componentReport, null, 2) }] }; } }; /** * Check design guidelines - validate against design standards */ export const check_design_guidelines = { name: 'check_design_guidelines', description: `Validate UI against specific design guidelines or standards. Checks compliance with: - Material Design - Human Interface Guidelines (iOS) - Custom design systems - Industry best practices - Brand guidelines Returns: - Compliance score - Specific violations - Fix recommendations - Implementation examples`, inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'URL to validate' }, guidelines: { type: 'array', description: 'Design guidelines to check against', items: { type: 'string', enum: ['material-design', 'ios-hig', 'wcag', 'custom'] } }, customGuidelines: { type: 'array', description: 'Custom guideline rules', items: { type: 'string' } } }, required: ['url', 'guidelines'] }, handler: async (args) => { const screenshots = await screenshotCapture.captureScreenshot({ url: args.url }); const analysis = await uiAnalyzer.analyzeUI(screenshots, args.url); // Prepare guidelines const guidelineRules = []; if (args.guidelines.includes('material-design')) { guidelineRules.push(...getMaterialDesignGuidelines()); } if (args.guidelines.includes('ios-hig')) { guidelineRules.push(...getIOSHIGGuidelines()); } if (args.customGuidelines) { guidelineRules.push(...args.customGuidelines); } const violations = await uiAnalyzer.checkDesignGuidelines(analysis, guidelineRules); const report = { url: args.url, guidelinesChecked: args.guidelines, complianceScore: Math.max(0, 100 - (violations.length * 5)), totalViolations: violations.length, violationsBySeverity: { errors: violations.filter(v => v.severity === 'error').length, warnings: violations.filter(v => v.severity === 'warning').length, info: violations.filter(v => v.severity === 'info').length }, violations: violations.map(v => ({ ...v, category: categorizeViolation(v.guideline), priority: v.severity === 'error' ? 'high' : v.severity === 'warning' ? 'medium' : 'low' })), recommendations: generateGuidelineRecommendations(violations, args.guidelines) }; await screenshotCapture.cleanup(); return { content: [{ type: 'text', text: JSON.stringify(report, null, 2) }] }; } }; /** * Create UI style guide - generate documentation from existing UI */ export const create_ui_style_guide = { name: 'create_ui_style_guide', description: `Automatically generate a comprehensive style guide from any website. Creates: - Complete design system documentation - Component library reference - Usage examples and code snippets - Design principles and patterns - Accessibility guidelines - Implementation notes Output formats: - Markdown documentation - HTML style guide - JSON design tokens - Figma-ready specifications`, inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'URL to generate style guide from' }, format: { type: 'string', enum: ['markdown', 'html', 'json', 'figma'], description: 'Output format', default: 'markdown' }, sections: { type: 'array', description: 'Sections to include', items: { type: 'string', enum: ['colors', 'typography', 'spacing', 'components', 'patterns', 'accessibility', 'usage'] } } }, required: ['url'] }, handler: async (args) => { const screenshots = await screenshotCapture.captureScreenshot({ url: args.url, fullPage: true }); const analysis = await uiAnalyzer.analyzeUI(screenshots, args.url); let styleGuide; switch (args.format) { case 'html': styleGuide = generateHTMLStyleGuide(analysis); break; case 'json': styleGuide = generateJSONStyleGuide(analysis); break; case 'figma': styleGuide = generateFigmaStyleGuide(analysis); break; default: styleGuide = generateMarkdownStyleGuide(analysis, args.sections); } await screenshotCapture.cleanup(); return { content: [{ type: 'text', text: styleGuide }] }; } }; /** * Analyze user flow - understand navigation and user journeys */ export const analyze_user_flow = { name: 'analyze_user_flow', description: `Analyze user flows and navigation patterns. Discovers: - Information architecture - Navigation structure - User journey paths - Conversion funnels - Pain points in flows - Optimization opportunities Helps with: - UX optimization - Conversion improvement - Navigation redesign - User journey mapping`, inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'Starting URL for flow analysis' }, flowType: { type: 'string', enum: ['general', 'conversion', 'onboarding', 'checkout', 'search'], description: 'Type of user flow to analyze' }, maxDepth: { type: 'number', description: 'Maximum navigation depth', default: 3 } }, required: ['url'] }, handler: async (args) => { const screenshots = await screenshotCapture.captureScreenshot({ url: args.url }); const analysis = await uiAnalyzer.analyzeUI(screenshots, args.url); const flowAnalysis = { url: args.url, flowType: args.flowType || 'general', navigation: { structure: analysis.navigation.structure, primaryPaths: analysis.navigation.userFlow.map(flow => ({ name: flow.name, steps: flow.steps.length, complexity: flow.complexity, completionRate: flow.completionRate })) }, keyFindings: { totalPaths: analysis.navigation.userFlow.length, avgPathLength: calculateAvgPathLength(analysis.navigation.userFlow), complexityScore: calculateFlowComplexity(analysis.navigation), bottlenecks: findFlowBottlenecks(analysis.navigation.userFlow) }, improvements: generateFlowImprovements(analysis.navigation, args.flowType), visualization: generateFlowDiagram(analysis.navigation) }; await screenshotCapture.cleanup(); return { content: [{ type: 'text', text: JSON.stringify(flowAnalysis, null, 2) }] }; } }; /** * Helper functions */ function generateCSSVariables(designSystem) { let css = ':root {\n'; // Colors designSystem.colors.primary.forEach((color, i) => { css += ` --color-primary-${i}: ${color};\n`; }); // Typography designSystem.typography.fonts.forEach((font, i) => { css += ` --font-family-${i}: ${font};\n`; }); // Spacing designSystem.spacing.scale.forEach((space, i) => { css += ` --spacing-${i}: ${space}px;\n`; }); css += '}'; return css; } function generateSCSSVariables(designSystem) { let scss = '// Design System Variables\n\n'; // Colors scss += '// Primary Colors\n'; designSystem.colors.primary.forEach((color, i) => { scss += `$color-primary-${i}: ${color};\n`; }); return scss; } function generateDesignTokens(designSystem) { return { color: designSystem.colors, typography: designSystem.typography, spacing: designSystem.spacing, effects: { shadows: designSystem.shadows, borders: designSystem.borders } }; } function groupIssuesByType(issues) { const grouped = {}; issues.forEach(issue => { grouped[issue.type] = (grouped[issue.type] || 0) + 1; }); return grouped; } function generateAccessibilityNextSteps(accessibility) { const steps = []; if (accessibility.score < 60) { steps.push('Address all critical accessibility issues immediately'); } if (accessibility.score < 80) { steps.push('Fix major accessibility issues within 30 days'); } steps.push('Implement automated accessibility testing'); steps.push('Conduct manual testing with screen readers'); return steps; } function calculateSimilarity(analysis1, analysis2) { // Simplified similarity calculation return 75; } function compareDesignSystems(ds1, ds2) { return { colorChanges: { added: [], removed: [], modified: [] }, typographyChanges: { fontChanges: [], sizeChanges: [] } }; } function findNewIssues(issues1, issues2) { return issues2.filter(i2 => !issues1.some(i1 => i1.type === i2.type && i1.description === i2.description)); } function findResolvedIssues(issues1, issues2) { return issues1.filter(i1 => !issues2.some(i2 => i1.type === i2.type && i1.description === i2.description)); } function findNewPatterns(patterns1, patterns2) { return patterns2.filter(p2 => !patterns1.some(p1 => p1.name === p2.name)); } function compareComponents(comps1, comps2) { return { added: comps2.filter(c2 => !comps1.some(c1 => c1.name === c2.name)), removed: comps1.filter(c1 => !comps2.some(c2 => c2.name === c1.name)), modified: [] }; } function generateComparisonRecommendations(analysis1, analysis2) { const recs = []; if (analysis2.accessibility.score > analysis1.accessibility.score) { recs.push('Continue accessibility improvements in the same direction'); } return recs; } function getImpactScore(impact) { return impact === 'high' ? 3 : impact === 'medium' ? 2 : 1; } function getEffortScore(effort) { return effort === 'high' ? 3 : effort === 'medium' ? 2 : 1; } function getTimeEstimate(effort) { return effort === 'low' ? '1-2 hours' : effort === 'medium' ? '1-2 days' : '3-5 days'; } function generateImplementationPlan(improvements) { return { phase1: improvements.filter(i => i.effort === 'low'), phase2: improvements.filter(i => i.effort === 'medium'), phase3: improvements.filter(i => i.effort === 'high') }; } function generateComponentRecommendations(comp) { const recs = []; if (comp.consistency < 80) { recs.push('Standardize component variations'); } return recs; } function identifyDesignPatterns(components) { return ['Card-based layout', 'Navigation drawer', 'Hero section']; } function calculateReusabilityScore(components) { const avgInstances = components.reduce((sum, c) => sum + c.instances, 0) / components.length; return Math.min(100, avgInstances * 10); } function findMissingComponents(analysis) { const common = ['Button', 'Card', 'Input', 'Modal', 'Navigation']; const existing = analysis.components.map((c) => c.name); return common.filter(c => !existing.includes(c)); } function findDuplicateComponents(components) { return components.filter(c => c.variants.length > 3); } function findInconsistentComponents(components) { return components.filter(c => c.consistency < 70); } function generateComponentCode(comp) { return `// ${comp.name} Component\nconst ${comp.name} = ({ variant = 'default', ...props }) => {\n return <div className="${comp.name.toLowerCase()}">{props.children}</div>\n}`; } function getMaterialDesignGuidelines() { return [ 'Use Material Design color system', 'Follow 8dp grid system', 'Use elevation for hierarchy', 'Implement proper touch targets (48dp minimum)' ]; } function getIOSHIGGuidelines() { return [ 'Use SF Pro font family', 'Follow iOS spacing guidelines', 'Implement proper tap targets (44pt minimum)', 'Use system colors when possible' ]; } function categorizeViolation(guideline) { if (guideline.includes('color')) return 'Color'; if (guideline.includes('spacing')) return 'Layout'; if (guideline.includes('font')) return 'Typography'; return 'General'; } function generateGuidelineRecommendations(violations, guidelines) { const recs = []; if (violations.filter(v => v.severity === 'error').length > 0) { recs.push('Address critical guideline violations first'); } return recs; } function generateMarkdownStyleGuide(analysis, sections) { let md = `# Style Guide\n\n`; md += `## Design System\n\n`; md += `### Colors\n\n`; md += `#### Primary Colors\n`; analysis.designSystem.colors.primary.forEach((color) => { md += `- ${color}\n`; }); // ... continue for other sections return md; } function generateHTMLStyleGuide(analysis) { return `<!DOCTYPE html><html><head><title>Style Guide</title></head><body>${JSON.stringify(analysis.designSystem)}</body></html>`; } function generateJSONStyleGuide(analysis) { return JSON.stringify({ version: '1.0', designSystem: analysis.designSystem, components: analysis.components, guidelines: [] }, null, 2); } function generateFigmaStyleGuide(analysis) { return JSON.stringify({ figmaTokens: { colors: analysis.designSystem.colors, typography: analysis.designSystem.typography } }, null, 2); } function calculateAvgPathLength(flows) { if (flows.length === 0) return 0; return flows.reduce((sum, f) => sum + f.steps.length, 0) / flows.length; } function calculateFlowComplexity(navigation) { return navigation.userFlow.reduce((max, f) => Math.max(max, f.complexity), 0); } function findFlowBottlenecks(flows) { return flows .filter(f => f.completionRate && f.completionRate < 50) .map(f => f.name); } function generateFlowImprovements(navigation, flowType) { const improvements = []; if (navigation.structure === 'network') { improvements.push('Consider simplifying navigation structure'); } return improvements; } function generateFlowDiagram(navigation) { return 'Flow diagram visualization data...'; } // Export all tools export const uiUnderstandingTools = [ analyze_ui_design, extract_design_system, check_ui_accessibility, compare_ui_designs, suggest_ui_improvements, analyze_ui_components, check_design_guidelines, create_ui_style_guide, analyze_user_flow ]; //# sourceMappingURL=ui-understanding-tools.js.map