DEV Community

Cover image for Como Criar um Servidor MCP para Capacitar Agentes de IA com Testes de API
Lucas
Lucas

Posted on Originally published at apidog.com

Como Criar um Servidor MCP para Capacitar Agentes de IA com Testes de API

RESUMO

Crie um servidor MCP com TypeScript para expor três ferramentas essenciais: run_test, validate_schema e list_environments. Configure em ~/.claude/settings.json para Claude Code ou .cursor/mcp.json para Cursor. Com isso, seus agentes de IA poderão executar testes Apidog, validar esquemas OpenAPI e acessar ambientes diretamente do chat. O código é enxuto (~150 linhas) utilizando o pacote @modelcontextprotocol/sdk.

Experimente o Apidog hoje

Crie um servidor MCP para permitir que Claude Code, Cursor e outros agentes de IA executem testes de API Apidog, validem esquemas e consultem ambientes de forma automatizada, sem sair da interface de bate-papo.

💡 Cenário: Você está codificando e seu agente de IA acabou de criar um endpoint. Em vez de copiar código, abrir o Apidog, criar testes e validar manualmente, apenas digite um comando e veja o resultado imediatamente.

O Model Context Protocol (MCP) permite que agentes de IA acessem ferramentas externas por uma interface padronizada. Com um servidor MCP para Apidog, o agente executa testes, valida esquemas e consulta ambientes sem trocar de contexto.

O Que É MCP?

O MCP (Model Context Protocol) é um protocolo para agentes de IA acessarem ferramentas externas e fontes de dados. Funciona como um sistema de plugins compatível com Claude Code, Cursor e outros clientes MCP.

Um servidor MCP expõe ferramentas (funções que o agente pode chamar) e recursos (dados que o agente pode ler). O servidor MCP para Apidog expõe ferramentas para automação de testes de API.

┌─────────────────┐         ┌──────────────────┐         ┌─────────────┐
│  AI Agent       │         │  MCP Server      │         │  Apidog     │
│  (Claude Code)  │◄───────►│  (Your Code)     │◄───────►│  API        │
└─────────────────┘   JSON  └──────────────────┘  HTTP   └─────────────┘
Enter fullscreen mode Exit fullscreen mode

Passo 1: Configure o Projeto

Crie um novo projeto TypeScript:

mkdir apidog-mcp-server
cd apidog-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk zod
npm install -D typescript @types/node
Enter fullscreen mode Exit fullscreen mode

Crie o arquivo tsconfig.json:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}
Enter fullscreen mode Exit fullscreen mode

Adicione scripts ao package.json:

{
  "scripts": {
    "build": "tsc",
    "start": "node dist/index.js"
  }
}
Enter fullscreen mode Exit fullscreen mode

Passo 2: Crie o Esqueleto do Servidor MCP

Crie src/index.ts:

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

const server = new McpServer({
  name: "apidog",
  version: "1.0.0",
  description: "Apidog API testing tools for AI agents"
});

// As ferramentas serão definidas aqui

const transport = new StdioServerTransport();
await server.connect(transport);
Enter fullscreen mode Exit fullscreen mode

Esse esqueleto instancia o servidor MCP e conecta pelo transporte stdio, responsável pela comunicação entre o agente de IA e seu servidor.

Passo 3: Defina a Ferramenta run_test

Adicione em src/index.ts:

// Tool: run_test
server.tool(
  "run_test",
  {
    projectId: z.string().describe("ID do projeto Apidog (veja na URL do projeto)"),
    environmentId: z.string().optional().describe("ID do ambiente (opcional)"),
    testSuiteId: z.string().optional().describe("ID da suíte de teste (opcional)")
  },
  async ({ projectId, environmentId, testSuiteId }) => {
    const apiKey = process.env.APIDOG_API_KEY;
    if (!apiKey) {
      return {
        content: [{
          type: "text",
          text: "Erro: variável de ambiente APIDOG_API_KEY não definida"
        }]
      };
    }

    let url = `https://api.apidog.com/v1/projects/${projectId}/tests/run?utm_source=dev.to&utm_medium=wanda&utm_content=n8n-post-automation`;
    const params = new URLSearchParams();
    if (environmentId) params.append("environmentId", environmentId);
    if (testSuiteId) params.append("testSuiteId", testSuiteId);
    if (params.toString()) url += `&${params.toString()}`;

    try {
      const response = await fetch(url, {
        method: "POST",
        headers: {
          "Authorization": `Bearer ${apiKey}`,
          "Content-Type": "application/json"
        }
      });

      if (!response.ok) {
        const error = await response.text();
        return {
          content: [{
            type: "text",
            text: `Erro da API: ${response.status} ${error}`
          }]
        };
      }

      const results = await response.json();
      return {
        content: [{
          type: "text",
          text: JSON.stringify(results, null, 2)
        }]
      };
    } catch (error) {
      return {
        content: [{
          type: "text",
          text: `Falha na requisição: ${error instanceof Error ? error.message : String(error)}`
        }]
      };
    }
  }
);
Enter fullscreen mode Exit fullscreen mode

Resumo:

  • Nome: run_test
  • Validação: Zod
  • Manipulador: Chama a API Apidog para execução de testes.

Passo 4: Adicione a Ferramenta validate_schema

Implemente validação de esquemas OpenAPI:

// Tool: validate_schema
server.tool(
  "validate_schema",
  {
    schema: z.object({}).describe("Objeto de esquema OpenAPI 3.x para validar"),
    strict: z.boolean().optional().default(false).describe("Modo estrito para validações adicionais")
  },
  async ({ schema, strict }) => {
    const apiKey = process.env.APIDOG_API_KEY;
    if (!apiKey) {
      return {
        content: [{
          type: "text",
          text: "Erro: variável de ambiente APIDOG_API_KEY não definida"
        }]
      };
    }

    try {
      const response = await fetch("https://api.apidog.com/v1/schemas/validate?utm_source=dev.to&utm_medium=wanda&utm_content=n8n-post-automation", {
        method: "POST",
        headers: {
          "Authorization": `Bearer ${apiKey}`,
          "Content-Type": "application/json"
        },
        body: JSON.stringify({ schema, strict })
      });

      const result = await response.json();

      if (!response.ok) {
        return {
          content: [{
            type: "text",
            text: `Validação falhou: ${JSON.stringify(result.errors, null, 2)}`
          }]
        };
      }

      return {
        content: [{
          type: "text",
          text: result.valid
            ? "Schema válido OpenAPI 3.x"
            : `Avisos: ${JSON.stringify(result.warnings, null, 2)}`
        }]
      };
    } catch (error) {
      return {
        content: [{
          type: "text",
          text: `Validação falhou: ${error instanceof Error ? error.message : String(error)}`
        }]
      };
    }
  }
);
Enter fullscreen mode Exit fullscreen mode

Passo 5: Adicione a Ferramenta list_environments

Permita consultar ambientes disponíveis:

// Tool: list_environments
server.tool(
  "list_environments",
  {
    projectId: z.string().describe("ID do projeto Apidog")
  },
  async ({ projectId }) => {
    const apiKey = process.env.APIDOG_API_KEY;
    if (!apiKey) {
      return {
        content: [{
          type: "text",
          text: "Erro: variável de ambiente APIDOG_API_KEY não definida"
        }]
      };
    }

    try {
      const response = await fetch(
        `https://api.apidog.com/v1/projects/${projectId}/environments?utm_source=dev.to&utm_medium=wanda&utm_content=n8n-post-automation`,
        {
          headers: {
            "Authorization": `Bearer ${apiKey}`
          }
        }
      );

      if (!response.ok) {
        const error = await response.text();
        return {
          content: [{
            type: "text",
            text: `Erro da API: ${response.status} ${error}`
          }]
        };
      }

      const environments = await response.json();
      return {
        content: [{
          type: "text",
          text: environments.length === 0
            ? "Nenhum ambiente encontrado para este projeto"
            : environments.map((e: any) =>
                `- ${e.name} (ID: ${e.id})${e.isDefault ? " [default]" : ""}`
              ).join("\n")
        }]
      };
    } catch (error) {
      return {
        content: [{
          type: "text",
          text: `Falha na requisição: ${error instanceof Error ? error.message : String(error)}`
        }]
      };
    }
  }
);
Enter fullscreen mode Exit fullscreen mode

Passo 6: Construa e Teste

Compile o servidor:

npm run build
Enter fullscreen mode Exit fullscreen mode

Teste com um cliente MCP básico (test-client.js):

import { spawn } from "child_process";

const server = spawn("node", ["dist/index.js"], {
  env: { ...process.env, APIDOG_API_KEY: "sua-api-key" }
});

server.stdout.on("data", (data) => {
  console.log(`Saída do servidor: ${data}`);
});

server.stderr.on("data", (data) => {
  console.error(`Erro do servidor: ${data}`);
});

// Mensagem de teste
const message = {
  jsonrpc: "2.0",
  id: 1,
  method: "initialize",
  params: {
    protocolVersion: "2024-11-05",
    capabilities: {},
    clientInfo: { name: "test-client", version: "1.0.0" }
  }
};

server.stdin.write(JSON.stringify(message) + "\n");
Enter fullscreen mode Exit fullscreen mode

Passo 7: Configure para Claude Code

Adicione o servidor MCP na configuração do Claude Code:

Crie/edite ~/.claude/settings.json:

{
  "mcpServers": {
    "apidog": {
      "command": "node",
      "args": ["/caminho/absoluto/para/apidog-mcp-server/dist/index.js"],
      "env": {
        "APIDOG_API_KEY": "sua-api-key-aqui"
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Reinicie o Claude Code. As ferramentas Apidog já estarão disponíveis para comandos.

Exemplos de uso:

Use a ferramenta run_test para rodar testes no meu projeto Apidog.
Project ID: proj_12345
Environment: staging
Enter fullscreen mode Exit fullscreen mode
Valide este schema OpenAPI contra as regras do Apidog:
[cole o schema]
Enter fullscreen mode Exit fullscreen mode
Liste todos os ambientes do projeto proj_12345
Enter fullscreen mode Exit fullscreen mode

Passo 8: Configure para Cursor

No Cursor, configure .cursor/mcp.json:

{
  "mcpServers": {
    "apidog": {
      "command": "node",
      "args": ["/caminho/absoluto/para/apidog-mcp-server/dist/index.js"],
      "env": {
        "APIDOG_API_KEY": "sua-api-key-aqui"
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Exemplo de uso:

@apidog run_test projectId="proj_12345" environmentId="staging"
Enter fullscreen mode Exit fullscreen mode

Código-Fonte Completo

src/index.ts:

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

const server = new McpServer({
  name: "apidog",
  version: "1.0.0",
  description: "Apidog API testing tools for AI agents"
});

// Tool: run_test
server.tool(
  "run_test",
  {
    projectId: z.string().describe("ID do projeto Apidog"),
    environmentId: z.string().optional().describe("ID do ambiente"),
    testSuiteId: z.string().optional().describe("ID da suíte de teste")
  },
  async ({ projectId, environmentId, testSuiteId }) => {
    const apiKey = process.env.APIDOG_API_KEY;
    if (!apiKey) {
      return {
        content: [{
          type: "text",
          text: "Erro: APIDOG_API_KEY não definida"
        }]
      };
    }

    let url = `https://api.apidog.com/v1/projects/${projectId}/tests/run?utm_source=dev.to&utm_medium=wanda&utm_content=n8n-post-automation`;
    const params = new URLSearchParams();
    if (environmentId) params.append("environmentId", environmentId);
    if (testSuiteId) params.append("testSuiteId", testSuiteId);
    if (params.toString()) url += `&${params.toString()}`;

    try {
      const response = await fetch(url, {
        method: "POST",
        headers: {
          "Authorization": `Bearer ${apiKey}`,
          "Content-Type": "application/json"
        }
      });

      const results = await response.json();
      return {
        content: [{
          type: "text",
          text: JSON.stringify(results, null, 2)
        }]
      };
    } catch (error) {
      return {
        content: [{
          type: "text",
          text: `Falha na requisição: ${error instanceof Error ? error.message : String(error)}`
        }]
      };
    }
  }
);

// Tool: validate_schema
server.tool(
  "validate_schema",
  {
    schema: z.object({}).describe("Schema OpenAPI"),
    strict: z.boolean().optional().default(false)
  },
  async ({ schema, strict }) => {
    const apiKey = process.env.APIDOG_API_KEY;
    if (!apiKey) {
      return {
        content: [{
          type: "text",
          text: "Erro: APIDOG_API_KEY não definida"
        }]
      };
    }

    const response = await fetch("https://api.apidog.com/v1/schemas/validate?utm_source=dev.to&utm_medium=wanda&utm_content=n8n-post-automation", {
      method: "POST",
      headers: {
        "Authorization": `Bearer ${apiKey}`,
        "Content-Type": "application/json"
      },
      body: JSON.stringify({ schema, strict })
    });

    const result = await response.json();
    return {
      content: [{
        type: "text",
        text: result.valid
          ? "Schema válido"
          : `Issues: ${JSON.stringify(result.errors || result.warnings, null, 2)}`
      }]
    };
  }
);

// Tool: list_environments
server.tool(
  "list_environments",
  {
    projectId: z.string().describe("ID do projeto Apidog")
  },
  async ({ projectId }) => {
    const apiKey = process.env.APIDOG_API_KEY;
    if (!apiKey) {
      return {
        content: [{
          type: "text",
          text: "Erro: APIDOG_API_KEY não definida"
        }]
      };
    }

    const response = await fetch(
      `https://api.apidog.com/v1/projects/${projectId}/environments?utm_source=dev.to&utm_medium=wanda&utm_content=n8n-post-automation`,
      {
        headers: { "Authorization": `Bearer ${apiKey}` }
      }
    );

    const environments = await response.json();
    return {
      content: [{
        type: "text",
        text: environments.map((e: any) =>
          `- ${e.name} (${e.id})${e.isDefault ? " [default]" : ""}`
        ).join("\n")
      }]
    };
  }
);

const transport = new StdioServerTransport();
await server.connect(transport);
Enter fullscreen mode Exit fullscreen mode

O Que Você Construiu

Componente Propósito
Servidor MCP Conecta agentes de IA à API Apidog
run_test Executa coleções de teste programaticamente
validate_schema Valida esquemas OpenAPI antes da implantação
list_environments Consulta ambientes de teste disponíveis
Validação Zod Segurança de tipos para parâmetros
Transporte Stdio Compatível com Claude Code, Cursor, qualquer cliente MCP

Próximos Passos

Extensões sugeridas:

  • Implemente compare_responses para comparar ambientes.
  • Adicione get_test_history para histórico de execuções.
  • Inclua trigger_mock_server para controlar mocks.

Para produção:

  • Adicione retentativas para requisições instáveis.
  • Implemente rate limiting.
  • Inclua logging detalhado de falhas.
  • Armazene a chave da API em um cofre seguro (não em variáveis de ambiente).

Compartilhamento:

  • Publique como pacote npm privado.
  • Documente variáveis de ambiente.
  • Forneça exemplos de configuração MCP.

Solução de Problemas Comuns

Servidor MCP não carrega no Claude Code:

  • Confirme se o caminho em ~/.claude/settings.json é absoluto.
  • Verifique se o comando node está no PATH.
  • Assegure que dist/index.js existe após build.
  • Veja logs MCP do Claude Code para detalhes.

Ferramentas não aparecem:

  • Reinicie o Claude Code completamente.
  • Execute npm run build para compilar TypeScript.
  • Certifique-se de que todas as ferramentas estão definidas antes de server.connect().
  • Inicie manualmente: node dist/index.js para checar erros.

API retorna 401:

  • Confirme se APIDOG_API_KEY está configurada corretamente.
  • Remova espaços/extras na chave.
  • Verifique se sua conta Apidog tem acesso à API.
  • Teste com curl:
  curl -H "Authorization: Bearer $APIDOG_API_KEY" https://api.apidog.com/v1/user?utm_source=dev.to&utm_medium=wanda&utm_content=n8n-post-automation
Enter fullscreen mode Exit fullscreen mode

Erro de validação Zod:

  • Parâmetros devem seguir o esquema exato.
  • Campos obrigatórios devem ser preenchidos.
  • Campos opcionais usam .optional() no Zod.
  • Leia a mensagem de erro retornada.

Compilação TypeScript falha:

  • Rode npm install para dependências.
  • Verifique a versão do TypeScript (use 5.x ou superior).
  • Limpe e reconstrua: rm -rf dist && npm run build.
  • Verifique tipos nas respostas do fetch.

Testando Seu Servidor MCP Localmente

Antes de implantar, teste localmente:

Teste manual via stdio:

# Inicie o servidor
node dist/index.js

# Em outro terminal, envie comando de listagem de ferramentas
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | node dist/index.js
Enter fullscreen mode Exit fullscreen mode

Saída esperada:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [
      { "name": "run_test", "description": "...", "inputSchema": {...} },
      { "name": "validate_schema", "description": "...", "inputSchema": {...} },
      { "name": "list_environments", "description": "...", "inputSchema": {...} }
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

Testando chamada de ferramenta:

echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"list_environments","arguments":{"projectId":"seu-project-id"}}}' | node dist/index.js
Enter fullscreen mode Exit fullscreen mode

Seus agentes de IA agora acessam diretamente os recursos do Apidog, sem copiar e colar, nem execuções manuais. Apenas um comando no chat para rodar testes e validar APIs.

Principais Conclusões

  • Servidores MCP conectam agentes de IA a APIs externas — implemente uma vez e use em Claude Code, Cursor e qualquer cliente MCP.
  • Três ferramentas suprem a maioria dos casos de teste de API: run_test (execução), validate_schema (validação OpenAPI), list_environments (descoberta de ambientes).
  • Validação Zod previne parâmetros inválidos, capturando erros antes das chamadas de API.
  • Configuração específica para cada ferramenta: Claude Code via ~/.claude/settings.json, Cursor via .cursor/mcp.json.
  • Ambiente de produção exige tratamento de erros, retentativas, rate limiting e armazenamento seguro de credenciais.

Perguntas Frequentes

O que é MCP em IA?

MCP (Model Context Protocol) é um protocolo padronizado para agentes de IA acessarem ferramentas e dados externos, funcionando como um sistema de plugins.

Como crio um servidor MCP para Apidog?

Instale @modelcontextprotocol/sdk, defina as ferramentas com Zod, implemente handlers que usam a API Apidog e conecte via StdioServerTransport.

Posso usar com Cursor?

Sim — configure .cursor/mcp.json na raiz do projeto. O mesmo servidor MCP funciona em Claude Code, Cursor e outros clientes MCP.

Quais ferramentas devo expor?

Comece com run_test (execução de testes), validate_schema (validação OpenAPI) e list_environments (consulta de ambientes).

O servidor MCP Apidog é pronto para produção?

O tutorial fornece um ponto de partida. Para produção, implemente retentativas, rate limit, tratamento de erros e armazene a chave de API com segurança.

Preciso de uma API key do Apidog?

Sim, defina APIDOG_API_KEY como variável de ambiente. O servidor usa essa chave para autenticar as requisições.

Posso compartilhar este servidor MCP com a equipe?

Sim. Publique como pacote npm privado, documente variáveis de ambiente e forneça exemplos de configuração MCP.

Top comments (0)