【AIエージェントの解剖学:第3回】プラグ&プレイの道具箱:Model Context Protocol (MCP)の革新
【新連載:AIエージェントの解剖学】
※本連載は、何も話せない空っぽの「チャットボット」の前に立ち、彼に命を吹き込みながら、自分の意志で動く「AIエージェント」へとパーツごとに作り上げていく開発ドキュメンタリーです。
1. プロローグ:次のパーツ「すべての道具をカチッと繋ぐ共通ポート」
前回、私たちはロボットのアームへ、言葉の意志をJSONデータとして送信し、関数を実行する「Function Calling」の神経を接続しました。
これにより、彼は「天気予報を調べる」「距離を計算する」といった特定のツールを、自分の意志で動かせるようになりました。
しかし、この方法には面倒な課題が残っています。
現実世界には、ファイルシステム、PostgreSQL、GitHub API、Slackなど、繋ぎたい道具(データやツール)が無数に存在します。新しい道具を追加するたびに、私たちが手作業で仕様書(JSON Schema)を書き起こし、それぞれ異なる通信コードをゴリゴリと書き足すのは、スマートではありません。
今回は、このツールの接続を劇的に標準化し、どんなデータや機能もUSBメモリのようにカチッと一発でプラグ&プレイできる共通規格、「Model Context Protocol (MCP)」のマルチポートをロボットの肩に装着します。
乱雑な配線をすっきりとまとめ、彼の可能性を世界中のすべてのツールへと繋げましょう。
2. 「N対M」の接続カオスと、共通USBハブの登場
従来のAIエージェント開発では、使用したいAIモデル(GPT, Claude, Geminiなど)が「N個」あり、連携したいデータベースやAPIが「M個」あった場合、それぞれを繋ぐために「N × M」の数だけ個別の接続コードやスキーマ定義を書く必要がありました。これがいわゆる「接続のスパゲッティコード化」です。
このカオスに終止符を打つべく、2024年末にAnthropicが発表したオープンソースの標準規格が、「Model Context Protocol (MCP)」です。
これはパソコンにおける「USBポート」と同じ役割を果たします。マウス、キーボード、プリンタなどのメーカーが異なっても、USBという共通ポートがあれば、挿すだけで即座に使えます。MCPは、AI(Client)とデータ/ツール(Server)の間を、中立かつシンプルなJSON-RPCベースの標準仕様でカチッとブリッジします。
3. MCPの3大アクター
MCPアーキテクチャは、以下の3つの役割分担で構成されています。

※図:ホスト、クライアント、および複数の外部MCPサーバーがJSON-RPCを介して標準ブリッジするMCPのアーキテクチャ(AI生成ダイアグラム)
- MCP Host (ホスト): LLMを動かし、ユーザーとの対話を制御する中心的なアプリケーション(Claude Desktopや、今回構築しているエージェントシステムなど)。
- MCP Client (クライアント): ホストの内部に組み込まれ、規格に則ってサーバー群との接続や要求の受け渡しを行うモジュール。
- MCP Server (サーバー): ツールやデータそのもの。ホストから「どんな機能が使える?」「このパラメータでこのツールを実行して」という標準規格のJSON-RPCリクエストをローカルストリーム(stdioなど)経由で受け取り、結果を返す軽量な子プロセス。
これにより、新しいツールを追加したいときは、「MCPサーバー」の仕様に則って1つサーバープログラムを作るだけで、すべてのAIモデル(ホスト)から即座に自動認識され、利用可能になるのです。
4. 【体験】30行の簡易MCPシミュレータを動かそう
MCPサーバーから「ツール一覧」を取得し、その仕様を元にクライアントが動的実行を指示する「標準プロトコル(JSON-RPC風)」のやり取りを再現したPythonコードです。
手元の環境で実行してみてください。
import json
# 1. MCP Serverのシミュレート(独自のツールを標準規格で提供する)
class MockMCPServer:
def get_manifest(self):
# サーバーが持つツールのリスト(スキーマ定義)を返す
return {
"tools": [
{
"name": "read_file",
"description": "ローカルファイルを読み取るツール",
"parameters": {"path": "str"}
}
]
}
def execute_tool(self, tool_name: str, arguments: dict) -> str:
# JSON-RPC経由でツールの実行命令を受け取る
if tool_name == "read_file":
path = arguments.get("path")
return f"【ファイル内容】: {path} の読み取りに成功しました。"
return "ERROR: Tool not found"
# 2. MCP Client(エージェントシステム)の動作
server = MockMCPServer()
# ステップA: サーバーからどんなツールが使えるかを標準規格で取得する
manifest = server.get_manifest()
print("🔌 Client: MCP Serverから利用可能なツールの一覧を取得しました:")
print(json.dumps(manifest, indent=2, ensure_ascii=False))
# ステップB: 取得したツール一覧をLLMに渡し、LLMが「read_fileを使う」と判断したと仮定
request_tool_name = "read_file"
request_args = {"path": "/workspace/data.txt"}
print(f"\n⚡ Client: ツール '{request_tool_name}' の実行リクエストを送信します...")
# ステップC: サーバーへ標準JSON-RPC形式で実行を要求
result = server.execute_tool(request_tool_name, request_args)
print(f"🔍 Observation (実行結果): {result}")
このコードを実行すると、クライアントが事前に個別の関数を知らなくても、MCPサーバーが提示したマニフェスト(仕様書)を動的に読み取り、標準のインターフェースを介して安全に実行する流れが再現されます。
5. エピローグ:世界中のツールが繋がる

※画像:ロボットのユニバーサルポート『MCP』に、外部APIやDBの接続ケーブルを一斉にプラグインするイメージ(AI生成画像)
これで、私たちのロボットの肩に「MCP」のユニバーサルソケットが装着されました。
彼は、世界中の開発者が公開している多種多様なMCPサーバーと、ケーブルを挿す感覚で即座に同期し、無限のデータへアクセスする手段を手に入れました。
しかし、いくら接続できるデータやツールが増えても、ロボットが一度に記憶・処理できる脳の作業スペース(コンテキストウィンドウ)には限界があります。
大量のデータを詰め込みすぎると、AIは混乱し、重要な指示を見失ってしまう「情報の埋もれ」を起こします。
次回、第4回。
限られた脳の作業スペースを賢く管理し、長大なコンテキストから目的のデータを一瞬で見つけ出す、「Prompt & Context Engineeringの限界突破」の集中力制御モジュールを彼に装着します。
彼の知能が、情報の洪水に溺れることなく、必要な情報へ鋭く焦点を合わせる瞬間へと進みましょう。