はじめに
Claude CodeなどのAIツールを利用していると頻繁に目にするMCP(Model Context Protocol)。
なんとなく使っていましたが、その通信仕様やアーキテクチャもいい加減少しは知っておこうと思い調べた内容を書きました。
MCPとは?
MCP (Model Context Protocol) は、AIアプリケーションを外部データソースやツールと接続するためのオープンな標準プロトコルです。2024年にAnthropic社によって発表されました。
MCPはよく「AIアプリケーション向けの USB-Cポート」と例えられます。
特定のAIモデルや特定のツールに依存せず、標準化されたインターフェースを提供することで、エコシステム全体の相互運用性を高める役割を果たします。
なぜMCPが必要なのか?
MCPが登場する前、AIアプリと外部サービスの連携は クライアントごとの個別実装が前提でした。たとえば Google Drive を連携したい場合でも、
- Claude Desktop 用
- VSCode 用
- Cursor 用
といったように、同じ機能を何度も実装・保守する必要がありました。
AIアプリが増えるほど、連携ロジックは分断され、開発・保守コストが膨らんでいきます。
MCPはこの問題を 「接続の標準化」 で解決します。
- Google Drive 用の MCPサーバーを1つ実装
- MCP対応のAIアプリから 同じインターフェースで利用可能
という構造にすることで、
「AIアプリが増えても、連携実装は増えない」 状態を作ります。
そのためMCPは、よく 「AIアプリケーション向けのUSB-Cポート」 と例えられます。
接続方法を標準化することで、エコシステム全体の相互運用性を高めることができます。
通信の登場人物
MCPのアーキテクチャは、以下の3つの役割で構成されます。
| 役割 | 概要 | 具体例 |
|---|---|---|
| MCPホスト | AIアプリケーション本体。1つ以上のクライアントを管理する。 | Claude Desktop, VSCode |
| MCPクライアント | サーバーへの接続を維持し、ホストが利用するコンテキストを取得する。 | ホスト内部の通信コンポーネント |
| MCPサーバー | ツール、リソース、プロンプトなどの機能をクライアントに提供するプログラム。 | 自作のPython/TSスクリプト, 外部公開API |
図にすると以下のようなイメージです。
通信の構造:トランスポート層とデータ層
MCPは、「どう運ぶか(トランスポート層)」と「何を話すか(データ層)」 を明確に分離して定義されています。
1. トランスポート層
環境に応じて主に2種類が使い分けられます。
A. Stdio(標準入出力)- ローカル接続
ローカルPC内でアプリがMCPサーバーを直接起動する方式です。
- 仕組み: クライアントがサーバーをサブプロセスとして起動
- 通信パス: stdin(標準入力)と stdout(標準出力)でJSONをやり取り
-
注意点:
サーバー側でprint()やconsole.log()を使うと通信が壊れます。
デバッグログは必ず stderr(標準エラー出力)に出すのが鉄則です。
B. HTTP with SSE (Server-Sent Events) - リモート接続
インターネット越しや別サーバーにあるMCPサーバーと通信する方式です。
-
仕組み:
クライアント → サーバー:HTTP POST
サーバー → クライアント:SSE -
認証:
リモート接続では OAuth 2.1 等の認証フローを組み込むことが可能です。
2. データ層
すべてのメッセージは JSON-RPC 2.0 形式で構造化されています。
JSON-RPC 自体は汎用プロトコルで、MCP 専用のものではありません。
内容は以下の記事がわかりやすいです。
通信シーケンス:4つのフェーズ
クライアントとサーバーは、以下のサイクルでやり取りを行います。
各フェーズの詳細
1. 初期化 (Initialization)
互いのプロトコルバージョンを確認し、サポートする機能(Capabilities)を合意します。
2. 機能の発見 (Discovery)
「どんなツールが使えるか?」を問い合わせます。
サーバーはツールの名前、説明、引数の型(JSON Schema)を返します。
3. 実行 (Execution)
LLMが「このツールが必要だ」と判断した際に、具体的な引数を渡して実行を依頼します。
4. リアルタイム更新 (Notifications)
サーバー側の状態が変わった際、 サーバーから「リストが更新されたよ」と通知を送ることができます。
MCPのやり取りをレストランでのやり取りに例える
MCPにおける4つのフェーズをレストランでの客と店のやり取りに例えてみます。
1. 入店とルールの合意(初期化 / Initialization)
客(クライアント)と店(サーバー)が、
共通の言葉で会話できるか(プロトコルバージョン) を確認します。
あわせて、
- セルフサービスかフルサービスか
- どんな対応が可能か
といった 「提供可能な機能(Capabilities)」 について、
入店時にお互いの前提条件を合意します。
2. メニューの閲覧(機能の発見 / Discovery)
客が店員に
「今日はどんな料理がありますか?」
と尋ねるフェーズです。
店側は、
- 提供できる 料理(ツール)の一覧
- 各料理の説明
- 注文時に必要な項目(注文票の書き方=引数スキーマ)
が詳しく書かれた メニュー を提示します。
3. 料理の注文と提供(実行 / Execution)
AI(客の執事)が
「今の状況では、この料理が必要だ」
と判断し、具体的な注文内容(引数)を伝えます。
店はその注文に従って調理を行い、
完成した料理(実行結果)を客に提供します。
4. 店員からのお知らせ(リアルタイム更新 / Notifications)
客から尋ねられなくても、
店側から次のような情報を 能動的に伝える フェーズです。
- 「季節限定の新メニューが追加されました」
- 「この料理は現在品切れです」
MCPでは、このような状態変化を
通知(Notification)としてリアルタイムにクライアントへ送信できます。
このようにMCPは、
「入店 → メニュー確認 → 注文 → お知らせ」
という流れで、クライアントとサーバーの対話を構築しています。
MCPにおけるプリミティブ(Primitive)
MCPでは、クライアントとサーバーがお互いに提供し合うことができる
「機能やデータの基本単位(構成要素)」 を定義しています。
これを MCPにおけるプリミティブ(Primitive) と呼びます。
プリミティブには、大きく分けて サーバーが提供するもの と
クライアントが提供するもの の2種類が存在します。
サーバーが提供するプリミティブ
サーバープリミティブは 「サーバーが持っている能力をAI(クライアント)に使わせる」 ための機能です。MCPでは、サーバーが提供するプリミティブとして、以下の3種類が定義されています。
Resources(リソース)
- AIが 「読む」 ための読み取り専用データ
- ファイル内容、DBのログ、設定情報、参照ドキュメントなど
- 主に コンテキストとして利用される情報
Tools(ツール)
- AIが 「実行する」 ための機能
- 外部API呼び出し、検索、計算、データ操作など
- MCPにおいて 現在最も多用されているプリミティブ
Prompts(プロンプト)
- AIの作業を開始するための 再利用可能な指示テンプレート
- 「休暇の計画」や「会議の要約」といった、特定のタスク向けに定義された定型プロンプト
- 対話やワークフローの起点として利用される
クライアントが提供するプリミティブ
MCPの特徴的な点として、「サーバー側からクライアント(AIアプリ)の機能を呼び出せる」 という仕組みがあります。
これらを クライアントプリミティブ と呼び、 サーバー開発者はこれを利用することで、より高度な対話フローを構築できます。
以下のような種類があります。
Sampling(サンプリング)
- サーバーが、クライアント側のLLM(AIモデル)を使って
テキスト生成や推論を行わせる機能。 - サーバー自身がAIを持たなくても、クライアントの高性能なAIを利用できる。
例
「このデータを要約したいが、サーバーにはAIがない。
クライアント側のAIで要約し、結果だけ返してほしい」
Elicitation(エリシテーション / 情報抽出)
- サーバーが、ユーザーに対して 追加情報の入力を求める 機能。
- 対話の途中でユーザー確認や補足入力が必要な場合に利用する。
例
ツール実行中に「この予約を確定しますか?」という確認をユーザーに表示する。
Roots(ルーツ)
- クライアントがサーバーに対して、
アクセスを許可する範囲(境界) を通知する仕組み。 - 「このディレクトリ(フォルダ)なら見てよい」といった
明示的なスコープ指定に使われる。
Logging(ロギング)
- サーバーが、デバッグ情報やエラーログを
クライアント側のコンソールに送信・表示させる機能。 - stdio接続時のデバッグや、ユーザーへの状態通知に役立つ。
まとめ
MCP(Model Context Protocol)についてまとめると以下になります。
-
接続(Transport)
ローカルなら「Stdio(パイプ)」、リモートなら「HTTP + SSE」。
環境を選ばない、AIのための USB-Cポート として機能します。 -
共通言語(Protocol)
データのやり取りはすべて JSON-RPC 2.0 に準拠。
トランスポートの違いを、このデータ層が吸収します。 -
作法(Lifecycle)
通信は次の4つのステップで進行します。-
初期化
互いにサポートする能力(Capabilities)を提示し、通信ルールを確定します。 -
発見
サーバーが提供する「ツール」「リソース」「プロンプト」のリストを確認します。 -
実行
AIが必要に応じて特定のツールを呼び出し、結果を受け取ります。 -
通知
サーバー側の状態変更(メニューの更新など)をリアルタイムで受け取ります。
-
初期化
この標準規格のおかげで、開発者は背後の通信経路を意識することなく、
SDKのメソッド(listTools や callTool)を呼ぶだけで、
あらゆる外部データや機能を備えた 「エージェント的なワークフロー」 を実装できるようになっています。
参考
