Einen MCP-Server veröffentlichen

ADK-Rust verwendet MCP-Server über McpToolset, kapselt jedoch nicht jede serverseitige SDK API. Serverautoren verwenden die offizielle rmcp SDK, die von adk_tool::mcp::rmcp re-exportiert wird, damit die Protokolltypen von Client und Server synchron bleiben.

Für ein eigenständiges Server-Crate ist es ebenfalls sinnvoll, direkt von derselben rmcp-Version abzuhängen:

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

Minimaler stdio-Server

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

Das deterministische examples/mcp_manager-Fixture verwendet diese Serverstruktur und wird von den MCP-Verifikationsprüfungen kompiliert und ausgeführt.

Ehrliche Fähigkeiten veröffentlichen

Gib eine Fähigkeit nur an, wenn der Handler sie implementiert. Ein Client verwendet die Initialisierungsantwort, um zu entscheiden, ob er Ressourcen, Prompts, Vervollständigung, Aufforderungen, Abonnements oder Aufgaben aufrufen darf.

Deklariere bei Tools, die Aufgaben unterstützen, die Aufgabenunterstützung des Tools und gib tasks.requests.tools.call an. Der Client kann ein erforderliches Aufgaben-Tool ablehnen, wenn der Server keine Aufgabenunterstützung ausgehandelt hat.

Tools sind Sicherheitsgrenzen

Beschreibungen und das JSON-Schema helfen dem Modell, einen Aufruf zu bilden; sie sind keine Eingabevalidierung und keine Autorisierung. Ein Server muss:

  • jede Eingabe unabhängig vom Modell validieren;
  • Identität und Mandantenbereich an der Servergrenze auflösen;
  • die konkrete Aktion und Ressource autorisieren;
  • Lesevorgänge von folgenreichen Schreibvorgängen trennen;
  • vermeiden, Geheimnisse oder unbegrenzte Daten zurückzugeben;
  • Wiederholungen und Idempotenz für Seiteneffekte explizit festlegen; und
  • ausreichend Belege aufzeichnen, um das Ergebnis zu erklären.

Einen Transport auswählen

Verwenden Sie stdio, wenn der Client den lokalen untergeordneten Prozess besitzt. Verwenden Sie Streamable HTTP, wenn der Server ein unabhängig bereitgestellter Dienst ist. Remote-Bereitstellungen benötigen außerdem Authentifizierung, Anfragelimits, Sitzungsrichtlinien, Beobachtbarkeit und eine Health-Prüfung auf Anwendungsebene.

Weitere Informationen finden Sie in der offiziellen Dokumentation zu rmcp zu Server-Routern, Ressourcen, Prompts, benutzerdefinierten Handlern, Transporten, Autorisierung und Erweiterung APIs.