「Ableton Live MCP」のShow HN投稿が今週初め、118ポイントと78件のコメントを獲得しました。このパターンは今や見慣れたものです。誰かが予期せぬツールのModel Context Protocolサーバーを書き、Claude Desktopのユーザーがそれを気に入り、「Xのために書くべきか?」という投稿が続きました。MCPはAnthropic専用の実験から、1年足らずでデフォルトのエージェント統合レイヤーへと発展しました。
この成長が隠しているのは、ツールの欠如です。MCPサーバーをテストするためのクリーンな方法を誰も提供していません。デバッガーを使ってstdio経由でJSON-RPCを手動で実行するのは「hello-world」には問題ありませんが、サーバーに12個のツール、3つのプロンプト、そして不安定なアップストリームAPIがある途端に破綻します。このガイドでは、MCPサーバーを手動でテストし、Apidogでテストを自動化するための実践的なプレイブックを提供します。これにより、契約、モック、回帰テストスイートを備え、他のAPIと同様の方法でMCPサーバーを出荷できるようになります。
より一般的なエージェントの文脈から来ている場合は、弊社のagents.mdガイドがこれとよく合います。そこにある規約は、MCPサーバーの契約をチームに伝えるのをより容易にします。
TL;DR
- MCPはAnthropicのModel Context Protocolであり、stdioまたはHTTPを介したJSON-RPC 2.0で、ツール、リソース、プロンプトの3つのプリミティブを公開します。
- MCPサーバーのテストとは、その
initialize、tools/list、tools/call、resources/read、およびprompts/getの応答を契約に対して検証することを意味します。 - 手動から始めましょう。コマンドラインからstdioでサーバーを操作し、応答を目視で確認し、クライアントを追加する前に形状のバグを修正します。
- 自動化へと移行しましょう。ApidogでJSON-RPCトラフィックをキャプチャし、各呼び出しを保存されたリクエストに変換し、応答の形状と内容に関するアサーションを構築し、CIでスイートを実行します。
- Apidogのモックサーバーを使用して、MCPサーバーが呼び出すアップストリームAPIをシミュレートし、テストが決定論的であることを保証します。
- リクエストコレクション、モックサーバー、CIランナーをすべて1か所で入手するには、Apidogをダウンロードしてください。
MCPの正体、2分で解説
Model Context Protocol仕様は、小さな表面を持つJSON-RPC 2.0のワイヤーフォーマットを定義しています。クライアント(Claude Desktop、Cursor、独自のAIエージェント)はMCPサーバーを起動し、initializeハンドシェイクを実行した後、呼び出しを発行します。
テストに費やす時間の90%を占める5つの呼び出し:
initialize:バージョンネゴシエーションと機能の開示。tools/list:サーバーは公開するツールを返します。これには引数のJSONスキーマも含まれます。tools/call:クライアントは引数とともに名前でツールを呼び出します。resources/listおよびresources/read:サーバーは読み取り可能なURI指定コンテンツを公開します。prompts/listおよびprompts/get:サーバーはクライアントがレンダリングできるプロンプトテンプレートを公開します。
トランスポートはstdio(stdin/stdoutで改行区切りのJSON-RPCフレーム)またはストリーミング可能なHTTP(通常はストリーミング用のSSE付きPOST /)のいずれかです。ほとんどのローカルサーバーはstdioを使用し、リモートサーバーはHTTPを使用します。
なぜテストが重要なのか:すべてのClaude Desktopユーザー、すべてのCursorユーザー、MCPサポートを追加するすべてのIDEがあなたのサーバーを呼び出すことになります。tools/listの形状におけるバグは、すべてのクライアントを一斉に機能不全に陥らせます。回帰によるコストは高くなります。
何をテストすべきか
堅牢なMCPサーバーテストスイートは、6つの側面をカバーします。
プロトコル準拠。 initializeは正しいprotocolVersionを返しますか?サーバーは実際にサポートしている機能を宣伝していますか?
スキーマの正確性。 tools/list内の各ツールは、引数に対して有効なJSONスキーマを持っていますか?必須フィールドはマークされていますか?説明は3単語より長いですか?空の説明はClaudeでのツール選択を妨げます。
ツールの動作。 各ツールについて、tools/callは正しいタイプ(text、image、resource)のコンテンツブロックを返しますか?エラーケースはJSON-RPCエラーをスローする代わりにisError: trueの結果を返しますか?
リソースアクセス。 resources/list URIはresources/read経由で呼び出されたときに解決されますか?ページネーションは最初のページを超えて機能しますか?
プロンプトのレンダリング。 プロンプトは整形式のmessages配列を返しますか?引数の置換は正しい場所に配置されますか?
障害モード。 アップストリームAPIがダウンした場合、どうなりますか?ツール引数が欠落している場合、どうなりますか?クライアントがタイムアウトした場合、どうなりますか?これらは「hello-world」ではなく、本番環境で現れるバグです。
このガイドの残りの部分では、これらのそれぞれについて、まず手動で、次に自動化して詳しく説明します。
stdioによる手動テスト
最もシンプルな設定から始めましょう。ターミナル、サーバーバイナリ、そしてMCPインスペクターまたは手動による生のJSON-RPCです。
まだサーバーを構築していない場合は、PythonまたはTypeScriptで公式MCP SDKクイックスタートを使用して足場を組んでください。2つのツールを持つ天気予報の例は、テストには十分です。
npx @modelcontextprotocol/inspector node your-server.js
インスペクターは、あなたのサーバーにMCPで通信し、すべてのリクエストとレスポンスを表示するローカルウェブUIを起動します。これは、サーバーが起動し、機能を宣伝し、tools/listに応答することを確認する最速の方法です。
インスペクターの表示が正しくなったら、生のstdioで同じフローを実行して、Apidog用のフレームをキャプチャできるようにします。
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2026-04-01","capabilities":{}}}' | node your-server.js
stdoutにJSON-RPC応答が表示されます。リクエストと応答を保存します。tools/list、tools/call、resources/list、その他についても繰り返します。この演習の終わりには、サーバーのワイヤーレベル契約を定義する6〜12組の標準的なリクエスト・応答ペアが得られます。
注意すべき2つの点。
まず、コンテンツブロックです。ツールの結果はcontent: [{ type: "text", text: "..." }]またはcontent: [{ type: "image", data: "...", mimeType: "image/png" }]を返します。1つの応答でタイプを混在させることは許可されており、クライアントはそれらをどのようにレンダリングするかで異なります。
次に、エラーです。MCP仕様は明確です。ツール実行エラーは、isError: trueと失敗を説明するコンテンツブロックを含む通常の結果を返します。ツール内からJSON-RPCエラー応答をスローしないでください。それはツールレベルの失敗ではなく、プロトコルレベルの失敗を示します。多くのクライアントはプロトコルエラーで接続を切断します。
手動から自動へ:Apidogでテストスイートを構築する
手動テストは明白なバグを表面化させます。「前回の変更でツール7の引数スキーマが壊れたか?」と自問し始め、その答えを見つけるために12個のcurlコマンドを入力したくない場合に自動化に移行します。
パターン:手動テスト中に保存したすべてのリクエスト・応答ペアをApidogに保存済みリクエストとして貼り付け、アサーションを追加し、すべてのプッシュでスイートを実行します。
1. MCPサーバー用のApidogプロジェクトを作成する
Apidogを開き、新しいプロジェクトを作成し、ベースURLをMCPサーバーのHTTPエンドポイント(またはstdioブリッジURL、下記参照)に設定します。ApidogプロジェクトはRESTとJSON-RPCの両方をサポートしています。JSON-RPC環境を作成してください。
HTTPインターフェースを持たないstdioサーバーの場合、テスト用に薄いHTTPラッパーの背後で実行します。公式インスペクターにはそれが同梱されています。あるいは、HTTP経由でJSON-RPCを読み取り、stdioに転送する30行のNodeスクリプトでも問題ありません。2026年のPostmanなしのAPIテストでも、非HTTPバックエンドに対して同じパターンを使用しています。
2. 標準リクエストを保存する
initialize、tools/list、tools/call、resources/list、resources/read、prompts/list、prompts/getのそれぞれについて、JSON-RPCボディをリクエストとして保存します。Apidogはこれらをボディ、ヘッダー、および期待されるステータスとともに保存します。
Apidogのリクエストボディビューでは、tools/callリクエストは次のようになります。
{
"jsonrpc": "2.0",
"id": 42,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": {
"city": "Tokyo"
}
}
}
3. アサーションを追加する
自動化の目的は、リクエストを送信することではなく、応答に対してアサーションを行うことです。ApidogはJSONPathアサーションをネイティブにサポートしています。tools/listについては、少なくとも以下を希望するでしょう。
$.result.toolsが存在すること$.result.tools.lengthがゼロより大きいこと- すべてのツールに
name、description、inputSchemaがあること - すべての
inputSchemaが有効なJSONスキーマであること
既知の正しい入力に対するtools/callについては、以下を希望するでしょう。
$.result.isErrorがfalseであること(または存在しないこと)$.result.contentが配列であること- 最初のコンテンツブロックが期待される
typeとコンテンツを持つこと
既知の不正な入力(必須引数なし)に対するtools/callについては、以下を希望するでしょう。
$.result.isErrorがtrueであること$.result.content[0].textが期待されるエラーメッセージと一致すること
Apidogはこれらのアサーションをリクエストごとに保存します。失敗は実行レポートに表示されます。
4. アップストリームAPIをモックする
ほとんどのMCPサーバーは外部API(天気データ、GitHub、Linear、内部データベースなど)をラップしています。CIの実行がコミットごとにライブAPIにヒットすることは望ましくありません。理由は2つあります。コストと不安定さです。
Apidogに組み込まれたモックサーバーがこれを解決します。各アップストリームエンドポイントを、リアルなJSONボディを返すモック化されたルートとして定義します。テスト中はMCPサーバーの設定をモックURLに向け、実際の実行中は本番環境に向けます。契約優先のAPI開発でモックワークフローについて詳しく説明しています。
その結果:数秒で実行され、外部ネットワークを必要とせず、スキーマの回帰をリリース前に早期に発見するテストスイートが得られます。
5. CIでスイートを実行する
ApidogプロジェクトはCLIランナーにエクスポートできます。apidog runコマンドはプロジェクトIDを受け取り、保存されたすべてのリクエストを実行し、アサーションを評価し、失敗した場合は非ゼロで終了します。これをGitHub Actionsまたは既に使用している任意のCIプロバイダーに組み込みます。
最小限のワークフロー:
name: MCP server tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 22 }
- run: npm ci
- name: Start MCP HTTP wrapper
run: node test/wrapper.js &
- name: Run Apidog suite
run: npx apidog run --project-id $APIDOG_PROJECT --env ci
env:
APIDOG_PROJECT: ${{ secrets.APIDOG_PROJECT }}
APIDOG_TOKEN: ${{ secrets.APIDOG_TOKEN }}
すべてのプッシュでMCPの契約全体が実行されます。ツール7のスキーマ回帰は、表面化せずにリリースされることはありません。
優れたテストカバレッジとはどのようなものか
Apidogにおける完全なMCPサーバーテスト計画は、通常以下を含みます。
- 機能アサーションを含む
initializeリクエスト1件 - 形状とJSONスキーマのアサーションを含む
tools/listリクエスト1件 - ツールごとに2〜4件の
tools/callリクエスト:ハッピーパス、引数不足、無効な型、アップストリームエラー - リソースファミリーごとに
resources/list1件とresources/read1件 - プロンプトテンプレートごとに
prompts/list1件とprompts/get1件
3つのリソースと4つのプロンプトを持つ10個のツールを持つサーバーの場合、スイートは50〜70件のリクエストを処理します。Apidogはモックサーバーが起動した状態で、これをローカルで10秒未満で実行します。
MCPサーバーテスト時のよくある間違い
これらは私たちが最もよく目にするパターンです。
initializeのラウンドトリップをスキップする。 いくつかのサーバーは、ハンドシェイク内でツールレジストリを遅延構築するため、initializeが呼び出されないとtools/listでクラッシュします。常にinitializeを最初に実行してください。- 生のエラーストリングでアサーションする。 ツールの失敗メッセージは変更される可能性があります。
isError: trueと安定したエラーコードまたは正規表現でアサーションし、厳密な文字列一致は避けてください。 - モックと本番の乖離を許す。 実際のAPIが決して返さない形状を返すモックは、壊れた統合に対して緑色のテスト(成功)を与えます。リリースごとに実際の応答からモックフィクスチャを再記録してください。
- ストリーミングを忘れる。 HTTP MCPサーバーはSSEを介してツール結果をストリーミングします。テストランナーはSSEを処理する必要があります。Apidogは対応していますが、リクエストでストリーミングを有効にする必要があります。
- 並行性をテストしない。 MCPクライアントはエージェントループで並行して
tools/callリクエストを送信します。サーバーがロックなしで共有状態を保持している場合、単一リクエストテストは合格しても本番環境が破損します。スイートに並行実行テストを追加してください。 - プロトコルエラーとツールエラーを混同する。 MCP仕様は意図的にこれらを分離しています。これらを混同するとClaude Desktopが接続を閉じます。APIプラットフォームの契約優先開発で同様の契約バグについて説明しました。
実世界のユースケース
自社のインシデント管理API用の内部MCPサーバーを構築しているチームは、Apidogのtools/list形状に関するアサーションを使用して、1週間で3つの回帰を発見しました。このテストがなければ、バグはClaude Desktopを使用しているすべてのエンジニアに同時に出荷されていただろう。
Notion用のオープンソースMCPサーバーを公開している一人の開発者は、Apidogモックを使用して、CI中にNotionのレート制限に達することなくテストスイートを実行しています。彼らのスイートはすべてのPRで実行され、8秒かかり、Apidogのモックフィクスチャをリポジトリにキャッシュするため、貢献者は開発のためにAPIアクセスを必要としません。
14の内部MCPサーバーを運用するプラットフォームチームは、各サーバーの契約が置かれる共有Apidogワークスペースを構築しました。新しいサーバーはベーステストスイートを継承し、レビュー担当者はマージ前にスキーマの差分を並べて比較できます。チームは、第1四半期に2件の障害を回避したと報告しており、どちらも社内のすべてのClaude Desktopユーザーに名前変更された引数を展開していただろうPRに対するtools/list形状のアサーションによって捕捉されました。
内部監視プラットフォーム用のMCPサーバーを構築する別のチームは、Apidogの環境スイッチャーを使用して、ステージングと本番環境に対して同じスイートを実行しています。各環境は異なるモックフィクスチャファイルを指しているため、同じ60のアサーションで、1つのリクエストを書き直すことなく両方のデプロイを確認できます。
結論
MCPは今年主流になりましたが、テストの現状は10年前のREST APIテストと同じく、場当たり的、手動、脆弱です。エコシステムが追いつくのを待つ必要はありません。MCPサーバーをAPIとして扱い、契約を設計し、アップストリームをモックし、CIでアサーションを実行してください。
5つのポイント:
- MCPサーバーはJSON-RPC APIです。REST APIと同じ厳密さでテストしてください。
- まずは公式インスペクターで手動で開始し、標準リクエストをキャプチャして自動化に移行します。
- Apidogは、JSON-RPC、アサーション、モック、CIを1つのプロジェクトで処理します。
- 6つの側面をカバーします。プロトコル準拠、スキーマの正確性、ツールの動作、リソースアクセス、プロンプトレンダリング、障害モード。
- ApidogでアップストリームAPIをモックし、テストスイートを高速かつ決定論的に保ちます。
次のステップ:Apidogを開き、プロジェクトを作成し、手動でキャプチャしたリクエストボディを貼り付け、tools/listのJSONPathアサーションを追加し、スイートを実行します。1時間以内に、あなたのサーバーの契約が出荷に足る堅牢さを持っているかどうかがわかるでしょう。
よくある質問
MCPとは何ですか?
MCP(Model Context Protocol)は、AIクライアント(Claude Desktopなど)が外部ツール、リソース、プロンプトを呼び出す方法に関するAnthropicのオープン仕様です。これはstdioまたはストリーミング可能なHTTPを介したJSON-RPC 2.0です。MCPの完全な仕様はmodelcontextprotocol.ioで公開されています。
HTTPラッパーなしでMCPサーバーをテストできますか?
はい、できます。公式MCPインスペクターはstdioと直接通信し、手動テスト用のUIを提供します。Apidogでの自動テストの場合、CI中はstdioを薄いHTTPサーバーでラップします。本番トラフィックは引き続きstdio経由で処理されます。
MCPサーバーが呼び出すアップストリームAPIをどのようにモックしますか?
各アップストリームエンドポイントをApidogプロジェクトでモックとして定義し、テスト中はMCPサーバーの設定をモックURLに向け、実行時には本番URLに切り替えます。QAエンジニア向けのAPIテストツールで同じパターンを詳しく説明しています。
ツール結果のストリーミングについてはどうですか?
HTTP MCPサーバーは、サーバー送信イベント(SSE)を介してツール結果をストリーミングします。Apidogは保存されたリクエストでSSEをサポートしています。リクエスト設定で有効にし、組み立てられたストリームに対してアサーションを実行します。
プロトコルバージョンをテストすべきですか?
はい。initializeでサポートするprotocolVersionを固定し、それに対してアサーションを実行してください。不一致はサイレントなクライアントの非互換性を引き起こします。
実際のClaude Desktopに対してMCPサーバーをテストできますか?
はい、可能です。そして、各リリース前に少なくとも一度は行うべきです。しかし、Claude Desktopをテストループとして頼りにしないでください。それは遅く、手動で、非決定論的です。回帰テストスイートにはApidogを使用し、スモークテストにはClaude Desktopを使用してください。
実際のMCPサーバーの例はどこで見られますか?
公式MCPサーバーリポジトリには、ファイルシステム、GitHub、Slack、Postgresなど、数十に及ぶリファレンス実装があります。ツールの定義を読んでみてください。それが、優れたMCPの形状がどのようなものかを理解する最も簡単な方法です。
