Skip to main content
Glama

UX/UI Tools for React + Material-UI

index.js17.2 kB
#!/usr/bin/env node /** * UX/UI MCP Server * * Servidor MCP customizado para aplicar diretrizes de UX/UI em componentes React * com Material-UI, seguindo Heurísticas de Nielsen e Vieses Cognitivos. */ import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js'; // ============================================================================ // DADOS DAS DIRETRIZES UX/UI // ============================================================================ const UX_GUIDELINES = { responsividade: { description: "Torna componente responsivo e mobile-friendly", instructions: ` **Responsividade Mobile-First:** 1. Use useMediaQuery do MUI: \`\`\`typescript import { useMediaQuery, useTheme } from '@mui/material'; const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down('sm')); \`\`\` 2. Dimensões adaptativas: - Mobile: calc(100vw - 16px) ou 100% - Desktop: valores fixos (420px, 600px, etc.) 3. Touch targets mínimo 44x44px: \`\`\`typescript <IconButton sx={{ minWidth: 44, minHeight: 44 }}> \`\`\` 4. Breakpoints MUI: - xs: 0px (mobile pequeno) - sm: 600px (mobile grande/tablet) - md: 900px (tablet grande) - lg: 1200px (desktop) - xl: 1536px (desktop grande) 5. Transições por dispositivo: - Mobile: Slide up - Desktop: Slide down ou Fade `, example: ` const isMobile = useMediaQuery(theme.breakpoints.down('sm')); <Box sx={{ width: isMobile ? 'calc(100vw - 16px)' : 420, height: isMobile ? '70vh' : 'min(600px, 80vh)', }} > <Slide direction={isMobile ? 'up' : 'down'}> {children} </Slide> </Box> ` }, materialUI: { description: "Aplica best practices do Material-UI", instructions: ` **Material-UI Best Practices:** 1. Use theme.spacing (múltiplos de 8px): \`\`\`typescript sx={{ padding: theme.spacing(2), margin: theme.spacing(1, 2) }} \`\`\` 2. Use alpha() para transparências: \`\`\`typescript import { alpha } from '@mui/material/styles'; bgcolor: alpha(theme.palette.primary.main, 0.1) \`\`\` 3. Prefira sx prop ao invés de styled: \`\`\`typescript <Box sx={{ display: 'flex', gap: 2 }} /> \`\`\` 4. Componentes nativos MUI: - Stack para layout linear - Box para container genérico - Paper para elevação/card 5. Transitions suaves: \`\`\`typescript transition: theme.transitions.create(['all'], { duration: theme.transitions.duration.standard, easing: theme.transitions.easing.easeInOut, }) \`\`\` `, example: ` <Paper sx={{ p: theme.spacing(3), bgcolor: alpha(theme.palette.background.paper, 0.95), transition: theme.transitions.create(['transform', 'box-shadow'], { duration: 250, easing: 'cubic-bezier(0.4, 0, 0.2, 1)', }), '&:hover': { transform: 'translateY(-2px)', boxShadow: theme.shadows[8], }, }} > ` }, appleDesign: { description: "Aplica padrões de design Apple", instructions: ` **Apple Design Patterns:** 1. Scrollbar customizada fina: \`\`\`typescript sx={{ overflowY: 'auto', '&::-webkit-scrollbar': { width: 8 }, '&::-webkit-scrollbar-thumb': { bgcolor: alpha(theme.palette.text.secondary, 0.2), borderRadius: 4, '&:hover': { bgcolor: alpha(theme.palette.text.secondary, 0.3), }, }, }} \`\`\` 2. Animações suaves com cubic-bezier: - transition: 'all 0.25s cubic-bezier(0.4, 0, 0.2, 1)' 3. Pulse animation para badges: \`\`\`typescript '@keyframes pulse': { '0%': { transform: 'scale(1)', opacity: 1 }, '50%': { transform: 'scale(1.1)', opacity: 0.8 }, '100%': { transform: 'scale(1)', opacity: 1 }, }, animation: 'pulse 2s infinite', \`\`\` 4. Design minimalista: - Espaçamento generoso - Cores neutras com acentos sutis - Bordas arredondadas (borderRadius: 2-3) `, example: ` <Box sx={{ overflowY: 'auto', '&::-webkit-scrollbar': { width: 8 }, '&::-webkit-scrollbar-thumb': { bgcolor: alpha(theme.palette.text.secondary, 0.2), borderRadius: 4, }, }} > <Badge badgeContent={count} sx={{ '& .MuiBadge-badge': { animation: count > 0 ? 'pulse 2s infinite' : 'none', }, }} /> </Box> ` }, nielsen1: { description: "Nielsen #1 - Visibilidade do Status do Sistema", instructions: ` **Feedback Visual Constante:** 1. Loading states em ações: \`\`\`typescript <Button disabled={isLoading}> {isLoading ? <CircularProgress size={20} /> : 'Salvar'} </Button> \`\`\` 2. Badges de contagem: \`\`\`typescript <Badge badgeContent={unreadCount} color="error"> \`\`\` 3. Progress indicators: \`\`\`typescript <LinearProgress variant="determinate" value={progress} /> \`\`\` 4. Tooltips informativos: \`\`\`typescript <Tooltip title="Carregando dados..."> \`\`\` 5. Snackbar para confirmações: \`\`\`typescript enqueueSnackbar('Salvo com sucesso!', { variant: 'success' }); \`\`\` ` }, nielsen2: { description: "Nielsen #2 - Relação Sistema-Mundo Real", instructions: ` **Linguagem do Usuário:** 1. Evite jargões técnicos: - ✅ "Conversas" ao invés de "Tickets" - ✅ "Taxa de conversão" ao invés de "CVR" 2. Ícones reconhecíveis: - NotificationsOutlined para notificações - PersonOutlined para usuário - SearchOutlined para busca 3. Ordenação natural: - Mais recente primeiro - Alfabética quando faz sentido - Por prioridade/urgência ` }, nielsen3: { description: "Nielsen #3 - Controle e Liberdade do Usuário", instructions: ` **Controle do Usuário:** 1. Sempre ofereça botão cancelar: \`\`\`typescript <DialogActions> <Button onClick={onClose}>Cancelar</Button> <Button variant="contained" onClick={onSave}>Salvar</Button> </DialogActions> \`\`\` 2. Ações reversíveis: - Botão fechar em modais - Confirmação antes de exclusão 3. Não trave fluxos: - Permita fechar/voltar a qualquer momento ` }, nielsen5: { description: "Nielsen #5 - Prevenção de Erros", instructions: ` **Prevenção de Erros:** 1. Validação em tempo real: \`\`\`typescript <TextField error={!!errors.cpf} helperText={errors.cpf?.message} inputProps={{ maxLength: 14, pattern: '[0-9.-]*' }} /> \`\`\` 2. Placeholders demonstrativos: \`\`\`typescript placeholder="000.000.000-00" \`\`\` 3. Disabled states: \`\`\`typescript <Button disabled={!isValid || isLoading}> \`\`\` 4. Confirmação em ações destrutivas: \`\`\`typescript <ConfirmDialog title="Excluir item?" message="Esta ação não pode ser desfeita" /> \`\`\` ` }, fittssLaw: { description: "Lei de Fitts - Targets maiores e próximos", instructions: ` **Lei de Fitts:** 1. Touch targets mínimo 44x44px: \`\`\`typescript <IconButton sx={{ minWidth: 44, minHeight: 44 }}> \`\`\` 2. Botões principais maiores: \`\`\`typescript <Button size="large" variant="contained"> \`\`\` 3. Espaçamento adequado: \`\`\`typescript <Stack spacing={2} direction="row"> \`\`\` 4. Ações frequentes próximas: - Coloque no header ou rodapé - Fácil acesso com polegar (mobile) ` }, groupingEffect: { description: "Efeito de Agrupamento - Itens relacionados juntos", instructions: ` **Agrupamento Visual:** 1. Stack para agrupar: \`\`\`typescript <Stack spacing={2}> <TextField label="Nome" /> <TextField label="Email" /> </Stack> \`\`\` 2. Divider entre seções: \`\`\`typescript <Divider sx={{ my: 2 }} /> \`\`\` 3. Cards para contextos: \`\`\`typescript <Paper elevation={2}> {/* conteúdo relacionado */} </Paper> \`\`\` 4. Typography para títulos de seção: \`\`\`typescript <Typography variant="h6" sx={{ mb: 2 }}> Dados Pessoais </Typography> \`\`\` ` }, completeUX: { description: "Aplica TODAS as diretrizes de UX/UI", instructions: ` **Checklist Completo:** ✅ Responsividade Mobile-First ✅ Material-UI Best Practices ✅ Apple Design Patterns ✅ 10 Heurísticas de Nielsen ✅ Vieses Cognitivos (Fitts, Grouping, Proximity, etc.) **Aplique:** 1. useMediaQuery para responsividade 2. theme.spacing para espaçamentos 3. alpha() para transparências 4. Tooltips em todos botões/ícones 5. Loading states em ações 6. Mensagens de erro claras 7. Touch targets ≥ 44px 8. Transições suaves 9. Scrollbar customizada 10. Validação em tempo real ` } }; // ============================================================================ // CRIAR SERVIDOR MCP // ============================================================================ const server = new Server( { name: 'better-ux-server', version: '1.0.0', }, { capabilities: { tools: {}, }, } ); // ============================================================================ // LISTAR TOOLS DISPONÍVEIS // ============================================================================ server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: 'apply_responsiveness', description: 'Aplica responsividade mobile-first em componente React/MUI', inputSchema: { type: 'object', properties: { component: { type: 'string', description: 'Código do componente ou nome do arquivo', }, }, required: ['component'], }, }, { name: 'apply_material_ui_best_practices', description: 'Aplica best practices do Material-UI (theme.spacing, alpha, sx prop)', inputSchema: { type: 'object', properties: { component: { type: 'string', description: 'Código do componente ou nome do arquivo', }, }, required: ['component'], }, }, { name: 'apply_apple_design', description: 'Aplica padrões de design Apple (scrollbar, animações, minimalismo)', inputSchema: { type: 'object', properties: { component: { type: 'string', description: 'Código do componente ou nome do arquivo', }, }, required: ['component'], }, }, { name: 'apply_nielsen_heuristic', description: 'Aplica uma heurística específica de Nielsen', inputSchema: { type: 'object', properties: { component: { type: 'string', description: 'Código do componente ou nome do arquivo', }, heuristic: { type: 'string', enum: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'], description: 'Número da heurística (1-10)', }, }, required: ['component', 'heuristic'], }, }, { name: 'apply_cognitive_bias', description: 'Aplica viés cognitivo específico para melhor UX', inputSchema: { type: 'object', properties: { component: { type: 'string', description: 'Código do componente ou nome do arquivo', }, bias: { type: 'string', enum: ['fitts', 'grouping', 'proximity', 'zeigarnik', 'serial-position', 'hicks'], description: 'Viés cognitivo a aplicar', }, }, required: ['component', 'bias'], }, }, { name: 'apply_complete_ux', description: 'Aplica TODAS as diretrizes de UX/UI (responsividade, MUI, Apple, Nielsen, vieses)', inputSchema: { type: 'object', properties: { component: { type: 'string', description: 'Código do componente ou nome do arquivo', }, }, required: ['component'], }, }, { name: 'get_ux_checklist', description: 'Retorna checklist de UX/UI para validação', inputSchema: { type: 'object', properties: {}, }, }, ], }; }); // ============================================================================ // EXECUTAR TOOLS // ============================================================================ server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { switch (name) { case 'apply_responsiveness': return { content: [ { type: 'text', text: `${UX_GUIDELINES.responsividade.instructions}\n\n**Exemplo:**\n${UX_GUIDELINES.responsividade.example}\n\n**Componente:** ${args.component}`, }, ], }; case 'apply_material_ui_best_practices': return { content: [ { type: 'text', text: `${UX_GUIDELINES.materialUI.instructions}\n\n**Exemplo:**\n${UX_GUIDELINES.materialUI.example}\n\n**Componente:** ${args.component}`, }, ], }; case 'apply_apple_design': return { content: [ { type: 'text', text: `${UX_GUIDELINES.appleDesign.instructions}\n\n**Exemplo:**\n${UX_GUIDELINES.appleDesign.example}\n\n**Componente:** ${args.component}`, }, ], }; case 'apply_nielsen_heuristic': const nielsenKey = `nielsen${args.heuristic}`; const nielsen = UX_GUIDELINES[nielsenKey]; if (!nielsen) { return { content: [ { type: 'text', text: `Heurística ${args.heuristic} não encontrada. Use 1-10.`, }, ], isError: true, }; } return { content: [ { type: 'text', text: `**${nielsen.description}**\n\n${nielsen.instructions}\n\n**Componente:** ${args.component}`, }, ], }; case 'apply_cognitive_bias': const biasMap = { fitts: 'fittssLaw', grouping: 'groupingEffect', }; const biasKey = biasMap[args.bias]; const bias = UX_GUIDELINES[biasKey]; if (!bias) { return { content: [ { type: 'text', text: `Viés ${args.bias} não encontrado.`, }, ], isError: true, }; } return { content: [ { type: 'text', text: `**${bias.description}**\n\n${bias.instructions}\n\n**Componente:** ${args.component}`, }, ], }; case 'apply_complete_ux': return { content: [ { type: 'text', text: `${UX_GUIDELINES.completeUX.instructions}\n\n**Componente:** ${args.component}\n\nAplique TODAS as diretrizes acima no componente especificado.`, }, ], }; case 'get_ux_checklist': return { content: [ { type: 'text', text: ` **Checklist UX/UI - better2 Frontend** Antes de finalizar qualquer componente visual: - [ ] Responsivo (mobile, tablet, desktop) - [ ] Touch targets ≥ 44px - [ ] Todos botões/ícones têm tooltip - [ ] Loading states implementados - [ ] Mensagens de erro claras - [ ] Theme.spacing usado - [ ] Alpha() para transparências - [ ] Transições suaves - [ ] Acessibilidade (tab navigation) - [ ] Testado em mobile real - [ ] Scrollbar customizada (se lista/scroll) - [ ] Validação em tempo real (se formulário) - [ ] Botão cancelar (se modal/dialog) - [ ] Feedback visual em ações - [ ] Agrupamento lógico de elementos `, }, ], }; default: return { content: [ { type: 'text', text: `Tool desconhecida: ${name}`, }, ], isError: true, }; } } catch (error) { return { content: [ { type: 'text', text: `Erro ao executar tool: ${error.message}`, }, ], isError: true, }; } }); // ============================================================================ // INICIAR SERVIDOR // ============================================================================ async function main() { const transport = new StdioServerTransport(); await server.connect(transport); console.error('better UX/UI MCP Server rodando via stdio'); } main().catch((error) => { console.error('Erro fatal:', error); process.exit(1); });

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/MarcusViniciusBarcelos/uiux-tools-react-mui'

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