发布 MCP 服务器
ADK-Rust 通过 McpToolset 使用 MCP 服务器,但它不会封装每个
服务器端 SDK API。服务器作者使用由
adk_tool::mcp::rmcp 重新导出的官方 rmcp SDK,以确保客户端和服务器协议类型保持一致。
对于独立的服务器 crate,直接依赖相同的 rmcp 版本也
是合适的:
[dependencies]
rmcp = { version = "2.2", features = ["transport-io", "schemars"] }
serde = { version = "1", features = ["derive"] }
tokio = { version = "1", features = ["full"] }
最小 stdio 服务器
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?;
确定性的 examples/mcp_manager 测试夹具采用了这种服务器形态,并由
MCP 验证门进行编译和执行。
发布真实的功能
仅当处理程序实现某项功能时才声明该功能。客户端使用 初始化响应来决定是否可以调用资源、提示、补全、引导、 订阅或任务。
对于支持任务的工具,声明工具的任务支持,并发布
tasks.requests.tools.call。当服务器未协商任务支持时,客户端可能会拒绝
所需的任务工具。
工具是安全边界
描述和 JSON Schema 可帮助模型形成调用;它们不是输入 验证或授权机制。服务器必须:
- 独立于模型验证每个输入;
- 在服务器边界解析身份和租户范围;
- 授权具体的操作和资源;
- 将读取操作与会产生后果的写入操作分开;
- 避免返回机密或无界数据;
- 明确副作用的重试和幂等性;以及
- 记录足够的证据以解释结果。
选择传输方式
当客户端拥有本地子进程时,使用 stdio。当服务器是独立部署的服务时,使用 Streamable HTTP。远程部署还需要身份验证、请求限制、会话策略、可观测性以及应用级健康探针。
有关服务器路由器、资源、提示、自定义处理程序、传输、授权和扩展 APIs,请参阅官方的 rmcp 文档。