DEV Community

Cover image for Comment créer un serveur MCP pour donner aux agents IA des pouvoirs de test API
Antoine Laurent
Antoine Laurent

Posted on • Originally published at apidog.com

Comment créer un serveur MCP pour donner aux agents IA des pouvoirs de test API

En bref

Créez un serveur MCP avec TypeScript qui expose trois outils : run_test, validate_schema et list_environments. Configurez-le dans ~/.claude/settings.json pour Claude Code ou .cursor/mcp.json pour Cursor. Vos agents IA pourront alors exécuter des tests Apidog, valider des schémas OpenAPI et récupérer des environnements sans quitter l'interface de chat. Le code source complet fait environ 150 lignes et utilise le package @modelcontextprotocol/sdk.

Essayez Apidog dès aujourd'hui

Créez un serveur MCP qui permet à Claude Code, Cursor et d'autres agents IA d'exécuter des tests d'API Apidog, de valider des schémas et de comparer des réponses, le tout sans quitter leur interface de chat.

💡
Vous êtes en pleine session de codage. Votre agent IA vient de terminer la création d'un point de terminaison d'API. Au lieu de copier le code, d'ouvrir Apidog, de créer une collection de tests et d'exécuter manuellement la validation, vous voulez taper une seule commande et obtenir les résultats.

C'est ce que le Protocole de Contexte de Modèle (MCP) rend possible. Le MCP permet aux agents IA d'accéder à des outils externes via une interface standardisée. Créez un serveur MCP pour Apidog, et votre agent IA pourra exécuter des tests, valider des schémas et récupérer des environnements sans changer de contexte.

Qu'est-ce que le MCP ?

Le MCP (Protocole de Contexte de Modèle) est un protocole permettant aux agents IA d'accéder à des outils et des sources de données externes. Considérez-le comme un système de plugins qui fonctionne avec Claude Code, Cursor et d'autres clients compatibles MCP.

Un serveur MCP expose des outils (fonctions que l'agent peut appeler) et des ressources (données que l'agent peut lire). Votre serveur MCP Apidog exposera des outils pour les tests d'API.

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

Étape 1 : Configurer le projet

Initialisez un projet 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

Créez 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

Ajoutez un script de build à package.json :

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

Étape 2 : Créer le squelette du serveur MCP

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

// Les outils seront ajoutés ici

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

Ce squelette crée un serveur MCP et le connecte au transport stdio. Le transport gère la communication entre l'agent IA et votre serveur via l'entrée/sortie standard.

Étape 3 : Définir l'outil run_test

Ajoutez l'outil principal à src/index.ts :

// Tool: run_test
server.tool(
  "run_test",
  {
    projectId: z.string().describe("ID du projet Apidog (voir l'URL du projet)"),
    environmentId: z.string().optional().describe("ID d'environnement optionnel"),
    testSuiteId: z.string().optional().describe("ID de suite de tests optionnel")
  },
  async ({ projectId, environmentId, testSuiteId }) => {
    const apiKey = process.env.APIDOG_API_KEY;
    if (!apiKey) {
      return {
        content: [{
          type: "text",
          text: "Erreur : variable d'environnement APIDOG_API_KEY non définie"
        }]
      };
    }

    // Construction de l'URL
    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: `Erreur 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: `Échec de la requête : ${error instanceof Error ? error.message : String(error)}`
        }]
      };
    }
  }
);
Enter fullscreen mode Exit fullscreen mode

La définition de l'outil comprend :

  1. Nomrun_test
  2. Schéma — Validation des paramètres via Zod
  3. Gestionnaire — Fonction asynchrone qui appelle l'API Apidog

Étape 4 : Ajouter l'outil validate_schema

Ajoutez la validation de schéma pour intercepter les erreurs OpenAPI avant le déploiement :

// Tool: validate_schema
server.tool(
  "validate_schema",
  {
    schema: z.object({}).describe("Objet schéma OpenAPI 3.x à valider"),
    strict: z.boolean().optional().default(false).describe("Mode strict pour contrôles additionnels")
  },
  async ({ schema, strict }) => {
    const apiKey = process.env.APIDOG_API_KEY;
    if (!apiKey) {
      return {
        content: [{
          type: "text",
          text: "Erreur : variable d'environnement APIDOG_API_KEY non définie"
        }]
      };
    }

    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: `Validation échouée : ${JSON.stringify(result.errors, null, 2)}`
          }]
        };
      }

      return {
        content: [{
          type: "text",
          text: result.valid
            ? "Le schéma est valide OpenAPI 3.x"
            : `Avertissements : ${JSON.stringify(result.warnings, null, 2)}`
        }]
      };
    } catch (error) {
      return {
        content: [{
          type: "text",
          text: `Validation échouée : ${error instanceof Error ? error.message : String(error)}`
        }]
      };
    }
  }
);
Enter fullscreen mode Exit fullscreen mode

Étape 5 : Ajouter l'outil list_environments

Ajoutez un outil pour récupérer les environnements disponibles pour un projet :

// Tool: list_environments
server.tool(
  "list_environments",
  {
    projectId: z.string().describe("ID du projet Apidog")
  },
  async ({ projectId }) => {
    const apiKey = process.env.APIDOG_API_KEY;
    if (!apiKey) {
      return {
        content: [{
          type: "text",
          text: "Erreur : variable d'environnement APIDOG_API_KEY non définie"
        }]
      };
    }

    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: `Erreur API : ${response.status} ${error}`
          }]
        };
      }

      const environments = await response.json();
      return {
        content: [{
          type: "text",
          text: environments.length === 0
            ? "Aucun environnement trouvé pour ce projet"
            : environments.map((e: any) =>
                `- ${e.name} (ID: ${e.id})${e.isDefault ? " [défaut]" : ""}`
              ).join("\n")
        }]
      };
    } catch (error) {
      return {
        content: [{
          type: "text",
          text: `Échec de la requête : ${error instanceof Error ? error.message : String(error)}`
        }]
      };
    }
  }
);
Enter fullscreen mode Exit fullscreen mode

Étape 6 : Compiler et tester

Compilez le serveur MCP :

npm run build
Enter fullscreen mode Exit fullscreen mode

Testez avec un client MCP simple. Exemple : créez 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(`Sortie serveur : ${data}`);
});

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

// Envoyer un message de test
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

Étape 7 : Configurer pour Claude Code

Ajoutez le serveur MCP à votre configuration Claude Code :

Créez ou modifiez ~/.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"
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Redémarrez Claude Code. Les outils Apidog s'affichent lorsque vous demandez de l'aide pour les tests d'API.

Utilisation dans Claude Code :

Utilisez l'outil run_test pour exécuter des tests sur mon projet Apidog.
ID du projet : proj_12345
Environnement : staging
Enter fullscreen mode Exit fullscreen mode
Validez ce schéma OpenAPI par rapport aux règles Apidog :
[coller le schéma]
Enter fullscreen mode Exit fullscreen mode
Listez tous les environnements pour le projet proj_12345
Enter fullscreen mode Exit fullscreen mode

Étape 8 : Configurer pour Cursor

Cursor utilise une configuration MCP similaire. Créez .cursor/mcp.json dans votre projet :

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

Utilisation dans Cursor :

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

Code source complet

Voici le fichier src/index.ts complet :

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 du projet Apidog"),
    environmentId: z.string().optional().describe("ID d'environnement"),
    testSuiteId: z.string().optional().describe("ID de suite de tests")
  },
  async ({ projectId, environmentId, testSuiteId }) => {
    const apiKey = process.env.APIDOG_API_KEY;
    if (!apiKey) {
      return {
        content: [{
          type: "text",
          text: "Erreur : APIDOG_API_KEY non défini"
        }]
      };
    }

    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: `Échec de la requête : ${error instanceof Error ? error.message : String(error)}`
        }]
      };
    }
  }
);

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

    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
          ? "Le schéma est valide"
          : `Problèmes : ${JSON.stringify(result.errors || result.warnings, null, 2)}`
      }]
    };
  }
);

// Tool: list_environments
server.tool(
  "list_environments",
  {
    projectId: z.string().describe("ID du projet Apidog")
  },
  async ({ projectId }) => {
    const apiKey = process.env.APIDOG_API_KEY;
    if (!apiKey) {
      return {
        content: [{
          type: "text",
          text: "Erreur : APIDOG_API_KEY non défini"
        }]
      };
    }

    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 ? " [défaut]" : ""}`
        ).join("\n")
      }]
    };
  }
);

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

Ce que vous avez construit

Composant Objectif
Serveur MCP Connecte les agents IA à l'API Apidog
run_test Exécute des collections de tests par programme
validate_schema Détecte les erreurs OpenAPI avant le déploiement
list_environments Découvre les environnements de test disponibles
Validation Zod Gestion des paramètres typée et sécurisée
Transport Stdio Fonctionne avec Claude Code, Cursor, tout client MCP

Prochaines étapes

Étendre le serveur :

  • Ajoutez l'outil compare_responses pour comparer les résultats des tests entre les environnements
  • Ajoutez get_test_history pour récupérer l'historique des exécutions de tests
  • Ajoutez trigger_mock_server pour démarrer/arrêter les points de terminaison fictifs

Considérations de production :

  • Ajoutez une logique de réessai pour les requêtes réseau instables
  • Implémentez une limitation de débit pour éviter le bridage de l'API
  • Ajoutez une journalisation pour le débogage des appels d'outils échoués
  • Stockez les clés API dans un coffre-fort sécurisé au lieu de variables d'environnement

Partagez avec votre équipe :

  • Publiez sur npm en tant que @your-org/apidog-mcp-server
  • Documentez les variables d'environnement requises
  • Incluez des exemples de configurations MCP pour les clients courants

Dépannage des problèmes courants

Le serveur MCP ne se charge pas dans Claude Code :

  • Vérifiez que le chemin dans ~/.claude/settings.json est absolu (pas relatif)
  • Vérifiez que node est dans votre PATH : which node
  • Assurez-vous que le fichier dist/index.js compilé existe : ls -la dist/
  • Recherchez les erreurs dans les journaux MCP de Claude Code

Les outils n'apparaissent pas après la configuration :

  • Redémarrez complètement Claude Code (quittez et rouvrez)
  • Exécutez npm run build pour vous assurer que TypeScript est compilé
  • Vérifiez que les trois outils sont définis avant server.connect()
  • Vérifiez que le serveur démarre sans erreurs : node dist/index.js

Les requêtes API échouent avec 401 :

  • Confirmez que APIDOG_API_KEY est défini dans la configuration
  • Vérifiez l'absence d'espaces supplémentaires ou de guillemets autour de la clé
  • Vérifiez que votre compte Apidog a l'accès API activé
  • Testez la clé manuellement : 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

Erreurs de validation Zod :

  • Assurez-vous que les noms des paramètres correspondent exactement au schéma
  • Vérifiez que les champs obligatoires sont fournis (pas de fautes de frappe dans projectId)
  • Vérifiez que les champs facultatifs utilisent .optional() dans le schéma
  • Lisez le message d'erreur complet — Zod indique quel champ a échoué

Erreurs de compilation TypeScript :

  • Exécutez npm install pour installer toutes les dépendances
  • Vérifiez la version de TypeScript : npx tsc --version (doit être 5.x)
  • Nettoyez et recompilez : rm -rf dist && npm run build
  • Recherchez les incompatibilités de type dans les réponses fetch (ajoutez des assertions de type as)

Tester votre serveur MCP localement

Avant de déployer, testez votre serveur localement :

Test manuel avec stdio :

# Démarrez le serveur
node dist/index.js

# Dans un autre terminal, envoyez un message de test
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | node dist/index.js
Enter fullscreen mode Exit fullscreen mode

Sortie attendue :

{
  "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

Testez un appel d'outil :

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

Vos agents IA ont désormais un accès direct aux capacités de test d'Apidog.

Plus besoin de copier-coller entre le chat et le navigateur. Plus d'exécution de tests manuelle. Tapez une commande, obtenez des résultats.

C'est la puissance du MCP : étendez vos agents IA avec des outils spécifiques à un domaine, et laissez-les vous aider à livrer plus rapidement.

Points clés à retenir

  • Les serveurs MCP connectent les agents IA aux API externes — Un seul développement, réutilisable avec Claude Code, Cursor et tout client MCP
  • Trois outils pour couvrir les besoins de test d'APIrun_test pour l'exécution, validate_schema pour la validation OpenAPI, list_environments pour la découverte
  • La validation Zod évite les mauvais paramètres — Les schémas typés détectent les erreurs avant les appels API
  • La configuration est spécifique à l'outil — Claude Code : ~/.claude/settings.json, Cursor : .cursor/mcp.json
  • La production nécessite une gestion des erreurs avancée — Ajoutez gestion d'erreurs réseau, limitation de débit et stockage sécurisé des clés API avant déploiement

FAQ

Qu'est-ce que le MCP en IA ?

Le MCP (Protocole de Contexte de Modèle) est un protocole standardisé qui permet aux agents IA d'accéder à des outils et des sources de données externes. Considérez-le comme un système de plugins pour les agents IA.

Comment créer un serveur MCP pour Apidog ?

Installez @modelcontextprotocol/sdk, définissez des outils avec la validation Zod, implémentez des gestionnaires qui appellent l'API Apidog et connectez-vous via StdioServerTransport.

Puis-je utiliser cela avec Cursor ?

Oui. Ajoutez la configuration du serveur MCP à .cursor/mcp.json à la racine de votre projet. Le même serveur fonctionne avec Claude Code, Cursor et d'autres clients MCP.

Quels outils devrais-je exposer ?

Commencez par run_test pour exécuter des collections de tests, validate_schema pour la validation OpenAPI et list_environments pour récupérer les environnements disponibles.

Le serveur MCP Apidog est-il prêt pour la production ?

Le code du tutoriel est un point de départ. Ajoutez une logique de réessai, une limitation de débit, une gestion appropriée des erreurs et un stockage sécurisé des clés API avant de l'utiliser en production.

Ai-je besoin d'une clé API Apidog ?

Oui. Définissez APIDOG_API_KEY comme variable d'environnement. Le serveur lit cette variable lors de l'exécution pour authentifier les requêtes API.

Puis-je partager ce serveur MCP avec mon équipe ?

Oui. Publiez-le sur npm en tant que package privé, documentez les variables d'environnement requises et incluez des exemples de configurations MCP.

Top comments (0)