# MCP Evaluation Guide > Guia para criar e executar evaluations de servidores MCP. > Baseado nos padrões do mcp-builder Anthropic. --- ## O que são Evaluations MCP? Evaluations são testes estruturados que validam o comportamento de um MCP em cenários reais. Não testam apenas se as ferramentas existem — testam se produzem **resultados correctos, seguros e previsíveis**. **Objectivos:** - Garantir que cada tool faz o que a descrição promete - Detectar regressões após alterações - Validar edge cases e erros esperados - Confirmar que annotations correspondem ao comportamento real --- ## Estrutura de uma Evaluation Cada evaluation é definida em XML e contém: ```xml get_customer_basic Verifica que get_customer retorna dados completos de um cliente existente get_customer 1 name email true ``` --- ## 10 Perguntas de Evaluation por MCP Para cada MCP novo, responder a estas 10 perguntas criando um teste para cada uma: ```xml A tool {principal} retorna dados quando recebe input válido? Input mínimo válido Resposta não é erro, contém campos esperados O que acontece com input inválido (ID negativo, campo obrigatório em falta)? Input inválido ou em falta Resposta tem isError=true, mensagem é accionável O que retorna quando o recurso pedido não existe (ID=99999)? Recurso não encontrado Mensagem clara "não encontrado", não retorna null silencioso Operações com idempotentHint=true produzem o mesmo resultado em chamadas repetidas? Chamar a mesma tool create/update duas vezes com os mesmos parâmetros Segundo resultado idêntico ao primeiro ou erro controlado Tools com destructiveHint=true apagam realmente dados? O utilizador é avisado? Executar delete em recurso existente Dados apagados. Mensagem confirma acção irreversível Tools com readOnlyHint=true não modificam dados? Executar get/list e verificar estado antes e depois Estado da BD/sistema idêntico antes e depois da chamada Tools de listagem com muitos resultados retornam dados paginados correctamente? Lista com 1000+ registos, pedir página 2 Retorna subset correcto, metadados de paginação presentes Chamadas sem credenciais válidas são rejeitadas? Remover variável de ambiente com API key e chamar tool Erro claro de autenticação, não crash do servidor O campo structuredContent contém os mesmos dados que o texto Markdown? Comparar campos em structuredContent com conteúdo do text Dados idênticos em ambos os formatos A tool responde em menos de 5 segundos em condições normais? Medir tempo de resposta em 10 chamadas consecutivas p95 < 5000ms, sem memory leaks após 100 chamadas ``` --- ## Como Executar Evaluations ### Método Manual (MCP Inspector) ```bash # Instalar MCP Inspector npx @modelcontextprotocol/inspector # Conectar ao MCP local # Interface web em http://localhost:5173 # Testar cada tool manualmente ``` ### Método Automatizado (Script TypeScript) ```typescript // eval/run-evals.ts import { Client } from '@modelcontextprotocol/sdk/client/index.js'; import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js'; interface EvalResult { id: string; passed: boolean; duration: number; error?: string; } async function runEval( client: Client, toolName: string, input: Record, assertions: { notError?: boolean; containsFields?: string[]; isError?: boolean; } ): Promise { const start = Date.now(); try { const result = await client.callTool({ name: toolName, arguments: input }); const duration = Date.now() - start; // Verificar assertions if (assertions.notError && result.isError) { return { id: toolName, passed: false, duration, error: 'Esperava sucesso, recebeu erro' }; } if (assertions.isError && !result.isError) { return { id: toolName, passed: false, duration, error: 'Esperava erro, recebeu sucesso' }; } if (assertions.containsFields) { const text = result.content[0]?.text || ''; for (const field of assertions.containsFields) { if (!text.includes(field)) { return { id: toolName, passed: false, duration, error: `Campo "${field}" não encontrado` }; } } } return { id: toolName, passed: true, duration }; } catch (err) { return { id: toolName, passed: false, duration: Date.now() - start, error: err instanceof Error ? err.message : String(err) }; } } // Executar todas as evaluations async function main() { const transport = new StdioClientTransport({ command: 'node', args: ['dist/index.js'] }); const client = new Client({ name: 'eval-client', version: '1.0.0' }); await client.connect(transport); const results: EvalResult[] = []; // Eval 1: Tool básica results.push(await runEval(client, 'get_customer', { customer_id: 1 }, { notError: true, containsFields: ['name', 'email'] })); // Eval 2: Input inválido results.push(await runEval(client, 'get_customer', { customer_id: -1 }, { isError: true })); // Eval 3: Recurso inexistente results.push(await runEval(client, 'get_customer', { customer_id: 99999 }, { isError: true })); // Sumário const passed = results.filter(r => r.passed).length; const total = results.length; console.log(`\nEvaluations: ${passed}/${total} passou`); results.filter(r => !r.passed).forEach(r => { console.log(` FALHOU ${r.id}: ${r.error}`); }); await client.close(); process.exit(passed === total ? 0 : 1); } main().catch(console.error); ``` **Adicionar ao package.json:** ```json { "scripts": { "eval": "tsx eval/run-evals.ts", "eval:ci": "npm run build && npm run eval" } } ``` --- ## Checklist de Evaluations (pré-deploy) - [ ] Eval 1 passa: tool principal com input válido - [ ] Eval 2 passa: input inválido retorna erro accionável - [ ] Eval 3 passa: recurso inexistente retorna erro claro - [ ] Eval 4 passa: idempotência verificada (se aplicável) - [ ] Eval 5 passa: operações destrutivas confirmadas - [ ] Eval 6 passa: read-only não altera estado - [ ] Eval 7 passa: paginação funciona (se aplicável) - [ ] Eval 8 passa: auth inválida rejeitada graciosamente - [ ] Eval 9 passa: structuredContent consistente - [ ] Eval 10 passa: p95 < 5000ms --- ## Integração CI/CD ```yaml # .gitea/workflows/eval.yml name: MCP Evaluations on: [push, pull_request] jobs: eval: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - run: npm ci - run: npm run eval:ci ``` --- *evaluation-guide.md v1.0 | 2026-03-10*