DEV Community

Cover image for Cara Membuat Server MCP untuk Memberi Agen AI Kemampuan Uji API
Walse
Walse

Posted on • Originally published at apidog.com

Cara Membuat Server MCP untuk Memberi Agen AI Kemampuan Uji API

TL;DR

Buat server MCP dengan TypeScript yang mengekspos tiga alat: run_test, validate_schema, dan list_environments. Konfigurasikan di ~/.claude/settings.json untuk Claude Code atau .cursor/mcp.json untuk Cursor. Agen AI Anda bisa menjalankan pengujian Apidog, memvalidasi skema OpenAPI, dan mengambil lingkungan tanpa keluar dari antarmuka obrolan. Kode sumber lengkapnya sekitar 150 baris dan menggunakan paket @modelcontextprotocol/sdk.

Buat server MCP yang memungkinkan Claude Code, Cursor, dan agen AI lain menjalankan pengujian API Apidog, validasi skema, dan membandingkan respons langsung dari chat.

Coba Apidog hari ini

💡 Anda sedang dalam sesi coding. Agen AI Anda baru saja membangun sebuah endpoint API. Alih-alih copy-paste kode, buka Apidog, buat koleksi pengujian, dan jalankan validasi manual, Anda cukup ketik satu perintah dan langsung dapat hasilnya.

Itulah yang dimungkinkan Model Context Protocol (MCP). MCP memudahkan agen AI mengakses alat eksternal dengan antarmuka standar. Bangun server MCP untuk Apidog, dan agen AI Anda bisa menjalankan pengujian, validasi skema, dan mengambil environment tanpa harus pindah aplikasi.

Apa Itu MCP?

MCP (Model Context Protocol) adalah protokol open-source yang memungkinkan agen AI mengakses alat dan sumber data eksternal. Anggap saja seperti sistem plugin universal untuk Claude Code, Cursor, dan klien MCP lainnya.

Server MCP mengekspos alat (fungsi yang bisa dipanggil agen) dan sumber daya (data yang bisa dibaca agen). Server MCP Apidog Anda akan mengekspos alat untuk pengujian API.

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

Langkah 1: Siapkan Proyek

Buat proyek TypeScript baru:

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

Buat file 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

Tambahkan skrip build ke package.json:

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

Langkah 2: Buat Kerangka Server MCP

Buat file 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 akan didefinisikan di bawah

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

Kerangka ini siap menerima definisi alat dan menghubungkan agen AI ke server Anda melalui stdio.

Langkah 3: Definisikan Alat run_test

Tambahkan alat pertama di src/index.ts:

// Tool: run_test
server.tool(
  "run_test",
  {
    projectId: z.string().describe("ID proyek Apidog (ditemukan di URL proyek)"),
    environmentId: z.string().optional().describe("ID environment opsional"),
    testSuiteId: z.string().optional().describe("ID test suite opsional")
  },
  async ({ projectId, environmentId, testSuiteId }) => {
    const apiKey = process.env.APIDOG_API_KEY;
    if (!apiKey) {
      return {
        content: [{
          type: "text",
          text: "Error: Variabel lingkungan APIDOG_API_KEY belum diatur"
        }]
      };
    }

    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: `Kesalahan 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: `Permintaan gagal: ${error instanceof Error ? error.message : String(error)}`
        }]
      };
    }
  }
);
Enter fullscreen mode Exit fullscreen mode

Definisi alat terdiri dari:

  1. Namarun_test
  2. Skema — Validasi parameter dengan Zod
  3. Handler — Fungsi async yang memanggil API Apidog

Langkah 4: Tambahkan Alat validate_schema

Validasi skema OpenAPI sebelum deployment:

// Tool: validate_schema
server.tool(
  "validate_schema",
  {
    schema: z.object({}).describe("Objek skema OpenAPI 3.x untuk divalidasi"),
    strict: z.boolean().optional().default(false).describe("Mode ketat untuk pemeriksaan tambahan")
  },
  async ({ schema, strict }) => {
    const apiKey = process.env.APIDOG_API_KEY;
    if (!apiKey) {
      return {
        content: [{
          type: "text",
          text: "Error: Variabel lingkungan APIDOG_API_KEY belum diatur"
        }]
      };
    }

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

      return {
        content: [{
          type: "text",
          text: result.valid
            ? "Skema adalah OpenAPI 3.x yang valid"
            : `Peringatan: ${JSON.stringify(result.warnings, null, 2)}`
        }]
      };
    } catch (error) {
      return {
        content: [{
          type: "text",
          text: `Validasi gagal: ${error instanceof Error ? error.message : String(error)}`
        }]
      };
    }
  }
);
Enter fullscreen mode Exit fullscreen mode

Langkah 5: Tambahkan Alat list_environments

Ambil environment pengujian yang tersedia:

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

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

      const environments = await response.json();
      return {
        content: [{
          type: "text",
          text: environments.length === 0
            ? "Tidak ada environment ditemukan"
            : environments.map((e: any) =>
                `- ${e.name} (ID: ${e.id})${e.isDefault ? " [default]" : ""}`
              ).join("\n")
        }]
      };
    } catch (error) {
      return {
        content: [{
          type: "text",
          text: `Permintaan gagal: ${error instanceof Error ? error.message : String(error)}`
        }]
      };
    }
  }
);
Enter fullscreen mode Exit fullscreen mode

Langkah 6: Build dan Uji

Build server:

npm run build
Enter fullscreen mode Exit fullscreen mode

Uji dengan klien MCP sederhana. Buat test-client.js:

import { spawn } from "child_process";

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

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

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

// Kirim pesan pengujian
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

Langkah 7: Konfigurasi untuk Claude Code

Tambahkan server MCP ke konfigurasi Claude Code:

Buat atau edit ~/.claude/settings.json:

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

Restart Claude Code. Alat Apidog kini akan muncul saat Anda minta bantuan pengujian API.

Contoh penggunaan di Claude Code:

Gunakan alat run_test untuk menjalankan pengujian pada proyek Apidog saya.
ID Proyek: proj_12345
Lingkungan: staging
Enter fullscreen mode Exit fullscreen mode
Validasi skema OpenAPI ini terhadap aturan Apidog:
[tempel skema]
Enter fullscreen mode Exit fullscreen mode
Daftar semua environment untuk proyek proj_12345
Enter fullscreen mode Exit fullscreen mode

Langkah 8: Konfigurasi untuk Cursor

Cursor memakai konfigurasi MCP serupa. Buat .cursor/mcp.json di project Anda:

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

Contoh penggunaan di Cursor:

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

Kode Sumber Lengkap

Berikut file src/index.ts lengkap:

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

    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: `Permintaan gagal: ${error instanceof Error ? error.message : String(error)}`
        }]
      };
    }
  }
);

// Tool: validate_schema
server.tool(
  "validate_schema",
  {
    schema: z.object({}).describe("Skema OpenAPI"),
    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 tidak diatur"
        }]
      };
    }

    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
          ? "Skema valid"
          : `Masalah: ${JSON.stringify(result.errors || result.warnings, null, 2)}`
      }]
    };
  }
);

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

    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);
Enter fullscreen mode Exit fullscreen mode

Apa yang Anda Bangun

Komponen Tujuan
Server MCP Menjembatani agen AI ke API Apidog
run_test Mengeksekusi koleksi pengujian secara terprogram
validate_schema Menangkap kesalahan OpenAPI sebelum deployment
list_environments Menemukan environment pengujian yang tersedia
Validasi Zod Penanganan parameter yang aman tipe
Transportasi Stdio Bekerja dengan Claude Code, Cursor, klien MCP mana pun

Langkah Selanjutnya

Perluas server:

  • Tambahkan alat compare_responses untuk membandingkan hasil di berbagai environment
  • Tambahkan get_test_history untuk mengambil riwayat eksekusi pengujian
  • Tambahkan trigger_mock_server untuk mengelola endpoint mock

Pertimbangan produksi:

  • Tambahkan logika retry untuk permintaan jaringan yang tidak stabil
  • Terapkan rate limiting agar tidak kena throttle API
  • Tambahkan logging untuk debugging alat yang gagal
  • Simpan API key di vault, bukan di variabel environment

Bagikan dengan tim:

  • Publikasikan ke npm sebagai @your-org/apidog-mcp-server
  • Dokumentasikan variabel lingkungan yang diperlukan
  • Sertakan contoh konfigurasi MCP untuk klien populer

Memecahkan Masalah Umum

Server MCP tidak muncul di Claude Code:

  • Pastikan path di ~/.claude/settings.json ABSOLUT
  • Pastikan node ada di PATH: which node
  • Pastikan dist/index.js sudah terbuild: ls -la dist/
  • Cek log MCP Claude Code

Alat tidak muncul setelah konfigurasi:

  • Restart Claude Code sepenuhnya
  • Jalankan npm run build agar TypeScript tercompile
  • Cek semua alat sudah didefinisikan sebelum server.connect()
  • Jalankan manual: node dist/index.js untuk melihat error

Permintaan API gagal 401:

  • Pastikan APIDOG_API_KEY benar di environment
  • Cek spasi/tanda kutip ekstra pada API key
  • Pastikan akun Apidog Anda punya akses API
  • Uji API key manual:
  curl -H "Authorization: Bearer $APIDOG_API_KEY" https://api.apidog.com/v1/user
Enter fullscreen mode Exit fullscreen mode

Error validasi Zod:

  • Nama parameter harus persis sama dengan skema
  • Cek field wajib disediakan (projectId dsb)
  • Untuk field opsional, gunakan .optional() di skema
  • Baca pesan error Zod untuk detail field yang gagal

Error kompilasi TypeScript:

  • Jalankan npm install agar dependensi lengkap
  • Cek versi TypeScript: npx tsc --version (sebaiknya 5.x)
  • Bersihkan dan build ulang: rm -rf dist && npm run build
  • Jika fetch bermasalah, tambahkan pernyataan tipe (as ...)

Menguji Server MCP Anda Secara Lokal

Sebelum deploy, uji server Anda lokal.

Pengujian manual via stdio:

# Jalankan server
node dist/index.js

# Di terminal lain, kirim pesan pengujian
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | node dist/index.js
Enter fullscreen mode Exit fullscreen mode

Output yang diharapkan:

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

Uji pemanggilan alat:

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

Agen AI Anda kini punya akses langsung ke kemampuan pengujian Apidog. Tidak perlu lagi copy-paste antara chat dan browser. Tidak perlu lagi menjalankan tes manual. Tinggal ketik perintah, hasil langsung kembali.

Itulah kekuatan MCP: perluas agen AI Anda dengan alat domain-specific, dan biarkan mereka membantu Anda shipping lebih cepat.

Poin Penting

  • Server MCP menjembatani agen AI ke API eksternal — Buat sekali, pakai di Claude Code, Cursor, dan klien MCP lain
  • Tiga alat utama cukup untuk workflow pengujian APIrun_test untuk eksekusi, validate_schema untuk validasi OpenAPI, list_environments untuk penemuan environment
  • Validasi Zod mencegah parameter salah — Definisi alat yang aman tipe menangkap error sebelum request API
  • Konfigurasi alat spesifik — Claude Code: ~/.claude/settings.json, Cursor: .cursor/mcp.json
  • Produksi butuh error handling — Tambahkan retry, rate limit, dan simpan key dengan aman sebelum go-live

FAQ

Apa itu MCP dalam AI?

MCP (Model Context Protocol) adalah protokol standar untuk agen AI supaya bisa mengakses alat dan sumber data eksternal, seperti sistem plugin universal.

Bagaimana cara membuat server MCP untuk Apidog?

Install @modelcontextprotocol/sdk, definisikan alat dengan validasi Zod, implementasikan handler yang memanggil API Apidog, lalu hubungkan via StdioServerTransport.

Bisa dipakai di Cursor?

Bisa. Tambahkan konfigurasi server MCP ke .cursor/mcp.json di root project Anda. Server yang sama bisa dipakai di Claude Code, Cursor, dan klien MCP lainnya.

Alat apa yang sebaiknya diekspos?

Mulai dengan run_test (eksekusi koleksi pengujian), validate_schema (validasi OpenAPI), dan list_environments (ambil daftar environment).

Apakah server MCP Apidog ini siap produksi?

Kode tutorial hanya baseline. Tambahkan retry logic, rate limiting, error handling, dan simpan API key dengan aman sebelum digunakan di production.

Apakah saya butuh API key Apidog?

Ya. Set APIDOG_API_KEY di environment. Server membaca ini saat runtime untuk autentikasi API.

Bisa dibagikan ke tim?

Bisa. Publikasikan ke npm, dokumentasikan environment variable yang diperlukan, dan sertakan contoh konfigurasi MCP.

Top comments (0)