From 9c3da20b3f6dadf60646d6fb16f5e357c234760d Mon Sep 17 00:00:00 2001 From: jif Date: Fri, 21 Aug 2026 13:15:46 +0000 Subject: [PATCH] Track remote MCP header environment variables (#39930) ## Why Remote HTTP MCP connections can source header values from the host environment, so those variables must remain part of the connection identity even when the MCP server runs in an executor environment. ## What changed - Track `env_http_headers` variables for remote HTTP MCP connections. - Continue tracking `bearer_token_env_var` only for local environments, where the host resolves the token. ## Testing Add coverage that verifies remote connections track host header variables without tracking executor bearer-token variables, while local connections track both. GitOrigin-RevId: 8fe175c54a101721a27b76495dcd298f0c2bc6a3 --- codex-rs/codex-mcp/src/server.rs | 8 ++++--- codex-rs/codex-mcp/src/server_tests.rs | 32 ++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 codex-rs/codex-mcp/src/server_tests.rs diff --git a/codex-rs/codex-mcp/src/server.rs b/codex-rs/codex-mcp/src/server.rs index f0e739a904..002e1d5e99 100644 --- a/codex-rs/codex-mcp/src/server.rs +++ b/codex-rs/codex-mcp/src/server.rs @@ -329,15 +329,13 @@ fn referenced_environment_variables(config: &McpServerConfig) -> Vec<(String, Op .filter(|env_var| !env_var.is_remote_source()) .map(|env_var| env_var.name().to_string()) .collect::>(), - McpServerTransportConfig::StreamableHttp { .. } if !config.is_local_environment() => { - Vec::new() - } McpServerTransportConfig::StreamableHttp { bearer_token_env_var, env_http_headers, .. } => bearer_token_env_var .iter() + .filter(|_| config.is_local_environment()) .chain(env_http_headers.iter().flat_map(|headers| headers.values())) .cloned() .collect(), @@ -421,3 +419,7 @@ impl From<&EffectiveMcpServer> for McpServerMetadata { } } } + +#[cfg(test)] +#[path = "server_tests.rs"] +mod tests; diff --git a/codex-rs/codex-mcp/src/server_tests.rs b/codex-rs/codex-mcp/src/server_tests.rs new file mode 100644 index 0000000000..87992a8800 --- /dev/null +++ b/codex-rs/codex-mcp/src/server_tests.rs @@ -0,0 +1,32 @@ +use super::referenced_environment_variables; +use codex_config::DEFAULT_MCP_SERVER_ENVIRONMENT_ID; +use codex_config::McpServerConfig; +use pretty_assertions::assert_eq; + +#[test] +fn remote_http_connections_track_host_headers_but_not_executor_bearer_tokens() { + let mut config: McpServerConfig = serde_json::from_value(serde_json::json!({ + "url": "https://example.com/mcp", + "environment_id": "executor-1", + "bearer_token_env_var": "NODE_REPL_AUTH_TOKEN", + "env_http_headers": {"X-Api-Key": "PATH"}, + })) + .expect("remote MCP configuration should deserialize"); + + assert_eq!( + referenced_environment_variables(&config), + vec![("PATH".to_string(), std::env::var_os("PATH"))], + ); + + config.environment_id = DEFAULT_MCP_SERVER_ENVIRONMENT_ID.to_string(); + assert_eq!( + referenced_environment_variables(&config), + vec![ + ( + "NODE_REPL_AUTH_TOKEN".to_string(), + std::env::var_os("NODE_REPL_AUTH_TOKEN"), + ), + ("PATH".to_string(), std::env::var_os("PATH")), + ], + ); +}