The following content is generated by ai agent :
Feature Request: Support SSL_CERT_FILE environment variable for custom CA certificates
Problem
mcp2cli uses hyper-rustls with webpki-roots which bundles the Mozilla CA set at compile time. This means the binary cannot trust any CA certificates outside that bundle at runtime.
In corporate environments that use MITM/TLS-inspection proxies (e.g. mitmproxy, ZScaler, Cloudflare WARP, Fortinet), all outbound HTTPS traffic gets re-signed with a corporate root CA. Since mcp2cli doesn't trust that CA, connections fail with:
Error: streamable HTTP request failed: client error (Connect)
This is a hard blocker for anyone behind such a proxy — the binary simply cannot connect to any MCP server over HTTPS.
Proposed Solution
Support the SSL_CERT_FILE environment variable — an industry-standard convention shared by curl, Python requests, Go net/http, Ruby OpenSSL, and many other tools. When set, mcp2cli should read additional CA certificates from the specified PEM file and add them to the root store alongside the bundled webpki roots.
Implementation
The change is minimal (~40 lines in src/mcp/client.rs + 3 lines in Cargo.toml):
- Add explicit
rustls, rustls-pemfile, and webpki-roots dependencies to Cargo.toml
- In the HTTPS connector construction, build a
RootCertStore manually:
- Start with
webpki_roots::TLS_SERVER_ROOTS (preserves current behavior)
- If
SSL_CERT_FILE is set, parse the PEM file and add any certificates found
- Log via
tracing::debug how many extra certs were loaded (or tracing::warn if the file can't be opened)
- Build
rustls::ClientConfig with this store and pass it to HttpsConnectorBuilder::with_tls_config()
Verification
Tested on a sandboxed environment with mitmproxy transparent proxy:
| Condition |
Result |
Without SSL_CERT_FILE |
Error: streamable HTTP request failed: client error (Connect) |
With SSL_CERT_FILE=/opt/opensandbox/mitmproxy-ca-cert.pem |
Connection succeeds, tool calls work normally |
Diff
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -54,6 +54,9 @@
hyper-rustls = { version = "0.27", default-features = false, features = ["http1", "ring", "webpki-tokio", "tls12"] }
+rustls = { version = "0.23", default-features = false, features = ["ring", "std"] }
+rustls-pemfile = "2"
+webpki-roots = "1.0"
--- a/src/mcp/client.rs
+++ b/src/mcp/client.rs
@@ -56,6 +56,7 @@
+use rustls_pemfile;
@@ connector construction @@
- let connector = hyper_rustls::HttpsConnectorBuilder::new()
- .with_webpki_roots()
+ let mut root_store = rustls::RootCertStore::empty();
+ root_store.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned());
+
+ if let Ok(cert_file) = std::env::var("SSL_CERT_FILE") {
+ match std::fs::File::open(&cert_file) {
+ Ok(file) => {
+ let mut reader = std::io::BufReader::new(file);
+ let certs = rustls_pemfile::certs(&mut reader);
+ let mut added = 0u32;
+ for cert in certs.flatten() {
+ if root_store.add(cert).is_ok() {
+ added += 1;
+ }
+ }
+ tracing::debug!("loaded {} extra CA cert(s) from SSL_CERT_FILE={}", added, cert_file);
+ }
+ Err(e) => {
+ tracing::warn!("SSL_CERT_FILE={} set but could not open: {}", cert_file, e);
+ }
+ }
+ }
+
+ let tls_config = rustls::ClientConfig::builder()
+ .with_root_certificates(root_store)
+ .with_no_client_auth();
+ let connector = hyper_rustls::HttpsConnectorBuilder::new()
+ .with_tls_config(tls_config)
.https_or_http()
.enable_http1()
.build();
Notes
- No behavior change when
SSL_CERT_FILE is unset — the bundled webpki roots are used exactly as before.
- The env var name aligns with existing ecosystem conventions, minimizing user friction.
- A future enhancement could also support
SSL_CERT_DIR for directory-based trust stores.
The following content is generated by ai agent :
Feature Request: Support
SSL_CERT_FILEenvironment variable for custom CA certificatesProblem
mcp2cli uses
hyper-rustlswithwebpki-rootswhich bundles the Mozilla CA set at compile time. This means the binary cannot trust any CA certificates outside that bundle at runtime.In corporate environments that use MITM/TLS-inspection proxies (e.g. mitmproxy, ZScaler, Cloudflare WARP, Fortinet), all outbound HTTPS traffic gets re-signed with a corporate root CA. Since mcp2cli doesn't trust that CA, connections fail with:
This is a hard blocker for anyone behind such a proxy — the binary simply cannot connect to any MCP server over HTTPS.
Proposed Solution
Support the
SSL_CERT_FILEenvironment variable — an industry-standard convention shared by curl, Pythonrequests, Gonet/http, Ruby OpenSSL, and many other tools. When set, mcp2cli should read additional CA certificates from the specified PEM file and add them to the root store alongside the bundled webpki roots.Implementation
The change is minimal (~40 lines in
src/mcp/client.rs+ 3 lines inCargo.toml):rustls,rustls-pemfile, andwebpki-rootsdependencies toCargo.tomlRootCertStoremanually:webpki_roots::TLS_SERVER_ROOTS(preserves current behavior)SSL_CERT_FILEis set, parse the PEM file and add any certificates foundtracing::debughow many extra certs were loaded (ortracing::warnif the file can't be opened)rustls::ClientConfigwith this store and pass it toHttpsConnectorBuilder::with_tls_config()Verification
Tested on a sandboxed environment with mitmproxy transparent proxy:
SSL_CERT_FILEError: streamable HTTP request failed: client error (Connect)SSL_CERT_FILE=/opt/opensandbox/mitmproxy-ca-cert.pemDiff
Notes
SSL_CERT_FILEis unset — the bundled webpki roots are used exactly as before.SSL_CERT_DIRfor directory-based trust stores.