use anyhow::Result;
use std::collections::HashMap;
use crate::client::support::{ConvertArgs, protocol_name};
use crate::proxy::{McpClientConfig, ToolFilter};
use super::sse::run_sse_mode;
use super::stream::run_stream_mode;
pub async fn run_url_mode_with_retry(
args: &ConvertArgs,
url: &str,
merged_headers: HashMap<String, String>,
config_protocol: Option<crate::client::protocol::McpProtocol>,
tool_filter: ToolFilter,
verbose: bool,
quiet: bool,
) -> Result<()> {
tracing::info!("Starting protocol conversion");
tracing::info!("Target URL: {url}");
tracing::debug!("Header count: {}", merged_headers.len());
tracing::debug!(
"Ping interval: {}s, ping timeout: {}s",
args.ping_interval,
args.ping_timeout
);
tracing::debug!("Retry count: {} (0 = unlimited)", args.retries);
if !quiet && merged_headers.is_empty() {
eprintln!("🚀 MCP-Stdio-Proxy: {} → stdio", url);
}
if !quiet {
if let Some(ref allow_tools) = args.allow_tools {
tracing::info!("Tool allowlist: {:?}", allow_tools);
}
if let Some(ref deny_tools) = args.deny_tools {
tracing::info!("Tool denylist: {:?}", deny_tools);
}
}
let protocol = if let Some(ref proto) = args.protocol {
let detected = match proto {
crate::client::proxy_server::ProxyProtocol::Sse => {
crate::client::protocol::McpProtocol::Sse
}
crate::client::proxy_server::ProxyProtocol::Stream => {
crate::client::protocol::McpProtocol::Stream
}
};
tracing::info!(
"Using protocol from CLI argument: {}",
protocol_name(&detected)
);
if !quiet {
eprintln!("🔧 Using protocol from CLI: {}", protocol_name(&detected));
}
detected
} else if let Some(proto) = config_protocol {
tracing::info!("Using protocol from config: {}", protocol_name(&proto));
if !quiet {
eprintln!("🔧 Using protocol from config: {}", protocol_name(&proto));
}
proto
} else {
tracing::info!("Detecting protocol...");
if !quiet {
eprintln!("🔍 Detecting protocol...");
}
let detection_start = std::time::Instant::now();
let detected = crate::client::protocol::detect_mcp_protocol(url)
.await
.map_err(|e| {
tracing::error!("Protocol detection failed: {}", e);
e
})?;
let detection_duration = detection_start.elapsed();
tracing::info!(
"Protocol detection completed: protocol={}, duration={:?}",
protocol_name(&detected),
detection_duration
);
if !quiet {
eprintln!("🔍 Detected protocol: {}", protocol_name(&detected));
}
detected
};
tracing::debug!("Building MCP client config...");
let config = build_mcp_config(url, &merged_headers, args.auth.as_ref());
tracing::debug!("MCP client config ready");
tracing::info!("Using protocol: {}", protocol_name(&protocol));
match protocol {
crate::client::protocol::McpProtocol::Sse => {
run_sse_mode(config, args.clone(), tool_filter, verbose, quiet).await
}
crate::client::protocol::McpProtocol::Stream => {
run_stream_mode(config, args.clone(), tool_filter, verbose, quiet).await
}
crate::client::protocol::McpProtocol::Stdio => {
tracing::error!("Stdio protocol does not support URL conversion");
anyhow::bail!(
"Stdio protocol does not support URL conversion, please use --config for local commands"
)
}
}
}
pub fn build_mcp_config(
url: &str,
headers: &HashMap<String, String>,
auth: Option<&String>,
) -> McpClientConfig {
let mut config = McpClientConfig::new(url);
for (k, v) in headers {
config = config.with_header(k, v);
}
if let Some(auth_value) = auth {
config = config.with_header("Authorization", auth_value);
}
config
}