Plugin MCPs are disabled when plugin requirements contain no MCP allowlist
Summary
Plugin-provided MCP servers are all marked enabled = false when requirements.plugins is present but none of its entries declares mcp_servers.
A plugin requirement unrelated to MCP policy should not implicitly become an empty MCP allowlist. This can make plugin installation and codex mcp login succeed while new TUI, codex exec, and Desktop sessions receive none of the plugin MCP tools.
Root cause
In filter_plugin_mcp_servers_by_requirements() (codex-rs/core/src/config/mod.rs), the function returns early only when requirements.plugins is absent. When the plugins map exists but every PluginRequirementsToml::mcp_servers is None, allowed evaluates to false for every plugin MCP. Each server is disabled with McpServerDisabledReason::Requirements, so the connection manager never creates its client.
This is distinct from an explicit empty allowlist (mcp_servers = {}), which should continue to deny all plugin MCPs.
Minimal regression case
Construct requirements containing a plugin entry with mcp_servers: None, then pass an otherwise valid plugin MCP through filter_plugin_mcp_servers_by_requirements().
Expected: the MCP remains enabled because no MCP allowlist was declared.
Actual: the MCP is disabled with McpServerDisabledReason::Requirements.
Suggested fix
Skip MCP filtering unless at least one plugin requirement actually declares mcp_servers:
if !requirements
.value
.values()
.any(|plugin| plugin.mcp_servers.is_some())
{
return;
}
This preserves populated and explicitly empty allowlists while preventing unrelated plugin requirements from disabling every plugin MCP.
User-visible symptom
- Plugin inventory reports the plugin and MCP as installed/enabled.
codex mcp logincan complete successfully.- A fresh runtime does not connect to or expose the plugin MCP tools.
- Desktop may display
Auth unsupported, although the server was disabled by requirements before authentication.
Validation performed
Against Codex CLI 0.144.5 source:
- A focused regression test fails before the guard and passes after it.
- Existing explicit allowlist tests continue to pass.
codex-clibuilds successfully.- In an isolated smoke test, the unpatched binary materializes the plugin MCP as disabled; the patched binary enables it and completes
tools/list.
It would also help if the UI surfaced disabled_reason = Requirements instead of presenting this state as an authentication limitation.
Showing cached comments. Read the full discussion on GitHub ↗
1 Comment
Plugin MCPs are currently disabled when
requirements.pluginsexists but does not declare any MCP policy.Confirmed against current
mainat7844386e3d.The problem is in
filter_plugin_mcp_servers_by_requirements(): the presence of the plugins requirements map is treated as an MCP allowlist, even when everyPluginRequirementsToml::mcp_serversvalue isNone. That makes every plugin MCP fail theallowedcheck and assignsMcpServerDisabledReason::Requirements.I have a focused patch prepared:
mcp_servers.mcp_servers = {}distinct:Some(empty)still counts as a declared allowlist and continues to deny all plugin MCPs.mcp_servers: Noneleaves an otherwise enabled plugin MCP unchanged.Actual screenshots
Before — the focused test shows the server incorrectly changed to
falsewith aRequirementsreason instead of remainingtruewith no disabled reason:!Before: plugin MCP is incorrectly disabled
After — the same focused regression passes with the guard applied:
!After: plugin MCP remains enabled
Validation:
filter_plugin_mcp_servers*tests: 4 passed.just fix -p codex-core: passes.just fmt: passes.---
I have a PR ready if issue accepted