Optional / Lazy Loading of MCP Servers

Open 💬 7 comments Opened Aug 15, 2025 by sanand0

What feature would you like to see?

Some MCP servers take several seconds to start. If there’s an error, Codex waits 60s before timing out.

This makes the CLI startup _feel_ slow (though I can start typing immediately). That's a little distracting when we're not using those MCPs in that session.

Could MCPs be:

  • Loaded on demand when first invoked in a conversation?
  • Loaded explicitly via a command-line option (e.g. --with-mcp=playwright,github)
  • Loaded explicitly in-session slash command (e.g. /mcp load playwright).

That'd keep startup fast _and_ let us use MCPs when needed.

Are you interested in implementing this feature?

Yes, I'd love to!

Additional information

It's great that Codex is lightweight - interface _and_ feature-wise. I'd love to keep it that way. Happy to understand alternative approaches.

View original on GitHub ↗

7 Comments

dante01yoon · 6 months ago

This should be shipped soooooon...

Eriz1818 · 5 months ago

I implemented optional / lazy loading of MCP servers in my fork, xCodex (xcodex), and shipped it in v0.3.5.

xCodex: https://github.com/Eriz1818/xCodex
Release notes: https://github.com/Eriz1818/xCodex/blob/main/docs/xcodex/releases/0.3.5.md
Docs: https://github.com/Eriz1818/xCodex/blob/main/docs/xcodex/lazy-mcp-loading.md

What it adds:

  • Global + per-server MCP “startup_mode”: eager (default) | lazy | manual
  • lazy: don’t start servers at session start; start on first tool/resource use
  • manual: never auto-start; load explicitly
  • In-session command: /mcp load <name> (plus /mcp status + /mcp retry ...)
  • CLI one-run override: xcodex --mcp-startup-mode lazy (or eager/manual)

This keeps startup fast for sessions that don’t use MCP, while still making it easy to opt-in when you do. AND saving on context!

songunity · 3 months ago

Hitting the same issue on Windows with Codex CLI 0.116.0.

In my case I have multiple stdio MCP servers enabled in config at the same time, including context7, chrome-devtools, and image tooling launched via npx.

The current workarounds are only partial:

  • enabled = false disables the server entirely
  • startup_timeout_sec only reduces how long startup waits
  • neither option provides true lazy / on-demand connection

For local CLI usage, this feels like the wrong default. Paying startup cost for unused MCP servers on every run makes Codex feel slower even in sessions where I only need plain coding help.

What would help:

  • lazy-load MCP servers on first use
  • allow a CLI allowlist such as --with-mcp=context7,chrome-devtools
  • optionally load only required = true servers at startup
  • support an in-session command to load a server manually

This is more of a local CLI UX issue than just a timeout tuning issue.

wintercounter · 2 months ago

+1 here. I'm running multiple codex instances, often 8-10 at a time, all of them running all mcp servers all the time for no reason, I have +10 chromium instances running because of chrome-devtools-mcp alone...

odlev · 1 month ago

Adding a current Codex CLI data point from codex-cli 0.133.0.

This is still a real UX issue for rarely used MCP servers. In my setup, browser-control and browser-screen-click MCPs are only needed occasionally, but Codex tries to initialize them during session startup. When one is unhealthy, startup prints warnings like:

MCP client for `browser-control` failed to start: MCP startup failed: handshaking with MCP server failed: connection closed: initialize response
MCP startup incomplete (failed: browser-control)

The same applies to remote MCPs such as Atlassian: even if the current prompt does not need Jira/Confluence, the session still pays the startup/auth/network cost and can show unrelated MCP failures.

I checked the rust-v0.133.0 source to make sure this is not just configuration I missed:

  • config/src/mcp_types.rs: McpServerConfig has enabled, required, startup_timeout_sec/ms, tool filters, auth fields, etc., but no server-level lazy/manual startup mode.
  • core/src/session/session.rs: session setup calls McpConnectionManager::new(...) for the effective MCP server set.
  • codex-mcp/src/connection_manager.rs: McpConnectionManager::new iterates every server.enabled() and starts an AsyncManagedClient for each.
  • codex-mcp/src/rmcp_client.rs: startup performs MCP initialize and tools/list before the server's tools are considered ready.
  • tool_search_always_defer_mcp_tools only defers model-facing tool exposure behind tool_search; it does not defer server process/network startup.

The behavior I would expect is a server-level mode, for example:

[mcp_servers.browser-control]
startup_mode = "lazy" # eager | lazy | manual

Possible semantics:

  • eager: current behavior.
  • lazy: do not start the MCP server during session startup; start it on first tool/resource/template call, or when tool_search selects one of its tools.
  • manual: never auto-start; only start via something like /mcp load <server> or a CLI allowlist.
  • required = true can keep eager/blocking behavior, or at least fail the session if the required server cannot be started before first use.

For tool_search, it would be useful if Codex could search known tool metadata without requiring live server startup on every session. That could come from a cached prior tools/list, plugin-provided/static tool metadata, or a placeholder entry that triggers server initialization when selected.

Current workarounds (enabled = false, profiles, lower startup_timeout_sec) are coarse. They either remove the tools entirely or require restarting/reprofiling Codex for a tool that might be needed once in a long-running session.

sarendipitee · 21 days ago

This is so insane that there's no option to only start an MCP server when it's needed.

If I leave Codex running unchecked I have to go and manually kill literally _hundreds_ of node, uv and python processes that are taking up non inconsequential amounts of CPU and ram. Codex is instantiating these for every single sub agent even when they are only used maybe 1 out of 100 sessions. So I either have to constantly go in and out of config to enable/disable when I need each or just let them run and start up every time. Very frustrating.