Reject remote environment for HTTP MCP servers

This commit is contained in:
Ed Bayes
2026-04-16 00:17:49 -07:00
parent f11cc84bdc
commit 8a2b7973f6
3 changed files with 33 additions and 0 deletions

View File

@@ -32,6 +32,19 @@ Codex supports a rich set of configuration options. Note that the Rust CLI uses
Codex CLI functions as an MCP client that allows the Codex CLI and IDE extension to connect to MCP servers on startup. See the [`configuration documentation`](../docs/config.md#connecting-to-mcp-servers) for details.
#### Remote MCP stdio branch notes
The `dev/remote-mcp-executor-stdio` branch is PR `#18088`, stack item `[5/8] Add executor process transport for MCP stdio`, based on `dev/remote-mcp-stdio-runtime`. It is building support for running stdio MCP servers through the executor process API while keeping MCP framing in the orchestrator.
- External MCP stdio semantics are newline-delimited JSON-RPC over server `stdin`/`stdout`, with `stderr` reserved for logging. See the [MCP transport specification](https://mcp.mintlify.app/specification/draft/basic/transports).
- MCP server config now carries an `environment` field, with `local` as the default and `remote` serialized as `environment = "remote"`.
- The exec process protocol now distinguishes closed stdin from piped stdin. Normal non-interactive exec keeps stdin closed, while remote MCP stdio can start a pipe-backed process and feed JSON-RPC bytes later through `process/write`.
- The exec process API now pushes output/lifecycle events (`process/output`, `process/exited`, and `process/closed`) so streaming clients can subscribe instead of polling `process/read` for every chunk.
- `codex-rs/rmcp-client` now has a `StdioServerLauncher` abstraction. The local launcher preserves the existing child-process path, while the executor launcher starts a server through `ExecBackend` with `tty = false` and piped stdin.
- The executor-backed transport appends stdio newlines to rmcp JSON-RPC writes, maps executor stdout chunks back into rmcp messages, treats `stderr` as diagnostics, and terminates the executor process when rmcp closes the transport.
- Current branch wiring still constructs `LocalStdioServerLauncher` in `codex-mcp`, so the executor launcher is present for integration but is not yet selected for configured MCP servers.
- GitHub showed format, build-test, SDK, and cargo-deny checks passing for this PR, while Bazel and argument-comment-lint jobs were failing when this note was written.
#### MCP server (experimental)
Codex can be launched as an MCP _server_ by running `codex mcp-server`. This allows _other_ MCP clients to use Codex as a tool for another agent.

View File

@@ -241,6 +241,9 @@ impl TryFrom<RawMcpServerConfig> for McpServerConfig {
throw_if_set("streamable_http", "env_vars", env_vars.as_ref())?;
throw_if_set("streamable_http", "cwd", cwd.as_ref())?;
throw_if_set("streamable_http", "bearer_token", bearer_token.as_ref())?;
if matches!(environment, Some(McpServerEnvironment::Remote)) {
return Err("environment = remote is only supported for stdio".to_string());
}
McpServerTransportConfig::StreamableHttp {
url,
bearer_token_env_var,

View File

@@ -335,6 +335,23 @@ fn deserialize_rejects_env_for_http_transport() {
.expect_err("should reject env for http transport");
}
#[test]
fn deserialize_rejects_remote_environment_for_http_transport() {
let err = toml::from_str::<McpServerConfig>(
r#"
url = "https://example.com"
environment = "remote"
"#,
)
.expect_err("should reject remote environment for http transport");
assert!(
err.to_string()
.contains("environment = remote is only supported for stdio"),
"unexpected error: {err}"
);
}
#[test]
fn deserialize_rejects_headers_for_stdio() {
toml::from_str::<McpServerConfig>(