Créer un client MCP

Une application ADK-Rust est un client MCP lorsqu'elle se connecte à un serveur, lit son catalogue publié et met certaines capacités sélectionnées à la disposition d'un agent ou d'un workflow.

Installation

[dependencies]
adk-tool = { version = "2.1.0", features = ["mcp"] }

Pour un HTTP Streamable distant :

adk-tool = { version = "2.1.0", features = ["mcp", "http-transport"] }

Connexion stdio locale

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();

Utilisez un chemin absolu vers le binaire en production. Évitez les balises de paquet telles que latest dans la configuration de dĂ©ploiement, car elles rendent les builds et la rĂ©cupĂ©ration aprĂšs incident non reproductibles.

Découverte et filtrage des outils

McpToolset convertit chaque outil MCP publiĂ© en un ADK-Rust Tool. Il conserve inchangĂ©s les schĂ©mas d'entrĂ©e et de sortie du serveur. Le fournisseur de modĂšle sĂ©lectionnĂ© normalise une copie du schĂ©ma lors de la construction de sa requĂȘte.

L'adaptateur conserve également les annotations d'outils MCP. Un readOnlyHint indique que l'outil ADK est en lecture seule et compatible avec l'accÚs concurrent ; un idempotentHint autorise une nouvelle exécution sûre aprÚs une reconnexion, mais ne rend pas à lui seul l'outil éligible à une distribution parallÚle automatique. En l'absence d'indications, ces deux comportements restent désactivés.

Important : les annotations MCP sont des indications publiées par le serveur. N'utilisez les métadonnées de nouvelle exécution et de distribution automatiques qu'avec des serveurs situés à l'intérieur de la limite de confiance de l'application.

let reviewed = McpToolset::new(client).with_filter(|name| {
    matches!(name, "read_order" | "read_policy" | "request_replacement")
});

Le filtrage contrÎle la visibilité pour le modÚle. Il ne remplace pas l'autorisation au moment de l'exécution de l'outil.

Ressources, invites et complétion

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?;

La complétion des modÚles de ressources utilise complete_resource_argument. Un serveur qui n'implémente pas les opérations de liste renvoie une liste vide lorsqu'il répond avec MCP MethodNotFound ; les autres erreurs de protocole et de transport restent des erreurs.

Abonnements aux ressources

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 restaure les abonnements actifs aprĂšs son actualisation de connexion limitĂ©e. McpServerManager conserve Ă©galement les abonnements lors des redĂ©marrages gĂ©rĂ©s du processus. Les erreurs et les paniques des gestionnaires sont consignĂ©es sans mettre fin Ă  la connexion MCP. Pour HTTP Streamable, configurez le mĂȘme gestionnaire avec McpHttpClientBuilder::with_resource_notification_handler avant d’appeler connect_with_elicitation.

Élicitation

L’élicitation permet Ă  un serveur de demander des informations lors du traitement d’un appel d’outil. L’application dĂ©cide comment prĂ©senter la demande et s’il faut l’accepter, la refuser ou l’annuler.

let toolset = McpToolset::with_elicitation_handler(
    transport,
    Arc::new(MyElicitationHandler),
).await?;

ADK-Rust annonce l’élicitation par formulaire et URL. L’échec ou la panique d’un gestionnaire devient un refus, ce qui prĂ©serve la session MCP. L’application doit nĂ©anmoins valider les valeurs acceptĂ©es et appliquer la politique de consentement.

Consultez examples/mcp_elicitation pour voir un ensemble complet client-serveur.

Tùches négociées

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),
);

Le mode tùche est sélectionné à partir de deux éléments négociés :

  1. le serveur annonce tasks.requests.tools.call ; et
  2. l’outil dĂ©clare la prise en charge des tĂąches comme obligatoire ou facultative.

ADK-Rust envoie les mĂ©tadonnĂ©es de tĂąche avec tools/call, reçoit la tĂąche créée, interroge tasks/get, lit tasks/result et appelle tasks/cancel lorsque les limites locales sont dĂ©passĂ©es. input_required est renvoyĂ© comme une erreur typĂ©e, car un appel d’outil ADK ordinaire ne fournit pas encore de canal neutre vis-Ă -vis du protocole pour reprendre une tĂąche.

HTTP Streamable distant

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?;

Le gĂ©nĂ©rateur prend en charge les jetons bearer, un en-tĂȘte personnalisĂ© de clĂ© API et les identifiants client fixes OAuth 2.0. Consultez SĂ©curitĂ© et autorisation avant de choisir un flux d’authentification.

Créer un client MCP - Documentation ADK-Rust | ADK-Rust