From 23a09eb3c3d00ab2a2b96b69aa81454a0a88cca1 Mon Sep 17 00:00:00 2001 From: Alec Barber Date: Thu, 9 Jul 2026 16:04:02 +0100 Subject: [PATCH] fix(mcp): default Apps product SKU to codex (#31803) ## Motivation Host-owned Apps MCP requests currently omit `X-OpenAI-Product-Sku` unless `apps_mcp_product_sku` is explicitly configured. Codex requests should identify themselves with the `codex` product SKU by default. ## Changes - Default `X-OpenAI-Product-Sku` to `codex`. - Preserve explicitly configured SKU values. - Add coverage for both default and configured behavior. ## Impact Codex Apps MCP requests now include the expected product identity without requiring local configuration. Existing explicit SKU overrides are unchanged. ## Testing - `just test -p codex-mcp codex_apps_server_config_sets_product_sku_header` - `just fix -p codex-mcp` - `just fmt` --- codex-rs/codex-mcp/src/mcp/mod.rs | 9 ++++--- codex-rs/codex-mcp/src/mcp/mod_tests.rs | 34 +++++++++++++------------ 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/codex-rs/codex-mcp/src/mcp/mod.rs b/codex-rs/codex-mcp/src/mcp/mod.rs index 847dbe2866..6e827a404e 100644 --- a/codex-rs/codex-mcp/src/mcp/mod.rs +++ b/codex-rs/codex-mcp/src/mcp/mod.rs @@ -51,6 +51,7 @@ use crate::runtime::McpRuntimeContext; use crate::server::EffectiveMcpServer; pub const CODEX_APPS_MCP_SERVER_NAME: &str = "codex_apps"; +const DEFAULT_CODEX_APPS_MCP_PRODUCT_SKU: &str = "codex"; const MCP_TOOL_NAME_PREFIX: &str = "mcp"; const MCP_TOOL_NAME_DELIMITER: &str = "__"; const CODEX_CONNECTORS_TOKEN_ENV_VAR: &str = "CODEX_CONNECTORS_TOKEN"; @@ -523,9 +524,11 @@ fn mcp_server_config_for_url( apps_mcp_product_sku: Option<&str>, auth_mode: McpServerAuth, ) -> McpServerConfig { - let http_headers = apps_mcp_product_sku.map(|product_sku| { - HashMap::from([("X-OpenAI-Product-Sku".to_string(), product_sku.to_string())]) - }); + let product_sku = apps_mcp_product_sku.unwrap_or(DEFAULT_CODEX_APPS_MCP_PRODUCT_SKU); + let http_headers = Some(HashMap::from([( + "X-OpenAI-Product-Sku".to_string(), + product_sku.to_string(), + )])); McpServerConfig { transport: McpServerTransportConfig::StreamableHttp { diff --git a/codex-rs/codex-mcp/src/mcp/mod_tests.rs b/codex-rs/codex-mcp/src/mcp/mod_tests.rs index 7d166cbab8..5e884380d7 100644 --- a/codex-rs/codex-mcp/src/mcp/mod_tests.rs +++ b/codex-rs/codex-mcp/src/mcp/mod_tests.rs @@ -263,25 +263,27 @@ fn codex_apps_server_config_uses_legacy_codex_apps_path() { } #[test] -fn codex_apps_server_config_forwards_configured_product_sku_header() { - let config = codex_apps_mcp_server_config("https://chatgpt.com", Some("tpp")); +fn codex_apps_server_config_sets_product_sku_header() { + for (configured_product_sku, expected_product_sku) in [(None, "codex"), (Some("tpp"), "tpp")] { + let config = codex_apps_mcp_server_config("https://chatgpt.com", configured_product_sku); - match &config.transport { - McpServerTransportConfig::StreamableHttp { - http_headers, - env_http_headers, - .. - } => { - assert_eq!( + match &config.transport { + McpServerTransportConfig::StreamableHttp { http_headers, - &Some(HashMap::from([( - "X-OpenAI-Product-Sku".to_string(), - "tpp".to_string(), - )])) - ); - assert!(env_http_headers.is_none()); + env_http_headers, + .. + } => { + assert_eq!( + http_headers, + &Some(HashMap::from([( + "X-OpenAI-Product-Sku".to_string(), + expected_product_sku.to_string(), + )])) + ); + assert!(env_http_headers.is_none()); + } + other => panic!("expected streamable http transport, got {other:?}"), } - other => panic!("expected streamable http transport, got {other:?}"), } }