Codex CLI does not send a User-Agent header on MCP Streamable HTTP requests
What variant of Codex are you using?
CLI
What feature would you like to see?
Codex CLI's MCP client (via RMCP) does not send a User-Agent header on HTTP requests to MCP servers over the Streamable HTTP transport. Most other MCP clients include one, for example, Claude Code sends user-agent: claude-code/2.1.89 (cli).
This matters for MCP server maintainers who rely on standard HTTP headers for analytics, debugging, and client identification. Currently, the only way to identify Codex as the connecting client is through the clientInfo field in the MCP initialize handshake. But for servers running in stateless HTTP mode (where each request creates a new session), clientInfo from the initialization is lost on subsequent requests. The User-Agent header is the standard, transport-level mechanism for client identification that persists across all HTTP requests regardless of session semantics.
Without a User-Agent, Codex's requests are indistinguishable from raw HTTP traffic in server logs, load balancer metrics, and analytics pipelines. This is a gap relative to other MCP clients that do advertise themselves.
The fix is small. Codex already constructs its own reqwest::Client in codex-rs/rmcp-client/src/rmcp_client.rs via build_http_client(). Adding a .user_agent(...) call to the builder using the same name already passed in client_info during MCP initialization ("codex-mcp-client") would produce a header like User-Agent: codex-mcp-client/0.1.0 on every HTTP request. The value would stay in sync with the existing InitializeRequestParams.client_info.name in codex-rs/core/src/mcp_connection_manager.rs if they share a constant.
I have a working implementation on a fork (MCPCat/codex) and would be happy to open a PR if the team is interested. The change touches three files and is roughly a dozen lines total.
Additional information
I'm the founder of MCPCat, an analytics platform for MCP server maintainers. We instrument MCP servers to help developers understand how their tools are being used, by whom, and what value they're providing. We had customer concerns around this because Codex was the only major MCP client that failed to advertise itself properly on stateless HTTP MCP servers, making it invisible in their analytics dashboards. Accurate client identification across all HTTP requests is important for our product and our customers, which is how we discovered this gap.
Our fork with the implementation: https://github.com/MCPCat/codex/tree/feat/mcp-user-agent-header
The change is:
- Define a shared
MCP_CLIENT_NAMEconstant incodex-rmcp-client - Call
.user_agent(format!("{}/{}", MCP_CLIENT_NAME, env!("CARGO_PKG_VERSION")))on the reqwest client builder, placed before user-configured default headers so they can still override - Replace the hardcoded
"codex-mcp-client"string inmcp_connection_manager.rswith the shared constant
Worth noting that this is not an RMCP (upstream) issue — RMCP intentionally leaves User-Agent to the consumer to set, and reqwest doesn't set one by default. So this is squarely a Codex-level concern.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗