diff --git a/src/mcp/config.rs b/src/mcp/config.rs index 8b98b62..24b3c8e 100644 --- a/src/mcp/config.rs +++ b/src/mcp/config.rs @@ -63,6 +63,9 @@ pub struct McpServerConfig { /// Environment variables for stdio transport #[serde(default)] pub env: Option>, + /// Working directory for stdio transport (optional). If set, child process runs in this dir. + #[serde(default)] + pub cwd: Option, // HTTP transport fields /// Base URL for HTTP transport (Claude Desktop compatible naming) @@ -99,6 +102,7 @@ impl McpServerConfig { command, args: self.args.clone().unwrap_or_default(), env: self.env.clone().unwrap_or_default(), + cwd: self.cwd.as_ref().map(|s| std::path::PathBuf::from(s)), }) } "http" | "streamableHttp" => { @@ -124,6 +128,7 @@ impl McpServerConfig { command: Some(command.into()), args: Some(args), env: Some(HashMap::new()), + cwd: None, base_url: None, headers: None, description: None, @@ -139,6 +144,7 @@ impl McpServerConfig { command: None, args: None, env: None, + cwd: None, base_url: Some(url.into()), headers: Some(HashMap::new()), description: None, @@ -154,6 +160,7 @@ pub enum McpTransportConfig { command: String, args: Vec, env: HashMap, + cwd: Option, }, /// HTTP transport: connect to a remote server (Streamable HTTP) Http { @@ -300,6 +307,7 @@ mod tests { command: Some("npx".to_string()), args: Some(vec!["-y".to_string(), "server".to_string()]), env: None, + cwd: None, base_url: None, headers: None, description: None, @@ -317,6 +325,7 @@ mod tests { command: Some("npx".to_string()), args: Some(vec!["-y".to_string(), "server".to_string()]), env: None, + cwd: None, base_url: None, headers: None, description: None, @@ -335,6 +344,7 @@ mod tests { command: None, args: None, env: None, + cwd: None, base_url: None, headers: None, description: None, @@ -349,6 +359,7 @@ mod tests { command: None, args: None, env: None, + cwd: None, base_url: None, headers: None, description: None, @@ -363,6 +374,7 @@ mod tests { command: Some("cmd".to_string()), args: None, env: None, + cwd: None, base_url: None, headers: None, description: None, @@ -385,4 +397,27 @@ mod tests { assert!(matches!(transport_http, McpTransportConfig::Http { .. })); assert!(matches!(transport_streamable, McpTransportConfig::Http { .. })); } + + #[test] + fn test_stdio_cwd_field() { + let json = r#"{"mcpServers": {"test": {"type": "stdio", "command": "uv", "args": ["run", "server.py"], "cwd": "/some/path", "isActive": true}}}"#; + let config: McpConfig = serde_json::from_str(json).unwrap(); + let server = config.mcp_servers.get("test").unwrap(); + assert_eq!(server.cwd.as_deref(), Some("/some/path")); + let transport = server.transport().unwrap(); + match transport { + McpTransportConfig::Stdio { cwd, .. } => { + assert_eq!(cwd, Some(std::path::PathBuf::from("/some/path"))); + } + _ => panic!("Expected stdio transport"), + } + } + + #[test] + fn test_stdio_cwd_defaults_to_none() { + let json = r#"{"mcpServers": {"test": {"type": "stdio", "command": "uv", "args": ["run", "server.py"]}}}"#; + let config: McpConfig = serde_json::from_str(json).unwrap(); + let server = config.mcp_servers.get("test").unwrap(); + assert!(server.cwd.is_none()); + } } \ No newline at end of file