Skip to main content

mcp_stdio_proxy/client/support/
args.rs

1//! CLI 参数定义
2//!
3//! 定义所有命令行参数结构体
4
5use clap::Parser;
6use std::path::PathBuf;
7
8/// 通用日志配置参数
9///
10/// 用于多个命令之间共享日志配置
11#[derive(Parser, Debug, Clone)]
12pub struct LoggingArgs {
13    /// 启用详细诊断模式,输出连接和工具调用的详细时间信息(默认关闭
14    #[arg(
15        long,
16        default_value = "false",
17        help = "启用详细诊断模式,追踪连接生命周期和超时问题(默认关闭)"
18    )]
19    pub diagnostic: bool,
20
21    /// 日志输出目录(自动生成文件名)
22    #[arg(long, help = "日志输出目录,将自动生成日志文件名")]
23    pub log_dir: Option<PathBuf>,
24
25    /// 日志文件完整路径(手动指定)
26    #[arg(long, conflicts_with = "log_dir", help = "日志文件完整路径")]
27    pub log_file: Option<PathBuf>,
28
29    /// OTLP 追踪端点(如 http://localhost:4317)
30    ///
31    /// 启用 diagnostic 模式时,可配置此参数将追踪数据发送到 Jaeger 等 OTLP 兼容的后端。
32    /// 支持 gRPC (端口 4317) 和 HTTP (端口 4318) 协议。
33    #[arg(
34        long,
35        env = "OTEL_EXPORTER_OTLP_ENDPOINT",
36        help = "OTLP 追踪端点 (如 http://localhost:4317)"
37    )]
38    pub otlp_endpoint: Option<String>,
39
40    /// 追踪服务名称(用于 Jaeger 等追踪后端标识)
41    #[arg(
42        long,
43        default_value = "mcp-proxy",
44        help = "追踪服务名称(用于 Jaeger 等追踪后端标识)"
45    )]
46    pub service_name: String,
47}
48
49/// MCP-Proxy CLI 主命令结构
50#[derive(Parser, Debug)]
51#[command(name = "mcp-proxy")]
52#[command(version = env!("CARGO_PKG_VERSION"))]
53#[command(about = "MCP 协议转换代理工具", long_about = None)]
54pub struct Cli {
55    #[command(subcommand)]
56    pub command: Option<Commands>,
57
58    /// 直接URL模式(向后兼容)
59    #[arg(value_name = "URL", help = "MCP 服务的 URL 地址(直接模式)")]
60    pub url: Option<String>,
61
62    /// 全局详细输出
63    #[arg(short, long, global = true)]
64    pub verbose: bool,
65
66    /// 全局静默模式
67    #[arg(short, long, global = true)]
68    pub quiet: bool,
69}
70
71#[derive(clap::Subcommand, Debug)]
72pub enum Commands {
73    /// 协议转换模式 - 将 URL 转换为 stdio
74    Convert(ConvertArgs),
75
76    /// 检查服务状态
77    Check(CheckArgs),
78
79    /// 协议检测
80    Detect(DetectArgs),
81
82    /// 代理模式 - 将 stdio MCP 服务代理为 HTTP/SSE 服务
83    Proxy(crate::client::proxy_server::ProxyArgs),
84
85    /// 健康检查 - 验证 MCP 服务是否可用
86    Health(HealthArgs),
87}
88
89/// 协议转换参数
90#[derive(Parser, Debug, Clone)]
91pub struct ConvertArgs {
92    /// MCP 服务的 URL 地址(可选,与 --config/--config-file 二选一)
93    #[arg(value_name = "URL", help = "MCP 服务的 URL 地址")]
94    pub url: Option<String>,
95
96    /// MCP 服务配置 JSON
97    #[arg(long, conflicts_with = "config_file", help = "MCP 服务配置 JSON")]
98    pub config: Option<String>,
99
100    /// MCP 服务配置文件路径
101    #[arg(long, conflicts_with = "config", help = "MCP 服务配置文件路径")]
102    pub config_file: Option<PathBuf>,
103
104    /// MCP 服务名称(多服务配置时必需)
105    #[arg(short, long, help = "MCP 服务名称(多服务配置时必需)")]
106    pub name: Option<String>,
107
108    /// 指定远程服务协议类型(不指定则自动检测)
109    #[arg(long, value_enum, help = "指定远程服务协议类型(不指定则自动检测)")]
110    pub protocol: Option<crate::client::proxy_server::ProxyProtocol>,
111
112    /// 认证 header (如: "Bearer token")
113    #[arg(short, long, help = "认证 header")]
114    pub auth: Option<String>,
115
116    /// 自定义 HTTP headers
117    #[arg(short = 'H', long, value_parser = parse_key_val, help = "自定义 HTTP headers (KEY=VALUE 格式)")]
118    pub header: Vec<(String, String)>,
119
120    /// 重试次数
121    #[arg(long, default_value = "0", help = "重试次数,0 表示无限重试")]
122    pub retries: u32,
123
124    /// 工具白名单(逗号分隔),只允许指定的工具
125    #[arg(
126        long,
127        value_delimiter = ',',
128        help = "工具白名单(逗号分隔),只允许指定的工具"
129    )]
130    pub allow_tools: Option<Vec<String>>,
131
132    /// 工具黑名单(逗号分隔),排除指定的工具
133    #[arg(
134        long,
135        value_delimiter = ',',
136        help = "工具黑名单(逗号分隔),排除指定的工具"
137    )]
138    pub deny_tools: Option<Vec<String>>,
139
140    /// 客户端 ping 间隔(秒),0 表示禁用
141    #[arg(
142        long,
143        default_value = "30",
144        help = "客户端 ping 间隔(秒),0 表示禁用"
145    )]
146    pub ping_interval: u64,
147
148    /// 客户端 ping 超时(秒)
149    #[arg(
150        long,
151        default_value = "10",
152        help = "客户端 ping 超时(秒),超时则认为连接断开"
153    )]
154    pub ping_timeout: u64,
155
156    /// initialize 结果的内联 fallback JSON
157    #[arg(long)]
158    pub import_initialize: Option<String>,
159
160    /// initialize 结果的 fallback JSON 文件
161    #[arg(long)]
162    pub import_initialize_file: Option<PathBuf>,
163
164    /// 完整 tools/list 结果的内联 fallback JSON
165    #[arg(long)]
166    pub import_tools: Option<String>,
167
168    /// 完整 tools/list 结果的 fallback JSON 文件
169    #[arg(long)]
170    pub import_tools_file: Option<PathBuf>,
171
172    /// 将真实 initialize 结果导出到文件;使用 - 输出到 stdout
173    #[arg(long)]
174    pub export_initialize: Option<PathBuf>,
175
176    /// 将真实完整 tools/list 结果导出到文件;使用 - 输出到 stdout
177    #[arg(long)]
178    pub export_tools: Option<PathBuf>,
179
180    /// 日志配置(使用通用结构)
181    #[command(flatten)]
182    pub logging: LoggingArgs,
183}
184
185/// 检查参数
186#[derive(Parser, Debug)]
187pub struct CheckArgs {
188    /// 要检查的 MCP 服务 URL
189    #[arg(value_name = "URL")]
190    pub url: String,
191
192    /// 认证 header
193    #[arg(short, long)]
194    pub auth: Option<String>,
195
196    /// 自定义 HTTP headers
197    #[arg(short = 'H', long, value_parser = parse_key_val, help = "自定义 HTTP headers (KEY=VALUE 格式)")]
198    pub header: Vec<(String, String)>,
199
200    /// 超时时间
201    #[arg(long, default_value = "10")]
202    pub timeout: u64,
203}
204
205/// 协议检测参数
206#[derive(Parser, Debug)]
207pub struct DetectArgs {
208    /// 要检测的 MCP 服务 URL
209    #[arg(value_name = "URL")]
210    pub url: String,
211
212    /// 认证 header
213    #[arg(short, long)]
214    pub auth: Option<String>,
215
216    /// 自定义 HTTP headers
217    #[arg(short = 'H', long, value_parser = parse_key_val, help = "自定义 HTTP headers (KEY=VALUE 格式)")]
218    pub header: Vec<(String, String)>,
219}
220
221/// 健康检查参数
222#[derive(Parser, Debug)]
223#[command(after_help = "\
224退出码:
225  0  服务健康 - MCP 连接握手成功
226  1  服务不健康 - 连接失败、超时或握手失败
227
228示例:
229  # 基本用法
230  mcp-proxy health http://localhost:8080/mcp
231
232  # 带认证
233  mcp-proxy health http://localhost:8080/mcp -a \"Bearer token123\"
234
235  # 指定协议和超时
236  mcp-proxy health http://localhost:8080/mcp --protocol sse --timeout 5
237
238  # 静默模式(仅返回退出码,适合脚本使用)
239  mcp-proxy health http://localhost:8080/mcp -q
240
241  # 在 shell 脚本中使用
242  if mcp-proxy health http://localhost:8080/mcp -q; then
243      echo \"MCP 服务正常\"
244  else
245      echo \"MCP 服务不可用\"
246  fi
247")]
248pub struct HealthArgs {
249    /// 要检查的 MCP 服务 URL
250    #[arg(value_name = "URL")]
251    pub url: String,
252
253    /// 认证 header (如: "Bearer token")
254    #[arg(short, long, help = "认证 header")]
255    pub auth: Option<String>,
256
257    /// 自定义 HTTP headers
258    #[arg(short = 'H', long, value_parser = parse_key_val, help = "自定义 HTTP headers (KEY=VALUE 格式)")]
259    pub header: Vec<(String, String)>,
260
261    /// 超时时间(秒)
262    #[arg(long, default_value = "10")]
263    pub timeout: u64,
264
265    /// 指定远程服务协议类型(不指定则自动检测)
266    #[arg(long, value_enum, help = "指定远程服务协议类型(不指定则自动检测)")]
267    pub protocol: Option<crate::client::proxy_server::ProxyProtocol>,
268}
269
270/// 解析 KEY=VALUE 格式的辅助函数
271pub fn parse_key_val(s: &str) -> Result<(String, String), String> {
272    let pos = s
273        .find('=')
274        .ok_or_else(|| format!("无效的 KEY=VALUE 格式: {}", s))?;
275    Ok((s[..pos].to_string(), s[pos + 1..].to_string()))
276}