Skip to main content

codex_wrapper/command/
mcp_server.rs

1/// Start Codex as an MCP server (stdio).
2///
3/// Wraps `codex mcp-server`.
4use crate::Codex;
5use crate::command::CodexCommand;
6use crate::error::Result;
7use crate::exec::{self, CommandOutput};
8
9/// Start Codex as an MCP server over stdio.
10#[derive(Debug, Clone, Default)]
11pub struct McpServerCommand {
12    config_overrides: Vec<String>,
13    enabled_features: Vec<String>,
14    disabled_features: Vec<String>,
15}
16
17impl McpServerCommand {
18    #[must_use]
19    pub fn new() -> Self {
20        Self::default()
21    }
22
23    #[must_use]
24    pub fn config(mut self, key_value: impl Into<String>) -> Self {
25        self.config_overrides.push(key_value.into());
26        self
27    }
28
29    #[must_use]
30    pub fn enable(mut self, feature: impl Into<String>) -> Self {
31        self.enabled_features.push(feature.into());
32        self
33    }
34
35    #[must_use]
36    pub fn disable(mut self, feature: impl Into<String>) -> Self {
37        self.disabled_features.push(feature.into());
38        self
39    }
40}
41
42impl CodexCommand for McpServerCommand {
43    type Output = CommandOutput;
44
45    fn args(&self) -> Vec<String> {
46        let mut args = vec!["mcp-server".into()];
47        for v in &self.config_overrides {
48            args.push("-c".into());
49            args.push(v.clone());
50        }
51        for v in &self.enabled_features {
52            args.push("--enable".into());
53            args.push(v.clone());
54        }
55        for v in &self.disabled_features {
56            args.push("--disable".into());
57            args.push(v.clone());
58        }
59        args
60    }
61
62    async fn execute(&self, codex: &Codex) -> Result<CommandOutput> {
63        exec::run_codex(codex, self.args()).await
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use super::*;
70
71    #[test]
72    fn mcp_server_args() {
73        assert_eq!(McpServerCommand::new().args(), vec!["mcp-server"]);
74    }
75
76    #[test]
77    fn mcp_server_with_config_args() {
78        let args = McpServerCommand::new()
79            .config("model=\"gpt-5\"")
80            .enable("web-search")
81            .args();
82        assert_eq!(
83            args,
84            vec![
85                "mcp-server",
86                "-c",
87                "model=\"gpt-5\"",
88                "--enable",
89                "web-search"
90            ]
91        );
92    }
93}