use std::collections::HashMap;
use anyhow::Result;
use http::{HeaderName, HeaderValue};
use reqwest::Client as HttpClient;
use rmcp::transport::auth::AuthClient;
use rmcp::transport::streamable_http_client::{
StreamableHttpClientTransport, StreamableHttpClientTransportConfig,
};
use crate::auth::AuthOutcome;
pub enum RemoteTransport {
Anonymous(StreamableHttpClientTransport<HttpClient>),
Authorized(StreamableHttpClientTransport<AuthClient<HttpClient>>),
}
pub fn build(
server_url: &str,
headers: HashMap<HeaderName, HeaderValue>,
auth: AuthOutcome,
) -> Result<RemoteTransport> {
let config = StreamableHttpClientTransportConfig::with_uri(server_url.to_string())
.custom_headers(headers);
Ok(match auth {
AuthOutcome::Anonymous { http_client } => RemoteTransport::Anonymous(
StreamableHttpClientTransport::with_client(http_client, config),
),
AuthOutcome::Authorized { client } => {
RemoteTransport::Authorized(StreamableHttpClientTransport::with_client(client, config))
}
})
}
#[cfg(test)]
mod tests {
use super::*;
use http::{HeaderName, HeaderValue};
fn anon_outcome() -> AuthOutcome {
AuthOutcome::Anonymous {
http_client: reqwest::Client::new(),
}
}
#[tokio::test]
async fn build_returns_anonymous_variant_for_anonymous_outcome() {
let mut headers = HashMap::new();
headers.insert(
HeaderName::from_static("x-trace"),
HeaderValue::from_static("abc"),
);
let t = build("https://example.com/mcp", headers, anon_outcome()).expect("build");
assert!(
matches!(t, RemoteTransport::Anonymous(_)),
"anonymous outcome should produce anonymous transport"
);
}
#[tokio::test]
async fn build_accepts_empty_headers() {
let t = build("https://example.com/mcp", HashMap::new(), anon_outcome())
.expect("build with empty headers");
assert!(matches!(t, RemoteTransport::Anonymous(_)));
}
#[tokio::test]
async fn build_accepts_multiple_headers() {
let mut headers = HashMap::new();
headers.insert(
HeaderName::from_static("x-a"),
HeaderValue::from_static("1"),
);
headers.insert(
HeaderName::from_static("x-b"),
HeaderValue::from_static("2"),
);
let t = build("http://127.0.0.1:8080/mcp", headers, anon_outcome()).expect("build");
assert!(matches!(t, RemoteTransport::Anonymous(_)));
}
}