Skip to main content

xyz_rust/mcp/
mod.rs

1// mcp 是 MCP 前端,构建于官方 Rust SDK(rmcp)。每条注册命令成为一个
2// MCP 工具,经 stdio 与 streamable HTTP 两种传输服务,并支持钉定协议
3// 版本子集。
4//
5// 输出契约:每次成功调用返回人类可读文本(与 CLI 前端同款渲染)到
6// content,外加结构化 JSON 到 structuredContent;失败以 isError=true
7// 结果携带分类错误消息。
8
9use std::sync::Arc;
10use std::time::Duration;
11
12use crate::config::Config;
13use crate::ctx::Ctx;
14use crate::registry::Registry;
15
16pub mod args;
17pub mod handler;
18pub mod transport;
19
20#[cfg(test)]
21mod mcp_test;
22
23/// 官方 Rust SDK 已知的协议版本(rmcp::ProtocolVersion 常量的字符串形态;
24/// 与 Go SDK 同一集合,从 2024-11-05 到 2026-07-28)。
25pub const PROTOCOL_V2024_11_05: &str = "2024-11-05";
26pub const PROTOCOL_V2025_03_26: &str = "2025-03-26";
27pub const PROTOCOL_V2025_06_18: &str = "2025-06-18";
28pub const PROTOCOL_V2025_11_25: &str = "2025-11-25";
29pub const PROTOCOL_V2026_07_28: &str = "2026-07-28"; // latest revision
30
31/// 全集(协商偏好序:最新在前,对齐 Go DefaultVersions)。
32pub const DEFAULT_VERSIONS: &[&str] = &[
33    PROTOCOL_V2026_07_28,
34    PROTOCOL_V2025_11_25,
35    PROTOCOL_V2025_06_18,
36    PROTOCOL_V2025_03_26,
37    PROTOCOL_V2024_11_05,
38];
39
40/// Options 配置 MCP 前端。零值服务 SDK 已知的全部协议版本。
41#[derive(Debug, Clone, Default)]
42pub struct Options {
43    /// 服务器实现名与版本。默认:二进制名与 "0.0.0"。
44    pub name: String,
45    pub version: String,
46
47    /// 钉定协议版本子集(DEFAULT_VERSIONS 的子集);顺序即协商偏好序。
48    /// 空 = 全集。
49    pub versions: Vec<String>,
50
51    /// 初始化后展示给客户端的说明。
52    pub instructions: String,
53
54    /// sse/http 传输的监听地址。默认 ":8080"。
55    pub addr: String,
56
57    /// streamable HTTP 以 application/json 而非 text/event-stream 应答
58    /// (调试友好)。
59    pub json_response: bool,
60
61    /// 开启 streamable HTTP 无状态模式(SEP-2567)。
62    pub stateless: bool,
63
64    /// http 传输的 Bearer 校验(stdio 是本地进程,不受影响)。空 = 不校验。
65    pub bearer_tokens: Vec<String>,
66
67    /// streamable HTTP 空闲会话过期。
68    pub session_timeout: Duration,
69
70    /// http 传输的 CORS 白名单。
71    pub cors_origins: Vec<String>,
72
73    /// serve 模式 /mcp 挂载时注入的取消上下文(内部使用)。
74    #[doc(hidden)]
75    pub default_ctx: Option<Arc<Ctx>>,
76
77    /// 通道级默认参数(--default k=v):调用未显式提供时补上。
78    pub defaults: std::collections::HashMap<String, String>,
79
80    /// 附加到结果 _meta.xyz.headers 的自定义静态头(spec §12.8,对齐
81    /// HTTP 的 Config.ResponseHeaders / --xyz.header)。
82    pub response_headers: Vec<(String, String)>,
83
84    /// 关闭结果 _meta.xyz 的服务器上下文(spec §12.8 的单一开关,
85    /// 对齐 --xyz.no-server-headers)。
86    pub no_server_meta: bool,
87}
88
89/// 构建服务器实现:每条注册命令一个工具,inputSchema 直接来自注册表的
90/// JSON Schema 生成;共享 Invoke 管线做全部解码与校验。
91pub fn server(
92    reg: &Registry,
93    opts: Options,
94    ctx: Arc<Ctx>,
95) -> crate::errors::Result<handler::XyzServer> {
96    handler::build(reg, &opts, ctx)
97}
98
99/// 根派发器入口:解析 mcp 模式的参数并派发传输(等价 Go runWithOptions,
100/// cfg 注入 --xyz.* 折叠后的 preset)。
101pub fn run_with_config(ctx: &Ctx, reg: &Registry, args: &[String], cfg: Config) -> i32 {
102    let base = Options {
103        // §12.6:serverInfo 的应用身份(默认 basename / 版本槽,覆盖优先级
104        // 见 Options 文档;xyz 库版本单独报 _meta.xyz.sdk_version)。
105        name: cfg.resolved_name(),
106        version: cfg.resolved_version(),
107        addr: cfg.addr.clone(),
108        bearer_tokens: cfg.bearer_tokens.clone(),
109        response_headers: cfg.response_headers.clone(),
110        no_server_meta: cfg.no_server_headers,
111        ..Default::default()
112    };
113    transport::run(ctx, reg, args, base)
114}
115
116/// mcp 模式(默认 Options)。
117pub fn run_context(ctx: &Ctx, reg: &Registry, args: &[String]) -> i32 {
118    transport::run(ctx, reg, args, Options::default())
119}
120
121/// 供 serve 模式 /mcp 挂载的 streamable HTTP 路由;不可用时 None。
122pub fn mountable(reg: &Registry, opts: &Options) -> Option<axum::routing::Router> {
123    transport::mountable_router(reg, opts).ok()
124}
125
126/// 官方 SDK 的协议版本常量 ↔ 字符串(传输层转换用)。
127pub(crate) fn protocol_version(s: &str) -> Option<rmcp::model::ProtocolVersion> {
128    match s {
129        PROTOCOL_V2024_11_05 => Some(rmcp::model::ProtocolVersion::V_2024_11_05),
130        PROTOCOL_V2025_03_26 => Some(rmcp::model::ProtocolVersion::V_2025_03_26),
131        PROTOCOL_V2025_06_18 => Some(rmcp::model::ProtocolVersion::V_2025_06_18),
132        PROTOCOL_V2025_11_25 => Some(rmcp::model::ProtocolVersion::V_2025_11_25),
133        PROTOCOL_V2026_07_28 => Some(rmcp::model::ProtocolVersion::V_2026_07_28),
134        _ => None,
135    }
136}