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 { 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(()) }