diff --git a/apps/server/src/orchestration-v2/Adapters/CodexAdapterV2.test.ts b/apps/server/src/orchestration-v2/Adapters/CodexAdapterV2.test.ts index 21b398cdc7ad..7b12dc2ae036 100644 --- a/apps/server/src/orchestration-v2/Adapters/CodexAdapterV2.test.ts +++ b/apps/server/src/orchestration-v2/Adapters/CodexAdapterV2.test.ts @@ -640,12 +640,10 @@ describe("CodexAdapterV2 process spawning", () => { model: "gpt-5.4", config: { "tools.update_plan.enabled": true, - mcp_servers: { - "t3-code": { - url: "http://127.0.0.1:43123/mcp", - http_headers: { - Authorization: "Bearer secret-codex-token", - }, + "mcp_servers.t3-code": { + url: "http://127.0.0.1:43123/mcp", + http_headers: { + Authorization: "Bearer secret-codex-token", }, }, }, diff --git a/apps/server/src/orchestration-v2/Adapters/CodexAdapterV2.ts b/apps/server/src/orchestration-v2/Adapters/CodexAdapterV2.ts index 2256f4ff9e99..2bfa47694530 100644 --- a/apps/server/src/orchestration-v2/Adapters/CodexAdapterV2.ts +++ b/apps/server/src/orchestration-v2/Adapters/CodexAdapterV2.ts @@ -1216,12 +1216,12 @@ export function codexThreadRuntimeParams(input: { ...(mcpSession === undefined ? {} : { - mcp_servers: { - "t3-code": { - url: mcpSession.endpoint, - http_headers: { - Authorization: mcpSession.authorizationHeader, - }, + // Dotted key: thread config shares Codex's `-c` override layer, so a + // whole `mcp_servers` table would replace servers added by launch args. + "mcp_servers.t3-code": { + url: mcpSession.endpoint, + http_headers: { + Authorization: mcpSession.authorizationHeader, }, }, }), diff --git a/packages/effect-codex-app-server/src/replay.ts b/packages/effect-codex-app-server/src/replay.ts index 1c98c7bc3b8a..d8b3f3aee950 100644 --- a/packages/effect-codex-app-server/src/replay.ts +++ b/packages/effect-codex-app-server/src/replay.ts @@ -273,7 +273,11 @@ function normalizeThreadRequest(frame: unknown, ignoredConfigKeys: ReadonlySet; if (typeof config !== "object" || config === null) return { ...record, params }; - const { mcp_servers: _mcpServers, ...owned } = config as Record; + const owned = Object.fromEntries( + Object.entries(config as Record).filter( + ([key]) => key !== "mcp_servers" && !key.startsWith("mcp_servers."), + ), + ); for (const key of ignoredConfigKeys) delete owned[key]; return { ...record, params: { ...params, config: owned } }; }