2026年6月1日月曜日

MCP Appsの基本構造:Resources・Prompts・Toolsの役割分担からマルチエージェント、Smitheryへの展望

LLM外部連携における「密結合」の限界とMCPの登場

現在のLLMアプリケーション開発において、外部データや既存システムとの連携は避けて通れません。しかし、これまでの開発手法では、特定のLLMやAPIに依存した「個別最適化された密結合なシステム」になりがちでした。クライアントごとに独自の統合コードを書く必要があり、システムの柔軟性や拡張性が著しく制限されていたのです。

この課題を解決するために登場したのが、Anthropic社が提唱した「Model Context Protocol(MCP)」です。MCPは、LLMと外部システム(コンテキスト)を接続するためのオープンな標準規格です。AIモデルとデータソースの間に標準化されたインターフェースを設けることで、一度構築した連携機能を多様なクライアントから再利用可能にします。ビジネスの視点から言えば、これはAI統合にかかる開発コストを劇的に削減し、システム全体のポータビリティを向上させるインフラの誕生を意味します。

3つの基本機能:Resources・Prompts・Toolsの設計思想

MCPの仕様は極めてシンプルでありながら、強力です。その根幹を支えるのが「Resources」「Prompts」「Tools」という3つの基本抽象概念です。これらは、LLMにコンテキストを提供する際の「関心の分離」を厳密に定義したものです。なぜこれらが分かれているのか、その設計上の意図とトレードオフを理解することが重要です。

Resources:安全性が担保された読み取り専用データ

「Resources」は、LLMがコンテキストとして自由に読み取ることができるデータ源です。データベースのレコード、ローカルファイル、APIの実行結果などがこれに該当します。

設計上の重要なポイントは、Resourcesが「読み取り専用(Read-only)」であり、「冪等性(何度実行しても結果が同じであること)」が期待されている点です。LLMに対してデータを提供する際、意図しないシステムの改ざんを防ぎつつ、必要なコンテキストを安全に供給するための防御壁として機能します。

Prompts:定型的なコンテキスト生成と制御の分離

「Prompts」は、LLMに対する指示のテンプレートをサーバー側で管理・提供する機能です。これにより、開発者はシステム特有のプロンプトエンジニアリングのノウハウを、クライアント側ではなくサーバー側に「カプセル化」できます。

クライアントは必要に応じてサーバーから最適なプロンプトテンプレートを取得し、動的なパラメータを流し込むだけで済みます。プロンプトの更新がシステム全体の再デプロイを伴わずに実行できるため、プロンプトのライフサイクル管理が非常に容易になります。

Tools:副作用を伴うアクションの実行

「Tools」は、外部システムの状態を変更する、あるいは動的な計算処理を実行するための「関数(Function)」をLLMに提供します。ファイルの書き込み、API経由でのデータ更新、特定コマンドの実行などがこれにあたります。

ToolsはResourcesとは異なり、システムに「副作用(Side effects)」をもたらします。そのため、セキュリティ設計上、実行前にユーザーの承認を挟む「Human-in-the-loop」の仕組みが推奨されます。この強力な権限移譲こそが、LLMを単なる「回答者」から「実行エージェント」へと進化させる鍵となります。

実装コードから学ぶMCPの構造

実際にMCPサーバーを構築する際の、Pythonを用いたシンプルな実装例を以下に示します。ここでは、公式が提供する「FastMCP」フレームワークを使用します。ResourcesとToolsがどのように区別され、定義されているかに注目してください。

from mcp.server.fastmcp import FastMCP

# MCPサーバーの初期化
app = FastMCP("System-Integration-Server")

# 1. Resourcesの定義(読み取り専用コンテキスト)
@app.resource("system://status")
def get_system_status() -> str:
    """システムのステータス情報を取得します(読み取り専用)"""
    # 実際にはDB参照やAPIコールなどを行う
    return "System Status: Normal. Database connection is active."

# 2. Toolsの定義(副作用を伴う書き込み処理)
@app.tool()
def update_user_role(user_id: str, role: str) -> str:
    """ユーザーのロールを更新します(副作用あり)"""
    # データベースの更新処理を想定
    print(f"Executing database update for user {user_id} with role {role}")
    return f"Successfully updated user {user_id} to role {role}."

このコードが示すように、デコレータを使い分けることで、システムに危害を加えない安全なデータ取得(@app.resource)と、慎重な取り扱いが必要な書き込み処理(@app.tool)が、コードレベルで明確に分離されています。LLMクライアントはこのスキーマを自動的に解釈し、適切に呼び出すことが可能になります。

マルチエージェントとパッケージ管理「Smithery」が拓く未来

MCPの登場により、AIエコシステムは「単一のエージェントによる対話」から「自律的なマルチエージェント連携」へと急速にシフトしています。複数の特化型MCPサーバーをオーケストレーターが束ねることで、複雑な業務プロセスを自動化するエコシステムが形成されつつあります。

このエコシステムの普及において重要なマイルストーンとなるのが、MCPサーバーのパッケージ管理ツール「Smithery」です。Smitheryは、Dockerコンテナ技術や各種設定を抽象化し、多様なMCPサーバーの発見、インストール、そしてデプロイを標準化します。開発者は手元で作成したMCPサーバーを迅速に共有し、他のシステムにシームレスに組み込めるようになります。これは、オープンソースのソフトウェアライブラリが現代の開発を爆発的に加速させたのと同様のダイナミズムを、AIコンテキストの領域にもたらします。

さらに、Next.jsなどを用いた独自エージェントUIの多様化も進んでいます。企業は自社専用のインターフェースを用意し、背後で稼働する複数のMCPエージェントと連携させることで、真に実用的な「AI駆動型アプリケーション」を内製化することが可能になります。

テクノロジーをシステムとして統合する

AIを単なる個人の生産性向上ツールとしてではなく、企業全体の「自律的なエコシステム」として捉え直す時期が来ています。MCPは、その基盤となる接続標準を提供するものです。Resources、Prompts、Toolsの役割分担を正しく理解し、適切に設計されたMCPサーバーを配置することは、変化の激しいAI技術に追従し続けるための最も賢明な投資となるでしょう。