Files
claude-plugins/infraestrutura/skills/mcp-dev/SKILL.md
Emanuel Almeida 9404af7ac9 feat: sync all plugins, skills, agents updates
New plugins: core-tools
New skills: auto-expense, ticket-triage, design, security-check,
  aiktop-tasks, daily-digest, imap-triage, index-update, mindmap,
  notebooklm, proc-creator, tasks-overview, validate-component,
  perfex-module, report, calendar-manager
New agents: design-critic, design-generator, design-lead,
  design-prompt-architect, design-researcher, compliance-auditor,
  metabase-analyst, gitea-integration-specialist
Updated: all plugin configs, knowledge datasets, existing skills

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 17:16:32 +00:00

28 KiB

name, description, author, version, quality_score, user_invocable, desk_task, allowed-tools
name description author version quality_score user_invocable desk_task allowed-tools
mcp-dev MCP server development and testing. Creates new MCP servers following Descomplicar standards with SSE transport. Use when user mentions "mcp development", "novo mcp", "criar mcp", "mcp server", "mcp testing". Descomplicar® Crescimento Digital 1.3.0 75 true 1476 Grep

/mcp-dev - Desenvolvimento de MCPs

Skill para criação, configuração e gestão de servidores MCP customizados.

Regra #48: Novos MCPs devem ser desenvolvidos no container dev (server:"dev", path /root/Dev/<nome-mcp>). O path /home/ealmeida/mcp-servers/ é para MCPs já em produção. Desenvolvimento inicial -> /root/Dev/ -> depois mover para mcp-servers/ no deploy final.


Comandos

Comando Descrição
/mcp-dev create <nome> Criar novo MCP (scaffold TypeScript)
/mcp-dev config <nome> Configurar MCP em ~/.claude.json
/mcp-dev test <nome> Testar conexão e ferramentas
/mcp-dev docs <nome> Gerar documentação Obsidian
/mcp-dev list Listar MCPs instalados
/mcp-dev status Estado dos MCPs activos

Estrutura MCP Padrão

~/mcp-servers/<nome>/
├── package.json
├── tsconfig.json
├── src/
│   ├── index.ts          # Entry point
│   ├── tools/            # Ferramentas MCP
│   │   └── example.ts
│   └── types.ts          # Tipos TypeScript
├── README.md
├── .env.example
└── .gitignore

/mcp-dev create

Cria scaffold completo para novo MCP.

Execução

1. Criar pasta ~/mcp-servers/<nome>/
2. Gerar package.json com dependências MCP
3. Gerar tsconfig.json
4. Criar src/index.ts com estrutura base
5. Criar README.md
6. Criar .env.example
7. npm install
8. Sugerir configuração

Template package.json

{
  "name": "mcp-<nome>",
  "version": "1.0.0",
  "type": "module",
  "main": "dist/index.js",
  "scripts": {
    "build": "tsc",
    "start": "node dist/index.js",
    "dev": "tsx src/index.ts"
  },
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.0.0",
    "zod": "^3.22.0"
  },
  "devDependencies": {
    "@types/node": "^20.0.0",
    "typescript": "^5.0.0",
    "tsx": "^4.0.0"
  }
}

Template index.ts

#!/usr/bin/env node
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
} from '@modelcontextprotocol/sdk/types.js';

const server = new Server(
  {
    name: 'mcp-<nome>',
    version: '1.0.0',
  },
  {
    capabilities: {
      tools: {},
    },
  }
);

// List available tools
server.setRequestHandler(ListToolsRequestSchema, async () => ({
  tools: [
    {
      name: 'example_tool',
      description: 'Descrição da ferramenta',
      inputSchema: {
        type: 'object',
        properties: {
          param: {
            type: 'string',
            description: 'Parâmetro exemplo',
          },
        },
        required: ['param'],
      },
    },
  ],
}));

// Handle tool calls
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;

  switch (name) {
    case 'example_tool':
      return {
        content: [
          {
            type: 'text',
            text: `Resultado: ${args?.param}`,
          },
        ],
      };
    default:
      throw new Error(`Unknown tool: ${name}`);
  }
});

// Start server
async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error('MCP Server running on stdio');
}

main().catch(console.error);

/mcp-dev config

Adiciona MCP ao ficheiro de configuração.

Claude Code (~/.claude.json)

{
  "mcpServers": {
    "<nome>": {
      "command": "node",
      "args": ["/home/ealmeida/mcp-servers/<nome>/dist/index.js"],
      "env": {}
    }
  }
}

Claude Desktop (~/.config/claude/claude_desktop_config.json)

{
  "mcpServers": {
    "<nome>": {
      "command": "node",
      "args": ["/home/ealmeida/mcp-servers/<nome>/dist/index.js"]
    }
  }
}

Verificação

# Testar se compila
cd ~/mcp-servers/<nome> && npm run build

# Testar manualmente
echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | node dist/index.js

/mcp-dev test

Testa conexão e lista ferramentas disponíveis.

Output Esperado

🔧 MCP Test: <nome>
──────────────────
Status:     ✅ Conectado
Versão:     1.0.0
Transport:  stdio

Ferramentas (3):
  • tool_1 - Descrição
  • tool_2 - Descrição
  • tool_3 - Descrição

Recursos (0):
  (nenhum)

Prompts (0):
  (nenhum)

/mcp-dev docs

Gera documentação Obsidian para o MCP.

Output

Cria Stack/Claude Code/MCPs/MCP-<Nome>.md:

---
title: MCP <Nome>
date: YYYY-MM-DD
type: mcp
status: active
tags: [mcp, <nome>]
---

# MCP <Nome>

Descrição do MCP.

## Ferramentas

| Tool | Descrição | Parâmetros |
|------|-----------|------------|
| tool_1 | ... | param1, param2 |

## Configuração

...

## Exemplos

...

/mcp-dev list

Lista todos os MCPs em ~/mcp-servers/.

Output

📋 MCPs Instalados
──────────────────
~/mcp-servers/
├── desk-crm-v3/     ✅ Configurado
├── memory-supabase/ ✅ Configurado
├── google-workspace/ ✅ Configurado
├── novo-mcp/        ⚠️ Não configurado
└── teste/           ❌ Não compila

Total: 5 | Activos: 3 | Pendentes: 2

/mcp-dev status

Estado dos MCPs activos na sessão.

Output

🔌 MCPs Activos
───────────────
✅ desk-crm-v3        (15 tools)
✅ memory-supabase    (5 tools)
✅ google-workspace   (42 tools)
✅ filesystem         (8 tools)
⚠️ youtube-uploader  (auth required)

Total: 5 | OK: 4 | Problemas: 1

Padrões de Desenvolvimento

Limites de Nomes de Tools

REGRA 31/01/2026: Nomes de tools MCP têm limite de caracteres.

Limite Valor Cálculo
Tool name ≤40 chars Nome da função
Total com prefixo ≤64 chars mcp__<server>__<tool_name>

Exemplo:

mcp__desk-crm-v3__get_customer_notes
     └─────────┘  └────────────────┘
      server=12     tool_name=18     = 30 chars ✅

mcp__desk-crm-v3__get_customer_alternate_addresses_with_details
     └─────────┘  └──────────────────────────────────────────┘
      server=12     tool_name=46     = 58 chars ❌ (tool > 40)

Validação recomendada:

function validateToolName(name: string): void {
  if (name.length > 40) {
    throw new Error(`Tool name "${name}" exceeds 40 char limit (${name.length})`);
  }
}

// Aplicar a todas as tools no array
allTools.forEach(t => validateToolName(t.name));

Error Handling

try {
  // operação
} catch (error) {
  return {
    content: [{
      type: 'text',
      text: `Erro: ${error instanceof Error ? error.message : 'Unknown error'}`,
    }],
    isError: true,
  };
}

Validação com Zod

import { z } from 'zod';

const InputSchema = z.object({
  param: z.string().min(1),
  optional: z.number().optional(),
});

// No handler
const validated = InputSchema.parse(args);

Logging

// Usar console.error (não console.log - interfere com stdio)
console.error(`[MCP] Processing: ${param}`);

Transporte HTTP (StreamableHTTP) - RECOMENDADO

Padrão oficial MCP SDK. Usar para todos os novos MCPs.

Vantagens HTTP vs SSE

Aspecto HTTP (StreamableHTTP) SSE (deprecated)
Padrão Oficial MCP SDK ⚠️ Deprecated
Stateless Suportado Sempre stateful
Simplicidade Um endpoint /sse + /message
Gate ready REST-like Streaming complexo

Template index-http.ts (PADRÃO)

#!/usr/bin/env node
/**
 * MCP <Nome> - HTTP Server Mode
 * StreamableHTTP transport for web/remote access
 * @author Descomplicar® | @link descomplicar.pt | @copyright 2026
 */

import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
import {
  ListToolsRequestSchema,
  CallToolRequestSchema,
} from '@modelcontextprotocol/sdk/types.js';
import * as http from 'http';
import { URL } from 'url';
import { randomUUID } from 'crypto';

const PORT = parseInt(process.env.MCP_HTTP_PORT || '32XX', 10);
const HOST = process.env.MCP_HTTP_HOST || '127.0.0.1';
const STATEFUL = process.env.MCP_STATEFUL !== 'false';

// Track active sessions (stateful mode)
const sessions = new Map<string, { transport: StreamableHTTPServerTransport }>();

// Define tools array
const allTools = [
  {
    name: 'example_tool',
    description: 'Descrição da ferramenta',
    inputSchema: {
      type: 'object',
      properties: {
        param: { type: 'string', description: 'Parâmetro exemplo' }
      },
      required: ['param']
    },
    handler: async (args: any) => ({
      content: [{ type: 'text', text: `Resultado: ${args.param}` }]
    })
  }
];

function createMcpServer(): Server {
  const server = new Server(
    { name: 'mcp-nome', version: '1.0.0' },
    { capabilities: { tools: {} } }
  );

  server.setRequestHandler(ListToolsRequestSchema, async () => ({
    tools: allTools.map(t => ({
      name: t.name,
      description: t.description,
      inputSchema: t.inputSchema
    }))
  }));

  server.setRequestHandler(CallToolRequestSchema, async (request) => {
    const { name, arguments: args } = request.params;
    const tool = allTools.find(t => t.name === name);

    if (!tool) {
      return { content: [{ type: 'text', text: `Tool not found: ${name}` }] };
    }

    try {
      return await tool.handler(args);
    } catch (error) {
      return {
        content: [{
          type: 'text',
          text: `Error: ${error instanceof Error ? error.message : String(error)}`
        }],
        isError: true
      };
    }
  });

  return server;
}

async function main() {
  const httpServer = http.createServer(async (req, res) => {
    // CORS headers
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS');
    res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Mcp-Session-Id');

    if (req.method === 'OPTIONS') {
      res.writeHead(200);
      res.end();
      return;
    }

    const url = new URL(req.url || '/', `http://${HOST}:${PORT}`);

    // Health check endpoint
    if (url.pathname === '/health') {
      res.writeHead(200, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify({
        status: 'ok',
        transport: 'streamable-http',
        version: '1.0.0',
        sessions: sessions.size,
        stateful: STATEFUL,
        tools: allTools.length
      }));
      return;
    }

    // Stats endpoint
    if (url.pathname === '/stats') {
      res.writeHead(200, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify({
        totalTools: allTools.length,
        activeSessions: sessions.size
      }, null, 2));
      return;
    }

    // MCP endpoint
    if (url.pathname === '/mcp') {
      try {
        const transport = new StreamableHTTPServerTransport({
          sessionIdGenerator: STATEFUL ? () => randomUUID() : undefined
        });

        const server = createMcpServer();

        if (STATEFUL && transport.sessionId) {
          sessions.set(transport.sessionId, { transport });
          transport.onclose = () => {
            if (transport.sessionId) {
              sessions.delete(transport.sessionId);
            }
          };
        }

        await server.connect(transport);
        await transport.handleRequest(req, res);
      } catch (error) {
        if (!res.headersSent) {
          res.writeHead(500, { 'Content-Type': 'application/json' });
          res.end(JSON.stringify({ error: 'Internal server error' }));
        }
      }
      return;
    }

    // 404
    res.writeHead(404, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ error: 'Not found' }));
  });

  httpServer.listen(PORT, HOST, () => {
    console.log(`MCP HTTP Server v1.0.0`);
    console.log(`  Endpoint: http://${HOST}:${PORT}/mcp`);
    console.log(`  Health:   http://${HOST}:${PORT}/health`);
    console.log(`  Mode:     ${STATEFUL ? 'Stateful' : 'Stateless'}`);
    console.log(`  Tools:    ${allTools.length}`);
  });

  // Graceful shutdown
  const shutdown = () => {
    httpServer.close(() => process.exit(0));
  };
  process.on('SIGINT', shutdown);
  process.on('SIGTERM', shutdown);
}

main().catch(console.error);

Configuração HTTP

// ~/.claude.json - HTTP transport
{
  "mcpServers": {
    "meu-mcp": {
      "type": "http",
      "url": "http://127.0.0.1:32XX/mcp"
    }
  }
}

Portas HTTP Reservadas

Porta MCP Estado
3200 outline-postgresql HTTP
3201+ disponíveis -

Scripts package.json (HTTP)

{
  "scripts": {
    "start:http": "node dist/index-http.js",
    "dev:http": "tsx src/index-http.ts",
    "reload:http": "npm run build && systemctl --user restart mcp-nome && sleep 2 && curl -s http://127.0.0.1:32XX/health"
  }
}

Transporte SSE (Server-Sent Events) - DEPRECATED

⚠️ DEPRECATED: Usar HTTP (StreamableHTTP) para novos MCPs. SSE mantido apenas para retrocompatibilidade.

Para MCPs que precisam de conexao persistente (ex: Claude Code com multiplos terminais).

IMPORTANTE: Verificar MCPs existentes (desk-crm-v3, moloni) antes de implementar!

Configuracao SSE

// ~/.claude.json
{
  "mcpServers": {
    "meu-mcp": {
      "type": "sse",
      "url": "http://127.0.0.1:31XX/sse"
    }
  }
}

Template index-sse.ts (http nativo - RECOMENDADO)

#!/usr/bin/env node
/** @author Descomplicar | @link descomplicar.pt | @copyright 2026 */

import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
import {
  ListToolsRequestSchema,
  CallToolRequestSchema,
  ListResourcesRequestSchema,
  ListPromptsRequestSchema
} from '@modelcontextprotocol/sdk/types.js';
import * as http from 'http';
import { URL } from 'url';

const PORT = parseInt(process.env.MCP_SSE_PORT || '31XX');
const HOST = process.env.MCP_SSE_HOST || '127.0.0.1';

// Track active sessions
const sessions = new Map<string, SSEServerTransport>();

// Define tools array
const allTools = [
  // ... your tools
];

// Create MCP server for each session
function createMcpServer(): Server {
  const server = new Server({
    name: 'mcp-nome',
    version: '1.0.0'
  });

  // Set capabilities
  (server as any)._capabilities = {
    tools: {},
    resources: {},
    prompts: {}
  };

  // List tools
  server.setRequestHandler(ListToolsRequestSchema, async () => ({
    tools: allTools.map((t) => ({
      name: t.name,
      description: t.description,
      inputSchema: t.inputSchema
    }))
  }));

  // List resources (empty)
  server.setRequestHandler(ListResourcesRequestSchema, async () => ({
    resources: []
  }));

  // List prompts (empty)
  server.setRequestHandler(ListPromptsRequestSchema, async () => ({
    prompts: []
  }));

  // Call tool
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
    const { name, arguments: args } = request.params;
    const tool = allTools.find((t) => t.name === name);

    if (!tool) {
      return { content: [{ type: 'text', text: 'Tool not found' }] };
    }

    try {
      return await tool.handler(args);
    } catch (error) {
      return {
        content: [{
          type: 'text',
          text: `Error: ${error instanceof Error ? error.message : String(error)}`
        }]
      };
    }
  });

  return server;
}

async function main() {
  const httpServer = http.createServer(async (req, res) => {
    // CORS headers
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
    res.setHeader('Access-Control-Allow-Headers', 'Content-Type');

    if (req.method === 'OPTIONS') {
      res.writeHead(200);
      res.end();
      return;
    }

    const url = new URL(req.url || '/', `http://${HOST}:${PORT}`);

    // Health check
    if (url.pathname === '/health') {
      res.writeHead(200, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify({
        status: 'ok',
        sessions: sessions.size,
        tools: allTools.length
      }));
      return;
    }

    // SSE endpoint - new session
    if (url.pathname === '/sse' && req.method === 'GET') {
      const transport = new SSEServerTransport('/message', res);
      const sessionId = transport.sessionId; // USAR sessionId do transport!
      sessions.set(sessionId, transport);

      // Criar NOVO server por sessao
      const server = createMcpServer();

      transport.onclose = () => {
        sessions.delete(sessionId);
      };

      await server.connect(transport);
      return;
    }

    // Message endpoint
    if (url.pathname === '/message' && req.method === 'POST') {
      const sessionId = url.searchParams.get('sessionId');

      if (!sessionId) {
        res.writeHead(400, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({ error: 'Missing sessionId' }));
        return;
      }

      const transport = sessions.get(sessionId);
      if (!transport) {
        res.writeHead(404, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({ error: 'Session not found' }));
        return;
      }

      await transport.handlePostMessage(req, res);
      return;
    }

    // 404
    res.writeHead(404, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify({ error: 'Not found' }));
  });

  httpServer.listen(PORT, HOST, () => {
    console.log(`MCP SSE Server running at http://${HOST}:${PORT}/sse`);
  });

  // Graceful shutdown
  process.on('SIGTERM', () => httpServer.close(() => process.exit(0)));
  process.on('SIGINT', () => httpServer.close(() => process.exit(0)));
}

main().catch(console.error);

Pontos Criticos SSE

Aspecto Correcto Errado
sessionId transport.sessionId Date.now().toString()
Server Novo por sessao Reutilizar mesmo
HTTP http.createServer Express (overhead)
/message Com ?sessionId= Sem sessionId

Template systemd Service

Criar em ~/.config/systemd/user/mcp-nome.service:

[Unit]
Description=MCP Nome SSE Server
After=network.target

[Service]
Type=simple
WorkingDirectory=/home/ealmeida/mcp-servers/mcp-nome
ExecStart=/home/ealmeida/.nvm/versions/node/v22.18.0/bin/node dist/index.js --sse --port 31XX
Restart=on-failure
RestartSec=5
Environment=NODE_ENV=production
Environment=LOG_LEVEL=error
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=default.target

Comandos systemd

# Activar
systemctl --user daemon-reload
systemctl --user enable mcp-nome.service
systemctl --user start mcp-nome.service

# Ver estado
systemctl --user status mcp-nome

# Ver logs
journalctl --user -u mcp-nome -f

# Reiniciar apos alteracoes
systemctl --user restart mcp-nome

Portas SSE Reservadas

Porta MCP
3100 desk-crm-v3
3101 memory-supabase
3102 wikijs
3103 ssh-unified
3104 dify-kb
3105 n8n
3106 cwp
3107 youtube-research
3108 moloni
3109+ disponiveis

Script de Desenvolvimento (reload:sse)

Adicionar ao package.json:

{
  "scripts": {
    "start:sse": "node dist/index.js --sse",
    "reload:sse": "npm run build && systemctl --user restart mcp-nome && sleep 2 && curl -s http://127.0.0.1:31XX/health"
  }
}

Padrões SQL (Perfex CRM)

Para MCPs que integram com Perfex CRM:

Campos FK (Foreign Keys)

// CORRECTO: Perfex usa 0 como "não definido", NÃO NULL
client_id || 0,
project_id || 0,
country || 0,
assigned || 0,

// EXCEPÇÃO: source em leads precisa ID válido (buscar da BD)
let leadSource = source;
if (!leadSource) {
  const [defaultSource] = await client.query(
    'SELECT id FROM tblleads_sources ORDER BY id ASC LIMIT 1'
  );
  leadSource = defaultSource?.id || 1;
}

Padrão de Fallback

// Para campos que aceitam 0 como default
field || 0

// Para campos que precisam valor válido da BD
const defaultValue = await getDefaultFromDB();
field || defaultValue

Tabelas Perfex (prefixo tbl)

tblclients, tblprojects, tbltasks, tblinvoices,
tblleads, tblleads_sources, tblleads_status,
tblstaff, tbltaskstimers, tblexpenses

Checklist de Segurança MCP

Baseado em audit MCP Outline PostgreSQL (164 tools, 7 bugs corrigidos).

Antes de Commit

  • SQL Injection: Todos os inputs validados antes de entrar em queries?

    // ERRADO: interpolação directa
    const query = `ORDER BY ${field} ASC`;
    
    // CORRECTO: validar primeiro
    validateFieldName(field); // rejeita keywords SQL
    const query = `ORDER BY ${field} ASC`;
    
  • Transações: Operações multi-query relacionadas em transação?

    // ERRADO: queries separadas
    await query('DELETE FROM children WHERE parentId = $1', [id]);
    await query('DELETE FROM parents WHERE id = $1', [id]);
    
    // CORRECTO: transação
    await withTransaction(async (client) => {
      await client.query('DELETE FROM children WHERE parentId = $1', [id]);
      await client.query('DELETE FROM parents WHERE id = $1', [id]);
    });
    
  • Recursos: Aquisição tem finally com release?

    // ERRADO: release pode não executar
    const client = await pool.connect();
    await client.query('SELECT 1');
    client.release();
    
    // CORRECTO: finally garante release
    let client = null;
    try {
      client = await pool.connect();
      await client.query('SELECT 1');
    } finally {
      if (client) client.release();
    }
    
  • Cleanup: Código de cleanup tem try-catch próprio?

    // ERRADO: ROLLBACK pode falhar e mascarar erro
    catch (error) {
      await client.query('ROLLBACK');
      throw error;
    }
    
    // CORRECTO: ROLLBACK com try-catch
    catch (error) {
      try {
        await client.query('ROLLBACK');
      } catch (rollbackError) {
        console.error('Rollback failed', rollbackError);
      }
      throw error;
    }
    
  • Random: Usando crypto.randomBytes() e não Math.random()?

  • Versão: Sincronizada com package.json?

Grep de Validação

# Verificar interpolação SQL perigosa
grep -rn '`.*\${.*}`' src/ | grep -i 'select\|insert\|update\|delete\|order'

# Verificar Math.random em produção
grep -rn 'Math.random' src/

# Verificar .connect() sem finally
grep -rn '\.connect()' src/

MCPs Existentes (Referência)

MCP Path Tools
desk-crm-v3 ~/mcp-servers/desk-crm-v3/ 150+
memory-supabase ~/mcp-servers/memory-supabase/ 5
google-workspace (npm package) 42
filesystem (npm package) 8

Integração com Agente

O agente mcp-protocol-developer é invocado para:

  • Desenvolvimento complexo de ferramentas
  • Debug de problemas MCP
  • Optimização de performance
  • Implementação de recursos avançados

Datasets Dify

mcp__notebooklm__notebook_query, mcp__dify-kb__dify_kb_retrieve_segments dataset:"MCP Servers" query:"..."
mcp__dify-kb__dify_kb_retrieve_segments dataset:"Claude Code" query:"..."
mcp__dify-kb__dify_kb_retrieve_segments dataset:"Desenvolvimento de Software" query:"..."

Referências e Documentação

Procedimentos Obrigatórios (D7-Tecnologia)

SEMPRE consultar antes de criar/modificar MCPs:

Quick Reference (ver PROC-MCP-Desenvolvimento.md)

  • ESLint + Prettier: Ver PROC secção "Scripts package.json"
  • Husky pre-commit: Ver PROC secção "Husky + Lint-Staged"
  • Checklist novo MCP: Ver PROC secção "Checklist Desenvolvimento MCP"
  • Schema BD: Ver PROC secção "Documentação Schema BD"
  • Validação pre-deploy: Ver PROC secção "Validação Obrigatória"

Agente Especializado

  • Agent: mcp-protocol-developer - Desenvolvimento complexo, debug, optimização, recursos avançados

Documentação Técnica



Changelog

v1.3.0 (2026-01-31)

  • HTTP StreamableHTTP como padrão oficial (template completo)
  • SSE marcado como DEPRECATED (retrocompatibilidade)
  • Checklist de Segurança MCP (baseado em audit 164 tools)
    • SQL injection prevention
    • Transacções para operações multi-query
    • Resource release em finally blocks
    • Cleanup error handling
    • crypto.randomBytes() vs Math.random()
  • Grep de validação para code review
  • Portas HTTP reservadas (3200+)

v1.2.0 (2026-01-27)

  • Template SSE completo com http nativo (nao Express)
  • Pontos criticos SSE documentados (sessionId, Server por sessao)
  • Template systemd service para MCPs SSE
  • Tabela de portas SSE reservadas
  • Comandos systemd documentados

v1.1.0 (2026-01-27)

  • Adicionada seccao SSE (Server-Sent Events)
  • Script reload:sse para desenvolvimento
  • Padroes SQL Perfex CRM (FKs usam 0, nao NULL)
  • Workflow de desenvolvimento documentado

v1.0.0 (2026-01-27)

  • Versao inicial

Skill v1.3 | Descomplicar®


Instrumentação Automática

Esta skill grava métricas automaticamente para análise PDCA.

Query para Gravar (executar no final)

INSERT INTO tblskill_agent_metrics (
  type, name, duration_ms, status, staff_id,
  kb_consulted, kb_cache_hit, tool_calls, project_id
) VALUES (
  'skill', '/$SKILL_NAME', {DURACAO_MS}, '{STATUS}', 25,
  {KB_CONSULTADO}, {CACHE_HIT}, {TOOL_CALLS}, {PROJECT_ID}
);

Instrumentação: Activa | Data: 2026-02-03


Quando NÃO Usar

  • Para tarefas fora do domínio de especialização desta skill
  • Quando outra skill mais específica está disponível
  • Para operações que requerem confirmação manual do utilizador

Protocolo

  1. Analisar requisitos da tarefa
  2. Verificar disponibilidade de ferramentas necessárias
  3. Executar operações de forma incremental
  4. Validar resultados antes de concluir
  5. Reportar status e próximos passos