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

Ashley Innocent

Ashley Innocent

19 março 2026

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

Apidog para empresas

Implantação local

SSO & RBAC

Conforme SOC 2

Explorar Apidog Enterprise

RESUMO

Crie um servidor MCP com TypeScript que exponha três ferramentas: run_test, validate_schema e list_environments. Configure-o em ~/.claude/settings.json para Claude Code ou .cursor/mcp.json para Cursor. Seus agentes de IA poderão então executar testes Apidog, validar esquemas OpenAPI e buscar ambientes sem sair da interface de bate-papo. O código-fonte completo tem cerca de 150 linhas e utiliza o pacote @modelcontextprotocol/sdk.

Crie um servidor MCP que permita a Claude Code, Cursor e outros agentes de IA executar testes de API Apidog, validar esquemas e comparar respostas, tudo sem sair da interface de bate-papo.

💡
Você está no meio de uma sessão de codificação. Seu agente de IA acabou de construir um endpoint de API. Em vez de copiar o código, abrir o Apidog, criar uma coleção de testes e executar a validação manualmente, você quer digitar um comando e obter os resultados de volta.
botão

É isso que o Model Context Protocol (MCP) permite. O MCP permite que agentes de IA acessem ferramentas externas através de uma interface padronizada. Crie um servidor MCP para Apidog, e seu agente de IA poderá executar testes, validar esquemas e buscar ambientes sem troca de contexto.

O Que É MCP?

MCP (Model Context Protocol) é um protocolo para agentes de IA acessarem ferramentas externas e fontes de dados. Pense nele como um sistema de plugins que funciona em Claude Code, Cursor e outros clientes compatíveis com MCP.

Um servidor MCP expõe ferramentas (funções que o agente pode chamar) e recursos (dados que o agente pode ler). Seu servidor MCP Apidog exporá ferramentas para teste de API.

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

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

Crie 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"]
}

Adicione um script de build ao package.json:

{
  "scripts": {
    "build": "tsc",
    "start": "node dist/index.js"
  }
}

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"
});

// Tools will be defined here

const transport = new StdioServerTransport();
await server.connect(transport);

Este esqueleto cria um servidor MCP e o conecta ao transporte stdio. O transporte lida com a comunicação entre o agente de IA e seu servidor através da entrada/saída padrão.

Passo 3: Defina a Ferramenta run_test

Adicione a primeira ferramenta a 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("Apidog project ID (found in project URL)"),
    environmentId: z.string().optional().describe("Optional environment ID for test execution"),
    testSuiteId: z.string().optional().describe("Optional test suite ID to run specific suite")
  },
  async ({ projectId, environmentId, testSuiteId }) => {
    const apiKey = process.env.APIDOG_API_KEY;
    if (!apiKey) {
      return {
        content: [{
          type: "text",
          text: "Error: APIDOG_API_KEY environment variable not set"
        }]
      };
    }

    // Build API URL
    let url = `https://api.apidog.com/v1/projects/${projectId}/tests/run`;
    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: `API Error: ${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: `Request failed: ${error instanceof Error ? error.message : String(error)}`
        }]
      };
    }
  }
);

const transport = new StdioServerTransport();
await server.connect(transport);

A definição da ferramenta tem três partes:

  1. Nomerun_test (os agentes selecionam as ferramentas pelo nome, então torne-o descritivo)
  2. Esquema — Validação Zod para parâmetros com descrições
  3. Manipulador (Handler) — Função assíncrona que chama a API Apidog

Passo 4: Adicione a Ferramenta validate_schema

Adicione validação de esquema para capturar erros OpenAPI antes da implantação:

// Tool: validate_schema
server.tool(
  "validate_schema",
  {
    schema: z.object({}).describe("OpenAPI 3.x schema object to validate"),
    strict: z.boolean().optional().default(false).describe("Enable strict mode for additional checks")
  },
  async ({ schema, strict }) => {
    const apiKey = process.env.APIDOG_API_KEY;
    if (!apiKey) {
      return {
        content: [{
          type: "text",
          text: "Error: APIDOG_API_KEY environment variable not set"
        }]
      };
    }

    try {
      const response = await fetch("https://api.apidog.com/v1/schemas/validate", {
        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: `Validation failed: ${JSON.stringify(result.errors, null, 2)}`
          }]
        };
      }

      return {
        content: [{
          type: "text",
          text: result.valid
            ? "Schema is valid OpenAPI 3.x"
            : `Warnings: ${JSON.stringify(result.warnings, null, 2)}`
        }]
      };
    } catch (error) {
      return {
        content: [{
          type: "text",
          text: `Validation failed: ${error instanceof Error ? error.message : String(error)}`
        }]
      };
    }
  }
);

Passo 5: Adicione a Ferramenta list_environments

Adicione uma ferramenta para buscar ambientes de teste disponíveis:

// Tool: list_environments
server.tool(
  "list_environments",
  {
    projectId: z.string().describe("Apidog project ID")
  },
  async ({ projectId }) => {
    const apiKey = process.env.APIDOG_API_KEY;
    if (!apiKey) {
      return {
        content: [{
          type: "text",
          text: "Error: APIDOG_API_KEY environment variable not set"
        }]
      };
    }

    try {
      const response = await fetch(
        `https://api.apidog.com/v1/projects/${projectId}/environments`,
        {
          headers: {
            "Authorization": `Bearer ${apiKey}`
          }
        }
      );

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

      const environments = await response.json();
      return {
        content: [{
          type: "text",
          text: environments.length === 0
            ? "No environments found for this project"
            : environments.map((e: any) =>
                `- ${e.name} (ID: ${e.id})${e.isDefault ? " [default]" : ""}`
              ).join("\n")
        }]
      };
    } catch (error) {
      return {
        content: [{
          type: "text",
          text: `Request failed: ${error instanceof Error ? error.message : String(error)}`
        }]
      };
    }
  }
);

Passo 6: Construa e Teste

Construa o servidor:

npm run build

Teste com um cliente MCP simples. Crie test-client.js:

import { spawn } from "child_process";

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

server.stdout.on("data", (data) => {
  console.log(`Server output: ${data}`);
});

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

// Send a test message
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");

Passo 7: Configure para Claude Code

Adicione o servidor MCP à sua configuração do Claude Code:

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

{
  "mcpServers": {
    "apidog": {
      "command": "node",
      "args": ["/absolute/path/to/apidog-mcp-server/dist/index.js"],
      "env": {
        "APIDOG_API_KEY": "your-api-key-here"
      }
    }
  }
}

Reinicie o Claude Code. As ferramentas Apidog devem agora aparecer quando você pedir ajuda para testes de API.

Uso no Claude Code:

Use the run_test tool to run tests on my Apidog project.
Project ID: proj_12345
Environment: staging
Validate this OpenAPI schema against Apidog rules:
[paste schema]
List all environments for project proj_12345

Passo 8: Configure para Cursor

O Cursor usa uma configuração MCP semelhante. Crie .cursor/mcp.json em seu projeto:

{
  "mcpServers": {
    "apidog": {
      "command": "node",
      "args": ["/absolute/path/to/apidog-mcp-server/dist/index.js"],
      "env": {
        "APIDOG_API_KEY": "your-api-key-here"
      }
    }
  }
}

Uso no Cursor:

@apidog run_test projectId="proj_12345" environmentId="staging"

Código-Fonte Completo

Aqui está o src/index.ts completo:

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("Apidog project ID"),
    environmentId: z.string().optional().describe("Environment ID"),
    testSuiteId: z.string().optional().describe("Test suite ID")
  },
  async ({ projectId, environmentId, testSuiteId }) => {
    const apiKey = process.env.APIDOG_API_KEY;
    if (!apiKey) {
      return {
        content: [{
          type: "text",
          text: "Error: APIDOG_API_KEY not set"
        }]
      };
    }

    let url = `https://api.apidog.com/v1/projects/${projectId}/tests/run`;
    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: `Request failed: ${error instanceof Error ? error.message : String(error)}`
        }]
      };
    }
  }
);

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

    const response = await fetch("https://api.apidog.com/v1/schemas/validate", {
      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 is valid"
          : `Issues: ${JSON.stringify(result.errors || result.warnings, null, 2)}`
      }]
    };
  }
);

// Tool: list_environments
server.tool(
  "list_environments",
  {
    projectId: z.string().describe("Apidog project ID")
  },
  async ({ projectId }) => {
    const apiKey = process.env.APIDOG_API_KEY;
    if (!apiKey) {
      return {
        content: [{
          type: "text",
          text: "Error: APIDOG_API_KEY not set"
        }]
      };
    }

    const response = await fetch(
      `https://api.apidog.com/v1/projects/${projectId}/environments`,
      {
        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);

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 Captura erros OpenAPI antes da implantação
list_environments Descobre ambientes de teste disponíveis
Validação Zod Manipulação de parâmetros com segurança de tipo
Transporte Stdio Funciona com Claude Code, Cursor, qualquer cliente MCP

Próximos Passos

Estenda o servidor:

Considerações para Produção:

Compartilhe com sua equipe:

Solução de Problemas Comuns

Servidor MCP não carregando no Claude Code:

Ferramentas não aparecendo após a configuração:

Requisições de API falhando com 401:

Erros de validação Zod:

Erros de compilação TypeScript:

Testando Seu Servidor MCP Localmente

Antes de implantar em produção, teste seu servidor localmente:

Teste manual com stdio:

# Inicie o servidor
node dist/index.js

# Em outro terminal, envie uma mensagem de teste
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | node dist/index.js

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": {...} }
    ]
  }
}

Teste uma chamada de ferramenta:

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

Seus agentes de IA agora têm acesso direto às capacidades de teste do Apidog. Chega de copiar e colar entre o chat e o navegador. Chega de execuções de teste manuais. Digite um comando, receba os resultados.

Esse é o poder do MCP: estenda seus agentes de IA com ferramentas específicas do domínio e deixe-os fazer o que devem fazer — ajudá-lo a entregar mais rapidamente.

Principais Conclusões

botão

Perguntas Frequentes

O que é MCP em IA?MCP (Model Context Protocol) é um protocolo padronizado que permite que agentes de IA acessem ferramentas externas e fontes de dados. Pense nele como um sistema de plugins para agentes de IA.

Como crio um servidor MCP para Apidog?Instale @modelcontextprotocol/sdk, defina ferramentas com validação Zod, implemente manipuladores que chamem a API Apidog e conecte-se via StdioServerTransport.

Posso usar isso com o Cursor?Sim. Adicione a configuração do servidor MCP a .cursor/mcp.json na raiz do seu projeto. O mesmo servidor funciona com Claude Code, Cursor e outros clientes MCP.

Quais ferramentas devo expor?Comece com run_test para executar coleções de teste, validate_schema para validação OpenAPI e list_environments para buscar ambientes disponíveis.

O servidor MCP Apidog está pronto para produção?O código do tutorial é um ponto de partida. Adicione lógica de retentativa, limitação de taxa, tratamento de erros adequado e armazenamento seguro de chaves de API antes de usar em produção.

Preciso de uma chave de API Apidog?Sim. Defina APIDOG_API_KEY como uma variável de ambiente. O servidor lê isso em tempo de execução para autenticar requisições de API.

Posso compartilhar este servidor MCP com minha equipe?Sim. Publique no npm como um pacote privado, documente as variáveis de ambiente necessárias e inclua exemplos de configurações MCP.

Pratique o design de API no Apidog

Descubra uma forma mais fácil de construir e usar APIs