DEV Community

Cover image for สร้าง MCP Server เสริมพลัง AI ทดสอบ API
Thanawat Wongchai
Thanawat Wongchai

Posted on • Originally published at apidog.com

สร้าง MCP Server เสริมพลัง AI ทดสอบ API

สรุปใจความสำคัญ

สร้างเซิร์ฟเวอร์ MCP ด้วย TypeScript ที่เปิดเผยเครื่องมือสามอย่าง: run_test, validate_schema, และ list_environments กำหนดค่าใน ~/.claude/settings.json สำหรับ Claude Code หรือ .cursor/mcp.json สำหรับ Cursor จากนั้นเอเจนต์ AI ของคุณจะสามารถรันการทดสอบ Apidog, ตรวจสอบความถูกต้องของสคีมา OpenAPI และดึงข้อมูลสภาพแวดล้อมได้โดยไม่ต้องออกจากอินเทอร์เฟซการแชท ซอร์สโค้ดทั้งหมดมีประมาณ 150 บรรทัด และใช้แพ็คเกจ @modelcontextprotocol/sdk

ทดลองใช้ Apidog วันนี้

สร้างเซิร์ฟเวอร์ MCP ที่ช่วยให้ Claude Code, Cursor, และเอเจนต์ AI อื่นๆ สามารถรันการทดสอบ Apidog API, ตรวจสอบความถูกต้องของสคีมา และเปรียบเทียบการตอบสนองได้ โดยไม่ต้องออกจากอินเทอร์เฟซการแชท

💡 Context: ขณะเขียนโค้ด เอเจนต์ AI ของคุณสร้าง endpoint API เสร็จแล้ว คุณไม่ต้องการคัดลอกโค้ด, เปิด Apidog, สร้างคอลเลกชันทดสอบ, และรันตรวจสอบเอง — แค่พิมพ์คำสั่งเดียวก็ได้ผลลัพธ์ทันที

นี่คือสิ่งที่ Model Context Protocol (MCP) ทำให้เป็นไปได้ MCP ช่วยให้เอเจนต์ AI สามารถเข้าถึงเครื่องมือภายนอกผ่านอินเทอร์เฟซที่เป็นมาตรฐาน สร้างเซิร์ฟเวอร์ MCP สำหรับ Apidog แล้วเอเจนต์ AI ของคุณจะสามารถรันการทดสอบ, ตรวจสอบความถูกต้องของสคีมา, และดึงข้อมูลสภาพแวดล้อมได้โดยไม่ต้องเปลี่ยนบริบท

MCP คืออะไร?

MCP (Model Context Protocol) คือโปรโตคอลสำหรับเอเจนต์ AI ในการเข้าถึงเครื่องมือและแหล่งข้อมูลภายนอก คิดว่ามันเป็นระบบปลั๊กอินที่ทำงานได้ทั่วทั้ง Claude Code, Cursor และไคลเอนต์อื่นๆ ที่เข้ากันได้กับ MCP

เซิร์ฟเวอร์ MCP จะเปิดเผย เครื่องมือ (ฟังก์ชันที่เอเจนต์สามารถเรียกใช้ได้) และ ทรัพยากร (ข้อมูลที่เอเจนต์สามารถอ่านได้) เซิร์ฟเวอร์ MCP ของ Apidog ของคุณจะเปิดเผยเครื่องมือสำหรับการทดสอบ API

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

ขั้นตอนที่ 1: ตั้งค่าโปรเจกต์

สร้างโปรเจกต์ 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

สร้าง 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

เพิ่มสคริปต์ build ลงใน package.json:

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

ขั้นตอนที่ 2: สร้างโครงเซิร์ฟเวอร์ MCP

สร้าง 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"
});

// จะเพิ่มเครื่องมือที่นี่

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

ตัวอย่างนี้สร้างเซิร์ฟเวอร์ MCP และเชื่อมต่อด้วย stdio transport เพื่อรับส่งข้อมูลกับ AI agent

ขั้นตอนที่ 3: กำหนดเครื่องมือ run_test

เพิ่มเครื่องมือแรกใน src/index.ts:

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

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

โครงสร้างเครื่องมือ:

  1. ชื่อrun_test
  2. สคีมา — ตรวจสอบความถูกต้องของพารามิเตอร์ด้วย Zod
  3. แฮนเดลเลอร์ — ฟังก์ชัน async เรียก Apidog API

ขั้นตอนที่ 4: เพิ่มเครื่องมือ validate_schema

ตรวจสอบความถูกต้องของสคีมา OpenAPI ก่อนใช้งาน:

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

ขั้นตอนที่ 5: เพิ่มเครื่องมือ 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)}`
        }]
      };
    }
  }
);
Enter fullscreen mode Exit fullscreen mode

ขั้นตอนที่ 6: Build และ Test

Build เซิร์ฟเวอร์:

npm run build
Enter fullscreen mode Exit fullscreen mode

สร้างไฟล์ test-client.js เพื่อทดสอบ MCP Server ผ่าน stdio:

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

// ส่งข้อความทดสอบ
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

ขั้นตอนที่ 7: ตั้งค่าสำหรับ Claude Code

เพิ่ม MCP server ใน ~/.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

รีสตาร์ท Claude Code แล้วเครื่องมือ Apidog จะปรากฏเมื่อขอให้ช่วยทดสอบ API

ตัวอย่างการใช้งาน:

ใช้เครื่องมือ run_test เพื่อรันการทดสอบในโปรเจกต์ Apidog ของฉัน
Project ID: proj_12345
Environment: staging
Enter fullscreen mode Exit fullscreen mode
ตรวจสอบความถูกต้องของสคีมา OpenAPI นี้ตามกฎของ Apidog:
[วางสคีมา]
Enter fullscreen mode Exit fullscreen mode
แสดงสภาพแวดล้อมทั้งหมดสำหรับโปรเจกต์ proj_12345
Enter fullscreen mode Exit fullscreen mode

ขั้นตอนที่ 8: ตั้งค่าสำหรับ Cursor

สำหรับ Cursor ให้สร้าง .cursor/mcp.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

ใช้งานใน Cursor:

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

ซอร์สโค้ดฉบับสมบูรณ์

นี่คือ 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);
Enter fullscreen mode Exit fullscreen mode

สิ่งที่คุณสร้างขึ้น

ส่วนประกอบ วัตถุประสงค์
เซิร์ฟเวอร์ MCP เชื่อมต่อเอเจนต์ AI เข้ากับ Apidog API
run_test รันคอลเลกชันการทดสอบด้วยโปรแกรม
validate_schema ตรวจจับข้อผิดพลาดของ OpenAPI ก่อนการใช้งาน
list_environments ค้นหาสภาพแวดล้อมการทดสอบที่มีอยู่
การตรวจสอบความถูกต้องด้วย Zod การจัดการพารามิเตอร์ที่ปลอดภัยต่อชนิดข้อมูล
Stdio transport ใช้งานได้กับ Claude Code, Cursor, และไคลเอนต์ MCP อื่นๆ

ขั้นตอนต่อไป

ขยายเซิร์ฟเวอร์:

  • เพิ่มเครื่องมือ compare_responses เพื่อเปรียบเทียบผลลัพธ์ทดสอบในสภาพแวดล้อมต่างๆ
  • เพิ่ม get_test_history เพื่อดึงข้อมูลย้อนหลังของการรันทดสอบ
  • เพิ่ม trigger_mock_server เพื่อเริ่ม/หยุด mock endpoints

ข้อควรพิจารณาในการใช้งานจริง:

  • เพิ่ม retry logic สำหรับคำขอเครือข่าย
  • ใช้ rate limiting เพื่อป้องกันการถูกจำกัด API
  • เพิ่ม logging สำหรับการดีบั๊ก
  • เก็บ API key ใน secure vault แทน environment variable

แชร์กับทีม:

  • เผยแพร่เป็น npm package เช่น @your-org/apidog-mcp-server
  • จัดทำเอกสาร environment variables ที่จำเป็น
  • รวมตัวอย่าง config MCP สำหรับไคลเอนต์หลัก

การแก้ไขปัญหาทั่วไป

MCP Server ไม่โหลดใน Claude Code:

  • ตรวจสอบว่า path ใน ~/.claude/settings.json เป็น absolute
  • ตรวจสอบให้มี node อยู่ใน PATH: which node
  • ตรวจสอบว่า build แล้วมีไฟล์ dist/index.js: ls -la dist/
  • ตรวจสอบ log MCP ใน Claude Code

เครื่องมือไม่ปรากฏหลังการกำหนดค่า:

  • รีสตาร์ท Claude Code (ปิด-เปิดใหม่)
  • รัน npm run build ให้แน่ใจว่า TypeScript ถูก compile
  • ตรวจสอบว่าเครื่องมือถูกกำหนดก่อน server.connect()
  • เช็กว่า server รันได้ไม่มี error: node dist/index.js

API request fail ด้วยรหัส 401:

  • ตรวจสอบว่า APIDOG_API_KEY ถูกตั้งค่าถูกต้อง
  • ตรวจสอบว่า key ไม่มีช่องว่าง/quote เกิน
  • ตรวจสอบสิทธิ์เปิด API ในบัญชี Apidog
  • ทดสอบ key:
  curl -H "Authorization: Bearer $APIDOG_API_KEY" https://api.apidog.com/v1/user
Enter fullscreen mode Exit fullscreen mode

Zod validation error:

  • ชื่อพารามิเตอร์ตรง schema
  • ฟิลด์ที่จำเป็นต้องให้ค่าครบ
  • ฟิลด์ optional ใช้ .optional() ใน schema
  • อ่าน error message Zod ชี้ตรงจุด

TypeScript compile error:

  • รัน npm install ให้ครบ dependencies
  • เช็ก TypeScript version: npx tsc --version (ควร 5.x)
  • ล้าง build & build ใหม่: rm -rf dist && npm run build
  • ตรวจสอบชนิดข้อมูลใน fetch (ปรับด้วย type assertion)

การทดสอบเซิร์ฟเวอร์ MCP ของคุณในเครื่อง

Test ด้วย stdio:

# เริ่มเซิร์ฟเวอร์
node dist/index.js

# อีกเทอร์มินัล ส่งข้อความทดสอบ
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | node dist/index.js
Enter fullscreen mode Exit fullscreen mode

คาดหวังผลลัพธ์:

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

ทดสอบเรียกใช้เครื่องมือ:

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

ตอนนี้เอเจนต์ AI ของคุณสามารถเข้าถึงความสามารถในการทดสอบของ Apidog ได้โดยตรง — ไม่ต้องสลับบริบท ไม่ต้องรันทดสอบเอง แค่พิมพ์คำสั่งแล้วรับผลลัพธ์กลับทันที

MCP ช่วยขยายขีดความสามารถของเอเจนต์ AI ของคุณด้วยเครื่องมือเฉพาะ และให้คุณทำงานได้เร็วขึ้น

ประเด็นสำคัญ

  • เซิร์ฟเวอร์ MCP เชื่อมต่อเอเจนต์ AI กับ API ภายนอก — สร้างครั้งเดียว ใช้กับ Claude Code, Cursor และไคลเอนต์ที่รองรับ MCP
  • เครื่องมือสามอย่างครอบคลุมงานทดสอบ API ส่วนใหญ่run_test, validate_schema, list_environments
  • Zod validation ช่วยป้องกันค่าพารามิเตอร์ผิด — ปลอดภัยต่อชนิดข้อมูล
  • config แยกตามไคลเอนต์ — Claude Code ใช้ ~/.claude/settings.json, Cursor ใช้ .cursor/mcp.json
  • production ต้อง handle error — เพิ่ม retry, rate limit, และจัดการ API key อย่างปลอดภัย

คำถามที่พบบ่อย

MCP ใน AI คืออะไร?

MCP (Model Context Protocol) คือโปรโตคอลมาตรฐานที่ช่วยให้เอเจนต์ AI สามารถเข้าถึงเครื่องมือและแหล่งข้อมูลภายนอกได้ เหมือนระบบปลั๊กอินสำหรับ AI agent

จะสร้าง MCP server สำหรับ Apidog ได้อย่างไร?

ติดตั้ง @modelcontextprotocol/sdk กำหนดเครื่องมือด้วย Zod validation และ implement handler ที่เรียก Apidog API แล้ว connect ผ่าน StdioServerTransport

ใช้กับ Cursor ได้ไหม?

ได้ แค่เพิ่ม MCP server config ใน .cursor/mcp.json ใช้เซิร์ฟเวอร์เดียวกับ Claude Code/ไคลเอนต์อื่น

ควรเปิดเผยเครื่องมืออะไรบ้าง?

เริ่มที่ run_test (รัน test), validate_schema (ตรวจ schema), list_environments (ดึง environment)

เซิร์ฟเวอร์ Apidog MCP พร้อมใช้งานจริงไหม?

โค้ดนี้คือจุดตั้งต้น คุณควรเพิ่ม retry, rate limiting, error handling, การเก็บ API key ที่ปลอดภัย ก่อนใช้งานจริง

ต้องมี Apidog API key ไหม?

ต้อง ตั้ง APIDOG_API_KEY เป็น environment variable

แชร์ MCP server นี้กับทีมได้ไหม?

ได้ เผยแพร่เป็น npm private package, document environment variable ที่จำเป็น, และรวมตัวอย่าง config MCP

Top comments (0)