core-agent-ide/codex-rs/exec-server/Cargo.toml

58 lines
1.3 KiB
TOML
Raw Normal View History

2025-11-18 16:20:19 -08:00
[package]
edition = "2024"
name = "codex-exec-server"
version = { workspace = true }
[[bin]]
chore: refactor exec-server to prepare it for standalone MCP use (#6944) This PR reorganizes things slightly so that: - Instead of a single multitool executable, `codex-exec-server`, we now have two executables: - `codex-exec-mcp-server` to launch the MCP server - `codex-execve-wrapper` is the `execve(2)` wrapper to use with the `BASH_EXEC_WRAPPER` environment variable - `BASH_EXEC_WRAPPER` must be a single executable: it cannot be a command string composed of an executable with args (i.e., it no longer adds the `escalate` subcommand, as before) - `codex-exec-mcp-server` takes `--bash` and `--execve` as options. Though if `--execve` is not specified, the MCP server will check the directory containing `std::env::current_exe()` and attempt to use the file named `codex-execve-wrapper` within it. In development, this works out since these executables are side-by-side in the `target/debug` folder. With respect to testing, this also fixes an important bug in `dummy_exec_policy()`, as I was using `ends_with()` as if it applied to a `String`, but in this case, it is used with a `&Path`, so the semantics are slightly different. Putting this all together, I was able to test this by running the following: ``` ~/code/codex/codex-rs$ npx @modelcontextprotocol/inspector \ ./target/debug/codex-exec-mcp-server --bash ~/code/bash/bash ``` If I try to run `git status` in `/Users/mbolin/code/codex` via the `shell` tool from the MCP server: <img width="1589" height="1335" alt="image" src="https://github.com/user-attachments/assets/9db6aea8-7fbc-4675-8b1f-ec446685d6c4" /> then I get prompted with the following elicitation, as expected: <img width="1589" height="1335" alt="image" src="https://github.com/user-attachments/assets/21b68fe0-494d-4562-9bad-0ddc55fc846d" /> Though a current limitation is that the `shell` tool defaults to a timeout of 10s, which means I only have 10s to respond to the elicitation. Ideally, the time spent waiting for a response from a human should not count against the timeout for the command execution. I will address this in a subsequent PR. --- Note `~/code/bash/bash` was created by doing: ``` cd ~/code git clone https://github.com/bminor/bash cd bash git checkout a8a1c2fac029404d3f42cd39f5a20f24b6e4fe4b <apply the patch below> ./configure make ``` The patch: ``` diff --git a/execute_cmd.c b/execute_cmd.c index 070f5119..d20ad2b9 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -6129,6 +6129,19 @@ shell_execve (char *command, char **args, char **env) char sample[HASH_BANG_BUFSIZ]; size_t larray; + char* exec_wrapper = getenv("BASH_EXEC_WRAPPER"); + if (exec_wrapper && *exec_wrapper && !whitespace (*exec_wrapper)) + { + char *orig_command = command; + + larray = strvec_len (args); + + memmove (args + 2, args, (++larray) * sizeof (char *)); + args[0] = exec_wrapper; + args[1] = orig_command; + command = exec_wrapper; + } + ```
2025-11-19 16:38:14 -08:00
name = "codex-execve-wrapper"
path = "src/bin/main_execve_wrapper.rs"
[[bin]]
name = "codex-exec-mcp-server"
path = "src/bin/main_mcp_server.rs"
[lib]
name = "codex_exec_server"
path = "src/lib.rs"
2025-11-18 16:20:19 -08:00
[lints]
workspace = true
[dependencies]
anyhow = { workspace = true }
async-trait = { workspace = true }
2025-11-18 16:20:19 -08:00
clap = { workspace = true, features = ["derive"] }
codex-core = { workspace = true }
libc = { workspace = true }
path-absolutize = { workspace = true }
rmcp = { workspace = true, default-features = false, features = [
"auth",
"elicitation",
"base64",
"client",
"macros",
"schemars",
"server",
"transport-child-process",
"transport-streamable-http-client-reqwest",
"transport-streamable-http-server",
"transport-io",
] }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
shlex = { workspace = true }
2025-11-18 16:20:19 -08:00
socket2 = { workspace = true }
tokio = { workspace = true, features = [
"io-std",
"macros",
"process",
"rt-multi-thread",
"signal",
] }
tracing = { workspace = true }
tracing-subscriber = { workspace = true, features = ["env-filter", "fmt"] }
[dev-dependencies]
pretty_assertions = { workspace = true }
tempfile = { workspace = true }