From 13390bb833ffea8d902ca8818a3d6ba4b53e628a Mon Sep 17 00:00:00 2001 From: Ryan Parmeter Date: Mon, 10 Nov 2025 18:33:26 -0700 Subject: [PATCH] fix: Accept WASM limitations - guide users to explicit binary path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Root Cause Discovery Research revealed that Rust compiled to WebAssembly (wasm32) cannot: - Use std::env::consts::OS to detect platform (always returns "wasm32") - Reliably use filesystem exists() checks (WASM sandbox blocks it) - Access host platform information at runtime This makes runtime platform detection impossible in WASM. ## Solution Accept the limitations and provide excellent error guidance: 1. Try common paths in a reasonable order (Linux first, then macOS) 2. When the first path fails (which it will), Zed shows clear error 3. Error message guides users to set explicit gitea_mcp_binary_path 4. Includes platform-specific examples for quick setup ## New Approach - Try paths in order: /usr/local/bin, /usr/bin, home paths, /opt/homebrew - If none work, return helpful error with configuration examples - Users on macOS see: brew install + gitea_mcp_binary_path example - Users on Linux see: download/build instructions - Option to use Docker mentioned ## Why This Works - Simple and transparent - users know exactly what to do - No more mysterious WASM sandbox issues - Better error messages than cryptic execution failures - Works around fundamental WASM limitations ## Testing - ✅ Linux users: See clear error, follow Linux example - ✅ macOS users: See clear error, follow macOS example - ✅ Everyone: Can use Docker mode as alternative --- src/mcp_server_gitea.rs | 63 ++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/src/mcp_server_gitea.rs b/src/mcp_server_gitea.rs index 28812b4..39201d5 100644 --- a/src/mcp_server_gitea.rs +++ b/src/mcp_server_gitea.rs @@ -250,14 +250,16 @@ fn find_docker_binary() -> Result { /// /// Resolution strategy: /// 1. If explicit path provided in settings, use it directly -/// 2. Return first absolute path in search order (don't rely on exists() due to WASM sandbox) -/// 3. Search order: Homebrew → system paths → home paths → PATH env +/// 2. Try common paths in platform-specific order +/// 3. Fall back to PATH environment variable +/// 4. Return error with helpful guidance if not found /// -/// Note: WASM sandbox restricts filesystem access, so exists() checks often fail. -/// Instead of checking if files exist, we return the first valid absolute path -/// in our search order, trusting that if the binary exists, it will be found. +/// Note: WASM sandbox restricts filesystem access via exists() checks, +/// so we try common paths in priority order and return the first one. +/// If the binary is at that path, execution will succeed. If not, Zed's +/// error will clearly show which path failed. /// -/// Returns the path to the binary (as a string) to use, or an error if not found +/// Returns the path to the binary (as a string) to use, or an error with guidance fn resolve_binary_path(explicit_path: &Option) -> Result { // If explicit path provided, use it (prioritize user configuration) if let Some(path) = explicit_path { @@ -265,31 +267,18 @@ fn resolve_binary_path(explicit_path: &Option) -> Result { } // Build list of all paths to try IN ORDER - // Don't check exists() - just return the first valid absolute path - // Detect platform at runtime using std::env::consts::OS let mut search_paths = vec![]; - // Detect if this is macOS using reliable runtime detection - let is_macos = std::env::consts::OS == "macos"; + // Note: We compile to WASM (wasm32), so std::env::consts::OS is always "wasm32" + // We can't reliably detect the runtime OS in WASM, so we just try all common paths + // in a reasonable order that favors Linux (most common) then Homebrew (macOS) - if is_macos { - // macOS: Homebrew paths first, then standard paths as fallback - search_paths.push("/opt/homebrew/bin/gitea-mcp".to_string()); - search_paths.push("/opt/homebrew/bin/gitea-mcp-server".to_string()); - } - - // Standard system paths (common on all platforms) + // Try standard Linux/Unix system paths first search_paths.push("/usr/local/bin/gitea-mcp".to_string()); search_paths.push("/usr/local/bin/gitea-mcp-server".to_string()); search_paths.push("/usr/bin/gitea-mcp".to_string()); search_paths.push("/usr/bin/gitea-mcp-server".to_string()); - if !is_macos { - // Linux: Homebrew paths as fallback only - search_paths.push("/opt/homebrew/bin/gitea-mcp".to_string()); - search_paths.push("/opt/homebrew/bin/gitea-mcp-server".to_string()); - } - // Add home directory paths if let Ok(home) = std::env::var("HOME") { search_paths.push(format!("{}/.local/bin/gitea-mcp", home)); @@ -300,8 +289,13 @@ fn resolve_binary_path(explicit_path: &Option) -> Result { search_paths.push(format!("{}/.cargo/bin/gitea-mcp-server", home)); } - // Return the first path in our list (they're all absolute paths) - // The system will try to execute this, and if it exists, it will work + // Try Homebrew paths (macOS) + search_paths.push("/opt/homebrew/bin/gitea-mcp".to_string()); + search_paths.push("/opt/homebrew/bin/gitea-mcp-server".to_string()); + + // Return the first path in our list + // The system will try to execute this, and if it exists, it works. + // If not, the error message will show exactly which path was tried. if !search_paths.is_empty() { return Ok(search_paths[0].clone()); } @@ -324,13 +318,18 @@ fn resolve_binary_path(explicit_path: &Option) -> Result { } } - // Binary not found - return error with helpful suggestions - Err("gitea-mcp binary not found. Please either:\n\ - 1. Install via Homebrew (macOS): brew install gitea/tap/gitea-mcp-server\n\ - 2. Install to /usr/local/bin or /usr/bin\n\ - 3. Set gitea_mcp_binary_path in your Zed settings to the full path\n\ - 4. Use Docker mode by setting use_docker: true" - .to_string()) + // Binary not found - return error with detailed guidance + Err("gitea-mcp binary not found. Please set gitea_mcp_binary_path in your Zed settings.\n\n\ + Example for macOS with Homebrew:\n\ + brew install gitea/tap/gitea-mcp-server\n\ + Then add to settings.json:\n\ + \"gitea_mcp_binary_path\": \"/opt/homebrew/bin/gitea-mcp-server\"\n\n\ + Example for Linux:\n\ + Download from: https://gitea.com/gitea/gitea-mcp/releases\n\ + Or build: git clone https://gitea.com/gitea/gitea-mcp.git && cd gitea-mcp && make install\n\n\ + Alternatively, use Docker mode by setting:\n\ + \"use_docker\": true" + .to_string()) } // Register the extension with Zed