Skip to main content
Glama

FitSlot MCP Server

by osmarsant
AGENTS.md16.6 kB
# AI Agent Guidelines for FitSlot MCP Server Este documento fornece diretrizes, padrões e boas práticas para agentes de IA trabalhando neste projeto. Siga estas instruções para manter consistência, qualidade e segurança no código. ## 🎯 Visão Geral do Projeto **FitSlot MCP Server** é um servidor MCP (Model Context Protocol) para integração com a API FitSlot, fornecendo: - Gerenciamento de tickets de suporte - Chatbot com FAQs - Análise de documentos PDF de bioimpedância **Stack Tecnológica:** - TypeScript 5.x - Node.js 18+ - MCP SDK (@modelcontextprotocol/sdk) - Arquitetura em camadas (Services, Tools, Utils) ## 📐 Padrões Arquiteturais ### Arquitetura em Camadas ``` ┌─────────────────────────────────────┐ │ index.ts (MCP Server) │ ← Entry point ├─────────────────────────────────────┤ │ tools/ (MCP Tools) │ ← Interface MCP ├─────────────────────────────────────┤ │ services/ (Business Logic) │ ← Lógica de negócio ├─────────────────────────────────────┤ │ utils/ (Utilities) │ ← Funções auxiliares ├─────────────────────────────────────┤ │ types/ (Type Definitions) │ ← Tipos TypeScript └─────────────────────────────────────┘ ``` **Princípios:** 1. **Separação de Responsabilidades**: Cada camada tem uma responsabilidade específica 2. **Dependência Unidirecional**: Camadas superiores dependem das inferiores, nunca o contrário 3. **Injeção de Dependências**: Services são injetados em Tools no `index.ts` ### Estrutura de Arquivos ``` src/ ├── index.ts # MCP Server principal ├── services/ # Camada de serviços │ ├── fitslot-api.service.ts # Integração com API externa │ ├── chatbot.service.ts # Lógica do chatbot │ └── pdf-analysis.service.ts # Análise de PDFs ├── tools/ # Ferramentas MCP │ ├── ticket.tools.ts # Tools de tickets │ ├── chatbot.tools.ts # Tools de chatbot │ └── pdf.tools.ts # Tools de PDF ├── types/ # Definições de tipos │ └── index.ts # Tipos centralizados └── utils/ # Utilitários ├── logger.ts # Sistema de logging └── validation.ts # Validações dist/ # Código compilado (não commitar) node_modules/ # Dependências (não commitar) ``` ## 🔧 Padrões de Código ### 1. Nomenclatura #### Classes e Interfaces ```typescript // ✅ Correto - PascalCase export class FitSlotAPIService { } export interface Ticket { } export interface BioimpedanceData { } // ❌ Incorreto export class fitslotAPIService { } export interface ticket { } ``` #### Funções e Métodos ```typescript // ✅ Correto - camelCase, verbos descritivos async createTicket(request: CreateTicketRequest): Promise<Ticket> { } async analyzeBioimpedancePDF(filePath: string): Promise<BioimpedanceData> { } // ❌ Incorreto async CreateTicket() { } // PascalCase async ticket() { } // Substantivo ``` #### Variáveis e Constantes ```typescript // ✅ Correto const ticketId = 'ticket_123'; const MAX_RETRIES = 3; const API_TIMEOUT = 30000; // ❌ Incorreto const TicketId = 'ticket_123'; const maxRetries = 3; // Constante deve ser UPPER_SNAKE_CASE ``` #### Arquivos ```typescript // ✅ Correto - kebab-case fitslot-api.service.ts chatbot.service.ts pdf-analysis.service.ts // ❌ Incorreto FitSlotApiService.ts chatbot_service.ts ``` ### 2. Estrutura de Serviços **Template de Service:** ```typescript /** * [Nome do Serviço] * [Descrição do que o serviço faz] */ import { logger } from '../utils/logger.js'; import { /* tipos necessários */ } from '../types/index.js'; export class [Nome]Service { private config: [ConfigType]; constructor(config: [ConfigType]) { this.config = config; // Inicialização } /** * [Descrição do método] * @param param - Descrição do parâmetro * @returns Descrição do retorno * @throws Condições de erro */ async [nomeMetodo](param: Type): Promise<ReturnType> { try { logger.info('[Ação iniciada]', { param }); // Lógica do método logger.info('[Ação concluída]'); return result; } catch (error) { logger.error('[Ação falhou]', error); throw error; } } } ``` **Exemplo Real:** ```typescript export class PDFAnalysisService { async analyzeBioimpedancePDF(filePath: string): Promise<BioimpedanceData> { try { logger.info('Starting PDF analysis', { filePath }); const dataBuffer = await fs.readFile(filePath); const pdfParser = new PDFParse({ data: dataBuffer }); const textResult = await pdfParser.getText(); const extractedData = this.extractBioimpedanceData(textResult.text); const analysis = this.generateAnalysis(extractedData); const recommendations = this.generateRecommendations(extractedData); logger.info('PDF analysis completed successfully'); return { ...extractedData, analysis, recommendations }; } catch (error) { logger.error('Failed to analyze PDF', error); throw new Error(`PDF analysis failed: ${error instanceof Error ? error.message : 'Unknown error'}`); } } } ``` ### 3. Estrutura de Tools **Template de Tool:** ```typescript /** * [Nome das Tools] para MCP Server */ import { z } from 'zod'; import { logger } from '../utils/logger.js'; import { validateNotEmpty, validateEnum } from '../utils/validation.js'; export function create[Nome]Tools(service: [ServiceType]) { return { tool_name: { description: 'Descrição clara do que a ferramenta faz', parameters: z.object({ param1: z.string().describe('Descrição do parâmetro'), param2: z.enum(['option1', 'option2']).optional().describe('Parâmetro opcional') }), execute: async (args: { param1: string; param2?: string }) => { try { logger.info('Executing tool', args); // Validações validateNotEmpty(args.param1, 'Param1'); // Executar lógica usando o service const result = await service.method(args.param1); // Retornar sucesso return { content: [{ type: 'text', text: JSON.stringify({ success: true, result }, null, 2) }] }; } catch (error) { logger.error('Tool execution failed', error); return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: error instanceof Error ? error.message : 'Unknown error' }, null, 2) }], isError: true }; } } } }; } ``` ### 4. Sistema de Logging **Sempre use o logger estruturado:** ```typescript import { logger } from '../utils/logger.js'; // ✅ Correto logger.debug('Detailed info', { data: complexObject }); logger.info('Action completed', { userId, ticketId }); logger.warn('Unexpected condition', { condition }); logger.error('Operation failed', error); // ❌ Incorreto console.log('Something happened'); // Não use console.log console.error(error); // Não use console.error ``` **Níveis de Log:** - `DEBUG`: Informações detalhadas para debugging - `INFO`: Eventos importantes da aplicação - `WARN`: Situações inesperadas mas recuperáveis - `ERROR`: Erros que precisam atenção ### 5. Validação de Entrada **SEMPRE valide inputs do usuário:** ```typescript import { validateNotEmpty, validateEnum, validateRange } from '../utils/validation.js'; // ✅ Correto validateNotEmpty(args.title, 'Title'); validateEnum(args.priority, TicketPriority, 'Priority'); validateRange(args.age, 0, 120, 'Age'); // Validação customizada if (!args.email.includes('@')) { throw new Error('Email must be valid'); } // ❌ Incorreto - sem validação const ticket = await service.createTicket(args); // Perigoso! ``` ### 6. Tratamento de Erros **Padrão de Error Handling:** ```typescript // ✅ Correto try { logger.info('Starting operation', { params }); const result = await riskyOperation(); logger.info('Operation completed successfully'); return result; } catch (error) { logger.error('Operation failed', error); throw new Error('User-friendly error message'); } // ❌ Incorreto try { const result = await riskyOperation(); return result; } catch (error) { throw error; // Não adiciona contexto } ``` **Erros em Tools MCP:** ```typescript // ✅ Sempre retorne estrutura consistente return { content: [{ type: 'text', text: JSON.stringify({ success: false, error: 'Clear error message', details: additionalInfo // Opcional }, null, 2) }], isError: true }; ``` ## 🛡️ Guardrails de Segurança ### 1. Nunca Commite Credenciais ```typescript // ✅ Correto - use variáveis de ambiente const apiKey = process.env.FITSLOT_API_KEY; const apiUrl = process.env.FITSLOT_API_URL || 'https://api.fitslot.com'; // ❌ NUNCA faça isso const apiKey = 'sk-123456789abcdef'; // PERIGOSO! ``` ### 2. Sanitize User Input ```typescript import { sanitizeText } from '../utils/validation.js'; // ✅ Correto const cleanTitle = sanitizeText(userInput.title); // ❌ Incorreto - usar input direto const query = `SELECT * FROM tickets WHERE title = '${userInput.title}'`; // SQL Injection! ``` ### 3. Limite Tamanho de Inputs ```typescript // ✅ Correto if (args.description.length > 5000) { throw new Error('Description must be less than 5000 characters'); } // Ou use Zod parameters: z.object({ description: z.string().max(5000).describe('Ticket description') }) ``` ### 4. Valide File Paths ```typescript import * as path from 'path'; import * as fs from 'fs/promises'; // ✅ Correto async function readFile(filePath: string) { // Normalize path const normalizedPath = path.normalize(filePath); // Check if file exists try { await fs.access(normalizedPath); } catch { throw new Error(`File not found: ${filePath}`); } // Prevent directory traversal if (normalizedPath.includes('..')) { throw new Error('Invalid file path'); } return await fs.readFile(normalizedPath); } // ❌ Incorreto async function readFile(filePath: string) { return await fs.readFile(filePath); // Vulnerável a path traversal } ``` ## 📝 Documentação ### JSDoc para Funções Públicas ```typescript /** * Create a new support ticket in the FitSlot system * * @param request - Ticket creation parameters including title, description, and priority * @returns Created ticket with generated ID and timestamps * @throws {Error} If validation fails or API is unavailable * * @example * ```typescript * const ticket = await service.createTicket({ * title: 'Login issue', * description: 'Cannot login', * priority: TicketPriority.HIGH, * userId: 'user123' * }); * ``` */ async createTicket(request: CreateTicketRequest): Promise<Ticket> { // Implementation } ``` ### Comentários no Código ```typescript // ✅ Bons comentários - explicam o "porquê" // Calculate BMI if not found in PDF // BMI formula: weight(kg) / (height(m))^2 const heightInMeters = data.height / 100; data.bmi = parseFloat((data.weight / (heightInMeters * heightInMeters)).toFixed(2)); // ❌ Comentários ruins - explicam o "como" (óbvio) // Loop through array for (const item of array) { // Add to sum sum += item; } ``` ## 🧪 Testes (Futuro) ### Estrutura de Testes ```typescript describe('FitSlotAPIService', () => { let service: FitSlotAPIService; beforeEach(() => { service = new FitSlotAPIService({ apiUrl: 'https://test.api.com', apiKey: 'test-key' }); }); describe('createTicket', () => { it('should create ticket with valid data', async () => { const request: CreateTicketRequest = { title: 'Test', description: 'Test description', priority: TicketPriority.MEDIUM, userId: 'user123' }; const result = await service.createTicket(request); expect(result.id).toBeDefined(); expect(result.status).toBe(TicketStatus.OPEN); }); it('should throw error with empty title', async () => { const request: CreateTicketRequest = { title: '', description: 'Test', priority: TicketPriority.MEDIUM, userId: 'user123' }; await expect(service.createTicket(request)).rejects.toThrow(); }); }); }); ``` ## 🚀 Workflow de Desenvolvimento ### 1. Antes de Adicionar Nova Funcionalidade ```bash # 1. Criar branch git checkout -b feature/nova-funcionalidade # 2. Verificar build atual npm run build # 3. Instalar dependências se necessário npm install ``` ### 2. Durante o Desenvolvimento ```bash # Desenvolvimento com hot reload npm run dev # Build incremental npm run build # Limpar build anterior npm run clean ``` ### 3. Antes de Commitar ```bash # Build final npm run build # Verificar tipos npx tsc --noEmit # Verificar se não há erros npm run build ``` ## 📦 Adicionando Novas Dependências ### Checklist - [ ] A dependência é realmente necessária? - [ ] Não há alternativa nativa ou já incluída? - [ ] A licença é compatível (ISC, MIT, Apache 2.0)? - [ ] Não há vulnerabilidades conhecidas? - [ ] A dependência é mantida ativamente? ### Instalação ```bash # Produção npm install --save nome-da-dependencia # Desenvolvimento npm install --save-dev nome-da-dependencia # Verificar vulnerabilidades npm audit ``` ## 🎨 Padrões de Resposta ### Sucesso ```json { "success": true, "message": "Operation completed successfully", "data": { // Dados relevantes } } ``` ### Erro ```json { "success": false, "error": "User-friendly error message", "details": "Additional context (optional)" } ``` ### Lista ```json { "success": true, "count": 10, "items": [ // Array de itens ] } ``` ## ⚠️ Anti-Patterns a Evitar ### 1. God Objects ```typescript // ❌ Incorreto - classe faz tudo class FitSlotService { createTicket() { } updateTicket() { } answerFAQ() { } analyzePDF() { } sendEmail() { } generateReport() { } } // ✅ Correto - responsabilidades separadas class TicketService { } class ChatbotService { } class PDFAnalysisService { } ``` ### 2. Magic Numbers ```typescript // ❌ Incorreto if (priority > 3) { } setTimeout(() => { }, 30000); // ✅ Correto const MAX_PRIORITY = 3; const API_TIMEOUT = 30000; if (priority > MAX_PRIORITY) { } setTimeout(() => { }, API_TIMEOUT); ``` ### 3. Callback Hell ```typescript // ❌ Incorreto getData((data) => { processData(data, (result) => { saveData(result, (saved) => { notify(saved, () => { // ... }); }); }); }); // ✅ Correto - use async/await const data = await getData(); const result = await processData(data); const saved = await saveData(result); await notify(saved); ``` ## 📚 Recursos - [TypeScript Handbook](https://www.typescriptlang.org/docs/) - [MCP Documentation](https://modelcontextprotocol.io/) - [Node.js Best Practices](https://github.com/goldbergyoni/nodebestpractices) - [Clean Code JavaScript](https://github.com/ryanmcdermott/clean-code-javascript) ## 🤝 Quando Modificar Este Documento Este documento deve ser atualizado quando: - Novos padrões são estabelecidos - Mudanças arquiteturais são feitas - Novos anti-patterns são identificados - Ferramentas ou dependências principais mudam --- **Lembre-se:** Estes padrões existem para manter qualidade, consistência e segurança. Quando em dúvida, consulte este documento ou revise o código existente para exemplos.

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/osmarsant/fitslot-mcp'

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