MCP 클라이언트 빌드
ADK-Rust 애플리케이션은 서버에 연결하고, 서버가 게시한 카탈로그를 읽으며, 선택한 기능을 에이전트 또는 워크플로에서 사용할 수 있도록 제공할 때 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로 변환합니다. 서버의 입력 및 출력 스키마는 변경하지 않습니다. 선택한 모델 제공자는 요청을 생성할 때 스키마의 복사본을 정규화합니다.
어댑터는 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 연결을 종료하지 않고 기록됩니다.
Streamable 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은 형식화된 오류로 반환됩니다.
원격 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?;
빌더는 bearer 토큰, 사용자 지정 API-key 헤더 및 고정된 OAuth 2.0 클라이언트 자격 증명을 지원합니다. 인증 흐름을 선택하기 전에 보안 및 권한 부여를 참조하세요.