MCP(Model Context Protocol)とは何か、その仕組み

Clint Adair / Unsplash
すべてのAIアシスタントは同じ限界に直面します。トレーニングのカットオフ日までの世界については詳しいものの、あなたのファイル、データベース、社内APIについては何も知りません。Model Context Protocol(MCP)は、まさにそのギャップを埋めるために生まれました。Anthropicが2024年末にオープンスタンダードとしてリリースして以来、MCPは事実上、言語モデルを外部ツールやデータに接続するためのUSB-Cのような存在になっています。
MCPとは
Model Context Protocolは、JSON-RPC 2.0ベースのオープンプロトコルであり、言語モデル(またはそれをホストするアプリケーション)が外部のデータソースやツールに接続するための標準化された方法を定義します。各AIアシスタントがファイルの読み取り、データベースのクエリ、自動化のトリガーなどを独自に実装する代わりに、MCPは共通のインターフェースを提供し、どのサーバーでも実装でき、どのクライアントでも利用できます。
実際には、例えばGitHubやGoogle Driveへのコネクタを構築する開発者は、その作業をMCPサーバーの形で一度だけ行います。すると、Claude Desktop、Claude Code、IDE、カスタムエージェントなどの互換アプリケーションは、特別なコードを書くことなくその統合を利用できるようになります。プロトコルは通信を3つのブロックに整理します。tools(モデルが実行できるアクション)、resources(モデルが読み取れるデータ)、prompts(再利用可能な指示テンプレート)であり、これらはすべてモデルが実行時に解釈できる形式で記述されます。
MCPが解決する問題
MCP以前は、LLMを外部システムに接続するには、カスタム統合を書くのが一般的でした。プラグイン、カスタマイズされたfunction calling、特定のAPIラッパーで囲まれたエージェントなどです。各AIアプリケーションには独自のツール公開方法があり、各ツールは各アプリケーションに適応させる必要がありました。企業が5つの内部ツールを維持し、それらを3つの異なるアシスタントで動作させたい場合、結果として15の個別の統合を維持する必要があり、それぞれに独自の認証スキームとリクエスト形式がありました。
これは古典的な「M×N」問題です。M個のツールとN個のアプリケーションを掛け合わせると、M×N個の統合ブリッジが必要になります。MCPはこの方程式をM+Nに平坦化します。各ツールは一度構築されたMCPサーバーになり、各アプリケーションは一度構築された互換性のあるMCPクライアントになり、両者の任意の組み合わせが追加作業なしで機能するようになります。これは基本的に、以前にコードエディターが個別に各プログラミング言語のネイティブサポートを実装する必要をなくすために作られたLanguage Server Protocolと同じ考え方です。
プロトコルのアーキテクチャ
MCPは、明確に定義された3つの役割を持つクライアント-サーバーアーキテクチャに従います。
- Host: エンドユーザーが直接使用するアプリケーション。例:Claude Desktop、AIを内蔵したIDE、カスタムエージェント。
- MCPクライアント: ホスト内のコンポーネントで、特定のMCPサーバーとの個別かつ分離された接続を維持します。
- MCPサーバー: ローカルまたはリモートの独立したプロセスで、外部システムに対するtools、resources、promptsを公開します。
1つのホストは同時に複数のMCPクライアントを維持でき、それぞれが異なるサーバーに接続します。ファイルシステム用、Slack用、Postgresデータベース用などです。この1クライアント・1サーバーのルールは意図的であり、分離を保証します。1つのサーバーで障害やクラッシュが発生しても、他の接続には影響しません。
以下の図はこの設計をまとめたものです。
クライアントとサーバー間の通信は、主に2つのトランスポートで行われます。ローカルサーバーの場合、標準はstdio、つまりプロセスの標準入出力で、ネットワークを必要としないためシンプルで高速です。リモートサーバーの場合、トランスポートはHTTPとStreamable HTTP(Server-Sent Eventsベースの旧トランスポートの進化版)で、MCPサーバーをクラウドでホストし、複数のクライアントに同時にサービスを提供できます。
MCPクライアント
クライアントはホスト内に存在し、3つのことを担当します。サーバーとの接続を開いて維持すること、モデルの決定をJSON-RPCメッセージに変換すること、サーバーからの応答を会話のコンテキストに戻すことです。実際には、クライアントは最初のハンドシェイク、つまりクライアントとサーバーがプロトコルバージョンとサポートする機能に関する情報を交換するinitializeステップと、サーバーが提供するtools、resources、promptsを問い合わせるディスカバリープロセスも実行します。
あまり知られていない詳細ですが、クライアントは単独でツールを使用するタイミングを決定しません。その決定はモデルが行います。クライアントは利用可能なツールのリストを会話のコンテキストの一部としてLLMに提供し、ユーザーのリクエストに基づいてツールを呼び出すかどうか、またどのツールを呼び出すかをモデル自身が選択します。クライアントはモデルが決定した後にのみ技術的な呼び出しを実行します。
MCPサーバー
一方、サーバーは、データベース、サードパーティAPI、ローカルファイルシステムなど、外部システムと実際にやり取りする方法を知っています。適切に構築されたMCPサーバーは、その機能を自己記述的に公開します。各toolには、名前、自然言語による説明、および通常はJSON Schemaで、受け入れるパラメータを定義するスキーマが含まれています。
この自己記述性こそが、MCPをプラグ可能にしている理由です。サーバーはどのモデルがそれを使用するかを知る必要はなく、クライアントはプロトコルを話す以外にそのサーバーに固有のコードを必要としません。現在、GitHub、Stripe、Cloudflare、Sentryなどの企業によって公開された数百のMCPサーバーが存在し、データベース、生産性ツール、内部サービス向けのコミュニティサーバーの大規模なエコシステムもあります。
MCPのツール
ToolsはMCPで最もよく使われる機能です。モデルが実行できるアクションで、通常は副作用があるか、計算結果を返します。例としては、天気予報の取得、Trelloでのカード作成、SQLクエリの実行などがあります。プロトコルはさらに2つの機能を定義しています。
- Resources: サーバーが読み取り用に公開するデータ。ファイルの内容、データベースの行、クエリ結果など。ツールとは異なり、リソースには通常副作用がなく、ホストが会話に添付できる単なるコンテキストです。
- Prompts: サーバーが提供する再利用可能な指示テンプレート。プルリクエストのレビューやサポートチケットの要約などの定型シナリオで、ユーザーが直接呼び出すことができます。
各toolは、name、description、inputSchemaを含むオブジェクトで記述されます。この自然言語でありながら構造化された記述により、モデルは明示的な使用ルールをプログラムすることなく、ツールの機能を理解できます。
MCP呼び出しの完全なフロー
実際にこれらがどのように連携するかを理解するために、実際の呼び出しのライフサイクルを、JSON-RPC 2.0を介してクライアントとサーバー間をどのように流れるかを見てみましょう。
まず、接続時に、クライアントはサーバーがどのツールを提供しているかを尋ねます。
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list"
}
サーバーは、各ツールのスキーマを含む完全なリストで応答します。
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [
{
"name": "get_weather",
"description": "都市の現在の天気予報を返します",
"inputSchema": {
"type": "object",
"properties": {
"city": { "type": "string" }
},
"required": ["city"]
}
}
]
}
}
このカタログは、利用可能なコンテキストの一部としてモデルに提供されます。ユーザーがリクエストを行い、モデルがそれをget_weatherツールを必要とするものと解釈すると、クライアントはtools/call呼び出しを構築して送信します。
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": { "city": "São Paulo" }
}
}
サーバーはツールの背後にある実際のロジックを実行します。この場合は実際の天気APIへの呼び出しを行い、結果を同じJSON-RPC形式で返します。
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [
{ "type": "text", "text": "23°C、サンパウロは晴天" }
]
}
}
クライアントはこの結果を会話に注入し、モデルはその情報を使用して最終的な応答をユーザーに作成します。アシスタントと会話しているユーザーから見ると、これらすべては透過的に行われ、質問と回答だけが見え、舞台裏でプロトコルの交渉が行われていることはわかりません。
MCP vs 従来のAPI
よくある疑問として、すべての外部ツールにはすでにREST APIがあるのに、なぜそのAPIを直接使わないのか?というものがあります。その答えは、人間の開発者がドキュメントを読んでシステムを統合することと、モデルがリアルタイムでシステムを発見して自律的に使用することの違いにあります。
| 側面 | 従来のREST API | MCP |
|---|---|---|
| 機能の発見 | 人間が読む外部ドキュメント(Swagger/OpenAPI) | クライアントがサーバーにリアルタイムでツールのリストを問い合わせる(tools/list) |
| システムごとの統合 | 各APIに専用のコネクタ | 任意のMCPサーバーに対する単一の標準プロトコル |
| 通信形式 | HTTP + JSON、プロバイダごとにスキーマが異なる | 標準化されたJSON-RPC 2.0 |
| モデルへのコンテキスト | 開発者が手動でLLMに公開する内容を決定 | サーバーがツールを記述し、モデル自身が使用するものを決定 |
| トランスポート | ほぼ常にHTTP | stdio(ローカル)またはHTTP + Streamable HTTP(リモート) |
| AIアプリ間の再利用性 | 低い、各アプリが統合を再実装 | 高い、互換性のあるホストは同じサーバーを使用 |
実際には、MCPはサーバーの背後にあるREST APIを置き換えるのではなく、その上に標準化レイヤーを提供します。例えば、GitHub用のMCPサーバーは、内部的にGitHubのREST APIを呼び出すでしょう。違いは、モデルはそのことを知る必要がなく、背後にあるAPIに関係なく、一貫した名前とスキーマを持つツールだけを見ることです。
実践例:シンプルなMCPサーバー
プロトコルを具体的に理解するために、公式SDKのFastMCPクラスを使用した最小限のPython MCPサーバーを数行で示します。
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("clima-server")
@mcp.tool()
def get_weather(city: str) -> str:
"""都市の現在の天気予報を返します。"""
# 実際の天気API呼び出しはここに入ります
return f"23°C、{city}は晴天"
if name == "main":
mcp.run(transport="stdio")
このサーバーは、get_weatherという1つのツールを公開します。@mcp.tool()デコレータは、関数のシグネチャとdocstringからJSONスキーマを自動生成するため、JSONスキーマを手書きする必要はありません。このスクリプトを実行すると、stdio経由で待機し、ローカルに設定されたClaude DesktopなどのMCPクライアントが接続してツールを自動的に発見できるようになります。
この例は意図的にシンプルですが、同じパターンはより複雑なサーバーにも当てはまります。ビジネスロジック(データベースのクエリ、有料APIの呼び出し、自動化のトリガーなど)は関数本体に入り、SDKがプロトコル、ハンドシェイク、シリアル化の部分をすべて処理します。
MCPのセキュリティ
言語モデルに、ファイルの読み取り、データベースへの書き込み、サードパーティAPIの呼び出しを行うツールへの直接アクセスを許可すると、明らかな疑問が生じます。制御不能にならない保証はどこにあるのでしょうか?プロトコルはいくつかの保護手段を定義していますが、最終的な責任はサーバー、クライアント、システムを構成する人の間で分担されます。
サーバーレベルでは、最小権限の原則を適用するのがベストプラクティスです。例えば、ファイルシステム用のMCPサーバーは、ディスク全体ではなく特定のディレクトリへのアクセスを制限する必要があります。HTTPトランスポートを使用するリモートサーバーは、通常OAuth 2.1を介した認証を必要とし、プロトコル仕様はこれを詳細に扱っています。これは、設定を誤ったサーバーが最も明白な攻撃ベクトルであるためです。
クライアントとホストのレベルでは、エンドユーザーにとって最も目に見えるセキュリティレイヤーは人間の同意です。Claude Desktopなどのホストは、特にツールが初めて使用される場合、ファイルの書き込みやメッセージの送信などの機密性の高いツールを実行する前に確認を求めます。また、resourcesを介したprompt injectionのリスクもあります。モデルが読み取るドキュメントに悪意のあるコンテンツが埋め込まれ、モデルを操作して不適切なアクションを実行させようとするものです。信頼できないソース(Webページや受信メールなど)からのコンテンツを公開するサーバーは、サーバーを構築する人と、それを広範な権限を持つエージェントに接続することを決定する人の両方にとって、特別な注意が必要です。
MCPの制限
MCPは標準化の問題を解決しますが、すべてに対する魔法の解決策ではありません。その上に構築することを決定する前に、実際の限界を知っておく価値があります。
第一に、プロトコルはまだ比較的新しく、2024年末にリリースされたばかりであり、エコシステムは急速に成長しているものの、まだギャップがあります。すべての一般的なツールに成熟した公式にメンテナンスされたMCPサーバーがあるわけではありません。第二に、同時に利用可能なツールが増えると、それらのツールを会話のコンテキストで記述するためにより多くのトークンを消費し、コストが増加し、極端な場合には会話の残りの部分とコンテキストスペースを競合する可能性があります。第三に、プロトコルはモデルの信頼性の問題を単独で解決しません。モデルは依然として間違ったツールを選択したり、誤った引数を構築したり、サーバーから返された結果を誤って解釈したりする可能性があるため、慎重なオーケストレーションはエージェントを構築する人の仕事であり続けます。
最後に、エンタープライズ環境での認証とアクセスガバナンス、つまり誰がどのサーバーをどの権限で接続できるか、どのように監査するかは、まだ成熟途上の分野であり、コミュニティやプロトコルを本番環境で採用している企業で多くの作業が行われています。
FAQ
MCPはAnthropicとClaude専用ですか?
いいえ。MCPはオープンプロトコルであり、公開仕様があります。Anthropic内で生まれましたが、他のAI企業やエージェントフレームワークもサポートを発表しています。
MCPサーバーを使用するにはプログラミングの知識が必要ですか?
Claude Desktopなどのアプリ内で、ファイルアクセスやGoogle Drive用などの既製のサーバーを使用する場合は不要です。プログラミングが必要なのは、ゼロから新しいサーバーを構築したい場合のみです。
MCPはfunction callingを置き換えますか?
正確には異なります。Function callingは、モデルがツール呼び出しを選択してフォーマットする機能です。MCPはその機能を内部的に使用しますが、function calling単独では定義されていない、クライアントとサーバー間のディスカバリー、標準化、トランスポートのレイヤーを追加します。
MCPサーバーはクラウドで実行できますか?
はい。リモートサーバーはHTTPトランスポートを使用し、通常どおりホストでき、OAuthを介した認証で複数のクライアントに同時にサービスを提供できます。
MCPの真の利点は、技術的、つまり「もう一つのAPI」という意味ではなく、組織的なものです。それは、各ツールと各アプリケーションの組み合わせごとに統合が必要という乗算的に成長していた問題を、加算的に成長する問題に変えます。今日AIエージェントを構築している人にとって、このプロトコルを理解することはもはやオプションではありません。これは、モデルの外側にあるすべてのものにモデルを接続するための、デファクトスタンダードに最も近いインフラストラクチャの部品です。
このコンテンツは私たちのチーム(iatoskill.com)によって作成およびレビューされました。問題がある場合は、こちらからお問い合わせください


