En resumen
Crea un servidor MCP con TypeScript que exponga tres herramientas clave: run_test, validate_schema y list_environments. Configura este servidor en ~/.claude/settings.json para Claude Code o en .cursor/mcp.json para Cursor. Así, tus agentes de IA podrán ejecutar pruebas de Apidog, validar esquemas OpenAPI y consultar entornos directamente desde la interfaz de chat. El código fuente es compacto (~150 líneas) y utiliza el paquete @modelcontextprotocol/sdk.
Crea y configura un servidor MCP para que Claude Code, Cursor y otros agentes de IA ejecuten pruebas de API de Apidog, validen esquemas y consulten entornos, todo sin salir de la interfaz de chat.
💡 Caso de uso: Estás codificando y tu agente de IA termina de construir un endpoint. En vez de copiar código, abrir Apidog y validar manualmente, ejecuta un comando y obtén los resultados al instante.
El Model Context Protocol (MCP) permite a agentes de IA acceder a herramientas externas mediante una interfaz estandarizada. Al construir un servidor MCP para Apidog, 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 que permite a los agentes de IA acceder a herramientas y fuentes de datos externas, similar a un sistema de plugins. Funciona con Claude Code, Cursor y cualquier cliente compatible con MCP.
Un servidor MCP expone herramientas (funciones que el agente puede invocar) y recursos (datos consultables). En este caso, el servidor MCP de Apidog expone funciones para pruebas de API.
┌─────────────────┐ ┌──────────────────┐ ┌─────────────┐
│ Agente de IA │ │ Servidor MCP │ │ Apidog │
│ (Claude Code) │◄───────►│ (Tu Código) │◄───────►│ API │
└─────────────────┘ JSON └──────────────────┘ HTTP └─────────────┘
Paso 1: Configura 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 el archivo 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"]
}
Agrega scripts de build y start en package.json:
{
"scripts": {
"build": "tsc",
"start": "node dist/index.js"
}
}
Paso 2: Crea 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"
});
// Aquí irán las herramientas
const transport = new StdioServerTransport();
await server.connect(transport);
Este esqueleto crea un servidor MCP y lo conecta al transporte stdio, que maneja la comunicación entre el agente de IA y tu servidor.
Paso 3: Implementa la herramienta run_test
Agrega la herramienta run_test a src/index.ts:
server.tool(
"run_test",
{
projectId: z.string().describe("Apidog project ID (en la URL del proyecto)"),
environmentId: z.string().optional().describe("ID de entorno opcional"),
testSuiteId: z.string().optional().describe("ID de test suite opcional")
},
async ({ projectId, environmentId, testSuiteId }) => {
const apiKey = process.env.APIDOG_API_KEY;
if (!apiKey) {
return {
content: [{
type: "text",
text: "Error: APIDOG_API_KEY no definida"
}]
};
}
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: `Error 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: `Fallo en la petición: ${error instanceof Error ? error.message : String(error)}`
}]
};
}
}
);
Estructura de la herramienta:
-
Nombre —
run_test - Esquema — Validación de parámetros con Zod y descripciones
- Manejador — Llama a la API de Apidog y retorna el resultado
Paso 4: Añade la herramienta validate_schema
Permite validar esquemas OpenAPI antes de su despliegue:
server.tool(
"validate_schema",
{
schema: z.object({}).describe("Objeto schema OpenAPI 3.x a validar"),
strict: z.boolean().optional().default(false).describe("Modo estricto para validaciones adicionales")
},
async ({ schema, strict }) => {
const apiKey = process.env.APIDOG_API_KEY;
if (!apiKey) {
return {
content: [{
type: "text",
text: "Error: APIDOG_API_KEY no definida"
}]
};
}
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: `Validación fallida: ${JSON.stringify(result.errors, null, 2)}`
}]
};
}
return {
content: [{
type: "text",
text: result.valid
? "El esquema es válido OpenAPI 3.x"
: `Advertencias: ${JSON.stringify(result.warnings, null, 2)}`
}]
};
} catch (error) {
return {
content: [{
type: "text",
text: `Validación fallida: ${error instanceof Error ? error.message : String(error)}`
}]
};
}
}
);
Paso 5: Añade la herramienta list_environments
Permite consultar los entornos disponibles de un proyecto:
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 no definida"
}]
};
}
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: `Error API: ${response.status} ${error}`
}]
};
}
const environments = await response.json();
return {
content: [{
type: "text",
text: environments.length === 0
? "No se encontraron entornos para este proyecto"
: environments.map((e: any) =>
`- ${e.name} (ID: ${e.id})${e.isDefault ? " [default]" : ""}`
).join("\n")
}]
};
} catch (error) {
return {
content: [{
type: "text",
text: `Fallo en la petición: ${error instanceof Error ? error.message : String(error)}`
}]
};
}
}
);
Paso 6: Compila y prueba el servidor
Compila el TypeScript:
npm run build
Prueba con un cliente MCP simple (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}`);
});
// Mensaje de prueba
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: Configura para Claude Code
Edita ~/.claude/settings.json así:
{
"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. Ahora podrás invocar las herramientas de Apidog directamente desde el chat:
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: Configura para Cursor
Para Cursor, agrega .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"
}
}
}
}
Ejemplo de uso en Cursor:
@apidog run_test projectId="proj_12345" environmentId="staging"
Código fuente 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 |
Ejecuta colecciones de pruebas programáticamente |
validate_schema |
Detecta errores de OpenAPI antes del despliegue |
list_environments |
Descubre entornos de prueba disponibles |
| Validación Zod | Maneja parámetros con seguridad de tipos |
| Transporte Stdio | Compatible con Claude Code, Cursor y cualquier MCP |
Próximos pasos
Extiende el servidor:
- Agrega la herramienta
compare_responsespara comparar resultados entre entornos - Añade
get_test_historypara consultar el historial de pruebas - Implementa
trigger_mock_serverpara iniciar/detener mocks
Consideraciones para producción:
- Implementa retries para solicitudes inestables
- Limita la velocidad para evitar bloqueos de la API
- Añade logs para depuración de errores
- Guarda las claves API en una bóveda segura
Comparte con tu equipo:
- Publica en npm como
@tu-organizacion/apidog-mcp-server - Documenta variables de entorno requeridas
- Incluye ejemplos de configuración MCP
Solución de problemas comunes
El servidor MCP no carga en Claude Code:
- Asegúrate de que la ruta en
~/.claude/settings.jsones absoluta - Verifica que
nodeestá en tu PATH (which node) - Confirma que
dist/index.jsexiste y está compilado - Revisa los logs MCP de Claude Code
Las herramientas no aparecen después de la configuración:
- Reinicia completamente Claude Code
- Ejecuta
npm run buildpara compilar TypeScript - Verifica que las tres herramientas se definan antes de
server.connect() - Asegúrate de que el servidor inicia sin errores (
node dist/index.js)
Las solicitudes a la API fallan con 401:
- Confirma que
APIDOG_API_KEYestá configurada correctamente - Elimina espacios extra o comillas en el valor de la clave
- Verifica que tu cuenta de Apidog tiene acceso a la API habilitado
- Prueba la clave manualmente:
curl -H "Authorization: Bearer $APIDOG_API_KEY" https://api.apidog.com/v1/user
Errores de validación de Zod:
- Los nombres de los parámetros deben coincidir con el esquema
- Incluye todos los campos obligatorios (sin errores de tipado)
- Usa
.optional()para los campos opcionales - Lee el mensaje de error completo; Zod indica el campo con problema
Errores de compilación de TypeScript:
- Ejecuta
npm installpara instalar dependencias - Verifica la versión de TypeScript (
npx tsc --version, debe ser 5.x) - Limpia y recompila (
rm -rf dist && npm run build) - Añade aserciones de tipo si es necesario en las respuestas de fetch
Probando tu servidor MCP 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. Olvídate de copiar/pegar entre chat y navegador. Escribe un comando, recibe resultados automáticos.
Ese es el poder de MCP: amplía tus agentes de IA con herramientas especializadas y acelera tus ciclos de desarrollo.
Puntos clave
- Servidores MCP conectan agentes de IA a APIs externas: Implementa una vez y úsalo en Claude Code, Cursor y cualquier cliente MCP.
-
Tres herramientas cubren los flujos principales:
run_testpara ejecutar pruebas,validate_schemapara validación OpenAPI,list_environmentspara descubrir entornos. - La validación Zod previene errores de parámetros: Las definiciones de herramientas seguras detectan problemas antes de invocar la API.
-
La configuración es específica por herramienta: Claude Code usa
~/.claude/settings.json, Cursor usa.cursor/mcp.json. - Para producción agrega manejo de errores: Implementa retries, rate limiting y almacenamiento seguro de claves.
Preguntas frecuentes
¿Qué es MCP en IA?
MCP (Model Context Protocol) es un protocolo estandarizado para que los agentes de IA accedan a herramientas y fuentes de datos externas, similar a un sistema de plugins.
¿Cómo creo un servidor MCP para Apidog?
Instala @modelcontextprotocol/sdk, define herramientas con Zod, implementa manejadores que llamen a la API de Apidog y conecta usando StdioServerTransport.
¿Puedo usar esto con Cursor?
Sí, agrega la configuración MCP en .cursor/mcp.json. El mismo servidor funciona tanto en Claude Code como en Cursor y otros clientes MCP.
¿Qué herramientas debo exponer?
Comienza con run_test (ejecución de pruebas), validate_schema (validación OpenAPI) y list_environments (consulta de entornos).
¿El servidor MCP de Apidog está listo para producción?
El código presentado es un punto de partida. Agrega retries, limitación de velocidad, manejo de errores robusto y almacenamiento seguro de claves antes de usarlo en producción.
¿Necesito una clave API de Apidog?
Sí. Define APIDOG_API_KEY como variable de entorno. El servidor la usará para autenticar las peticiones a la API.
¿Puedo compartir este servidor MCP con mi equipo?
Sí, publícalo en npm (privado), documenta las variables de entorno necesarias e incluye ejemplos de configuración MCP.
Top comments (0)