feat: refactor 30+ skills to Anthropic progressive disclosure pattern

- All SKILL.md files now <500 lines (avg reduction 69%)
- Detailed content extracted to references/ subdirectories
- Frontmatter standardised: only name + description (Anthropic standard)
- New skills: brand-guidelines, spec-coauthor, report-templates, skill-creator
- Design skills: anti-slop guidelines, premium-proposals reference
- Removed non-standard frontmatter fields (triggers, version, author, category)

Plugins affected: infraestrutura, marketing, dev-tools, crm-ops, gestao,
core-tools, negocio, perfex-dev, wordpress, design-media

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-12 15:05:03 +00:00
parent 9404af7ac9
commit 6b3a6f2698
397 changed files with 67154 additions and 17257 deletions

View File

@@ -0,0 +1,280 @@
# 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
<evaluation>
<name>get_customer_basic</name>
<description>Verifica que get_customer retorna dados completos de um cliente existente</description>
<tool>get_customer</tool>
<input>
<customer_id>1</customer_id>
</input>
<expected>
<contains>name</contains>
<contains>email</contains>
<not_error>true</not_error>
</expected>
</evaluation>
```
---
## 10 Perguntas de Evaluation por MCP
Para cada MCP novo, responder a estas 10 perguntas criando um teste para cada uma:
```xml
<!-- 1. A tool mais básica funciona? -->
<evaluation id="1">
<question>A tool {principal} retorna dados quando recebe input válido?</question>
<scenario>Input mínimo válido</scenario>
<assert>Resposta não é erro, contém campos esperados</assert>
</evaluation>
<!-- 2. Erros de input são tratados graciosamente? -->
<evaluation id="2">
<question>O que acontece com input inválido (ID negativo, campo obrigatório em falta)?</question>
<scenario>Input inválido ou em falta</scenario>
<assert>Resposta tem isError=true, mensagem é accionável</assert>
</evaluation>
<!-- 3. O recurso inexistente é tratado correctamente? -->
<evaluation id="3">
<question>O que retorna quando o recurso pedido não existe (ID=99999)?</question>
<scenario>Recurso não encontrado</scenario>
<assert>Mensagem clara "não encontrado", não retorna null silencioso</assert>
</evaluation>
<!-- 4. Operações de escrita são idempotentes quando declaradas? -->
<evaluation id="4">
<question>Operações com idempotentHint=true produzem o mesmo resultado em chamadas repetidas?</question>
<scenario>Chamar a mesma tool create/update duas vezes com os mesmos parâmetros</scenario>
<assert>Segundo resultado idêntico ao primeiro ou erro controlado</assert>
</evaluation>
<!-- 5. Operações destrutivas têm confirmação ou são irreversíveis como declarado? -->
<evaluation id="5">
<question>Tools com destructiveHint=true apagam realmente dados? O utilizador é avisado?</question>
<scenario>Executar delete em recurso existente</scenario>
<assert>Dados apagados. Mensagem confirma acção irreversível</assert>
</evaluation>
<!-- 6. Tools read-only não alteram estado? -->
<evaluation id="6">
<question>Tools com readOnlyHint=true não modificam dados?</question>
<scenario>Executar get/list e verificar estado antes e depois</scenario>
<assert>Estado da BD/sistema idêntico antes e depois da chamada</assert>
</evaluation>
<!-- 7. Paginação e listas grandes funcionam? -->
<evaluation id="7">
<question>Tools de listagem com muitos resultados retornam dados paginados correctamente?</question>
<scenario>Lista com 1000+ registos, pedir página 2</scenario>
<assert>Retorna subset correcto, metadados de paginação presentes</assert>
</evaluation>
<!-- 8. Autenticação/autorização é validada? -->
<evaluation id="8">
<question>Chamadas sem credenciais válidas são rejeitadas?</question>
<scenario>Remover variável de ambiente com API key e chamar tool</scenario>
<assert>Erro claro de autenticação, não crash do servidor</assert>
</evaluation>
<!-- 9. structuredContent é consistente com content textual? -->
<evaluation id="9">
<question>O campo structuredContent contém os mesmos dados que o texto Markdown?</question>
<scenario>Comparar campos em structuredContent com conteúdo do text</scenario>
<assert>Dados idênticos em ambos os formatos</assert>
</evaluation>
<!-- 10. Performance é aceitável? -->
<evaluation id="10">
<question>A tool responde em menos de 5 segundos em condições normais?</question>
<scenario>Medir tempo de resposta em 10 chamadas consecutivas</scenario>
<assert>p95 < 5000ms, sem memory leaks após 100 chamadas</assert>
</evaluation>
```
---
## 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<string, unknown>,
assertions: {
notError?: boolean;
containsFields?: string[];
isError?: boolean;
}
): Promise<EvalResult> {
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*