モデルコンテキストプロトコル (MCP)
ドキュメントマップ: 概要とアーキテクチャ · クライアント · 動的マネージャー · サーバーオーサリング · セキュリティ · テスト
MCPは、AIアプリケーションが別のプロセスまたはサービスが所有する機能を検出して使用するための標準的な方法を提供します。サーバーは以下を公開できます。
- ツール: アクションを実行します。
- リソース: 読み取り可能なコンテキストを返します。
- プロンプト: 再利用可能なメッセージテンプレートを提供します。
- 補完: クライアントがプロンプトまたはリソースの引数を入力するのに役立つ提案。
ADK-Rustは通常、MCP クライアントです。McpToolsetは、検出されたMCPツールを通常のADK-Rust Tool値に変換するため、LlmAgentがそれらを選択して呼び出すことができます。フレームワークは、リソース、プロンプト、補完、サブスクリプション、引き出し、およびネゴシエートされたタスクライフサイクルも公開します。MCPサーバーオーサリングおよび高度なプロトコル作業の場合、ADK-Rustは使用する正確なrmcp SDKバージョンを再エクスポートします。
ADK-Rust 2は現在、MCP 2025-11-25仕様に準拠した公式のRust SDKであるrmcp 2.2を使用しています。
アーキテクチャ
2つの異なるレイヤーがあります。
McpToolsetは、初期化されたMCPクライアント接続を1つ所有しています。サーバーの機能を検出し、それらをADK-Rustに適合させます。McpServerManagerは、ローカルstdioサーバーの変更可能なレジストリを所有しています。これらの接続を開始、監視、再起動、更新、有効化、無効化、永続化、および集約します。
マネージャーはツールの承認を付与しません。互換性のある構成を読み取る際にautoApproveを保持しますが、アプリケーションは通常のADK-Rust承認および承認ポリシーを適用する必要があります。
インストール
ローカルstdio MCPサポートはオプトインです。
[dependencies]
adk-tool = { version = "2.0.0", features = ["mcp"] }
リモートサービスに接続する際にStreamable HTTPを追加します。
adk-tool = { version = "2.0.0", features = ["mcp", "http-transport"] }
レガシーサンプリングコールバックには、個別のmcp-sampling機能が必要です。MCPプロジェクトは、SEP-2577を通じてサンプリング、ルート、およびロギングを非推奨にしました。互換性のあるデプロイメントを維持する場合にのみ、それらのAPIsを使用してください。
1つのローカルサーバーに接続する
use adk_tool::{
McpToolset,
mcp::rmcp::{ServiceExt, transport::TokioChildProcess},
};
use std::sync::Arc;
use tokio::process::Command;
let command = Command::new("./target/release/company-mcp");
let client = ().serve(TokioChildProcess::new(command)?).await?;
let toolset = McpToolset::new(client)
.with_name("company_tools")
.with_tools(&["find_customer", "read_order", "request_refund"]);
let agent = LlmAgentBuilder::new("support")
.model(model)
.toolset(Arc::new(toolset.clone()))
.build()?;
// Keep the token when the application owns the process lifecycle.
let shutdown = toolset.cancellation_token().await;
// ... run the agent ...
shutdown.cancel();
McpToolsetは、サーバーの入力および出力スキーマをそのまま保持します。各モデルアダプターは、モデルリクエストを構築する際に、プロバイダー用にコピーを正規化します。これにより、同じMCPサーバーがGemini、OpenAI、Anthropic、およびその他のプロバイダーと、ソーススキーマを損なうことなく連携できます。
ツールを超えてプロトコルを使用する
use serde_json::json;
let resources = toolset.list_resources().await?;
let templates = toolset.list_resource_templates().await?;
let contents = toolset.read_resource("company://policy/refunds").await?;
let prompts = toolset.list_prompts().await?;
let prompt = toolset
.get_prompt(
"investigate_order",
Some(serde_json::Map::from_iter([
("order_id".to_string(), json!("ORD-1042")),
])),
)
.await?;
let suggestions = toolset
.complete_prompt_argument("investigate_order", "order_id", "ORD-", None)
.await?;
toolset.subscribe_resource("company://inventory/sku-42").await?;
// ... receive notifications in a custom ClientHandler ...
toolset.unsubscribe_resource("company://inventory/sku-42").await?;
古いサーバーがリソースまたはプロンプトのリストを実装していない場合、コンビニエンスメソッドは空のリストを返します。宣言されたリソースまたはプロンプトに対する操作は、リモート呼び出しが失敗した場合にエラーを返します。
動的サーバー管理
アプリケーションが1つの静的接続ではなく、ローカルMCP子プロセスのフリートを必要とする場合は、McpServerManagerを使用します。
use adk_tool::mcp::manager::{McpServerConfig, McpServerManager};
use std::collections::HashMap;
use std::sync::Arc;
use std::time::Duration;
let manager = Arc::new(McpServerManager::from_json_file("mcp.json")?
.with_name("product_mcp_servers")
.with_health_check_interval(Duration::from_secs(15))
.with_grace_period(Duration::from_secs(2)));
let outcomes = manager.start_all().await;
for (server_id, outcome) in outcomes {
if let Err(error) = outcome {
eprintln!("{server_id} did not start: {error}");
}
}
manager.start_monitoring();
let agent = LlmAgentBuilder::new("operator")
.model(model)
.toolset(manager.clone())
.build()?;
ランタイムレジストリは以下をサポートします。
manager.add_server("billing".into(), billing_config).await?;
manager.start_server("billing").await?;
manager.update_server("billing", replacement_config).await?;
manager.disable_server("billing").await?;
manager.enable_server("billing").await?;
manager.save_json_file("mcp.json").await?;
manager.remove_server("billing").await?;
manager.shutdown().await?;
2つのサーバーが同じツール名を公開する場合、集約されたツールセットは両方の名前に{server_id}__{tool_name}をプレフィックスとして付けます。一意の名前は変更されません。
ヘルスモニターは、閉じたMCP接続を検出します。構成されたRestartPolicyは、指数関数的バックオフによる制限付き再試行を制御します。これは接続監視であり、アプリケーションレベルのヘルスチェックではありません。サーバーのバックエンドデータベースまたは外部APIを検証する必要がある場合は、ドメインツールまたは個別のサービスプローブを使用してください。
決定論的な例を実行します。
cargo run --manifest-path examples/mcp_manager/Cargo.toml
これは、実際のRust MCP子サーバーを起動し、検出、ツール呼び出し、ランタイムの追加/有効化/更新/無効化/削除、構成の永続化、およびシャットダウンを実行します。パッケージをダウンロードしたり、APIキーを必要としたりしません。
リモートStreamable HTTP
use adk_tool::{McpAuth, McpHttpClientBuilder};
use std::time::Duration;
let toolset = McpHttpClientBuilder::new("https://mcp.example.com/mcp")
.with_auth(McpAuth::bearer(std::env::var("MCP_TOKEN")?))
.header("X-Tenant-ID", "tenant-42")
.timeout(Duration::from_secs(30))
.reinit_on_expired_session(true)
.connect()
.await?;
ビルダーは、リクエストタイムアウト、カスタムヘッダー、ベアラートークン、カスタムAPIキーヘッダー、およびHTTPセッションの期限切れ時の制限付きリカバリを適用します。
OAuth2Configは、固定のOAuth 2.0クライアント資格情報トークンリクエストを実装します。これは、既知のトークンエンドポイントを持つサーバーに役立ちます。これは完全なMCP認証フローではありません。保護されたリソースのメタデータ検出、認証サーバーの検出、ブラウザ認証、PKCE、またはリソースインジケーターのネゴシエーションは実行しません。デプロイメントがそのフローを必要とする場合は、rmcpの認証APIsまたは外部IDコンポーネントを使用してください。
引き出し
MCPサーバーは、ツール引数に含まれていない情報を必要とする場合があります。その場合、クライアントに引き出しリクエストを送信し返すことができます。アプリケーションは、リクエストを人にどのように表示するか、そしてそれを受け入れるか、拒否するか、キャンセルするかを決定します。
let toolset = McpToolset::with_elicitation_handler(
transport,
Arc::new(MyElicitationHandler),
).await?;
ADK-Rustは、フォームとURLの両方の引き出しを宣伝します。ハンドラーエラーまたはパニックは拒否に変換され、MCP接続は引き続き使用可能です。結果を伴うリクエストを受け入れる前に、返された値を検証し、アプリケーションで同意ルールを適用してください。
完全なサーバーとインタラクティブなクライアントについては、examples/mcp_elicitationを参照してください。
長時間実行されるMCPタスク
MCP 2025-11-25は、ツール呼び出しをプロトコルタスクに移動できます。ADK-Rustは、サーバーがtasks.requests.tools.callをネゴシエートし、ツールが必要またはオプションのタスクサポートを宣言した場合にのみタスクフローを使用します。
use adk_tool::McpTaskConfig;
use std::time::Duration;
let toolset = McpToolset::new(client).with_task_support(
McpTaskConfig::enabled()
.poll_interval(Duration::from_secs(1))
.timeout(Duration::from_secs(120))
.max_attempts(120),
);
タスクモードの場合、ADK-Rustは次のことを行います。
- 公式のタスクメタデータとともに
tools/callを送信します。 - 作成されたタスクを受信します。
- サーバーが提案する間隔を使用して
tasks/getをポーリングします。 tasks/resultを通じて最終ペイロードを読み取ります。- ローカルタイムアウトまたはポーリング制限に達した場合、
tasks/cancelを呼び出します。
通常のADKツール呼び出しには、不足している入力を提供するためのプロトコルに依存しない再開チャネルがまだないため、input_requiredは型付きエラーとして返されます。所有するワークフローでそのインタラクションを明示的に設計してください。
機能マップ
| MCP 機能 | ADK-Rust インターフェース | 備考 |
|---|---|---|
| ツールの検出と呼び出し | McpToolset, Toolset | 生のスキーマ; マルチモーダルおよび構造化された結果が保持されます |
| ツールのフィルタリング | with_filter, with_tools | モデルに公開する前にフィルタリング |
| リソースとテンプレート | list/read メソッド | 古いサーバーではメソッドが見つからない場合も処理されます |
| プロンプト | list/get メソッド | 型付き引数マップ |
| 補完 | prompt/resource completion メソッド | 公式の CompletionInfo を返します |
| リソースの購読 | subscribe/unsubscribe メソッド | 通知には適切なクライアントハンドラーが必要です |
| 誘発 | ElicitationHandler | 形式と URL モード |
| タスク | McpTaskConfig | 交渉された tool-call タスクライフサイクル |
| ローカル stdio | TokioChildProcess | 直接的またはマネージャー所有 |
| ストリーミング可能 HTTP | McpHttpClientBuilder | タイムアウト、ヘッダー、認証インジェクション、セッションリカバリ |
| 動的ローカル registry | McpServerManager | 追加/更新/有効化/無効化/削除/保存/監視/再起動 |
| サーバーオーサリングと拡張 | adk_tool::mcp::rmcp | 高度な使用のための正確な SDK 再エクスポート |
| サンプリング、ルート、ロギング | 互換性機能 / rmcp | SEP-2577 を通じて上流で非推奨 |
境界の選択
機能が同じプロセスとリリースに属する場合は、Rust FunctionToolを使用します。別のプログラム、チーム、言語、セキュリティ境界、またはデプロイメントがその機能を所有し、独自の契約を公開すべき場合は、MCPを使用します。
本番環境でのデプロイメントの場合:
- 最小限の有用なツールセットを公開する。
- 読み取り専用のアクションと結果を伴うアクションを分離する。
- コマンドライン引数やコミットされた
mcp.jsonファイルからシークレットを除外する。 - リモートのHTTPサーバーを認証し、資格情報の範囲を狭くする。
- ツールの説明とサーバーから返されたコンテンツを信頼できない入力として扱う。
- ツール実行に関するADK-Rustの承認と許可を保持する。
- 接続、ツール、およびタスクのタイムアウトを制限する。
- ツール呼び出し、承認、エラー、およびサーバーのライフサイクル変更を記録する。
現在の制限
McpServerManagerはローカルのstdio子プロセスを管理します。リモートのHTTPサービスはMcpHttpClientBuilderとアプリケーションが所有する構成を使用します。- マネージャーのヘルスチェックは閉じられたMCP接続を検出します。ビジネスレベルのヘルスツールは呼び出しません。
- レジストリの変更は、子がMCPハンドシェイクを完了する間、シリアル化されます。
autoApproveは構成の互換性であり、認可の強制ではありません。- 組み込みのOAuthヘルパーはクライアント資格情報であり、完全なMCP OAuthディスカバリおよびユーザー認可フローではありません。
これらの制限は、デプロイメントの決定が明確に保たれるように明記されています。