Skip to content

Gemini engine: MCP gateway URLs use host.docker.internal which doesn't resolve on host runner #29812

@lpcox

Description

@lpcox

Problem

The Gemini engine compiler generates MCP gateway URLs using host.docker.internal, but Gemini CLI runs directly on the host runner (not inside a Docker container). On Linux GitHub Actions runners, host.docker.internal does not resolve from the host — it only resolves inside Docker containers that are started with --add-host host.docker.internal:host-gateway.

This causes all MCP tools (github, safeoutputs) to be unreachable, which means:

  • Gemini cannot call list_pull_requests, search_issues, etc.
  • Gemini cannot call noop, add_comment, add_labels (safe outputs)
  • The "Validate safe outputs were invoked" step fails every time

Root Cause

The start_mcp_gateway.cjs script correctly writes Gemini-format config to .gemini/settings.json with MCP server entries. However, it uses the MCP_GATEWAY_DOMAIN value (host.docker.internal) for the URLs:

{
  "mcpServers": {
    "github": {
      "url": "http://host.docker.internal:8080/mcp/github",
      "headers": { "Authorization": "Bearer <key>" }
    },
    "safeoutputs": {
      "url": "http://host.docker.internal:8080/mcp/safeoutputs",
      "headers": { "Authorization": "Bearer <key>" }
    }
  }
}

This works for Claude because Claude runs inside the AWF sandbox container (where host.docker.internal resolves). But Gemini runs directly on the host where that hostname does not resolve.

Evidence

Failed run (before fix)

https://github.com/github/gh-aw-firewall/actions/runs/25259025540

Gateway logs show it wrote the config correctly:

[info] Gemini configuration written to .gemini/settings.json
[info] "github": { "url": "http://host.docker.internal:8080/mcp/github" }
[info] "safeoutputs": { "url": "http://host.docker.internal:8080/mcp/safeoutputs" }

But Gemini CLI reported:

MCP issues detected. Run /mcp list for status.

And tool calls failed:

Tool "noop" not found. Did you mean one of: "glob", "cli_help", "read_file"?
Tool "github:list_pull_requests" not found.

Successful run (after manual lock file patch)

https://github.com/github/gh-aw-firewall/actions/runs/25259435566

After replacing host.docker.internal with localhost in the lock file, all MCP tools work:

tool_name: "mcp_github_list_pull_requests" → success
tool_name: "mcp_safeoutputs_add_comment" → success  
tool_name: "mcp_safeoutputs_add_labels" → success

Workaround PR

github/gh-aw-firewall#2405 — manual .lock.yml patch that adds a post-processing step to replace host.docker.internallocalhost in the Gemini settings.

Suggested Fix

In start_mcp_gateway.cjs (or wherever Gemini-format config is generated), detect when the engine runs on the host (not in a container) and use localhost instead of host.docker.internal for the MCP server URLs.

Possible approaches:

  1. Engine-aware domain selection: For engines that run on the host (Gemini, Codex), use localhost. For engines that run in containers (Claude via AWF), use host.docker.internal.
  2. Always use localhost for the Gemini settings.json since Gemini always runs on the host, and let the gateway bind to 0.0.0.0 (it already does — the health endpoint responds on localhost:8080).
  3. Add a MCP_GATEWAY_HOST_DOMAIN variable that defaults to localhost and is used for host-side config generation, separate from MCP_GATEWAY_DOMAIN which is used for container-side config.

Additional Context

  • The MCP_GATEWAY_DOMAIN is set to host.docker.internal in the compiled lock file
  • The gateway health endpoint responds on http://localhost:8080/health confirming it binds to all interfaces
  • The "Write Gemini Config" step does a jq deep merge ($existing * $base) which correctly preserves the mcpServers block — the merge logic is fine
  • This likely affects any engine that runs directly on the host (not inside AWF/Docker)

Metadata

Metadata

Assignees

Labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions