-
Notifications
You must be signed in to change notification settings - Fork 182
Description
Summary
Enable MCP servers running on the host to be accessible by agents running inside the awf (aw-firewall) container through the mcp-gateway, using the standard MCP streamable-http protocol.
Current State
mcp-gateway (awmg) currently:
- Exposes custom HTTP endpoints:
/health,/servers,/mcp/{server}(POST) - Uses simple JSON-RPC over HTTP, NOT the standard MCP streamable-http protocol
- Only supports command/stdio transport for backend MCP servers
- Has config rewriting that generates
http://host.docker.internal:PORT/mcp/{server}URLs
awf (firewall) currently:
- Runs agents in isolated containers on dedicated network (172.30.0.0/24)
- Routes HTTP traffic through Squid proxy with domain whitelisting
- Allows localhost traffic (stdio MCP servers work automatically)
- Supports
host.docker.internalfor accessing host services
The Problem
The current gateway's /mcp/{server} endpoint is a custom JSON POST API, not a proper MCP streamable-http endpoint. An MCP client using StreamableClientTransport (which is the standard way to connect via HTTP) won't be able to communicate with it correctly.
Proposed Architecture
┌─────────────────────────────────────────────────────────────────┐
│ HOST MACHINE │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ mcp-gateway (awmg) │ │
│ │ │ │
│ │ HTTP Server (:8080) │ │
│ │ └── /mcp ← StreamableHTTPHandler (NEW) │ │
│ │ └── routes to appropriate backend MCP server │ │
│ │ │ │
│ │ Backend MCP Sessions (stdio): │ │
│ │ ├── gh-aw mcp-server │ │
│ │ ├── filesystem server │ │
│ │ └── other MCP servers... │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ▲ │
│ │ host.docker.internal:8080 │
│ ┌────────────────────────┼─────────────────────────────────┐ │
│ │ awf container │ │ │
│ │ │ │ │
│ │ Agent (Copilot/Claude/Codex) │ │
│ │ └── MCP Client │ │
│ │ └── StreamableClientTransport │ │
│ │ Endpoint: http://host.docker.internal:8080/mcp │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Required Changes
1. Gateway: Add StreamableHTTPHandler endpoint
The gateway needs to expose a proper MCP streamable-http endpoint. The go-sdk already has StreamableHTTPHandler available (used in mcp_server.go:762-794):
handler := mcp.NewStreamableHTTPHandler(func(req *http.Request) *mcp.Server {
// Route based on request path or header to appropriate backend
return server
}, &mcp.StreamableHTTPOptions{
SessionTimeout: 2 * time.Hour,
})The gateway would need to:
- Create a virtual "aggregated" MCP server that combines tools from all backends
- Expose this via
StreamableHTTPHandleron/mcp - When tools are called, route to the appropriate backend MCP session
2. Tool Aggregation Strategy
Two approaches to consider:
Option A - Namespace prefixing: Tools from different servers get prefixed (e.g., gh-aw:list_files, filesystem:read_file)
Option B - Flat namespace: All tools exposed without prefix, conflicts resolved by priority
3. Agent Configuration
The agent inside awf would use a single MCP config entry:
{
"mcpServers": {
"gateway": {
"url": "http://host.docker.internal:8080/mcp"
}
}
}4. Firewall Whitelist
host.docker.internal needs to be whitelisted in the Squid proxy configuration for the awf container.
Benefits
- Security: MCP servers run on host with full access; agent runs in restricted container
- Simplicity: Agent sees single MCP endpoint with all tools aggregated
- Standard Protocol: Uses proper MCP streamable-http, not custom API
- Existing Patterns: Both
StreamableClientTransportandStreamableHTTPHandlerare already used in the codebase
Implementation Scope
Main work in pkg/cli/mcp_gateway_command.go:
- Create an aggregated
mcp.Serverthat combines tools from all backend sessions - Replace current HTTP handlers with
StreamableHTTPHandler - Implement tool routing logic to dispatch calls to appropriate backends
References
- Existing StreamableHTTPHandler usage:
pkg/cli/mcp_server.go:762-794 - Existing StreamableClientTransport usage:
pkg/cli/mcp_inspect_mcp.go:238-276 - Current gateway implementation:
pkg/cli/mcp_gateway_command.go - Gateway spec:
specs/mcp-gateway.md