Skip to content

bug: stale Codex MCP servers resurrected from provider config and takeover backup #4012

@wu-clan

Description

@wu-clan

Summary

CC Switch can resurrect deleted Codex MCP servers after restart/import because stale MCP definitions remain embedded in internal DB snapshots/config blobs, not only in the mcp_servers table or live ~/.codex/config.toml.

This looks related to #3824 and older #955, but the failure mode is different: even after cleaning the live Codex config and CC Switch's mcp_servers table, a restart/provider takeover rewrites stale [mcp_servers.*] sections back into ~/.codex/config.toml. Then clicking “Import existing MCP” imports the stale servers again.

Environment

  • CC Switch: 3.16.2
  • macOS: 26.3.2 / Darwin 25.3.0 arm64
  • Affected app: Codex
  • Affected live config: ~/.codex/config.toml
  • CC Switch DB: ~/.cc-switch/cc-switch.db

What happened

Desired MCP set:

  • apifox-new-mcp
  • augment-context-engine
  • codegraph

Unwanted MCP servers kept coming back after CC Switch restart + “Import existing MCP”:

  • fetch
  • chrome-devtools
  • exa
  • playwright
  • sometimes node_repl was also present in the CC Switch MCP table

Initial cleanup removed the unwanted servers from:

  • ~/.codex/config.toml
  • ~/.cc-switch/cc-switch.db table mcp_servers

After restart, CC Switch wrote these sections back into ~/.codex/config.toml:

[mcp_servers.fetch]
command = "uvx"
args = ["mcp-server-fetch"]

[mcp_servers.chrome-devtools]
command = "npx"
args = ["chrome-devtools-mcp@latest"]

[mcp_servers.exa]
command = "npx"
args = ["-y", "mcp-remote", "https://mcp.exa.ai/mcp"]

[mcp_servers.playwright]
command = "npx"
args = ["@playwright/mcp@latest"]

Clicking “Import existing MCP” then imported them back into the CC Switch MCP panel.

Root cause observed locally

The stale MCP definitions were also embedded in CC Switch internal DB fields:

  1. providers.settings_config

    • The current Codex provider (app_type = 'codex') stored a full TOML config string containing stale [mcp_servers.*] sections.
    • At least fetch was present there.
  2. proxy_live_backup.original_config

    • The Codex takeover/live backup stored an old full Codex config containing stale [mcp_servers.*] sections.
    • fetch, chrome-devtools, exa, and playwright were present there.
  3. settings.value for common_config_opencode

    • Also contained stale MCP definitions for OpenCode. This was not the direct Codex reinjection source in this case, but it is another stale internal MCP copy that can later pollute app configs.

After cleaning all of the following, the issue stopped reproducing:

  • live ~/.codex/config.toml
  • DB table mcp_servers
  • embedded TOML in providers.settings_config
  • embedded backup config in proxy_live_backup.original_config
  • stale MCP JSON in settings.common_config_opencode

Expected behavior

When a user deletes/disables/removes MCP servers from CC Switch and/or live Codex config:

  • stale MCP entries should not be resurrected from provider config snapshots or takeover backups
  • provider sync should not write old [mcp_servers.*] sections back into ~/.codex/config.toml
  • “Import existing MCP” should not import MCP servers that CC Switch itself just resurrected from stale internal state

Actual behavior

CC Switch can rehydrate old MCP definitions from its own DB blobs/backups into ~/.codex/config.toml. The import flow then treats them as live external MCP servers and adds them back into the unified MCP table.

Suggested fix

  1. Treat mcp_servers in provider settings_config.config as stale/legacy during Codex provider sync, or merge with an explicit precedence policy where the unified MCP table/live user config wins.
  2. Do not use proxy_live_backup.original_config to restore/merge stale [mcp_servers.*] entries once the unified MCP table has removed them.
  3. Add a cleanup/migration that strips MCP sections from existing Codex provider config blobs and old takeover backups, or at least reconciles them with the current mcp_servers table.
  4. Consider adding diagnostics in the MCP panel: when “Import existing MCP” finds servers, show the exact source file and whether that source was just written by CC Switch provider sync.

Notes

No secrets are included here. Local config values/tokens were redacted during diagnosis.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions