Adds `codex mcp add`, `codex mcp list`, `codex mcp remove`. Currently writes to global config.
107 lines
3.2 KiB
Rust
107 lines
3.2 KiB
Rust
use std::path::Path;
|
|
|
|
use anyhow::Result;
|
|
use predicates::str::contains;
|
|
use pretty_assertions::assert_eq;
|
|
use serde_json::Value as JsonValue;
|
|
use tempfile::TempDir;
|
|
|
|
fn codex_command(codex_home: &Path) -> Result<assert_cmd::Command> {
|
|
let mut cmd = assert_cmd::Command::cargo_bin("codex")?;
|
|
cmd.env("CODEX_HOME", codex_home);
|
|
Ok(cmd)
|
|
}
|
|
|
|
#[test]
|
|
fn list_shows_empty_state() -> Result<()> {
|
|
let codex_home = TempDir::new()?;
|
|
|
|
let mut cmd = codex_command(codex_home.path())?;
|
|
let output = cmd.args(["mcp", "list"]).output()?;
|
|
assert!(output.status.success());
|
|
let stdout = String::from_utf8(output.stdout)?;
|
|
assert!(stdout.contains("No MCP servers configured yet."));
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn list_and_get_render_expected_output() -> Result<()> {
|
|
let codex_home = TempDir::new()?;
|
|
|
|
let mut add = codex_command(codex_home.path())?;
|
|
add.args([
|
|
"mcp",
|
|
"add",
|
|
"docs",
|
|
"--env",
|
|
"TOKEN=secret",
|
|
"--",
|
|
"docs-server",
|
|
"--port",
|
|
"4000",
|
|
])
|
|
.assert()
|
|
.success();
|
|
|
|
let mut list_cmd = codex_command(codex_home.path())?;
|
|
let list_output = list_cmd.args(["mcp", "list"]).output()?;
|
|
assert!(list_output.status.success());
|
|
let stdout = String::from_utf8(list_output.stdout)?;
|
|
assert!(stdout.contains("Name"));
|
|
assert!(stdout.contains("docs"));
|
|
assert!(stdout.contains("docs-server"));
|
|
assert!(stdout.contains("TOKEN=secret"));
|
|
|
|
let mut list_json_cmd = codex_command(codex_home.path())?;
|
|
let json_output = list_json_cmd.args(["mcp", "list", "--json"]).output()?;
|
|
assert!(json_output.status.success());
|
|
let stdout = String::from_utf8(json_output.stdout)?;
|
|
let parsed: JsonValue = serde_json::from_str(&stdout)?;
|
|
let array = parsed.as_array().expect("expected array");
|
|
assert_eq!(array.len(), 1);
|
|
let entry = &array[0];
|
|
assert_eq!(entry.get("name"), Some(&JsonValue::String("docs".into())));
|
|
assert_eq!(
|
|
entry.get("command"),
|
|
Some(&JsonValue::String("docs-server".into()))
|
|
);
|
|
|
|
let args = entry
|
|
.get("args")
|
|
.and_then(|v| v.as_array())
|
|
.expect("args array");
|
|
assert_eq!(
|
|
args,
|
|
&vec![
|
|
JsonValue::String("--port".into()),
|
|
JsonValue::String("4000".into())
|
|
]
|
|
);
|
|
|
|
let env = entry
|
|
.get("env")
|
|
.and_then(|v| v.as_object())
|
|
.expect("env map");
|
|
assert_eq!(env.get("TOKEN"), Some(&JsonValue::String("secret".into())));
|
|
|
|
let mut get_cmd = codex_command(codex_home.path())?;
|
|
let get_output = get_cmd.args(["mcp", "get", "docs"]).output()?;
|
|
assert!(get_output.status.success());
|
|
let stdout = String::from_utf8(get_output.stdout)?;
|
|
assert!(stdout.contains("docs"));
|
|
assert!(stdout.contains("command: docs-server"));
|
|
assert!(stdout.contains("args: --port 4000"));
|
|
assert!(stdout.contains("env: TOKEN=secret"));
|
|
assert!(stdout.contains("remove: codex mcp remove docs"));
|
|
|
|
let mut get_json_cmd = codex_command(codex_home.path())?;
|
|
get_json_cmd
|
|
.args(["mcp", "get", "docs", "--json"])
|
|
.assert()
|
|
.success()
|
|
.stdout(contains("\"name\": \"docs\""));
|
|
|
|
Ok(())
|
|
}
|