Hyphenated MCP server names cause working servers to render as 'Tools: (none)'
Summary
Codex can show Tools: (none) for a working MCP server if the configured MCP server name contains -.
This is not a transport failure and not a tools/list failure. The bug is in how Codex sanitizes fully-qualified MCP tool names and then later groups them back by server name for mcpServerStatus/list.
User-visible symptom
A configured server like:
autok-local
shows up in Codex as:
Status: enabledAuth: OAuthURL: http://localhost:8000/mcpTools: (none)
But the same server immediately works if the config key is renamed to:
autok_local
Root cause
In codex-rs/core/src/mcp_connection_manager.rs, qualify_tools() builds raw fully-qualified names like:
mcp__autok-local__browse_content
Then sanitize_responses_api_tool_name() replaces disallowed characters with _, producing:
mcp__autok_local__browse_content
Later, group_tools_by_server() in codex-rs/core/src/mcp/mod.rs splits the sanitized qualified key and reconstructs the server name as:
autok_local
Finally, mcpServerStatus/list in codex-rs/app-server/src/codex_message_processor.rs renders per-server status rows using the configured MCP server name from config, which is still:
autok-local
So the lookup misses and that server renders with no tools.
Why this is especially confusing
initializesucceedstools/listsucceeds- the MCP server can be fully functional
- official MCP SDK clients can list and call tools just fine
- only Codex's inventory/status rendering drops the tools
This makes it look like the MCP server is broken even though the issue is the Codex-side regrouping path.
Minimal repro
- Configure an MCP server in Codex using a hyphenated name, for example:
autok-local
- Ensure the server returns a non-empty
tools/list. - Open the MCP server status view in Codex.
- Observe
Tools: (none). - Rename only the config key to
autok_local. - Restart/reload Codex.
- Observe the tools now appear.
Expected behavior
Codex should preserve the original MCP server name for grouping/rendering and should not reconstruct the server name from a sanitized fully-qualified tool key.
Actual behavior
Codex groups sanitized tool keys under autok_local while rendering the configured server row autok-local, so the tool list disappears.
Suggested fix
Avoid deriving the server name for status grouping from the sanitized fully-qualified tool key.
Instead, preserve the original configured/server-reported server name separately through the snapshot/status path and group/render against that canonical name.
Additional note
This also explains why some built-in or external MCP servers appear unaffected:
- names like
figmaandlinearhave no-, so sanitization does not change the grouping key.
4 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
I took a local-first pass on current
main, and the hyphenated-name bug is reproducible in both status surfaces, not just one.Exact results:
cargo test -p codex-core group_tools_by_known_server_namespassedcargo test -p codex-app-server mcp_server_statuspassedINSTA_UPDATE=always cargo test -p codex-tui mcp_tools_output_passedWhat that narrowed:
qualify_tools()sanitizes a raw key likemcp__autok-local__browse_contentintomcp__autok_local__browse_contentmcpServerStatus/listthen regroups from the sanitized key, so the configured rowautok-localmisses its tools/mcphad the same failure shape through prefix matching on the unsanitized configured server nameThe narrow fix I could support was a shared regrouping helper that maps sanitized tool keys back to canonical configured server names when that mapping is unique. That fixed both the app-server status path and the TUI
/mcppath without widening the protocol shape.If two configured server names collapse to the same sanitized key, for example
autok-localandautok_local, the canonical identity is no longer perfectly recoverable from the flattened tool key alone. The local helper falls back in that case instead of guessing.Current
mainhas a real MCP hyphenated-name regrouping bug across both app-server and TUI, and a narrow shared-helper fix is enough for the common unique-name case.If that direction sounds right, I can turn the local patch into a small PR.
Opened draft PR #15797 for this fix: https://github.com/openai/codex/pull/15797
This appears to be a duplicate of #15832.
This PR addresses this issue. It will be included in the next release.