Einen MCP-Client erstellen
Eine ADK-Rust-Anwendung ist ein MCP-Client, wenn sie eine Verbindung zu einem Server herstellt, dessen veröffentlichten Katalog liest und ausgewählte Funktionen einem Agenten oder Workflow zur Verfügung stellt.
Installation
[dependencies]
adk-tool = { version = "2.1.0", features = ["mcp"] }
Für entferntes Streamable HTTP:
adk-tool = { version = "2.1.0", features = ["mcp", "http-transport"] }
Lokale stdio-Verbindung
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();
Verwenden Sie in Produktionsumgebungen einen absoluten Binärpfad. Vermeiden Sie Paket-Tags wie latest
in der Bereitstellungskonfiguration, da sie Builds und die Wiederherstellung nach
Vorfällen nicht reproduzierbar machen.
Ermittlung und Filterung von Tools
McpToolset konvertiert jedes veröffentlichte MCP-Tool in ein ADK-Rust-Tool. Dabei bleiben
die Eingabe- und Ausgabeschemas des Servers unverändert. Der ausgewählte Modellanbieter
normalisiert eine Kopie des Schemas, wenn er seine Anfrage erstellt.
Der Adapter bewahrt außerdem die MCP-Toolanmerkungen. Ein readOnlyHint kennzeichnet das ADK-
Tool als schreibgeschützt und nebenläufigkeitssicher; ein idempotentHint erlaubt eine sichere
Wiederholung nach der erneuten Verbindungsherstellung, macht das Tool jedoch nicht automatisch
für den parallelen Versand geeignet. Fehlende Hinweise deaktivieren beide Verhaltensweisen.
Wichtig: MCP-Anmerkungen sind vom Server veröffentlichte Hinweise. Verwenden Sie automatische Wiederholungs- und Versandmetadaten nur mit Servern innerhalb der Vertrauensgrenze der Anwendung.
let reviewed = McpToolset::new(client).with_filter(|name| {
matches!(name, "read_order" | "read_policy" | "request_replacement")
});
Die Filterung steuert die Sichtbarkeit für das Modell. Sie ersetzt nicht die Autorisierung zum Zeitpunkt der Toolausführung.
Ressourcen, Prompts und Vervollständigung
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?;
Die Vervollständigung von Ressourcen-Vorlagen verwendet complete_resource_argument. Ein Server, der
keine Listenoperationen implementiert, gibt eine leere Liste zurück, wenn er mit
MCP MethodNotFound antwortet; andere Protokoll- und Transportfehler bleiben Fehler.
Ressourcenabonnements
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 stellt aktive Abonnements nach seiner begrenzten Verbindungsaktualisierung wieder her.
McpServerManager behält Abonnements auch über verwaltete Neustarts des Prozesses hinweg bei.
Fehler und Panics von Handlern werden protokolliert, ohne die MCP-Verbindung zu beenden.
Für Streamable HTTP konfigurieren Sie denselben Handler mit
McpHttpClientBuilder::with_resource_notification_handler, bevor Sie
connect_with_elicitation aufrufen.
Informationsabfrage
Mit der Informationsabfrage kann ein Server während der Verarbeitung eines Tool-Aufrufs Informationen anfordern. Die Anwendung entscheidet, wie die Anfrage dargestellt wird und ob sie angenommen, abgelehnt oder abgebrochen wird.
let toolset = McpToolset::with_elicitation_handler(
transport,
Arc::new(MyElicitationHandler),
).await?;
ADK-Rust kündigt Formular- und URL-Informationsabfragen an. Ein Fehler oder eine Panik des Handlers wird zu einer Ablehnung, wobei die MCP-Sitzung erhalten bleibt. Die Anwendung muss akzeptierte Werte weiterhin validieren und die Einwilligungsrichtlinie anwenden.
Unter examples/mcp_elicitation finden Sie ein vollständiges Client- und Server-Paar.
Ausgehandelte Aufgaben
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),
);
Der Aufgabenmodus wird anhand von zwei ausgehandelten Fakten ausgewählt:
- der Server kündigt
tasks.requests.tools.callan; und - das Tool deklariert die Aufgabenunterstützung als erforderlich oder optional.
ADK-Rust sendet Aufgabenmetadaten mit tools/call, empfängt die erstellte Aufgabe, fragt
tasks/get ab, liest tasks/result und ruft tasks/cancel auf, wenn lokale Grenzen
überschritten werden. input_required wird als typisierter Fehler zurückgegeben, da ein gewöhnlicher ADK-
Tool-Aufruf derzeit noch keinen protokollneutralen Eingabekanal zum Fortsetzen von Aufgaben bereitstellt.
Remote 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?;
Der Builder unterstützt Bearer-Token, einen benutzerdefinierten API-Schlüssel-Header und feste OAuth- 2.0-Clientanmeldedaten. Lesen Sie Sicherheit und Autorisierung, bevor Sie einen Authentifizierungsablauf auswählen.