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:
shows up in Codex as:
Status: enabled
Auth: OAuth
URL: http://localhost:8000/mcp
Tools: (none)
But the same server immediately works if the config key is renamed to:
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:
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:
So the lookup misses and that server renders with no tools.
Why this is especially confusing
initialize succeeds
tools/list succeeds
- 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:
- 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
figma and linear have no -, so sanitization does not change the grouping key.
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/listfailure. The bug is in how Codex sanitizes fully-qualified MCP tool names and then later groups them back by server name formcpServerStatus/list.User-visible symptom
A configured server like:
autok-localshows 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_localRoot cause
In
codex-rs/core/src/mcp_connection_manager.rs,qualify_tools()builds raw fully-qualified names like:mcp__autok-local__browse_contentThen
sanitize_responses_api_tool_name()replaces disallowed characters with_, producing:mcp__autok_local__browse_contentLater,
group_tools_by_server()incodex-rs/core/src/mcp/mod.rssplits the sanitized qualified key and reconstructs the server name as:autok_localFinally,
mcpServerStatus/listincodex-rs/app-server/src/codex_message_processor.rsrenders per-server status rows using the configured MCP server name from config, which is still:autok-localSo the lookup misses and that server renders with no tools.
Why this is especially confusing
initializesucceedstools/listsucceedsThis makes it look like the MCP server is broken even though the issue is the Codex-side regrouping path.
Minimal repro
autok-localtools/list.Tools: (none).autok_local.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_localwhile rendering the configured server rowautok-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:
figmaandlinearhave no-, so sanitization does not change the grouping key.