Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions docs/setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,48 @@ goose> Help me search for files related to authentication

---

### 🚀 Google Antigravity

Google Antigravity is an AI-powered IDE built on VS Code with deep Gemini integration and built-in MCP support.

**⚠️ Important:** Antigravity uses `serverUrl` (not `url`) for HTTP-based MCP servers. Using `url` will cause a connection error.

**Config file location:**

| Platform | Path |
|----------|------|
| macOS | `~/.gemini/antigravity/mcp_config.json` |
| Linux | `~/.gemini/antigravity/mcp_config.json` |
| Windows | `%USERPROFILE%\.gemini\antigravity\mcp_config.json` |

**Setup via UI:**

1. Open the Agent Panel (right sidebar)
2. Click **"..."** (More Options) → **MCP Servers** → **Manage MCP Servers**
3. Click **"View raw config"**
4. Add the MCPProxy configuration (see below)
5. Click **Refresh** to apply changes

**Setup via Configuration File:**

Edit your `mcp_config.json`:

```json
{
"mcpServers": {
"mcpproxy": {
"serverUrl": "http://127.0.0.1:8080/mcp"
}
}
}
```

**📝 Note:** MCPProxy's MCP endpoint does not require API key authentication, so no `headers` block is needed. Antigravity does not support `${workspaceFolder}` — use absolute paths in any server configuration.

**📚 Reference:** [Antigravity MCP Documentation](https://antigravity.google/docs/mcp)

---

## Optional HTTPS Setup

MCPProxy supports secure HTTPS connections with automatic certificate generation. **HTTP is enabled by default** for immediate compatibility, but HTTPS provides enhanced security for production use.
Expand Down
34 changes: 30 additions & 4 deletions internal/secureenv/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,19 +165,45 @@ func (m *Manager) discoverUnixPaths() []string {

// discoverWindowsPaths discovers common Windows tool paths
func (m *Manager) discoverWindowsPaths() []string {
// CRITICAL FIX for Issue #302:
// Try to read PATH from Windows registry first.
// This is necessary because when mcpproxy is launched via installer/service,
// it doesn't inherit the user's PATH environment variable.
// The registry is the source of truth for Windows PATH configuration.
if registryPaths := discoverWindowsPathsFromRegistry(); len(registryPaths) > 0 {
return registryPaths
}

// Fallback to hardcoded discovery if registry read fails
// This expanded list includes more common tool locations
homeDir, _ := os.UserHomeDir()

commonPaths := []string{
// System paths
`C:\Windows\System32`,
`C:\Windows`,

// Common development tools
`C:\Program Files\Docker\Docker\resources\bin`,
`C:\Program Files\Git\bin`,
`C:\Program Files\Git\cmd`,
`C:\Program Files\nodejs`,
`C:\Program Files\Go\bin`,

// User-specific tool paths (if homeDir is available)
}

// Add user-specific paths
if homeDir, err := os.UserHomeDir(); err == nil {
if homeDir != "" {
commonPaths = append(commonPaths,
homeDir+`\AppData\Local\Programs\Python\Python311\Scripts`,
homeDir+`\AppData\Roaming\npm`,
homeDir+`\.cargo\bin`, // Rust tools (cargo, uv)
homeDir+`\.local\bin`, // Python user scripts
homeDir+`\go\bin`, // Go binaries
homeDir+`\AppData\Roaming\npm`, // npm globals
homeDir+`\scoop\shims`, // Scoop packages
homeDir+`\AppData\Local\Programs\Python\Python313\Scripts`, // Python 3.13
homeDir+`\AppData\Local\Programs\Python\Python312\Scripts`, // Python 3.12
homeDir+`\AppData\Local\Programs\Python\Python311\Scripts`, // Python 3.11
homeDir+`\AppData\Local\Programs\Python\Python310\Scripts`, // Python 3.10
)
}

Expand Down
11 changes: 11 additions & 0 deletions internal/secureenv/manager_unix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//go:build !windows

package secureenv

// discoverWindowsPathsFromRegistry is a stub for non-Windows platforms
// On Unix/macOS, this function is never called because discoverWindowsPaths()
// is only called when runtime.GOOS == "windows"
func discoverWindowsPathsFromRegistry() []string {
// This should never be called on non-Windows platforms
return nil
}
97 changes: 97 additions & 0 deletions internal/secureenv/manager_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
//go:build windows

package secureenv

import (
"os"
"strings"

"golang.org/x/sys/windows/registry"
)

// expandWindowsEnvVars expands Windows-style %VAR% environment variables.
// os.ExpandEnv only handles $VAR/${VAR} syntax, NOT Windows %VAR%.
// registry.ExpandString calls the Windows ExpandEnvironmentStrings API.
func expandWindowsEnvVars(s string) string {
expanded, err := registry.ExpandString(s)
if err != nil {
return s // fallback to unexpanded
}
return expanded
}

// readWindowsRegistryPath reads the PATH environment variable from Windows registry
// This is necessary because when mcpproxy is launched via installer/service,
// it doesn't inherit the user's PATH environment variable.
// The registry is the source of truth for Windows PATH configuration.
func readWindowsRegistryPath() (string, error) {
var paths []string

// 1. Read USER PATH from HKEY_CURRENT_USER\Environment\Path
// This contains user-specific PATH additions (e.g., .cargo\bin, go\bin)
userKey, err := registry.OpenKey(registry.CURRENT_USER,
`Environment`, registry.QUERY_VALUE)
if err == nil {
defer userKey.Close()

userPath, _, err := userKey.GetStringValue("Path")
if err == nil && userPath != "" {
// CRITICAL: Expand Windows %VAR% environment variables
// Registry stores paths as REG_EXPAND_SZ with embedded %USERPROFILE% etc.
paths = append(paths, expandWindowsEnvVars(userPath))
}
}

// 2. Read SYSTEM PATH from HKEY_LOCAL_MACHINE\...\Environment\Path
// This contains system-wide PATH (e.g., C:\Windows\System32, Program Files)
sysKey, err := registry.OpenKey(registry.LOCAL_MACHINE,
`SYSTEM\CurrentControlSet\Control\Session Manager\Environment`,
registry.QUERY_VALUE)
if err == nil {
defer sysKey.Close()

systemPath, _, err := sysKey.GetStringValue("Path")
if err == nil && systemPath != "" {
paths = append(paths, expandWindowsEnvVars(systemPath))
}
}

// Combine User PATH + System PATH (user takes precedence)
fullPath := strings.Join(paths, string(os.PathListSeparator))

if fullPath == "" {
// If both registry reads failed, return error
return "", registry.ErrNotExist
}

return fullPath, nil
}

// discoverWindowsPathsFromRegistry reads PATH from registry and returns as slice
// This replaces the hardcoded discovery list when registry is available
func discoverWindowsPathsFromRegistry() []string {
registryPath, err := readWindowsRegistryPath()
if err != nil {
// Registry read failed, return empty slice (caller will use hardcoded fallback)
return nil
}

// Split the combined PATH into individual directories
parts := strings.Split(registryPath, string(os.PathListSeparator))

// Filter to only existing directories
var existingPaths []string
for _, path := range parts {
path = strings.TrimSpace(path)
if path == "" {
continue
}

// Check if directory exists
if info, err := os.Stat(path); err == nil && info.IsDir() {
existingPaths = append(existingPaths, path)
}
}

return existingPaths
}
Loading