Skip to content

Strengthen the MCP server configuration specification for stdin/stdio transport and localhost network isolation scenarios #6004

Description

@lpcox

Problem

As surfaced in github/gh-aw#44113, the current MCP server configuration specification has gaps around how stdio and HTTP MCP servers behave under different network isolation modes. This leads to confusing failure modes and implicit compiler behaviors that aren't documented anywhere.

Specific gaps

  1. Localhost HTTP MCP servers under network isolation — When sandbox.agent.sudo: false (network isolation enabled), an HTTP MCP server configured with url: http://localhost:PORT/mcp silently gets rewritten to http://host.docker.internal:PORT/mcp by the compiler (rewriteLocalhostToDockerHost). However:

    • The spec never documents this rewrite behavior
    • Authors aren't told their server process must bind to 0.0.0.0 (not 127.0.0.1) to be reachable from the gateway container via host.docker.internal
    • There's no validation or warning when a server in the same workflow binds to --host 127.0.0.1 while the URL will be rewritten to host.docker.internal
  2. Stdio vs HTTP transport confusion for local servers — The workflow frontmatter supports command: for stdio servers (e.g., command: "uvx") but the MCP gateway spec says command: is NOT supported and requires container:. The relationship between frontmatter-level config and what the gateway actually receives is unclear.

  3. No unified "network reachability" section — There's no spec section that explains: "If your MCP server runs on the host and you're in network isolation mode, here are the constraints on addressing, binding, and transport selection."

Proposal: Clearer and stronger stdin/MCP configuration spec

1. Document the localhost rewrite rule

Add a section to the MCP gateway spec (or a new dedicated spec) that explicitly states:

When network isolation is enabled (sandbox.agent.sudo: false), the compiler rewrites loopback URLs (localhost, 127.0.0.1, ::1) in HTTP MCP server configurations to host.docker.internal. This is required because the MCP gateway runs inside a Docker container and cannot reach the runner's loopback interface.

2. Specify server binding requirements

Document that any host-side MCP server process started in workflow steps: MUST bind to 0.0.0.0 (all interfaces) when network isolation is active, because host.docker.internal resolves to the Docker bridge IP, not 127.0.0.1.

Add a compile-time lint or warning when:

  • An HTTP MCP server URL contains localhost AND
  • The same workflow starts a server process with --host 127.0.0.1 or --bind 127.0.0.1

3. Add a "Network Reachability Matrix"

A clear table documenting what works in each mode:

MCP Type URL / Address Network Isolation OFF Network Isolation ON
HTTP localhost:PORT ✅ Works directly ⚠️ Rewritten to host.docker.internal:PORT — server must bind 0.0.0.0
HTTP host.docker.internal:PORT ✅ Works (if Docker available) ✅ Works — server must bind 0.0.0.0
HTTP External URL ✅ Works ✅ Works (domain must be in allowlist)
Stdio container: image ✅ Containerized ✅ Containerized
Stdio command: (frontmatter) ✅ Compiled to gateway stdin config ❓ Unclear — needs specification

4. Reconcile frontmatter command: vs gateway spec

The frontmatter allows command: "uvx" + args: [...] for stdio servers, but the gateway spec says command: is unsupported. The compiler clearly bridges this gap (likely converting to container execution), but this translation should be explicitly specified so authors understand what happens to their config.

Context

Metadata

Metadata

Assignees

Labels

documentationImprovements or additions to documentation

Type

No type

Fields

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