[Windows] plugin-scoped Context7 MCP disable override is silently ignored
Environment
- Codex Desktop:
26.810.6296.0 - Codex CLI:
0.147.0 - Plugin:
context7@context7-marketplaceversion1.0.1 - Platform: Windows x64
Summary
A one-run plugin-scoped config override is accepted without an error but does not disable the plugin's MCP server.
The installed plugin inventory reports Context7 as installed and enabled. The baseline MCP inventory contains one enabled context7 streamable-HTTP server.
Reproduction
Run the read-only inventory with this one-run override:
codex mcp list --json --config 'plugins."context7@context7-marketplace".mcp_servers.context7.enabled=false'
Actual result:
{
"name": "context7",
"enabled": true,
"disabled_reason": null
}
The command exits normally and does not report that the key was unsupported or ignored.
As a control, the equivalent top-level override is honored:
codex mcp list --json --config 'mcp_servers.context7.enabled=false'
With that control, the Context7 MCP entry is absent from the resulting inventory. This confirms that --config forwarding is functioning and isolates the mismatch to the plugin-scoped path.
Expected behavior
One of the following should happen deterministically:
- the plugin-scoped MCP override disables only that plugin MCP server for the invocation; or
- Codex rejects the unsupported key with an actionable validation error.
Actual impact
The supported-looking override silently has no effect. Users cannot rely on it to keep a plugin installed while disabling only its MCP surface for one bounded invocation.
This report does not claim a provider or authentication failure. No Context7 tool or external data request was made; only local plugin/MCP inventory commands were used.
Suggested correction
- Apply plugin-scoped
mcp_servers.<name>.enabledoverrides during effective MCP inventory construction; or - reject unknown/unsupported nested plugin keys instead of silently accepting them;
- add a regression test comparing plugin-scoped and top-level one-run overrides.
No account identifiers, credentials, private data, local paths, or raw unrelated logs are included.
2 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Root-caused on
main@ 1f41cc5d92 — the plugin-scoped policy machinery works; what's broken is the-c/--configkey-path parser, which is not TOML-quote-aware, so the quoted plugin key never matches the installed plugin.The mechanism. CLI overrides are applied by
apply_toml_override, which splits the dotted path naively:https://github.com/openai/codex/blob/1f41cc5d92722748e45cae9cecc6d883a4e7cbb1/codex-rs/config/src/overrides.rs#L18-L27
path.split('.')has no notion of TOML quoting, soproduces the table key
"context7@context7-marketplace"— with the literal quote characters in the string. The policy lookup, however, keys plugins by the unquoted id (load_configured_plugin_mcp_servers→configured_plugins.get("context7@context7-marketplace"),core-plugins/src/loader.rs#L1383-L1398) → miss → the override contributes nothing. And becausepluginsis aHashMap<String, PluginConfig>(config/src/types.rs#L451area), the quoted-key entry deserializes as a perfectly valid map entry — no unknown-field error, even under--strict-config. That's the exact "accepted without error, silently no effect" you observed. Your control case works becausemcp_servers.context7.enabledcontains no quoted segment.Confirmation + immediate workaround. Since the naive split only breaks on quoted segments, and your plugin id contains no dot, dropping the quotes should make the override work today:
If that returns
enabled: false, the diagnosis is confirmed end-to-end. (Caveat: this only works for plugin ids without literal dots — it's a workaround, not the fix.)The fix already exists in-tree, one crate over. The app-server's
config/batchWritepath has a proper quote- and escape-aware key-path parser —parse_key_pathincodex-rs/app-server/src/config_manager_service.rs#L519-L560handles quoted segments and\"/\.escapes precisely so keys like plugin ids can be addressed. Hoisting that parser into a shared util and using it inapply_toml_override(instead ofsplit('.')) fixes-cfor every quoted key path, not just plugins — the same silent mis-key currently affects any-coverride touching quoted table keys (mcp_servers."name.with.dot",projects."/path", etc.).Suggested regression tests: (1)
apply_toml_overridewith a quoted segment produces the unquoted key; (2) end-to-end:codex mcp list --json -c 'plugins."x@y".mcp_servers.s.enabled=false'reports the server disabled; (3) apluginsoverride key containing literal"after parsing is rejected or warned on, as defense against reintroduction.