gestura_core_mcp/
cmd_utils.rs

1use std::collections::HashMap;
2use std::path::PathBuf;
3
4/// Resolves a generic command name to its platform-specific executable variant.
5/// On Windows, `npx` becomes `npx.cmd`, `uvx` becomes `uvx.exe`, etc.
6#[allow(dead_code)]
7pub fn resolve_mcp_command(command: &str) -> String {
8    #[cfg(target_os = "windows")]
9    {
10        if command == "npx" {
11            return "npx.cmd".to_string();
12        }
13        if command == "npm" {
14            return "npm.cmd".to_string();
15        }
16        if command == "uv" {
17            return "uv.exe".to_string(); // Or uv.cmd depending on install method
18        }
19        if command == "uvx" {
20            return "uvx.exe".to_string();
21        }
22    }
23    command.to_string()
24}
25
26/// Injects additional standard paths into a process environment map,
27/// ensuring that GUI apps (which often launch with restricted profiles on macOS/Linux)
28/// can still find `npx`, `uv`, `docker` etc., where they are typically installed.
29#[allow(dead_code)]
30pub fn inject_enriched_path(provided_env: &mut HashMap<String, String>) {
31    // Only apply enrichment if PATH doesn't exist explicitly in the user-provided env map
32    if provided_env.keys().any(|k| k.eq_ignore_ascii_case("PATH")) {
33        return;
34    }
35
36    if let Some(existing_path) = std::env::var_os("PATH") {
37        let mut paths = std::env::split_paths(&existing_path).collect::<Vec<_>>();
38
39        let extra_paths = vec!["/usr/local/bin", "/opt/homebrew/bin", "/opt/local/bin"];
40
41        for ep in extra_paths {
42            let p = PathBuf::from(ep);
43            if p.exists() && !paths.contains(&p) {
44                paths.push(p);
45            }
46        }
47
48        // Add ~/.cargo/bin if it exists
49        if let Some(mut home) = dirs::home_dir() {
50            home.push(".cargo");
51            home.push("bin");
52            if home.exists() && !paths.contains(&home) {
53                paths.push(home);
54            }
55        }
56
57        if let Ok(new_path) = std::env::join_paths(paths) {
58            provided_env.insert("PATH".to_string(), new_path.to_string_lossy().to_string());
59        }
60    }
61}