Cómo Crear un Servidor MCP para Potenciar Agentes IA en Pruebas API

Ashley Innocent

Ashley Innocent

19 March 2026

Cómo Crear un Servidor MCP para Potenciar Agentes IA en Pruebas API

Apidog para empresas

Despliegue local

SSO & RBAC

Conforme con SOC 2

Explorar Apidog Enterprise

En resumen

Crea un servidor MCP con TypeScript que exponga tres herramientas: run_test, validate_schema y list_environments. Configúralo en ~/.claude/settings.json para Claude Code o .cursor/mcp.json para Cursor. Tus agentes de IA podrán entonces ejecutar pruebas de Apidog, validar esquemas OpenAPI y obtener entornos sin salir de la interfaz de chat. El código fuente completo tiene unas 150 líneas y utiliza el paquete @modelcontextprotocol/sdk.

Crea un servidor MCP que permita a Claude Code, Cursor y otros agentes de IA ejecutar pruebas de API de Apidog, validar esquemas y comparar respuestas, todo sin salir de su interfaz de chat.

💡
Estás en medio de una sesión de codificación. Tu agente de IA acaba de terminar de construir un punto de conexión de API. En lugar de copiar código, abrir Apidog, crear una colección de pruebas y ejecutar la validación manualmente, quieres escribir un comando y obtener los resultados.
botón

Eso es lo que permite el Protocolo de Contexto del Modelo (MCP). MCP permite a los agentes de IA acceder a herramientas externas a través de una interfaz estandarizada. Construye un servidor MCP para Apidog, y tu agente de IA podrá ejecutar pruebas, validar esquemas y obtener entornos sin cambiar de contexto.

¿Qué es MCP?

MCP (Model Context Protocol) es un protocolo para que los agentes de IA accedan a herramientas y fuentes de datos externas. Piensa en ello como un sistema de complementos que funciona en Claude Code, Cursor y otros clientes compatibles con MCP.

Un servidor MCP expone herramientas (funciones que el agente puede llamar) y recursos (datos que el agente puede leer). Tu servidor MCP de Apidog expondrá herramientas para las pruebas de API.

┌─────────────────┐         ┌──────────────────┐         ┌─────────────┐
│  Agente de IA   │         │  Servidor MCP    │         │  Apidog     │
│  (Claude Code)  │◄───────►│  (Tu Código)     │◄───────►│  API        │
└─────────────────┘   JSON  └──────────────────┘  HTTP   └─────────────┘

Paso 1: Configurar el proyecto

Crea un nuevo proyecto TypeScript:

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

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

Añade un script de construcción a package.json:

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

Paso 2: Crear el esqueleto del servidor MCP

Crea 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 crea un servidor MCP y lo conecta al transporte stdio. El transporte gestiona la comunicación entre el agente de IA y tu servidor a través de la entrada/salida estándar.

Paso 3: Definir la herramienta run_test

Añade la primera herramienta 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);

La definición de la herramienta tiene tres partes:

  1. Nombrerun_test (los agentes seleccionan herramientas por nombre, así que hazlo descriptivo)
  2. Esquema — Validación Zod para parámetros con descripciones
  3. Manejador — Función asíncrona que llama a la API de Apidog

Paso 4: Añadir la herramienta validate_schema

Añade la validación de esquemas para detectar errores de OpenAPI antes del despliegue:

// 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)}`
        }]
      };
    }
  }
);

Paso 5: Añadir la herramienta list_environments

Añade una herramienta para obtener los entornos de prueba disponibles:

// 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)}`
        }]
      };
    }
  }
);

Paso 6: Construir y probar

Construye el servidor:

npm run build

Prueba con un cliente MCP simple. Crea 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");

Paso 7: Configurar para Claude Code

Añade el servidor MCP a tu configuración de Claude Code:

Crea o edita ~/.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"
      }
    }
  }
}

Reinicia Claude Code. Las herramientas de Apidog deberían aparecer ahora cuando pidas ayuda para pruebas de API.

Uso en Claude Code:

Usa la herramienta run_test para ejecutar pruebas en mi proyecto Apidog.
ID del proyecto: proj_12345
Entorno: staging
Valida este esquema OpenAPI según las reglas de Apidog:
[pegar esquema]
Lista todos los entornos para el proyecto proj_12345

Paso 8: Configurar para Cursor

Cursor utiliza una configuración MCP similar. Crea .cursor/mcp.json en tu proyecto:

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

Uso en Cursor:

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

Código fuente completo

Aquí está el archivo 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("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);

Lo que has construido

Componente Propósito
Servidor MCP Conecta agentes de IA a la API de Apidog
run_test Ejecutar colecciones de pruebas programáticamente
validate_schema Detectar errores de OpenAPI antes del despliegue
list_environments Descubrir entornos de prueba disponibles
Validación Zod Manejo de parámetros con seguridad de tipos
Transporte Stdio Funciona con Claude Code, Cursor, cualquier cliente MCP

Próximos pasos

Extiende el servidor:

Consideraciones para producción:

Comparte con tu equipo:

Solución de problemas comunes

El servidor MCP no carga en Claude Code:

Las herramientas no aparecen después de la configuración:

Las solicitudes a la API fallan con 401:

Errores de validación de Zod:

Errores de compilación de TypeScript:

Probando tu servidor MCP localmente

Antes de desplegar en producción, prueba tu servidor localmente:

Pruebas manuales con stdio:

# Inicia el servidor
node dist/index.js

# En otra terminal, envía un mensaje de prueba
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | node dist/index.js

Salida esperada:

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

Prueba una llamada a una herramienta:

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

Tus agentes de IA ahora tienen acceso directo a las capacidades de prueba de Apidog. No más copiar y pegar entre el chat y el navegador. No más ejecuciones manuales de pruebas. Escribe un comando, obtén los resultados.

Ese es el poder de MCP: extiende tus agentes de IA con herramientas específicas del dominio y déjalos hacer lo que se supone que deben hacer: ayudarte a lanzar más rápido.

Puntos clave

botón

Preguntas frecuentes

¿Qué es MCP en IA?MCP (Model Context Protocol) es un protocolo estandarizado que permite a los agentes de IA acceder a herramientas y fuentes de datos externas. Piensa en ello como un sistema de complementos para agentes de IA.

¿Cómo creo un servidor MCP para Apidog?Instala @modelcontextprotocol/sdk, define herramientas con validación Zod, implementa manejadores que llamen a la API de Apidog y conéctate a través de StdioServerTransport.

¿Puedo usar esto con Cursor?Sí. Añade la configuración del servidor MCP a .cursor/mcp.json en la raíz de tu proyecto. El mismo servidor funciona con Claude Code, Cursor y otros clientes MCP.

¿Qué herramientas debo exponer?Comienza con run_test para ejecutar colecciones de pruebas, validate_schema para la validación de OpenAPI y list_environments para obtener los entornos disponibles.

¿El servidor MCP de Apidog está listo para producción?El código del tutorial es un punto de partida. Añade lógica de reintentos, limitación de velocidad, manejo de errores adecuado y almacenamiento seguro de claves API antes de usarlo en producción.

¿Necesito una clave API de Apidog?Sí. Establece APIDOG_API_KEY como una variable de entorno. El servidor la lee en tiempo de ejecución para autenticar las solicitudes a la API.

¿Puedo compartir este servidor MCP con mi equipo?Sí. Publica en npm como un paquete privado, documenta las variables de entorno requeridas e incluye ejemplos de configuraciones MCP.

Practica el diseño de API en Apidog

Descubre una forma más fácil de construir y usar APIs