MCP — Model Context Protocol
MCPとは?
MCP(Model Context Protocol)は、AIアシスタントを外部ツール、データソース、サービスに接続するためのオープン標準です。サーバーは「ツール」 — 名前、説明、入力スキーマを持つ関数 — を公開し、AIモデルが会話中にいつ呼び出すかを判断します。2024年末にAnthropicによって作成され、現在ではClaude、ChatGPT、IDEプラグイン、増え続けるエージェントフレームワークによってサポートされているMCPは、AIにとってUSBがハードウェアに対して果たす役割と同じ役割を果たします:ケーブル1本で、どのデバイスでも。
なぜMCPが重要か
MCP以前は、各AIアシスタントは各外部サービスにカスタムの「プラグイン」または「function calling」コードを介して接続していました。各AIベンダーは独自の形式を持っていました。各ツール統合はベンダーごとに書き直す必要がありました — Claude用に1回、ChatGPT用に再度、Cursor用に再度、カスタムエージェント用に再度。
MCPはインターフェースを標準化します。1つのMCPサーバーは、すべてのMCP対応クライアントで動作します。それは:
- ツール開発者は統合をN回ではなく1回だけ書きます
- AIクライアントは公開された瞬間に新しいツールを取得します — クライアント更新不要
- エージェントはツールを実行時に発見、リスト、呼び出しできます — コンパイル時の配線なし
- オープンソースサーバーは監査、フォーク、セルフホストできます
プロプライエタリなプリンタードライバーとIP標準の違いです。プロトコルは退屈です。それに標準化することがエコシステムを解放します。
仕組み
すべての通信は単一のエンドポイント(例:/mcp)へのHTTP POST上のJSON-RPC 2.0を使用します:
- クライアントが
initializeを送信してセッションを確立 - サーバーが名前、バージョン、機能で応答
- クライアントが
tools/listを送信して利用可能なツールを発見 - サーバーが説明とスキーマ付きのツールリストを返す
- クライアントが
tools/callをツール名と引数とともに送信 - サーバーがツールを実行して結果を返す
MCP vs 代替手段
| 観点 | OpenAI function calling | OpenAPI / Swagger | MCP |
|---|---|---|---|
| ベンダー範囲 | 単一ベンダー | ベンダー中立 | ベンダー中立 |
| 設計対象 | LLMツール呼び出し | REST API | AIエージェント |
| 発見 | クライアントにハードコード | 静的spec | 実行時tools/list経由 |
| ストリーミング | 限定的 | ネイティブなし | 組み込み(SSE / Streamable HTTP) |
| ステートフルセッション | なし | なし | あり(initialize → 呼び出し) |
| 認証 | クライアント側キー | APIキー、OAuth | OAuth、bearer、カスタム |
| エコシステム | OpenAIのみ | 成熟、幅広い | 新しいが急成長 |
OpenAPIは設計時にREST APIを記述します。MCPはライブのツール面を実行時に記述します。2つは補完的です — 多くのMCPサーバーは既存のOpenAPIサービスをラップしてエージェント呼び出し可能なツールとして公開します。
実装例
app.post('/mcp', (req, res) => {
const { method, params, id } = req.body;
if (method === 'initialize') {
return res.json({ jsonrpc: '2.0', id, result: {
protocolVersion: '2024-11-05',
capabilities: { tools: {} },
serverInfo: { name: 'my-service', version: '1.0' }
}});
}
if (method === 'tools/list') {
return res.json({ jsonrpc: '2.0', id, result: {
tools: [{
name: 'search',
description: 'Search for items',
inputSchema: {
type: 'object',
properties: { query: { type: 'string' } },
required: ['query']
}
}]
}});
}
if (method === 'tools/call') {
const { name, arguments: args } = params;
return res.json({ jsonrpc: '2.0', id, result: {
content: [{ type: 'text', text: 'Search results...' }]
}});
}
res.json({ jsonrpc: '2.0', id, error: { code: -32601, message: 'Method not found' }});
});
トランスポートオプション
MCPは3つのトランスポートをサポートします — クライアントの実行場所に基づいて選択します:
- Streamable HTTP (リモートサーバー推奨):1つのエンドポイントへの平易なHTTP POST。サーバーはJSONレスポンスまたは進捗を出すツール用のSSEストリームを返します。CDN、ロードバランサー、ファイアウォールを通過します。claude.ai webとほとんどのホスト型クライアントが期待するものです。
- SSE(Server-Sent Events):サーバー→クライアント用の長期GETとクライアント→サーバー用のPOSTを使う古いトランスポート。まだサポートされていますが、新しいサーバーではStreamable HTTPに取って代わられています。
- stdio:プロセスパイプ — クライアントがあなたのサーバーをサブプロセスとして起動し、stdin/stdout経由で通信。Claude DesktopとCLIエージェントが使用。ネットワークなし、CORSなしですが、クライアントがあなたのコードをローカルで実行できる必要があります。
1つのMCPサーバーをClaude DesktopとClaude web appとChatGPTとCursorで動作させたい場合は、Streamable HTTPを出荷してください。ほとんどの人が今それを話します。
CORS — ブラウザベースのエージェントに必要
成長しているMCPクライアントのクラスはブラウザ内で動作します:Claude.ai web、ChatGPTブラウザ、ブラウザ拡張、埋め込みチャットウィジェット。claude.aiで実行されているJavaScriptがfetch('https://yourdomain.com/mcp')を呼び出すと、ブラウザは独自に2つのことを行います:
- リクエストをあなたのサーバーに実際に送信します。
- リクエストしたJavaScriptへのレスポンスの引き渡しを拒否します — ただし、あなたのサーバーのレスポンスに
claude.ai(または*)を指定するAccess-Control-Allow-Originヘッダーが含まれている場合を除いて。
つまりCORSヘッダーなしでは、サーバーは正常に動作して200を返しますが、ブラウザタブ内のMCPクライアントはネットワークエラーを見てボディを読み取ることができません。これはブラウザがユーザーを保護しているためです。Claude DesktopやMCP CLIのようなサーバー側クライアントはこれの対象ではありません。
ブラウザベースのMCPクライアントをサポートするには、すべての/mcpレスポンスにこれらのヘッダーを送信し、OPTIONSプリフライトを処理します:
app.use('/mcp', (req, res, next) => {
res.set('Access-Control-Allow-Origin', '*');
res.set('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
res.set('Access-Control-Allow-Headers', 'Content-Type, Accept, Authorization');
if (req.method === 'OPTIONS') return res.sendStatus(204);
next();
});
ワイルドカード vs 特定のオリジン
Access-Control-Allow-Origin: *は公開、読み取り専用のMCPエンドポイントには問題ありません。MCPエンドポイントが認証を必要とするか、ツール呼び出しに課金する場合は、特定のオリジンを返すか(またはリクエストのOriginを許可リストに対してエコーバック)、Access-Control-Allow-Credentials: trueを設定します。ワイルドカードオリジンは、CORS仕様により認証情報と一緒に使用できません。
プリフライトが重要な理由
「単純な」リクエスト — 平易なGETまたはContent-Type: text/plainのPOST — の場合、ブラウザはそれを送信するだけで、レスポンスだけがブロックされます。しかしMCPはContent-Type: application/jsonのPOSTを使用します。これはブラウザが最初に確認するほどリスキーと見なすものです。実際のPOSTを送信する前に、ブラウザはOPTIONSリクエストを送信して尋ねます:「このオリジンからこれらのヘッダーを持つPOSTを受け入れますか?」
サーバーがOPTIONSに2xxステータスと正しいCORSヘッダーで応答しない場合、ブラウザはPOSTを完全にキャンセルします — サーバーに到達しません。そのため、CORSミドルウェアは両方を処理する必要があります:OPTIONSプリフライトと実際のPOST。
認証
公開の読み取り専用サーバーには認証は不要です。プライベートまたは有料ツールには、MCPは以下をサポートします:
- Bearerトークンを
Authorizationヘッダーで(最もシンプル) - OAuth 2.1 + PKCE — ユーザー委任アクセスの標準;MCP仕様は
/.well-known/oauth-authorization-serverのメタデータエンドポイントを定義しており、クライアントがOAuthフローを自動的に発見できます - リクエストごとの支払い x402経由 — 事前に認証する代わりに支払い指示付きのHTTP 402を返す
ユーザーが自分自身の代わりに認可する場合はOAuthが正しいデフォルトです。Bearerトークンはサービス間に正しいです。x402は呼び出しが有料でステートレスな場合に正しいです。
MCPを使っている企業
- Anthropic Claude — Claude Desktop、Claude.ai web、Claude APIのネイティブMCPクライアント
- OpenAI ChatGPT — 2025年にMCPサポートを追加
- IDE統合 — Cursor、Zed、Windsurf、JetBrainsプラグインすべてがMCPを話します
- エージェントフレームワーク — LangChain、LlamaIndexなどほとんどのエージェントSDKがMCPトランスポートを含みます
- 公式MCPレジストリ
registry.modelcontextprotocol.ioは数百の公開サーバーを掲載 - Smithery
smithery.aiは最大のコミュニティ主導のMCPマーケットプレイス
AgentGradeは独自のMCPサーバー(com.agentgrade/mcp-server)を公開しており、MCP対応クライアント内からサイトをスキャンしたいエージェント向けです。
一般的なエラーとデバッグ
Method not found(-32601):クライアントがサーバーが実装していないメソッドを呼び出した。未知のメソッドには常に優雅にエラーを返してください。- CORSプリフライトが失敗:OPTIONSが404または405を返す。上記のミドルウェアを追加してください。
- クライアントUIでツールリストが空:
tools/listレスポンスは正しい形式ですが、クライアントは空でないtools配列を期待しています。少なくとも1つのツールが登録されていることを確認してください。 Invalid params(-32602):クライアントから送信された引数がinputSchemaと一致しない。JSON Schemaを見て — 必須フィールドの欠落や型の誤りが通常の原因です。- Desktopで動作、webで失敗:ほぼ常にCORS。ブラウザがレスポンスをブロックし、サーバーログは200sを示しますがクライアントは何も見ません。
主要概念
- Tools:サーバーが公開する関数(例:"search"、"create_invoice")
- inputSchema:各ツールが受け付ける引数を記述するJSON Schema
- Resources:サーバーがモデルに渡せる読み取り専用データ(ファイル、スニペット、クエリ結果)
- Prompts:サーバーが公開する再利用可能なプロンプトテンプレート
- Streamable HTTP:推奨されるトランスポート — すべてのメッセージは1つのエンドポイントへのPOST経由
- SSE:Server-Sent Events — 古いトランスポート、後方互換性のため保持
FAQ
MCPはAnthropicのプロトコルですか、オープン標準ですか?
Anthropicによって作成され、オープン仕様として公開されています。リファレンス実装はMITライセンスです。OpenAI、IDEベンダー、エージェントフレームワークはAnthropicとは独立して採用しました — 今や単一ベンダーのプロトコルではなく、コミュニティ標準です。
MCPとOpenAIのfunction callingはどう違いますか?
Function callingは1つのベンダーのAPIの機能です。MCPは任意のクライアントが話せるトランスポートレベルのプロトコルです。Function callingでは、モデルとツール定義は同じOpenAIリクエスト内に存在します;MCPでは、モデルはクライアントに存在し、ツールはサーバーに存在し、定義された通信形式で通信します。
既存のREST APIをMCPとして公開すべきですか、それともAIにOpenAPI specを渡すだけにすべきですか?
両方動作しますが、対象クライアントが異なります。ネイティブMCPサポートを持つモデル(Claude、Cursor)はMCP経由でツールを直接呼び出します。1つしか時間がない場合、MCPを出荷してください — ほとんどのエージェントクライアントは実行時発見のためにそれを好みます。
MCPはWebSocketを必要としますか?
いいえ。現在の標準はStreamable HTTP — 1つのエンドポイントへの平易なPOSTで、内部にオプションのSSEストリーミングがあります。以前のドラフトはWebSocketを使用していました;その経路は放棄されました。なぜなら平易なHTTPは設定なしでCDN、ロードバランサー、企業ファイアウォールを通過するからです。
MCPサーバーはツール呼び出しに課金できますか?
はい。プロトコル自体は支払いを含みませんが、その上にx402を重ねることができます:エージェントが有効な支払い受領書を添付するまで、サーバーがtools/callからHTTP 402を返すようにします。これはエージェントエコシステムで最も活発なパターンの1つです。
MCPサーバーをレジストリにリストするには?
マニフェストをregistry.modelcontextprotocol.ioに提出します。Smithery.aiはレジストリをミラーリングし、発見機能を追加します。リストは無料で、レビューキューは短いです。
MCPサーバーが遅いのはなぜですか?
プロトコル自体は安価です — HTTP上のJSON-RPC。遅さはほぼ常に(a)ツール実装、または(b)サーバーレスのコールドスタートです。トランスポートを責める前にtools/callハンドラをプロファイルしてください。
ツールごとに別々のサーバーが必要ですか、それとも多くのツールを持つ1つのサーバーが必要ですか?
多くのツールを持つ1つのサーバーが標準です。論理サービスごとにツールをグループ化してください(例:すべてのGitHub操作を1つのサーバーに)。クライアントは同時に複数のサーバーに接続できるので、分割は権限管理またはホスティングのニーズが異なる場合にのみ意味があります。
仕様成熟度
正式仕様。 MCPはバージョン管理された仕様でAnthropicによって維持されています。現在のプロトコルバージョン:2024-11-05。Claude、ChatGPT、Cursor、ほとんどのエージェントフレームワークでネイティブにサポート。Streamable HTTPトランスポートは安定しており、すべての主要クライアントで使用されています。
さらに学ぶ
- modelcontextprotocol.io — 公式仕様
- MCP TypeScript SDK — リファレンス実装
- 公式MCPレジストリ — MCPサーバーの公開カタログ
- Smithery — 最大のコミュニティマーケットプレイス
- MDN: CORS — クロスオリジンリソース共有リファレンス
- エージェント準備 — MCPがより広いエージェンティックWebの風景にどう収まるか