mcp_stdio_proxy/client/support/
args.rs1use clap::Parser;
6use std::path::PathBuf;
7
8#[derive(Parser, Debug, Clone)]
12pub struct LoggingArgs {
13 #[arg(
15 long,
16 default_value = "false",
17 help = "启用详细诊断模式,追踪连接生命周期和超时问题(默认关闭)"
18 )]
19 pub diagnostic: bool,
20
21 #[arg(long, help = "日志输出目录,将自动生成日志文件名")]
23 pub log_dir: Option<PathBuf>,
24
25 #[arg(long, conflicts_with = "log_dir", help = "日志文件完整路径")]
27 pub log_file: Option<PathBuf>,
28
29 #[arg(
34 long,
35 env = "OTEL_EXPORTER_OTLP_ENDPOINT",
36 help = "OTLP 追踪端点 (如 http://localhost:4317)"
37 )]
38 pub otlp_endpoint: Option<String>,
39
40 #[arg(
42 long,
43 default_value = "mcp-proxy",
44 help = "追踪服务名称(用于 Jaeger 等追踪后端标识)"
45 )]
46 pub service_name: String,
47}
48
49#[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 #[arg(value_name = "URL", help = "MCP 服务的 URL 地址(直接模式)")]
60 pub url: Option<String>,
61
62 #[arg(short, long, global = true)]
64 pub verbose: bool,
65
66 #[arg(short, long, global = true)]
68 pub quiet: bool,
69}
70
71#[derive(clap::Subcommand, Debug)]
72pub enum Commands {
73 Convert(ConvertArgs),
75
76 Check(CheckArgs),
78
79 Detect(DetectArgs),
81
82 Proxy(crate::client::proxy_server::ProxyArgs),
84
85 Health(HealthArgs),
87}
88
89#[derive(Parser, Debug, Clone)]
91pub struct ConvertArgs {
92 #[arg(value_name = "URL", help = "MCP 服务的 URL 地址")]
94 pub url: Option<String>,
95
96 #[arg(long, conflicts_with = "config_file", help = "MCP 服务配置 JSON")]
98 pub config: Option<String>,
99
100 #[arg(long, conflicts_with = "config", help = "MCP 服务配置文件路径")]
102 pub config_file: Option<PathBuf>,
103
104 #[arg(short, long, help = "MCP 服务名称(多服务配置时必需)")]
106 pub name: Option<String>,
107
108 #[arg(long, value_enum, help = "指定远程服务协议类型(不指定则自动检测)")]
110 pub protocol: Option<crate::client::proxy_server::ProxyProtocol>,
111
112 #[arg(short, long, help = "认证 header")]
114 pub auth: Option<String>,
115
116 #[arg(short = 'H', long, value_parser = parse_key_val, help = "自定义 HTTP headers (KEY=VALUE 格式)")]
118 pub header: Vec<(String, String)>,
119
120 #[arg(long, default_value = "0", help = "重试次数,0 表示无限重试")]
122 pub retries: u32,
123
124 #[arg(
126 long,
127 value_delimiter = ',',
128 help = "工具白名单(逗号分隔),只允许指定的工具"
129 )]
130 pub allow_tools: Option<Vec<String>>,
131
132 #[arg(
134 long,
135 value_delimiter = ',',
136 help = "工具黑名单(逗号分隔),排除指定的工具"
137 )]
138 pub deny_tools: Option<Vec<String>>,
139
140 #[arg(
142 long,
143 default_value = "30",
144 help = "客户端 ping 间隔(秒),0 表示禁用"
145 )]
146 pub ping_interval: u64,
147
148 #[arg(
150 long,
151 default_value = "10",
152 help = "客户端 ping 超时(秒),超时则认为连接断开"
153 )]
154 pub ping_timeout: u64,
155
156 #[arg(long)]
158 pub import_initialize: Option<String>,
159
160 #[arg(long)]
162 pub import_initialize_file: Option<PathBuf>,
163
164 #[arg(long)]
166 pub import_tools: Option<String>,
167
168 #[arg(long)]
170 pub import_tools_file: Option<PathBuf>,
171
172 #[arg(long)]
174 pub export_initialize: Option<PathBuf>,
175
176 #[arg(long)]
178 pub export_tools: Option<PathBuf>,
179
180 #[command(flatten)]
182 pub logging: LoggingArgs,
183}
184
185#[derive(Parser, Debug)]
187pub struct CheckArgs {
188 #[arg(value_name = "URL")]
190 pub url: String,
191
192 #[arg(short, long)]
194 pub auth: Option<String>,
195
196 #[arg(short = 'H', long, value_parser = parse_key_val, help = "自定义 HTTP headers (KEY=VALUE 格式)")]
198 pub header: Vec<(String, String)>,
199
200 #[arg(long, default_value = "10")]
202 pub timeout: u64,
203}
204
205#[derive(Parser, Debug)]
207pub struct DetectArgs {
208 #[arg(value_name = "URL")]
210 pub url: String,
211
212 #[arg(short, long)]
214 pub auth: Option<String>,
215
216 #[arg(short = 'H', long, value_parser = parse_key_val, help = "自定义 HTTP headers (KEY=VALUE 格式)")]
218 pub header: Vec<(String, String)>,
219}
220
221#[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 #[arg(value_name = "URL")]
251 pub url: String,
252
253 #[arg(short, long, help = "认证 header")]
255 pub auth: Option<String>,
256
257 #[arg(short = 'H', long, value_parser = parse_key_val, help = "自定义 HTTP headers (KEY=VALUE 格式)")]
259 pub header: Vec<(String, String)>,
260
261 #[arg(long, default_value = "10")]
263 pub timeout: u64,
264
265 #[arg(long, value_enum, help = "指定远程服务协议类型(不指定则自动检测)")]
267 pub protocol: Option<crate::client::proxy_server::ProxyProtocol>,
268}
269
270pub 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}