Plugin MCP servers: no workspace/project-root signal (hooks have cwd; MCP servers don't)
Open 💬 1 comment Opened Aug 11, 2026 by bartolli
Use case
A plugin ships a stdio MCP server that serves per-project data (in our case: a per-project knowledge index — the server must know which project the session is working in to serve the right one). Hooks can do this today: every hook payload carries cwd with the session working directory. Plugin MCP servers cannot.
Current behavior (codex-cli 0.146.0)
- A plugin-registered stdio MCP server with
"cwd": "."is spawned in the plugin's materialized cache directory (~/.codex/plugins/cache/<marketplace>/<plugin>/<version>/), soprocess.cwd()carries no project information. - No substitution token or injected environment variable exposes the workspace/session root to plugin MCP server configs (nothing analogous to hook payload
cwd;env_varsonly whitelists variables from the codex process environment, which requires a manual per-shell export). - The MCP client does not declare the
rootscapability, soroots/listis unavailable as an in-protocol signal (codex-rs/codex-mcp/src/rmcp_client.rsconstructs client capabilities withoutrootsas ofrust-v0.146.0).
The net effect: a plugin MCP server cannot be project-aware without asking users to export an environment variable in every shell before launching codex.
Ask
Any one of these would close the gap:
- A substitution token for plugin MCP server
env/argsvalues that resolves to the session workspace root (the equivalent of thecwdfield hooks already receive), or - An injected environment variable carrying the workspace root in the MCP server child process, or
- Declaring the
rootscapability and answeringroots/listwith the workspace folder.
Option 1 or 2 seems most consistent with the existing hook contract, and with the MCP spec's 2026-07-28 direction (Roots is deprecated there in favor of server configuration).
Environment
- codex-cli 0.146.0, macOS
- Plugin installed via
codex plugin addfrom a marketplace repo
1 Comment
Implementation note supporting option 1/2: the plumbing is one hop away. The stdio launcher already threads a
fallback_cwd(used when the server config omitscwd) plus per-serverenv_varsthrough spawn (https://github.com/openai/codex/blob/1f41cc5d92/codex-rs/rmcp-client/src/stdio_server_launcher.rs#L190-L199,#L94-L95) — so both proposed shapes are local changes at the same site:CODEX_WORKSPACE_ROOT(and maybeCODEX_SESSION_CWD, mirroring the hook payload'scwd) unconditionally in the child env at spawn. Smallest change, zero config surface.${workspaceRoot}inargs/envvalues before spawn. This pairs naturally with #38438, which reports that pluginmcp.json${VAR}env references aren't resolved at all today — one substitution pass could fix both.One caveat worth designing for: server processes are currently spawned per connection-set and can outlive a single session or serve a session whose cwd changes mid-thread (
ThreadSettingsOverridessupports cwd updates, and #38585 wants/cd). An env var freezes the value at spawn; if mid-session correctness matters, the MCP-spec answer is passing it per-request (e.g._meta) rather than per-process — worth stating which contract the feature promises.