Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions codex-rs/codex-mcp/src/mcp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use codex_config::types::AuthKeyringBackendKind;
use codex_config::types::OAuthCredentialsStoreMode;
use codex_connectors::ConnectorSnapshot;
use codex_login::CodexAuth;
use codex_login::default_client::originator;
use codex_model_provider::CHATGPT_CODEX_BASE_URL;
use codex_protocol::mcp::McpServerInfo;
use codex_protocol::mcp::Resource;
Expand Down Expand Up @@ -521,15 +522,16 @@ 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 mut http_headers = HashMap::from([("originator".to_string(), originator().value)]);
if let Some(product_sku) = apps_mcp_product_sku {
http_headers.insert("X-OpenAI-Product-Sku".to_string(), product_sku.to_string());
}

McpServerConfig {
transport: McpServerTransportConfig::StreamableHttp {
url,
bearer_token_env_var: codex_apps_mcp_bearer_token_env_var(),
http_headers,
http_headers: Some(http_headers),
env_http_headers: None,
},
auth: auth_mode,
Expand Down
34 changes: 30 additions & 4 deletions codex-rs/codex-mcp/src/mcp/mod_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,10 @@ 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_forwards_originator_header() {
let expected_originator = codex_login::default_client::originator().value;
let config =
codex_apps_mcp_server_config("https://chatgpt.com", /*apps_mcp_product_sku*/ None);

match &config.transport {
McpServerTransportConfig::StreamableHttp {
Expand All @@ -275,8 +277,8 @@ fn codex_apps_server_config_forwards_configured_product_sku_header() {
assert_eq!(
http_headers,
&Some(HashMap::from([(
"X-OpenAI-Product-Sku".to_string(),
"tpp".to_string(),
"originator".to_string(),
expected_originator,
)]))
);
assert!(env_http_headers.is_none());
Expand All @@ -285,6 +287,30 @@ fn codex_apps_server_config_forwards_configured_product_sku_header() {
}
}

#[test]
fn codex_apps_server_config_forwards_originator_and_configured_product_sku_headers() {
let expected_originator = codex_login::default_client::originator().value;
let config = codex_apps_mcp_server_config("https://chatgpt.com", Some("tpp"));

match &config.transport {
McpServerTransportConfig::StreamableHttp {
http_headers,
env_http_headers,
..
} => {
assert_eq!(
http_headers,
&Some(HashMap::from([
("originator".to_string(), expected_originator),
("X-OpenAI-Product-Sku".to_string(), "tpp".to_string()),
]))
);
assert!(env_http_headers.is_none());
}
other => panic!("expected streamable http transport, got {other:?}"),
}
}

#[tokio::test]
async fn effective_mcp_servers_preserve_runtime_servers() {
let codex_home = tempfile::tempdir().expect("tempdir");
Expand Down
Loading