## Summary
- let `codex sandbox` accept the JSON value from
`codex/sandbox-state-meta`
- require the payload `permissionProfile` instead of falling back to
ambient permissions
- reuse the existing macOS, Linux, and Windows launch paths, treating
external sandbox state conservatively as read-only
- let opaque forwarders add runtime read roots and disable direct
network access without decoding the payload
Builds on #29113, which is now on `main`.
## Tests
- `just test -p codex-cli debug_sandbox::tests`
- `cargo build -p codex-rmcp-client --bin test_stdio_server`
- `just test -p codex-core
stdio_mcp_tool_call_includes_sandbox_state_meta`
- `just test -p codex-mcp`
- `just fmt`
## Why
Remote stdio MCP servers can run in an environment whose path convention
differs from the Codex host. A Windows cwd such as
`C:\Users\openai\share` is absolute for the executor but was rejected by
a POSIX orchestrator.
Built on #29501, now merged, which only clarifies the host-native
`PathUri` constructor name.
## What changed
- Deserialize MCP cwd values as `LegacyAppPathString` so config does not
apply host path rules.
- Interpret that spelling as host-native for local launches and convert
it to `PathUri` at executor launch.
- Skip host filesystem and command resolution checks for remote stdio in
`codex doctor`.
- Add host-independent config and executor-boundary coverage using the
foreign path convention for each test platform.
## Validation
- `just test -p codex-utils-path-uri -p codex-config -p codex-mcp -p
codex-rmcp-client` (408 passed)
- `just test -p codex-cli -p codex-rmcp-client` (372 passed)
- `cargo check --workspace --tests`
- `just test` (11,311 passed; 43 unrelated environment/timing failures)
- `just fix -p codex-cli -p codex-config -p codex-core -p codex-mcp -p
codex-mcp-extension -p codex-rmcp-client -p codex-tui`
Scope MCP sandbox metadata to the MCP server's owning environment.
Previously, `codex/sandbox-state-meta` always used the turn's primary
cwd and rebuilt a legacy sandbox policy from that cwd. That can be wrong
for MCP servers owned by a different execution environment.
This now sends the owning environment cwd as a `file:` URI in
`sandboxCwd`, keeps `permissionProfile` as the permission source of
truth, and omits sandbox-state metadata when a non-default server
environment is not selected for the turn. Local/default MCP servers keep
the existing fallback cwd behavior.
Tests:
- `just fmt`
- `just bazel-lock-update`
- `just bazel-lock-check`
- `just test -p codex-mcp`
- `just test -p codex-core mcp_sandbox_cwd`
- `cargo build -p codex-rmcp-client --bin test_stdio_server`
- `just test -p codex-core
stdio_mcp_tool_call_includes_sandbox_state_meta`
## Summary
- route each configured MCP server through an explicit per-server
`environment_id` instead of a manager-wide remote toggle
- default omitted `environment_id` to `local`, resolve named ids through
`EnvironmentManager`, and fail only the affected MCP server when an
explicit id is unknown
- keep local stdio on the existing local launcher path for now, while
named-environment stdio uses the selected environment backend and
requires an absolute `cwd`
- allow local HTTP MCP servers to keep using the ambient HTTP client
when no local `Environment` is configured; named-environment HTTP MCPs
use that environment's HTTP client
## Validation
- devbox Bazel build: `bazel build --bes_backend= --bes_results_url=
//codex-rs/cli:codex //codex-rs/rmcp-client:test_stdio_server
//codex-rs/rmcp-client:test_streamable_http_server`
- devbox app-server config matrix with real `config.toml` /
`environments.toml` files covering omitted local, explicit local,
omitted local under remote default, explicit remote stdio, local HTTP
without local env, explicit remote HTTP, local stdio without local env,
unknown explicit env, and remote stdio without `cwd`