Codex MCP Not Working on Windows: Every Fix (2026)
Codex shows MCP client for `x` failed to start: program not found, crashes at launch with -32601: Method not found, or /mcp lists nothing even though your config.toml looks correct — this page covers every Windows failure mode we could trace to a real GitHub issue or an official doc, with the exact fix for each. It is the troubleshooting companion to our Codex client setup page; if you haven’t added a server yet, start there.

On this page · 18 sections▾
- TL;DR — symptom lookup
- How Codex loads MCP servers
- Fix 1 — -32601 startup crash
- Fix 2 — program not found
- Fix 3 — TOML path escaping
- Fix 4 — wrong config file
- Fix 5 — WSL vs native mismatch
- Fix 6 — env vars not passed
- Fix 7 — request timed out
- Fix 8 — SSE handshake failures
- Fix 9 — Desktop rewrites config
- Fix 10 — pin versions, update
- Validate your config.toml
- When it's the server, not Codex
- What we got wrong
- Community signal
- FAQ
- Sources
TL;DR — match your symptom, jump to the fix
Codex reads MCP servers from one TOML file. On Windows, ten distinct things break between that file and a running server. Find your error message, jump to the numbered fix:
| Symptom | Fix |
|---|---|
-32601: Method not found at startup, app hangs or crashes | Fix 1 |
failed to start: program not found | Fix 2 |
Config “ignored,” server name never appears in codex mcp list | Fix 3 / Fix 4 |
| Works in one terminal, fails in another (WSL involved) | Fix 5 |
Server starts but auth fails / literal ${VAR} sent upstream | Fix 6 |
failed to start: request timed out | Fix 7 |
connection closed: initialize response or 404 on a /sse URL | Fix 8 |
| Servers vanish from config.toml after launching Codex Desktop | Fix 9 |
| Worked yesterday, broke today, nothing changed | Fix 10 |
One framing note before the fixes: Codex is a Rust binary, not a Node app. Several Windows workarounds you know from Claude Desktop or Cursor (both Electron/Node) don’t transfer — and one of them, the cmd /c wrapper, actively misleads here. We’ll flag where Codex behaves differently. On Claude Code instead? Use the sibling Windows fix guide.
How Codex loads MCP servers
Everything lives in config.toml under your Codex home directory. Per the official configuration reference, that’s ~/.codex/config.toml — on Windows, %USERPROFILE%\.codex\config.toml, typically C:\Users\<you>\.codex\config.toml. The CODEX_HOME environment variable relocates the whole directory. The CLI, the VS Code extension, and the Desktop app all read this one file.
Each server is a [mcp_servers.<name>] table. Two transports: stdio (Codex spawns a local process and speaks JSON-RPC over its stdin/stdout) and streamable HTTP (Codex POSTs to a URL). The documented shape, from developers.openai.com/codex/mcp:
# stdio server — Codex spawns this process
[mcp_servers.context7]
command = "npx"
args = ["-y", "@upstash/context7-mcp"]
startup_timeout_sec = 60 # default 10
tool_timeout_sec = 60 # default 60
[mcp_servers.context7.env]
CONTEXT7_API_KEY = "your-key-here"
# streamable HTTP server — no local process at all
[mcp_servers.figma]
url = "https://mcp.figma.com/mcp"
bearer_token_env_var = "FIGMA_OAUTH_TOKEN"You rarely need to hand-write the stdio block — codex mcp add does it:
codex mcp add context7 -- npx -y @upstash/context7-mcp
codex mcp list # confirm it parsed and registered
codex mcp get context7 # show one server's resolved configThree more keys worth knowing because they appear in the fixes below: enabled = false disables a server without deleting it, required = true makes Codex fail startup if the server can’t initialize (leave it unset while debugging), and env_vars = ["NAME"] whitelists variables to forward from your environment. The opinionated takeaway: treat codex mcp list as your first diagnostic, always. If the server name is absent, you have a parsing or file-location problem (Fixes 3–4). If it’s present but failing, you have a spawn, handshake, or timeout problem (Fixes 1–2, 7–8).
Fix 1 — Codex crashes at startup with “-32601: Method not found”
Symptom
Codex (Desktop or CLI) launches, prints Mcp error: -32601: Method not found and Failed to list resource templates/resources for MCP servers, then hangs, crashes, or exits. Reported on Windows 11 in issue #16834; a related repro in #16502 shows the Store-packaged app’s whole process tree self-exiting ~46–55 seconds after launch with the same warnings.
Root cause. -32601 is JSON-RPC’s “method not found.” At session start, Codex asks each configured server to list its resources and resource templates. Those MCP methods are optional — plenty of servers implement only tools. A spec-minimal server answers -32601, which is correct behavior, and Codex surfaces it as a startup failure instead of skipping the server. The defect is in the client’s error handling, not in your config or the server.
Fix. Update Codex first — client-side handling improves release to release. If you’re stuck on a build that still dies, the workaround documented in the issue thread is to disable the servers that trigger it until startup is clean, then re-enable one at a time:
[mcp_servers.playwright]
command = "npx"
args = ["-y", "@playwright/mcp@latest"]
enabled = false # temporarily — re-enable after updating CodexAnd while debugging any startup failure, make sure no server has required = true — that flag turns “one busted server” into “Codex won’t start.”
Fix 2 — “program not found”: npx is a batch file, not a binary
Symptom
MCP client for `context7` failed to start: program not found — while the same npx command runs fine when you paste it into PowerShell. The highest-traffic Codex Windows bug: #2945, #2555, and a half-dozen duplicates.
Root cause. On Windows, npx, pnpm, and yarn ship as .cmd batch scripts, not .exe binaries. Your shell resolves them via PATHEXT; Rust’s std::process::Command — which Codex uses to spawn stdio servers — does not. It asks the OS for an executable literally named npx, finds nothing, and reports “program not found.”
Fix. PR #3828 (merged November 2025) taught Codex to resolve .cmd/.bat scripts through PATH/PATHEXT. So: update Codex (npm i -g @openai/codex or winget upgrade OpenAI.Codex) and command = "npx" works as-is. If you must stay on an older build, point at the script explicitly:
[mcp_servers.context7]
command = 'C:\Program Files\nodejs\npx.cmd'
args = ["-y", "@upstash/context7-mcp"]Find your real path with where npx (note: Python-based servers don’t have this problem — uvx.exe is a real executable). One warning about the folk fix: wrapping with command = "cmd", args = ["/c", "npx", ...] — the standard trick for Node-based clients like Claude Desktop — only changes the error here. The reporter in #2555 tried exactly that and got request timed out instead, because cmd /c npx adds shell startup plus a cold npx install on top of Codex’s 10-second handshake budget. If you use the wrapper anyway, pair it with Fix 7.
Fix 3 — Windows paths break TOML parsing
Symptom
You added a server with a full Windows path and now codex mcp list shows nothing — or the spawn fails with a mangled path like C:Program Filesnodejsnpx.cmd.
Root cause. In TOML, double-quoted strings treat backslash as an escape character — \n is a newline, \t a tab, and \P is simply invalid. So "C:\Program Files\nodejs\npx.cmd" is either a parse error or, worse, a silently corrupted string. This is the TOML spec working as designed; it just collides head-on with Windows path syntax.
Fix. Use single-quoted literal strings, where backslashes mean backslashes, or escape every backslash:
# ❌ broken — \P and \n are escape sequences inside double quotes
command = "C:\Program Files\nodejs\npx.cmd" # parse error / corrupted path
# ✅ option 1 — literal string (single quotes): backslashes are verbatim
command = 'C:\Program Files\nodejs\npx.cmd'
# ✅ option 2 — basic string with every backslash doubled
command = "C:\\Program Files\\nodejs\\npx.cmd"Real-world configs that work use exactly this shape — the reporter in issue #9676 runs command = 'C:\Program Files\nodejs\npx.cmd' and command = 'C:\Users\User\.local\bin\uvx.exe'. The rule worth memorizing: in config.toml, Windows paths always get single quotes.
Fix 4 — You’re editing a config Codex doesn’t read
Symptom
The TOML is valid, the command runs in a terminal, and /mcp is still empty. No error anywhere.
Root cause. There are more places a Codex config can live than places Codex actually reads, and the gaps are documented bugs:
- Project-scoped configs are second-class. A
.codex/config.tomlinside your repo is only loaded for trusted projects — and issue #13025 documents Codex Desktop ignoring project-level MCP servers entirely, loading only~/.codex/config.toml. - The VS Code extension can desync from the CLI. Issue #6465 reports servers visible in the Codex CLI but absent from the IDE extension on the same machine.
- A stale
CODEX_HOMEset in an old PowerShell profile points Codex at a directory you forgot exists. Check withecho $env:CODEX_HOME. - Updates have regressed config loading before. Issue #9676 tracked valid
[mcp_servers]entries going undetected after a version bump.
Fix. Put servers in the global file — %USERPROFILE%\.codex\config.toml — via codex mcp add, and verify with codex mcp list from the same shell you run Codex in. Treat project-scoped MCP config as a nice-to-have that the Desktop app will not honor, not as your primary registration path.
Fix 5 — WSL and native Windows are two different machines
Symptom
MCP servers work in your Ubuntu terminal but not in PowerShell, or vice versa. Or the Codex app’s WSL mode misbehaves outright (#26132), with WSL-probing failures showing up in logs (#22393).
Root cause. WSL is a separate filesystem with a separate home directory. A Codex running inside WSL reads /home/<you>/.codex/config.toml; a native Codex reads C:\Users\<you>\.codex\config.toml. Those are two unrelated files, and each side has its own Node. The classic mistake is one config referencing the other side’s binaries — a WSL Codex pointed at npx.cmd, or a native Codex pointed at a Linux-side uvx.
Fix. Pick a side and keep the whole chain — Codex, Node/Python, config.toml, and your project — on it. Quick audit:
# Native PowerShell — everything should be C:\ paths
where.exe codex
where.exe node
type $env:USERPROFILE\.codex\config.toml
# Inside WSL — everything should be Linux paths
which codex
which node
cat ~/.codex/config.tomlIf any line answers from the wrong world, that’s your bug. The same dual-home trap exists in Claude Code — our Claude Code Windows guide covers the WSL-side setup in detail and most of it transfers directly.
Fix 6 — Your env vars never reach the server
Symptom
The server process starts, then fails auth — or an upstream API receives the literal text ${MY_TOKEN} instead of your token. Documented on Windows Codex Desktop in issue #24362, where mcp-remote forwarded an unexpanded placeholder as an Authorization header.
Root cause. Codex does not hand stdio MCP children your full user environment. Per the config reference, a server gets the variables you declare in its env table plus names you whitelist in env_vars — a deliberate secrets-don’t-leak default. A token that’s visible in every PowerShell window can still be invisible to the spawned server.
Fix. Declare everything the server needs, explicitly:
[mcp_servers.github]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-github"]
env_vars = ["GITHUB_PERSONAL_ACCESS_TOKEN"] # forward from your environment
# — or pin the value in the config —
[mcp_servers.github.env]
GITHUB_PERSONAL_ACCESS_TOKEN = "ghp_..."The equivalent flag at add-time is codex mcp add github --env GITHUB_PERSONAL_ACCESS_TOKEN=ghp_... -- npx -y @modelcontextprotocol/server-github. Don’t confuse this with shell_environment_policy — that section of config.toml governs the shell commands the agent runs, not MCP server processes.
Fix 7 — “request timed out”: the 10-second handshake budget
Symptom
MCP client for `context7` failed to start: request timed out — especially on first run, especially with npx, especially on Windows. Issues #2905 and #3289.
Root cause. Codex gives each stdio server startup_timeout_sec (default 10) to finish the MCP initialize handshake. A cold npx on Windows has to hit the npm registry, download the package, and run every new file past Defender’s real-time scanner. That routinely blows a 10-second budget — issue #2905 was literally titled “MCP needs a greater timeout for startup (Windows),” and a maintainer closed it when configurable startup timeout shipped in the rust-v0.31.0 release.
Fix. Raise the budget and warm the cache:
[mcp_servers.context7]
command = "npx"
args = ["-y", "@upstash/context7-mcp"]
startup_timeout_sec = 60# Pre-warm once in a terminal so Codex never pays the cold start:
npx -y @upstash/context7-mcp --helpIf a server connects but individual calls abort on long operations, that’s the other knob: tool_timeout_sec, default 60.
Fix 8 — SSE endpoints fail the handshake (Codex never supported them)
Symptom
handshaking with MCP server failed: connection closed: initialize response, or an HTTP 404 when send initialize request against a URL ending in /sse. Collected in issue #6020.
Root cause. SSE (Server-Sent Events) was the MCP remote transport before streamable HTTP replaced it; the protocol deprecated it, and Codex never implemented it. A maintainer said so verbatim in #6020 — quoted in the community section below. Configs copied from 2025-era tutorials that point mcp-remote at https://.../sse endpoints fail the initialize exchange, with errors vague enough that people debug everything except the URL.
Fix. Use the provider’s streamable HTTP endpoint — for most vendors, same host, /mcp path — and prefer Codex’s native url config over an mcp-remote stdio bridge:
# ❌ SSE — Codex does not support this transport
[mcp_servers.linear]
command = "npx"
args = ["-y", "mcp-remote", "https://mcp.linear.app/sse"]
# ✅ streamable HTTP, no local process, no Windows spawn problems
[mcp_servers.linear]
url = "https://mcp.linear.app/mcp"This is also the broader opinionated move on Windows: every remote server you switch to url config removes an entire class of local spawn bugs — Fixes 2, 3, 6, and 7 simply don’t apply to a server Codex never has to spawn.
Fix 9 — Codex Desktop rewrites config.toml and drops your servers
Symptom
A server you registered by hand works for days, then vanishes after launching the Desktop app. Your [mcp_servers.<custom>] block is gone from the file; desktop-generated entries like [mcp_servers.node_repl] remain. Issue #24718, open at the time of writing.
Root cause. Codex Desktop on Windows rewrites %USERPROFILE%\.codex\config.toml during startup and plugin initialization. The rewrite preserves its own entries but has dropped user-defined server blocks — the reporter calls it a “blocking data-loss issue,” which is the right description for a config file that eats your edits.
Fix. Until the issue closes, defend your config:
# Snapshot before launching Desktop, diff after:
copy $env:USERPROFILE\.codex\config.toml $env:USERPROFILE\.codex\config.backup.toml
# After a Desktop session:
fc $env:USERPROFILE\.codex\config.backup.toml $env:USERPROFILE\.codex\config.tomlKeep the canonical copy in a dotfiles repo so restoring is one copy away. And don’t edit config.toml while any Codex surface (CLI, extension, Desktop) is running — last writer wins.
Fix 10 — Pin server versions; keep Codex itself current
Symptom
Everything worked yesterday. Today a server times out or errors, and you changed nothing.
Root cause. Two moving parts move under you. First, npx -y package@latest re-resolves against the npm registry, so a server release that ships overnight is what you boot next morning — new bugs included, plus a fresh download against your startup timeout. Second, the inverse: Codex’s own Windows MCP fixes (the PR #3828 .cmd resolution, the configurable startup timeout, the -32601 handling) only exist in newer builds, so a months-old Codex re-exposes you to every bug in this article.
Fix. Invert the defaults — float the client, pin the servers:
# ❌ floating — re-resolves and can break on any upstream release
args = ["-y", "@upstash/context7-mcp@latest"]
# ✅ pinned — same bits every boot; bump deliberately
args = ["-y", "@upstash/[email protected]"]Then put codex --version in your debugging muscle memory: before chasing any error in this guide, update Codex and retry. Half the GitHub threads above end with “fixed in a newer release.”
Validate your config.toml in 10 seconds
Most of the failures above are diagnosable from the file alone: escape-sequence damage in double-quoted Windows paths (Fix 3), bare npx on old builds (Fix 2), /sse URLs (Fix 8), missing startup_timeout_sec on npx servers (Fix 7). We built a free checker that catches all of these — paste your config.toml into the Codex CLI config validator and it flags structural problems with line-level pointers, entirely client-side (your config never leaves the browser). Then confirm the runtime half:
codex mcp list # every server parsed from the file, with status
/mcp # same view from inside the TUIWhen it’s the server, not Codex
After ten client-side fixes, fairness requires the other hypothesis. The fastest test: swap in a known-good server. Context7 is our standard probe — widely used, no auth required to start, available as both stdio and remote:
codex mcp add context7 -- npx -y @upstash/context7-mcpOne-line install · Context7
Open server pageInstall
If Context7 connects and your original server still doesn’t, your Codex plumbing is fine — the bug lives in the server. Two follow-ups from there. Run the server under MCP Inspector (npx @modelcontextprotocol/inspector <your command>) to watch the initialize exchange directly. And check whether the server writes logs to stdout — stdio framing means stdout is reserved for JSON-RPC, and a banner printed there corrupts the handshake on every client, not just Codex. For the full Context7 setup (API keys, remote endpoint, per-client config), see our Context7 complete guide; for a replacement server, browse the full directory.
What we got wrong
Three assumptions we carried into this research that the bug trackers corrected:
- We assumed
cmd /cwas the universal Windows fix. It is — for Node-based clients, wherechild_process.spawnneeds a shell to run.cmdscripts. Codex is Rust, the failure is PATH resolution rather than shell semantics, and the wrapper mostly converts “program not found” into “request timed out” (#2555 shows the exact progression). The real fix was a client-side patch (PR #3828) plus updating. - We blamed servers for startup timeouts. The guilty party was a 10-second default handshake budget colliding with cold
npxdownloads and Defender scans. One config line —startup_timeout_sec = 60— resolved “flaky” servers we’d written off. - We treated config.toml as ours. It’s shared state: Codex Desktop rewrites it at startup and has dropped user-defined server blocks (#24718). We now keep the canonical copy in version control and diff after Desktop sessions.
Community signal
Three primary-source quotes, each linked to a public, verifiable artifact.
“Codex only supports streamable http servers. SSE is deprecated and we may or may not backport support.”
gpeal (Codex maintainer, GitHub issue #6020) · Blog
The definitive first-party statement behind Fix 8 — every /sse endpoint failure traces back to this design decision.
“Same thing happened to me. All MCP servers seem to be bugged or something. I even tried [command = 'cmd', args = ['/c', 'npx', ...]] but got: MCP client for `supabase` failed to start: program not found.”
sloikodavid (GitHub issue #2945) · Blog
Representative of the pre-PR-#3828 era on Windows: every npx-based server failing identically, with the popular cmd /c folk fix not helping. Status: closed by the program-resolution fix.
“Codex Desktop overwrites %USERPROFILE%\.codex\config.toml during startup … and removes a manually configured custom MCP server. The rewritten file retains desktop-generated entries such as [mcp_servers.node_repl] while the existing custom server block is absent. This is a blocking data-loss issue.”
GitHub issue #24718 (open) · Blog
The contrarian data point: even a perfectly correct config can stop working through no action of yours. Back up config.toml.
Frequently asked questions
How do I add an MCP server to Codex?
Run codex mcp add <name> -- <command>, for example codex mcp add context7 -- npx -y @upstash/context7-mcp. That writes a [mcp_servers.context7] block into ~/.codex/config.toml. You can also edit the TOML directly: command, args, and env keys for stdio servers; a url key for streamable HTTP servers. Verify with codex mcp list or /mcp inside the TUI.
Where is the Codex config.toml on Windows?
%USERPROFILE%\.codex\config.toml — typically C:\Users\<you>\.codex\config.toml. The CODEX_HOME environment variable overrides the ~/.codex directory. The CLI, the VS Code extension, and the Desktop app all read this same file. A project-scoped .codex/config.toml exists but is only loaded for trusted projects, and the Desktop app has a documented bug ignoring it (issue #13025).
Why does Codex crash on startup with MCP errors?
GitHub issue #16834 documents Codex on Windows crashing or hanging at startup with 'Mcp error: -32601: Method not found.' At session start Codex asks every configured server to list resources and resource templates; servers that don't implement those optional methods return JSON-RPC -32601, and Codex surfaces the failure instead of skipping the server. Workaround from the thread: set enabled = false on the failing servers until you've updated Codex.
Why does Codex say 'program not found' for my MCP server?
On Windows, npx, pnpm, and yarn are .cmd batch scripts, not .exe binaries. Codex is a Rust binary, and Rust's process spawning doesn't consult PATHEXT, so command = "npx" finds nothing. PR #3828 (merged November 2025) fixed this by resolving .cmd/.bat through PATH. Update Codex first; on older builds, point command at the full path to npx.cmd using a single-quoted TOML string.
Why does my MCP server time out on startup in Codex?
Codex gives each server 10 seconds to complete the MCP initialize handshake (startup_timeout_sec, default 10). A cold npx run on Windows — package download plus Defender real-time scanning — routinely takes longer. Set startup_timeout_sec = 60 in the server's TOML block, and pre-warm the cache by running the npx command once in a terminal. Timeout config has existed since the rust-v0.31.0 release (issue #2905).
Does Codex support SSE MCP servers?
No. A Codex maintainer stated it directly in issue #6020: 'Codex only supports streamable http servers. SSE is deprecated and we may or may not backport support.' If your config points at a /sse endpoint — directly or through mcp-remote — you'll see handshake failures like 'connection closed: initialize response' or a 404. Switch to the provider's streamable HTTP endpoint, usually the same host with an /mcp path.
Does Codex pass my environment variables to MCP servers?
Not automatically. Stdio MCP servers get an explicit environment: variables you set in the server's env table, plus any names you whitelist in env_vars. Issue #24362 documents a Windows Desktop case where a user-level environment variable never reached an mcp-remote child, so the literal placeholder ${VAR} was sent as an Authorization header. Declare every variable the server needs in [mcp_servers.<name>.env].
How do I check which MCP servers Codex actually loaded?
Run codex mcp list in a terminal — it prints every server parsed from config.toml with its status. Inside the TUI, /mcp shows the same. If a server is missing from the list entirely, the problem is config parsing or file location (Fixes 3 and 4). If it's listed but errored, the problem is spawning, handshake, or timeout (Fixes 1, 2, 7, 8).
All sources & links
Primary sources (GitHub, openai/codex)
- Issue #16834 — “Codex crashes on startup due to MCP `Method not found` errors (Windows)” — the -32601 startup crash and its disable-servers workaround (Fix 1); related repro in #16502
- Issue #2945 + PR #3828 (merged Nov 2025) — “program not found” root cause and the PATH/PATHEXT resolution fix (Fix 2)
- Issue #2555 — Windows 11 Context7 failures across all three config shapes (npx / cmd /c / full path) (Fixes 2, 7)
- Issue #2905 — “MCP needs a greater timeout for startup (Windows)”; maintainer confirmation that configurable startup timeout shipped in rust-v0.31.0 (Fix 7)
- Issue #6020 — handshake failures; maintainer statement that Codex supports streamable HTTP only, not SSE (Fix 8)
- Issue #24362 — Windows Desktop stdio children don’t inherit user env vars (Fix 6)
- Issue #24718 — Desktop startup rewrites config.toml, dropping user servers (Fix 9)
- Issue #9676, #13025, #6465 — config not detected after update; project-scope config ignored by Desktop; VS Code extension desync (Fix 4)
- Issue #26132, #22393 — WSL-mode breakage and WSL probing failures (Fix 5)
Official documentation
- developers.openai.com/codex/mcp —
codex mcp addsyntax, stdio and streamable HTTP TOML schema,startup_timeout_sec/tool_timeout_secdefaults,enabled/requiredflags - developers.openai.com/codex/config-reference —
CODEX_HOME,env/env_varssemantics,shell_environment_policy, project-scoped config trust rules - toml.io — escape-sequence rules for basic vs literal strings (Fix 3)
Community / web
- User reports and workaround threads inside issues #2945, #2905, and #6020 (quoted above)
- vladimirsiedykh.com — independent walkthrough of sharing one config.toml between Codex CLI and the VS Code extension
Internal links
- /clients/codex — Codex client setup page (start here if nothing is configured yet)
- /tools/codex-cli-config-validator — paste-and-check your config.toml
- Claude Code MCP on Windows fix guide — the sibling guide for Anthropic’s CLI
- Context7 complete guide
- What is MCP — protocol primer
- /servers — browse all MCP servers
What to do next
Run the validator on your current config
The Codex config validator catches the TOML and transport mistakes from Fixes 3 and 8 before you burn another restart cycle.
Prefer url-based servers wherever they exist
Remote streamable HTTP config skips every process-spawning bug in this guide. Filter for hosted options in the directory.
Don’t stack five stdio servers while debugging one
Set enabled = false on everything except the server under test. One variable at a time is the whole game.