Conversation
When a session request carries _meta.codex.strictMcpConfig = true, the session's MCP servers are exactly the client's: every server in the effective Codex configuration for cwd is disabled by name, and the apps, plugins and skill_mcp_dependency_install features are turned off. A client server whose name matches a configured one is rejected with invalid_params. Applies to session/new, load, resume and fork. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
A client sometimes needs a session to have exactly the MCP servers it passed. One case is a client that routes every tool approval through its own UI and audit log, and must not let a session reach tools it never granted. Today a session gets the MCP servers in the user's Codex configuration plus the client's
mcpServers, and Codex can add more through plugins and the ChatGPT apps connector. The client can't opt out:mcp_serverstable removes nothing.DISABLE_MCP_CONFIG_FILTERINGonly changes how name conflicts are handled, and it is process-wide.claude-agent-acp offers the same guarantee as
_meta.claudeCode.options.strictMcpConfig, which maps to Claude Code's--strict-mcp-config. This adds the Codex equivalent under the same key name.What
When
session/new,session/load,session/resumeorsession/forkcarries_meta: {"codex": {"strictMcpConfig": true}},createSessionConfigbuilds the session config differently:cwd(config/read), and setsenabled = falsefor each one in the session config.apps,pluginsandskill_mcp_dependency_install, the features that add MCP servers of their own.invalid_params. Codex would deep-merge the two entries, so fields of the configured server would end up in the client's. The existing conflict filter handles this by dropping the client's server; in strict mode that would silently remove a server the client asked for.Only the effective configuration's servers are disabled, not every layer's. Servers in a disabled layer (an untrusted project's
.codex/config.toml, for example) never load. And trusting the project in the session config doesn't enable that layer. Naming such a server in the session config creates an entry with no transport, which Codex rejects ("invalid transport inmcp_servers.<name>"). The existinggetConfigMcpServerNamesstill reads all layers for the non-strict conflict filter.Without the key, or with
false, nothing changes. A non-boolean value is rejected withinvalid_params.Tests
src/__tests__/CodexACPAgent/strict-mcp-config.test.tschecks the config sent tothread/start,thread/resumeandthread/forkagainst a mocked app-server:cwd_relative_turn_diffsis still set;thread/start;falsechanges nothing;mcp-config-merge.test.tsruns a realcodex app-serverand reads each thread's servers back frommcpServerStatus/list, counting those whoseruntimeStatusisn'tdisabled:client-mcpandshared-mcp, and a strict session has onlyclient-mcp;project-mcp, and a strict session still has onlyclient-mcp;shared-mcpis rejected.npm run typecheckis clean andnpm testpasses (784 passed, 32 skipped).Docs
The README has a "Client-only MCP servers" section.
🤖 Generated with Claude Code