AIエージェントAPIテスト機能を備えたMCPサーバーの構築方法

Ashley Innocent

Ashley Innocent

19 3月 2026

AIエージェントAPIテスト機能を備えたMCPサーバーの構築方法

Apidog エンタープライズ

オンプレミスデプロイ

SSO & RBAC

SOC 2 準拠

Apidog Enterpriseを見る

要点

TypeScriptでMCPサーバーを構築し、`run_test`、`validate_schema`、`list_environments`の3つのツールを公開します。Claude Codeの場合は`~/.claude/settings.json`、Cursorの場合は`.cursor/mcp.json`で設定します。これにより、AIエージェントはチャットインターフェースを離れることなく、Apidogテストの実行、OpenAPIスキーマの検証、環境の取得が可能になります。全ソースコードは約150行で、`@modelcontextprotocol/sdk`パッケージを使用しています。

Claude Code、Cursor、およびその他のAIエージェントが、チャットインターフェースを離れることなく、Apidog APIテストの実行、スキーマの検証、応答の比較を行えるMCPサーバーを構築します。

💡
あなたはコーディングセッションの最中です。AIエージェントがAPIエンドポイントの構築を終えました。コードをコピーし、Apidogを開き、テストコレクションを作成し、手動で検証を実行する代わりに、1つのコマンドを入力するだけで結果を取得したいと考えています。
button

これこそが、モデルコンテキストプロトコル(MCP)が実現することです。MCPは、AIエージェントが標準化されたインターフェースを介して外部ツールにアクセスすることを可能にします。Apidog用のMCPサーバーを構築すれば、AIエージェントはコンテキストを切り替えることなく、テストの実行、スキーマの検証、環境の取得を行うことができます。

MCPとは何か?

MCP(モデルコンテキストプロトコル)は、AIエージェントが外部ツールやデータソースにアクセスするためのプロトコルです。Claude Code、Cursor、およびその他のMCP互換クライアント間で動作するプラグインシステムと考えることができます。

MCPサーバーは、ツール(エージェントが呼び出せる関数)とリソース(エージェントが読み取れるデータ)を公開します。あなたのApidog MCPサーバーは、APIテスト用のツールを公開することになります。

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

ステップ1: プロジェクトのセットアップ

新しいTypeScriptプロジェクトを作成します:

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

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

package.jsonにビルドスクリプトを追加します:

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

ステップ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"
});

// Tools will be defined here

const transport = new StdioServerTransport();
await server.connect(transport);

このスケルトンは、MCPサーバーを作成し、それを標準入出力(stdio)トランスポートに接続します。このトランスポートは、AIエージェントとサーバー間の通信を標準入出力経由で処理します。

ステップ3: run_testツールの定義

最初のツールを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);

ツールの定義は3つの部分から構成されます:

  1. 名前run_test(エージェントは名前でツールを選択するため、分かりやすく記述する)
  2. スキーマ — パラメータの説明付きZod検証
  3. ハンドラー — Apidog APIを呼び出す非同期関数

ステップ4: validate_schemaツールの追加

デプロイ前にOpenAPIエラーを捕捉するために、スキーマ検証を追加します:

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

ステップ5: list_environmentsツールの追加

利用可能なテスト環境を取得するツールを追加します:

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

ステップ6: ビルドとテスト

サーバーをビルドします:

npm run build

シンプルなMCPクライアントでテストします。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");

ステップ7: Claude Codeの構成

Claude Codeの設定にMCPサーバーを追加します:

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

Claude Codeを再起動します。APIテストのヘルプを求めると、Apidogツールが表示されるはずです。

Claude Codeでの使用法:

Use the run_test tool to run tests on my Apidog project.
Project ID: proj_12345
Environment: staging
Validate this OpenAPI schema against Apidog rules:
[paste schema]
List all environments for project proj_12345

ステップ8: Cursorの構成

Cursorは同様のMCP設定を使用します。プロジェクト内に.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"
      }
    }
  }
}

Cursorでの使用法:

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

完全なソースコード

以下に、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);

構築したもの

コンポーネント 目的
MCPサーバー AIエージェントとApidog APIを連携させる
run_test テストコレクションをプログラムで実行する
validate_schema デプロイ前にOpenAPIエラーを捕捉する
list_environments 利用可能なテスト環境を検出する
Zod検証 型安全なパラメータ処理
標準入出力トランスポート Claude Code、Cursor、任意のMCPクライアントで動作する

次のステップ

サーバーの拡張:

本番環境での考慮事項:

チームとの共有:

一般的な問題のトラブルシューティング

Claude CodeでMCPサーバーがロードされない:

設定後にツールが表示されない:

APIリクエストが401で失敗する:

Zod検証エラー:

TypeScriptコンパイルエラー:

MCPサーバーをローカルでテストする

本番環境にデプロイする前に、サーバーをローカルでテストします:

標準入出力による手動テスト:

# Start the server
node dist/index.js

# In another terminal, send a test message
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | node dist/index.js

期待される出力:

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

ツール呼び出しをテストする:

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

これで、AIエージェントはApidogのテスト機能に直接アクセスできるようになりました。チャットとブラウザの間でのコピー&ペーストは不要です。手動でのテスト実行も不要です。コマンドを入力するだけで結果が返ってきます。

これこそがMCPの力です。AIエージェントをドメイン固有のツールで拡張し、彼らが本来の役割を果たすようにします。つまり、より迅速な出荷を支援します。

主要なポイント

button

FAQ

AIにおけるMCPとは?MCP(モデルコンテキストプロトコル)は、AIエージェントが外部ツールやデータソースにアクセスできるようにする標準化されたプロトコルです。AIエージェント用のプラグインシステムと考えることができます。

Apidog用のMCPサーバーを作成するにはどうすればよいですか?`@modelcontextprotocol/sdk`をインストールし、Zod検証でツールを定義し、Apidog APIを呼び出すハンドラーを実装し、`StdioServerTransport`経由で接続します。

これをCursorで使用できますか?はい。プロジェクトルートの`.cursor/mcp.json`にMCPサーバー設定を追加してください。同じサーバーがClaude Code、Cursor、およびその他のMCPクライアントで動作します。

どのようなツールを公開すべきですか?まず、テストコレクション実行用の`run_test`、OpenAPI検証用の`validate_schema`、利用可能な環境取得用の`list_environments`から始めます。

Apidog MCPサーバーは本番環境に対応していますか?このチュートリアルコードは出発点です。本番環境で使用する前に、リトライロジック、レート制限、適切なエラーハンドリング、およびセキュアなAPIキー保存を追加してください。

Apidog APIキーは必要ですか?はい。`APIDOG_API_KEY`を環境変数として設定してください。サーバーは実行時にこれを読み取り、APIリクエストを認証します。

このMCPサーバーをチームと共有できますか?はい。プライベートパッケージとしてnpmに公開し、必要な環境変数を文書化し、MCP設定例を含めてください。

ApidogでAPIデザイン中心のアプローチを取る

APIの開発と利用をよりシンプルなことにする方法を発見できる