fix: add test that verifies that codex-exec-mcp-server starts up

This commit is contained in:
Michael Bolin
2025-12-04 16:41:00 -08:00
parent 073a8533b8
commit 8eae62769a
6 changed files with 121 additions and 2 deletions

1
codex-rs/Cargo.lock generated
View File

@@ -1253,6 +1253,7 @@ name = "codex-exec-server"
version = "0.0.0"
dependencies = [
"anyhow",
"assert_cmd",
"async-trait",
"clap",
"codex-core",

View File

@@ -1,8 +1,8 @@
[package]
name = "codex-exec-server"
version.workspace = true
edition.workspace = true
license.workspace = true
name = "codex-exec-server"
version.workspace = true
[[bin]]
name = "codex-execve-wrapper"
@@ -55,5 +55,6 @@ tracing = { workspace = true }
tracing-subscriber = { workspace = true, features = ["env-filter", "fmt"] }
[dev-dependencies]
assert_cmd = { workspace = true }
pretty_assertions = { workspace = true }
tempfile = { workspace = true }

View File

@@ -0,0 +1,3 @@
// Single integration test binary that aggregates all test modules.
// The submodules live in `tests/suite/`.
mod suite;

View File

@@ -0,0 +1,86 @@
use std::borrow::Cow;
use std::path::Path;
use std::process::Stdio;
use std::sync::Arc;
use anyhow::Result;
use pretty_assertions::assert_eq;
use rmcp::ServiceExt;
use rmcp::model::Tool;
use rmcp::model::object;
use rmcp::transport::ConfigureCommandExt;
use rmcp::transport::TokioChildProcess;
use serde_json::json;
use tokio::process::Command;
#[tokio::test(flavor = "current_thread")]
async fn auto_approve() -> Result<()> {
let mcp_executable = assert_cmd::Command::cargo_bin("codex-exec-mcp-server")?;
let execve_wrapper = assert_cmd::Command::cargo_bin("codex-execve-wrapper")?;
let bash = Path::new(env!("CARGO_MANIFEST_DIR"))
.join("tests")
.join("suite")
.join("bash");
let transport =
TokioChildProcess::new(Command::new(mcp_executable.get_program()).configure(|cmd| {
cmd.arg("--bash").arg(bash);
cmd.arg("--execve").arg(execve_wrapper.get_program());
// Important: pipe stdio so rmcp can speak JSON-RPC over stdin/stdout
cmd.stdin(Stdio::piped());
cmd.stdout(Stdio::piped());
// Optional but very helpful while debugging:
cmd.stderr(Stdio::inherit());
}))?;
let service = ().serve(transport).await?;
let tools = service.list_tools(Default::default()).await?.tools;
assert_eq!(
vec![Tool {
name: Cow::Borrowed("shell"),
title: None,
description: Some(Cow::Borrowed(
"Runs a shell command and returns its output. You MUST provide the workdir as an absolute path."
)),
input_schema: Arc::new(object(json!( {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"command": {
"description": "The bash string to execute.",
"type": "string",
},
"login": {
"description": "Launch Bash with -lc instead of -c: defaults to true.",
"nullable": true,
"type": "boolean",
},
"timeout_ms": {
"description": "The timeout for the command in milliseconds.",
"format": "uint64",
"minimum": 0,
"nullable": true,
"type": "integer",
},
"workdir": {
"description": "The working directory to execute the command in. Must be an absolute path.",
"type": "string",
},
},
"required": [
"command",
"workdir",
],
"title": "ExecParams",
"type": "object",
}))),
output_schema: None,
annotations: None,
icons: None,
meta: None
}],
tools
);
Ok(())
}

View File

@@ -0,0 +1,25 @@
#!/usr/bin/env dotslash
{
"name": "codex-bash",
"platforms": {
"macos-aarch64": {
"size": 37003612,
"hash": "blake3",
"digest": "d9cd5928c993b65c340507931c61c02bd6e9179933f8bf26a548482bb5fa53bb",
"format": "tar.gz",
"path": "package/vendor/aarch64-apple-darwin/bash/macos-15/bash",
"providers": [
{
"url": "https://github.com/openai/codex/releases/download/rust-v0.65.0/codex-shell-tool-mcp-npm-0.65.0.tgz"
},
{
"type": "github-release",
"repo": "openai/codex",
"tag": "rust-v0.65.0",
"name": "codex-shell-tool-mcp-npm-0.65.0.tgz"
}
]
}
}
}

View File

@@ -0,0 +1,3 @@
// TODO(mbolin): Open this up to more OS's once the Bash DotSlash file includes other platforms.
#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
mod auto_approve;