RustでModel Context Protocolを理解する - 仕様解析の実践と学び
Model Context Protocol (MCP)の仕様をRustで解析・実装することで得られた知見を共有します。Rustの型システムを活用したスキーマ定義を通じて、MCPの設計思想と実装の詳細に迫ります。
はじめに
Model Context Protocol(MCP)は、AI技術の発展における重要な課題の一つを解決するために、Anthropicが2024年に公開した新しいプロトコルです。このプロトコルは、LLMアプリケーションと外部データソース・ツールを統合するための標準化された方法を提供します。MCPは「MxN問題」(M個のLLMとN個のツールの組み合わせによる統合の複雑さ)に対する解決策として期待されています。
MCPはクライアント-サーバーアーキテクチャを採用しています。AIアプリケーション(例:Claude Desktop)がMCPクライアントとして動作し、データソースやツールを提供するMCPサーバーに接続します。このプロトコルは以下の主要な機能(プリミティブ)を定義しています:
- Prompts: 命令やテンプレートの提供
- Resources: 構造化データの共有
- Tools: 実行可能な関数の提供
- Roots: クライアント側ファイルシステムへのアクセス
- Sampling: クライアント側LLMの利用
このプロトコルの理解を深めるため、mcp-schemaというRustプロジェクトを作成し、プロトコルの型定義に取り組みました。
Rustによる実装
アーキテクチャ概要
mcp-schemaによる実装を説明する前に、MCPの基本的なアーキテクチャを見ていきましょう。以下の図は、MCPのクライアント-サーバーモデルと、主要なコンポーネントの関係を示しています。
このアーキテクチャでは、以下の順序で処理が行われます:
① LLMアプリケーションからリクエストが開始され、 ② Request Controllerを通じてJSON-RPCリクエストとして送信されます。 ③ サーバー側のHandlerがリクエストを処理し、 ④ 必要に応じてCore Primitivesが外部データソースにクエリを実行します。 ⑤ 取得したデータは、 ⑥ ⑦ Primitivesで処理され、JSON-RPCレスポンスとして返され、 ⑧ 最終的にLLMアプリケーションに結果が届きます。
コアプリミティブ
MCPの中核となるのが3つのコアプリミティブです。これらは異なる制御レベルと用途を持ち、LLMアプリケーションに豊かなコンテキストと機能を提供します:
1. Prompts(ユーザー制御)
プロンプトは、LLMとのインタラクションを導くための定義済みのテンプレートや指示を提供します。これらは主にユーザーの選択によって制御され、たとえばスラッシュコマンドやメニューオプションとして提供されます。プロンプトを通じて、サーバーは構造化されたメッセージやインストラクションをクライアントに提供できます。
2. Resources(アプリケーション制御)
リソースは、LLMに追加のコンテキストを提供する構造化データやコンテンツを表します。これらはアプリケーションによって制御され、管理されます。たとえば、ファイルの内容、Gitの履歴、データベースの内容などがリソースとして提供されます。リソースは読み取り専用で、データの整合性を保ちながらLLMに必要な情報を提供します。
3. Tools(モデル制御)
ツールは、LLMが外部システムと対話するための実行可能な関数を提供します。これらはモデルによって制御され、APIリクエストの送信やファイルの書き込み、計算の実行などのアクションを実行できます。ツールは動的な操作を表し、外部システムとの相互作用や状態の変更を可能にします。セキュリティとエラーハンドリングが特に重要な要素となります。
現在、公式のリファレンス実装やコミュニティによる実装の多くがToolsプリミティブを中心に構築されています。これは以下の理由によると考えられます:
- 即時の実用性: ファイルシステム、データベース、APIなど、既存のシステムとの統合が容易に実現できる
- 柔軟な制御: LLMがツールを通じて直接アクションを実行できるため、より動的な対話が可能
- 明確なユースケース: GitHub、Slack、PostgreSQLなど、多くの開発者ツールやサービスとの統合事例が豊富
この傾向は、MCPがAIアプリケーションのエコシステムを拡張するための実践的なアプローチとして機能していることを示しています。
基本的な型定義
これらのプリミティブと通信プロトコルを実装するため、mcp-schemaでは、まずMCPの基本的な定数とIDタイプを定義することから始めました。プロトコルの仕様に従い、バージョン管理と識別子の型安全な処理が、信頼性の高い通信の基盤となります。
1/// JSON-RPCのバージョン文字列
2pub const JSONRPC_VERSION: &str = "2.0";
3
4/// MCPの最新バージョン
5pub const LATEST_PROTOCOL_VERSION: &str = "2024-11-05";
6
7/// リクエストIDを表現する列挙型
8#[derive(Debug, Clone, Serialize, Deserialize)]
9#[serde(untagged)]
10pub enum RequestId {
11 String(String),
12 Number(i64),
13}
14
メッセージ構造
MCPの通信は、JSON-RPCをベースにしています。各メッセージは、リクエスト、レスポンス、または通知のいずれかの形式を取ります。これらの基本構造をジェネリクスを使って表現することで、型安全性と拡張性を両立しています。
1/// ジェネリックなJSON-RPCリクエスト
2#[derive(Debug, Clone, Serialize, Deserialize)]
3#[serde(rename_all = "camelCase")]
4pub struct JSONRPCRequest<T> {
5 #[serde(rename = "jsonrpc")]
6 pub json_rpc: String,
7 pub method: String,
8 pub id: RequestId,
9 pub params: T,
10}
11
12/// ジェネリックなJSON-RPC通知
13#[derive(Debug, Clone, Serialize, Deserialize)]
14#[serde(rename_all = "camelCase")]
15pub struct JSONRPCNotification<T> {
16 #[serde(rename = "jsonrpc")]
17 pub json_rpc: String,
18 pub method: String,
19 pub params: T,
20}
21
実装から得られた学び
プロトコルの設計面での発見
mcp-schemaプロジェクトを通じて、MCPの設計思想とその実装に関する重要な知見を得ることができました:
-
プロトコルの設計原則:MCPの仕様は、拡張性、後方互換性、型安全性を重視して設計されています。Rustの型システムを通じてこれらの原則を実装することで、その意図と重要性がより明確になりました。
-
プリミティブの分離:Prompts、Resources、Toolsという異なるプリミティブは、それぞれ異なる意図と用途を持っています。この分離は、単なる実装上の都合ではなく、AIシステムと外部リソースの関係を整理するための重要な設計判断であることがわかりました。
-
メタデータの重要性:すべてのメッセージに
_meta
フィールドが用意されているのは、将来の拡張を見据えた設計です。この方針により、プロトコルを破壊的な変更なく進化させることができます。
技術的な実装の知見
実装面では、Rustならではの技術的な知見も得られました:
-
型安全性の重要性:Rustの型システムとserdeの組み合わせにより、プロトコルの制約を型レベルで表現できます。これは単なる実装の利便性だけでなく、プロトコルの理解と正しい使用を助ける「実行可能なドキュメント」として機能します。
-
deriveマクロの活用:殆どすべての型で
Debug
,Clone
,Serialize
,Deserialize
のderiveを使用しており、これによりボイラープレートコードを大幅に削減できました。また、型定義の意図をより明確に表現することができます。 -
エラーハンドリング:プロトコルレベルのエラーとアプリケーションレベルのエラーを明確に区別し、それぞれに適切な処理を定義することの重要性を学びました。この区別は、プロトコルの信頼性と堅牢性に大きく貢献します。
Forbesの分析によると、MCPはAIエージェントやアジェンティックワークフローの発展における重要な要素として位置づけられています。今後の展望として以下の点が期待されます:
-
エンタープライズ統合の可能性:既存のシステムやエンタープライズアプリケーションとの統合において、MCPはSOA(Service-Oriented Architecture)の進化形として機能する可能性があります。特に、PromptsやResourcesプリミティブを活用することで、より豊かなコンテキスト共有が実現できます。
-
双方向コミュニケーション:MCPのアーキテクチャは、AIモデルとデータソース間の双方向の通信を可能にします。これは単なるツールの呼び出しを超えて、より複雑な対話やコンテキスト管理を実現する基盤となります。
-
標準化の進展:主要なAI企業やコミュニティの参加により、MCPはAI統合の標準プロトコルとして発展する可能性を秘めています。これにより、PromptsやResourcesを含めたより包括的な機能の活用が促進されるでしょう。
今後の展望と可能性
mcp-schemaプロジェクトは、MCPの理解を深めるための効果的なアプローチであることが証明されました。型定義を通じてプロトコルを理解することで、単なる技術仕様を超えて、AIシステムと外部リソースの統合に関する深い洞察を得ることができました。
また、このプロジェクトは、Rustの型システムがプロトコル設計の理解と実装に強力なツールとなることを示しています。MCPのエコシステムが今後さらに発展していく中で、この知見が他の実装やツールの開発にも活かされることを期待しています。