构建 MCP 客户端
当 ADK-Rust 应用连接到服务器、读取其发布的目录,并将选定的能力提供给 agent 或工作流时,它就是一个 MCP 客户端。
安装
[dependencies]
adk-tool = { version = "2.1.0", features = ["mcp"] }
对于远程 Streamable HTTP:
adk-tool = { version = "2.1.0", features = ["mcp", "http-transport"] }
本地 stdio 连接
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 shutdown = toolset.cancellation_token().await;
let agent = LlmAgentBuilder::new("support")
.model(model)
.toolset(Arc::new(toolset))
.build()?;
// Run the agent, then close the client-owned MCP session.
shutdown.cancel();
在生产环境中使用绝对二进制路径。避免在部署配置中使用 latest 等软件包标签,因为这会导致构建和事故恢复无法复现。
工具发现与筛选
McpToolset 会将每个已发布的 MCP 工具转换为一个 ADK-Rust Tool。它会保持服务器的输入和输出 schema 不变。所选模型提供商在构建请求时会对 schema 的副本进行规范化。
该适配器还会保留 MCP 工具注解。readOnlyHint 表示 ADK 工具是只读的,并且支持并发;idempotentHint 允许在重新连接后安全重放,但其本身不会使工具具备自动并行分发的资格。缺少提示会使这两种行为均保持禁用。
重要: MCP 注解是服务器发布的提示。仅对位于应用信任边界内的服务器使用自动重放和分发元数据。
let reviewed = McpToolset::new(client).with_filter(|name| {
matches!(name, "read_order" | "read_policy" | "request_replacement")
});
筛选控制模型可见性,但不能替代工具执行时的授权。
资源、提示和补全
use serde_json::json;
let resources = toolset.list_resources().await?;
let templates = toolset.list_resource_templates().await?;
let policy = 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?;
资源模板补全使用 complete_resource_argument。不实现列表操作的服务器在以 MCP MethodNotFound 响应时会返回空列表;其他协议和传输故障仍会作为错误处理。
资源订阅
use adk_tool::{AutoDeclineElicitationHandler, McpToolset, ResourceNotificationHandler};
use std::sync::Arc;
struct ResourceUpdates;
#[async_trait::async_trait]
impl ResourceNotificationHandler for ResourceUpdates {
async fn handle_resource_updated(
&self,
uri: &str,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
println!("Resource changed: {uri}");
Ok(())
}
async fn handle_resource_list_changed(
&self,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
println!("The resource catalog changed");
Ok(())
}
}
let toolset = McpToolset::with_handlers(
transport,
Arc::new(AutoDeclineElicitationHandler),
Arc::new(ResourceUpdates),
).await?;
toolset.subscribe_resource("company://inventory/sku-42").await?;
toolset.unsubscribe_resource("company://inventory/sku-42").await?;
McpToolset 在有界连接刷新后恢复活动订阅。
McpServerManager 还会在受管理的进程重启期间保留订阅。
处理程序错误和崩溃会被记录,而不会终止 MCP 连接。
对于可流式 HTTP,请在调用
connect_with_elicitation 之前使用
McpHttpClientBuilder::with_resource_notification_handler 配置相同的处理程序。
信息请求
信息请求允许服务器在处理工具调用时请求信息。 应用程序决定如何呈现请求,以及接受、拒绝还是取消请求。
let toolset = McpToolset::with_elicitation_handler(
transport,
Arc::new(MyElicitationHandler),
).await?;
ADK-Rust 宣布支持表单和 URL 信息请求。处理程序失败或崩溃会变为拒绝, 从而保留 MCP 会话。应用程序仍必须验证接受的值并应用同意策略。
请参阅 examples/mcp_elicitation,了解完整的客户端和服务器配对示例。
协商任务
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),
);
任务模式根据两个协商事实进行选择:
- 服务器宣布支持
tasks.requests.tools.call;以及 - 工具声明任务支持为必需或可选。
ADK-Rust 通过 tools/call 发送任务元数据,接收创建的任务,轮询
tasks/get,读取 tasks/result,并在超出本地限制时调用 tasks/cancel。
由于普通的 ADK 工具调用目前尚未提供协议中立的任务恢复输入通道,
input_required 会作为类型化错误返回。
远程可流式 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?;
构建器支持 bearer token、自定义 API-key 标头以及固定的 OAuth 2.0 client credentials。在选择身份验证流程之前,请参阅安全性和授权。