
mcp-gateway
Comprehensive management of MCP Gateway (gh-aw-mcpg) for running GitHub MCP servers. Use when: (1) S
MCP Gateway Management Skill
This skill provides comprehensive guidance for setting up, managing, and debugging the MCP Gateway (gh-aw-mcpg) for running GitHub MCP servers.
What is MCP Gateway?
The MCP Gateway (gh-aw-mcpg) is a proxy server that:
- Routes requests to multiple MCP (Model Context Protocol) backend servers
- Manages MCP server lifecycle (start/stop containers)
- Provides HTTP/SSE transport for MCP protocol
- Handles authentication and session management
- Supports both routed (
/mcp/<server>) and unified (/mcp) modes
Quick Start
1. Start the Gateway
python3 scripts/start-gateway.py
This will:
- Get GitHub token from
ghCLI (or use$GITHUB_PERSONAL_ACCESS_TOKEN) - Create MCP Gateway configuration
- Start gateway container on port 80
- Spawn GitHub MCP server container
- Display connection information
Key Environment Variables:
GATEWAY_VERSION- Gateway version (default: v0.0.59)GATEWAY_PORT- Host port (default: 80)GATEWAY_DOMAIN- Gateway domain (default: localhost)GATEWAY_API_KEY- API authentication key (auto-generated)GITHUB_PERSONAL_ACCESS_TOKEN- GitHub PAT for MCP server
2. Verify Gateway is Running
curl http://127.0.0.1:80/health | jq .
Expected response:
{
"status": "healthy",
"specVersion": "1.5.0",
"gatewayVersion": "v0.0.59",
"servers": {
"github": {
"status": "running",
"uptime": 0
}
}
}
3. Debug Issues
python3 scripts/debug-gateway.py
Shows:
- Container status
- Health check results
- Gateway logs
- MCP server containers
- Common configuration issues
4. Stop the Gateway
python3 scripts/stop-gateway.py
Stops and removes the gateway container and any MCP server containers.
Configuration
Gateway Config Format (v0.0.59+)
The gateway requires JSON configuration via stdin:
{
"mcpServers": {
"github": {
"type": "stdio",
"container": "ghcr.io/github/github-mcp-server:latest",
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxx"
}
}
},
"gateway": {
"port": 8000,
"domain": "localhost",
"apiKey": "your-api-key"
}
}
Key Points:
type: "stdio"- Containerized stdio-based MCP servercontainer- Docker image for the MCP serverenv.GITHUB_PERSONAL_ACCESS_TOKEN- Must be explicit value (not empty string)gateway.domain- Required field in v0.0.59+gateway.apiKey- Used for client authentication
Required Environment Variables (Container)
When starting the container, you MUST set:
MCP_GATEWAY_PORT=8000- Internal port (must match config)MCP_GATEWAY_DOMAIN=localhost- Gateway domain (must match config)MCP_GATEWAY_API_KEY=xxx- API key (must match config)GITHUB_PERSONAL_ACCESS_TOKEN=xxx- For token passthrough
Starting the Container
Important: The container must be started with -i flag and config piped via stdin:
cat config.json | docker run -i \
--name mcpg-gateway \
-p 80:8000 \
-v /var/run/docker.sock:/var/run/docker.sock \
-e "GITHUB_PERSONAL_ACCESS_TOKEN=${TOKEN}" \
-e "MCP_GATEWAY_PORT=8000" \
-e "MCP_GATEWAY_DOMAIN=localhost" \
-e "MCP_GATEWAY_API_KEY=${API_KEY}" \
ghcr.io/githubnext/gh-aw-mcpg:v0.0.59
Note: Do not use -d (detached) with -i - run in background using & instead:
(cat config.json | docker run -i ...) > /tmp/gateway.log 2>&1 &
Using with Copilot CLI
Setup
python3 scripts/setup-copilot.py
This creates /tmp/mcp-gateway-config.json:
{
"mcpServers": {
"github-gateway": {
"type": "http",
"url": "http://host.docker.internal:80/mcp/github",
"headers": {
"Authorization": "your-api-key"
},
"tools": ["*"]
}
}
}
Usage (Direct)
npx @github/copilot \
--disable-builtin-mcps \
--additional-mcp-config @/tmp/mcp-gateway-config.json \
--allow-all-tools \
--prompt "List 3 recent issues from githubnext/gh-aw"
Usage (With AWF)
sudo -E awf \
--enable-host-access \
--mount /tmp:/tmp:rw \
--allow-domains 'host.docker.internal,api.github.com,*.githubusercontent.com' \
-- npx -y @github/copilot \
--disable-builtin-mcps \
--additional-mcp-config @/tmp/mcp-gateway-config.json \
--allow-all-tools \
--prompt "Your prompt here"
Key Flags:
--enable-host-access- Enableshost.docker.internalresolution--mount /tmp:/tmp:rw- Makes MCP config accessible in container--disable-builtin-mcps- Prevents Copilot from spawning its own MCP server--additional-mcp-config- Uses HTTP-based gateway config
Troubleshooting
Gateway Won't Start
Symptom: Container immediately exits or restarts
Check:
- Are all required env vars set? (
MCP_GATEWAY_PORT,MCP_GATEWAY_DOMAIN,MCP_GATEWAY_API_KEY) - Is config being piped via stdin? (container must use
-iflag) - Is config format valid JSON?
Debug:
docker logs mcpg-gateway
Look for:
- "Required environment variables not set"
- "Container was not started with -i flag"
- "Configuration validation error"
GitHub MCP Server Fails to Launch
Symptom: Logs show "failed to register tools from github"
Check:
- Is
GITHUB_PERSONAL_ACCESS_TOKENexplicitly set in config (not empty string)? - Is the token valid and has required scopes?
- Is Docker socket mounted (
-v /var/run/docker.sock:/var/run/docker.sock)?
Debug:
docker logs mcpg-gateway 2>&1 | grep -A5 'GITHUB_PERSONAL_ACCESS_TOKEN'
Look for:
- "✗ WARNING: Env passthrough for GITHUB_PERSONAL_ACCESS_TOKEN requested but NOT FOUND"
- "❌ MCP Connection Failed"
Fix: Use explicit token value in config instead of variable expansion:
{
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_actualtoken123"
}
}
Copilot Can't Connect to Gateway
Symptom: "fetch failed" or "ECONNREFUSED" errors
Check:
- Is gateway running?
curl http://127.0.0.1:80/health - Is
--enable-host-accessflag set (for AWF)? - Is
host.docker.internalin allowed domains? - Is MCP config file path correct and mounted?
Debug:
# From within AWF container
curl -v http://host.docker.internal:80/health
"method is invalid during session initialization"
Symptom: Tool calls fail with initialization error
Cause: HTTP sessions are stateless - each request creates a new session
Solution: This is expected behavior for HTTP transport. The gateway handles initialization automatically for each request. If you see persistent errors, check:
- Is the Authorization header correct?
- Is the MCP Gateway version latest?
Port 80 Already in Use
Symptom: "address already in use" when starting container
Solution: Use different host port:
GATEWAY_PORT=8080 python3 scripts/start-gateway.py
Then update Copilot config to use port 8080.
Architecture
┌─────────────────────────────────────────────────────┐
│ HOST MACHINE │
│ │
│ ┌──────────────────┐ │
│ │ MCP Gateway │ │
│ │ Container │ │
│ │ Port 80:8000 │ │
│ └────────┬─────────┘ │
│ │ spawns via docker socket │
│ ▼ │
│ ┌──────────────────┐ │
│ │ GitHub MCP │ │
│ │ Server │ │
│ │ Container │ │
│ └──────────────────┘ │
│ │
│ Client connects to http://127.0.0.1:80/mcp/github │
└──────────────────────────────────────────────────────┘
With AWF:
┌─────────────────────────────────────────────────────┐
│ HOST │
│ ┌──────────────┐ │
│ │ MCP Gateway │◄──────────┐ │
│ │ Port 80 │ │ │
│ └──────────────┘ │ │
│ │ │
│ ┌──────────────────────────┼──────────────┐ │
│ │ AWF Network │ │ │
│ │ ┌────────┐ ┌─────────┴──┐ │ │
│ │ │ Agent │───▶│ Squid │ │ │
│ │ │ │ │ Proxy │──────────┘ │
│ │ │Copilot │ │ │ CONNECT to │
│ │ │ CLI │ │host.docker.│ host:80 │
│ │ └────────┘ │ internal │ │
│ │ └────────────┘ │
│ └───────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
Version Differences
v0.0.59 (Latest)
New Requirements:
- Config via stdin with
-iflag (not file mount) - Three required env vars:
MCP_GATEWAY_PORT,MCP_GATEWAY_DOMAIN,MCP_GATEWAY_API_KEY gateway.domainfield required in config- Explicit token values (variable expansion
${VAR}may not work reliably)
v0.0.10 (Older)
Simpler startup:
- No stdin config required
- Fewer env vars needed
- Default configuration works out of the box
Recommendation: Use v0.0.59+ for latest features and security improvements.
Best Practices
-
Token Management
- Use
gh auth tokento get current GitHub token - Store API key securely (don't commit to repo)
- Rotate tokens regularly
- Use
-
Container Lifecycle
- Run gateway in background with
¬-d - Redirect logs to file for debugging
- Use
--restart unless-stoppedfor production
- Run gateway in background with
-
Networking
- Use port 80 for simplicity (or custom port if needed)
- Always use
host.docker.internalfrom containers - Add to AWF allowed domains
-
Debugging
- Always check health endpoint first
- Use debug script for comprehensive diagnostics
- Check both gateway and MCP server logs
-
Security
- Only use
--enable-host-accesswith trusted workloads - Keep API keys secret
- Use restrictive domain whitelists in AWF
- Only use
Common Commands
# Start gateway
python3 scripts/start-gateway.py
# Check status
curl http://127.0.0.1:80/health | jq .
# View logs
docker logs mcpg-gateway -f
# Debug issues
python3 scripts/debug-gateway.py
# Setup Copilot
python3 scripts/setup-copilot.py
# Stop gateway
python3 scripts/stop-gateway.py
# Restart gateway
docker restart mcpg-gateway
# Check MCP servers
docker ps | grep mcp
# Clean up everything
docker stop mcpg-gateway && docker rm mcpg-gateway
docker ps -a | grep mcp | awk '{print $1}' | xargs -r docker rm -f