feat: MCP stdio 传输支持工作目录配置
This commit is contained in:
parent
b206e077e2
commit
a78f5c5512
@ -63,6 +63,9 @@ pub struct McpServerConfig {
|
|||||||
/// Environment variables for stdio transport
|
/// Environment variables for stdio transport
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub env: Option<HashMap<String, String>>,
|
pub env: Option<HashMap<String, String>>,
|
||||||
|
/// Working directory for stdio transport (optional). If set, child process runs in this dir.
|
||||||
|
#[serde(default)]
|
||||||
|
pub cwd: Option<String>,
|
||||||
|
|
||||||
// HTTP transport fields
|
// HTTP transport fields
|
||||||
/// Base URL for HTTP transport (Claude Desktop compatible naming)
|
/// Base URL for HTTP transport (Claude Desktop compatible naming)
|
||||||
@ -99,6 +102,7 @@ impl McpServerConfig {
|
|||||||
command,
|
command,
|
||||||
args: self.args.clone().unwrap_or_default(),
|
args: self.args.clone().unwrap_or_default(),
|
||||||
env: self.env.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" => {
|
"http" | "streamableHttp" => {
|
||||||
@ -124,6 +128,7 @@ impl McpServerConfig {
|
|||||||
command: Some(command.into()),
|
command: Some(command.into()),
|
||||||
args: Some(args),
|
args: Some(args),
|
||||||
env: Some(HashMap::new()),
|
env: Some(HashMap::new()),
|
||||||
|
cwd: None,
|
||||||
base_url: None,
|
base_url: None,
|
||||||
headers: None,
|
headers: None,
|
||||||
description: None,
|
description: None,
|
||||||
@ -139,6 +144,7 @@ impl McpServerConfig {
|
|||||||
command: None,
|
command: None,
|
||||||
args: None,
|
args: None,
|
||||||
env: None,
|
env: None,
|
||||||
|
cwd: None,
|
||||||
base_url: Some(url.into()),
|
base_url: Some(url.into()),
|
||||||
headers: Some(HashMap::new()),
|
headers: Some(HashMap::new()),
|
||||||
description: None,
|
description: None,
|
||||||
@ -154,6 +160,7 @@ pub enum McpTransportConfig {
|
|||||||
command: String,
|
command: String,
|
||||||
args: Vec<String>,
|
args: Vec<String>,
|
||||||
env: HashMap<String, String>,
|
env: HashMap<String, String>,
|
||||||
|
cwd: Option<std::path::PathBuf>,
|
||||||
},
|
},
|
||||||
/// HTTP transport: connect to a remote server (Streamable HTTP)
|
/// HTTP transport: connect to a remote server (Streamable HTTP)
|
||||||
Http {
|
Http {
|
||||||
@ -300,6 +307,7 @@ mod tests {
|
|||||||
command: Some("npx".to_string()),
|
command: Some("npx".to_string()),
|
||||||
args: Some(vec!["-y".to_string(), "server".to_string()]),
|
args: Some(vec!["-y".to_string(), "server".to_string()]),
|
||||||
env: None,
|
env: None,
|
||||||
|
cwd: None,
|
||||||
base_url: None,
|
base_url: None,
|
||||||
headers: None,
|
headers: None,
|
||||||
description: None,
|
description: None,
|
||||||
@ -317,6 +325,7 @@ mod tests {
|
|||||||
command: Some("npx".to_string()),
|
command: Some("npx".to_string()),
|
||||||
args: Some(vec!["-y".to_string(), "server".to_string()]),
|
args: Some(vec!["-y".to_string(), "server".to_string()]),
|
||||||
env: None,
|
env: None,
|
||||||
|
cwd: None,
|
||||||
base_url: None,
|
base_url: None,
|
||||||
headers: None,
|
headers: None,
|
||||||
description: None,
|
description: None,
|
||||||
@ -335,6 +344,7 @@ mod tests {
|
|||||||
command: None,
|
command: None,
|
||||||
args: None,
|
args: None,
|
||||||
env: None,
|
env: None,
|
||||||
|
cwd: None,
|
||||||
base_url: None,
|
base_url: None,
|
||||||
headers: None,
|
headers: None,
|
||||||
description: None,
|
description: None,
|
||||||
@ -349,6 +359,7 @@ mod tests {
|
|||||||
command: None,
|
command: None,
|
||||||
args: None,
|
args: None,
|
||||||
env: None,
|
env: None,
|
||||||
|
cwd: None,
|
||||||
base_url: None,
|
base_url: None,
|
||||||
headers: None,
|
headers: None,
|
||||||
description: None,
|
description: None,
|
||||||
@ -363,6 +374,7 @@ mod tests {
|
|||||||
command: Some("cmd".to_string()),
|
command: Some("cmd".to_string()),
|
||||||
args: None,
|
args: None,
|
||||||
env: None,
|
env: None,
|
||||||
|
cwd: None,
|
||||||
base_url: None,
|
base_url: None,
|
||||||
headers: None,
|
headers: None,
|
||||||
description: None,
|
description: None,
|
||||||
@ -385,4 +397,27 @@ mod tests {
|
|||||||
assert!(matches!(transport_http, McpTransportConfig::Http { .. }));
|
assert!(matches!(transport_http, McpTransportConfig::Http { .. }));
|
||||||
assert!(matches!(transport_streamable, 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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user