MCP サーバーを公開する

ADK-Rust は McpToolset を介して MCP サーバーを消費しますが、すべてのサーバーサイドの SDK API をラップするわけではありません。サーバーの作成者は、クライアントとサーバーのプロトコルタイプが整合するように、adk_tool::mcp::rmcp によって再エクスポートされた公式の rmcp SDK を使用します。

スタンドアロンのサーバークレートの場合、同じ rmcp リリースに直接依存することも適切です。

[dependencies]
rmcp = { version = "2.2", features = ["transport-io", "schemars"] }
serde = { version = "1", features = ["derive"] }
tokio = { version = "1", features = ["full"] }

最小限の stdio サーバー

use rmcp::{
    ServerHandler,
    handler::server::{router::tool::ToolRouter, wrapper::Parameters},
    model::{ServerCapabilities, ServerInfo},
    schemars, tool, tool_handler, tool_router,
};
use serde::Deserialize;

#[derive(Debug, Deserialize, schemars::JsonSchema)]
struct LookupInput {
    order_id: String,
}

#[derive(Debug, Clone)]
struct OrderServer {
    tool_router: ToolRouter<Self>,
}

#[tool_router]
impl OrderServer {
    #[tool(description = "Read one order by its public order ID")]
    async fn read_order(
        &self,
        Parameters(input): Parameters<LookupInput>,
    ) -> String {
        format!("Order {} is ready for investigation", input.order_id)
    }
}

#[tool_handler]
impl ServerHandler for OrderServer {
    fn get_info(&self) -> ServerInfo {
        ServerInfo::new(ServerCapabilities::builder().enable_tools().build())
            .with_instructions("Read-only order investigation tools")
    }
}

let service = rmcp::ServiceExt::serve(
    OrderServer { tool_router: OrderServer::tool_router() },
    rmcp::transport::io::stdio(),
).await?;
service.waiting().await?;

決定論的な examples/mcp_manager フィクスチャは、このサーバーの形状を使用し、MCP 検証ゲートによってコンパイルおよび実行されます。

正直な機能の公開

ハンドラーが実装している場合にのみ、機能を宣伝してください。クライアントは、初期化応答を使用して、リソース、プロンプト、完了、引き出し、サブスクリプション、またはタスクを呼び出すことができるかどうかを決定します。

タスク対応ツールの場合、ツールのタスクサポートを宣言し、tasks.requests.tools.call を宣伝してください。サーバーがタスクサポートをネゴシエートしなかった場合、クライアントは必須のタスクツールを拒否する可能性があります。

ツールはセキュリティ境界です

説明と JSON スキーマ は、モデルが呼び出しを形成するのに役立ちます。これらは入力検証や認可ではありません。サーバーは次のことを行う必要があります。

  • モデルとは独立してすべての入力を検証する。
  • サーバー境界でIDとテナントスコープを解決する。
  • 特定のアクションとリソースを認可する。
  • 読み取り操作を結果的な書き込みから分離する。
  • シークレットや無制限のデータを返さない。
  • 副作用のためにリトライと冪等性を明示的にする。
  • 結果を説明するのに十分な証拠を記録する。

トランスポートの選択

クライアントがローカルの子プロセスを所有している場合は、stdio を使用します。サーバーが独立してデプロイされたサービスである場合は、ストリーマブル HTTP を使用します。リモートデプロイメントには、認証、リクエスト制限、セッションポリシー、可観測性、およびアプリケーションレベルのヘルスプローブも必要です。

サーバールーター、リソース、プロンプト、カスタムハンドラー、トランスポート、認可、および拡張 APIs については、公式の rmcp ドキュメント を参照してください。