use crate::model::{McpJsonServerParameters, McpProtocol, McpServerConfig};
const HOWTOCOOK_MCP_JSON: &str = r#"{
"mcpServers": {
"howtocook-跳跳糖": {
"type": "sse",
"url": "https://testagent.xspaceagi.com/api/mcp/sse?ak=ak-27b83516dfd4417a82f764fe3e859a6e"
}
}
}"#;
fn build_zimage_mcp_json(api_key: &str) -> String {
format!(
r#"{{
"mcpServers": {{
"zimage": {{
"type": "streamableHttp",
"description": "Z-Image-Turbo 图像生成模型",
"isActive": true,
"name": "阿里云百炼_Z Image 图像生成",
"baseUrl": "https://dashscope.aliyuncs.com/api/v1/mcps/zimage/mcp",
"headers": {{
"Authorization": "Bearer {}"
}}
}}
}}
}}"#,
api_key
)
}
const ZIMAGE_TEST_PLACEHOLDER_KEY: &str = "test-placeholder-key";
#[test]
fn test_zimage_config_type_parsed_as_stream() {
let zimage_json = build_zimage_mcp_json(ZIMAGE_TEST_PLACEHOLDER_KEY);
let params = McpJsonServerParameters::from(zimage_json);
let config = params.try_get_first_mcp_server().unwrap();
match config {
McpServerConfig::Url(url_config) => {
assert_eq!(url_config.r#type, Some("streamableHttp".to_string()));
let protocol_type = url_config.get_protocol_type();
assert!(
protocol_type.is_some(),
"streamableHttp should be recognized"
);
assert!(protocol_type.as_ref().unwrap().is_streamable());
assert_eq!(
protocol_type.unwrap().to_mcp_protocol(),
McpProtocol::Stream
);
assert_eq!(
"streamableHttp".parse::<McpProtocol>(),
Ok(McpProtocol::Stream)
);
assert_eq!(
url_config.get_url(),
"https://dashscope.aliyuncs.com/api/v1/mcps/zimage/mcp"
);
let headers = url_config.headers.as_ref().unwrap();
assert!(headers.contains_key("Authorization"));
assert_eq!(
headers["Authorization"],
format!("Bearer {}", ZIMAGE_TEST_PLACEHOLDER_KEY)
);
}
McpServerConfig::Command(_) => panic!("Expected URL config"),
}
}
#[tokio::test]
#[ignore] async fn test_zimage_protocol_detection() {
let api_key = std::env::var("DASHSCOPE_API_KEY")
.expect("需要设置 DASHSCOPE_API_KEY 环境变量才能运行此测试");
let zimage_json = build_zimage_mcp_json(&api_key);
let params = McpJsonServerParameters::from(zimage_json);
let config = params.try_get_first_mcp_server().unwrap();
let (url, headers) = match config {
McpServerConfig::Url(url_config) => {
let url = url_config.get_url().to_string();
let headers = url_config.headers.clone().unwrap_or_default();
(url, headers)
}
_ => panic!("Expected URL config"),
};
println!("=== Protocol detection test: {} ===", url);
println!("\\n--- SSE Probing ---");
let is_sse = mcp_sse_proxy::is_sse_with_headers(&url, Some(&headers)).await;
println!("is_sse_with_headers = {}", is_sse);
assert!(!is_sse, "Streamable HTTP 服务不应被识别为 SSE");
println!("\\n--- Streamable HTTP probe ---");
let is_stream =
mcp_streamable_proxy::is_streamable_http_with_headers(&url, Some(&headers)).await;
println!("is_streamable_http_with_headers = {}", is_stream);
assert!(
is_stream,
"zimage 服务应被识别为 Streamable HTTP(需要传递 Authorization header)"
);
println!("\\n--- Comprehensive protocol detection ---");
let detected = crate::server::detect_mcp_protocol_with_headers(&url, Some(&headers))
.await
.unwrap();
println!("detect_mcp_protocol_with_headers = {:?}", detected);
assert_eq!(detected, McpProtocol::Stream, "综合探测应返回 Stream 协议");
println!("\\n=== All detection results are correct ===");
}
#[test]
fn test_howtocook_config_type_parsed_as_sse() {
let params = McpJsonServerParameters::from(HOWTOCOOK_MCP_JSON.to_string());
let config = params.try_get_first_mcp_server().unwrap();
match config {
McpServerConfig::Url(url_config) => {
assert_eq!(url_config.r#type, Some("sse".to_string()));
let protocol_type = url_config.get_protocol_type();
assert!(protocol_type.is_some(), "sse should be recognized");
assert!(!protocol_type.as_ref().unwrap().is_streamable());
assert_eq!(protocol_type.unwrap().to_mcp_protocol(), McpProtocol::Sse);
assert_eq!("sse".parse::<McpProtocol>(), Ok(McpProtocol::Sse));
assert_eq!("SSE".parse::<McpProtocol>(), Ok(McpProtocol::Sse));
assert_eq!(
url_config.get_url(),
"https://testagent.xspaceagi.com/api/mcp/sse?ak=ak-27b83516dfd4417a82f764fe3e859a6e"
);
assert!(url_config.headers.is_none());
}
McpServerConfig::Command(_) => panic!("Expected URL config"),
}
}
#[tokio::test]
#[ignore] async fn test_howtocook_sse_protocol_detection() {
let params = McpJsonServerParameters::from(HOWTOCOOK_MCP_JSON.to_string());
let config = params.try_get_first_mcp_server().unwrap();
let url = match config {
McpServerConfig::Url(url_config) => url_config.get_url().to_string(),
_ => panic!("Expected URL config"),
};
println!("=== SSE protocol detection test: {} ===", url);
println!("\\n--- SSE Probing ---");
let is_sse = mcp_sse_proxy::is_sse(&url).await;
println!("is_sse = {}", is_sse);
assert!(
is_sse,
"howtocook SSE 服务应被识别为 SSE(发现 event: endpoint)"
);
println!("\\n--- Streamable HTTP probe ---");
let is_stream = mcp_streamable_proxy::is_streamable_http(&url).await;
println!("is_streamable_http = {}", is_stream);
assert!(!is_stream, "SSE 服务不应被识别为 Streamable HTTP");
println!("\\n--- Comprehensive protocol detection ---");
let detected = crate::server::detect_mcp_protocol(&url).await.unwrap();
println!("detect_mcp_protocol = {:?}", detected);
assert_eq!(detected, McpProtocol::Sse, "综合探测应返回 Sse 协议");
println!("\\n=== SSE detection result is correct ===");
}
#[tokio::test]
#[ignore] async fn test_zimage_detection_without_headers() {
let url = "https://dashscope.aliyuncs.com/api/v1/mcps/zimage/mcp";
println!("=== No header detection test: {} ===", url);
let is_sse = mcp_sse_proxy::is_sse(url).await;
println!("is_sse = {}", is_sse);
assert!(!is_sse);
let detected = crate::server::detect_mcp_protocol(url).await.unwrap();
println!("detect_mcp_protocol = {:?}", detected);
assert_eq!(detected, McpProtocol::Stream, "无 header 时应兜底为 Stream");
println!("=== No header, the detection result is correct ===");
}