Skip to content
GitHub Agentic Workflows

MCP Gateway Specification

Version: 1.0.0
Status: Draft Specification
Latest Version: mcp-gateway
Editor: GitHub Agentic Workflows Team


This specification defines the Model Context Protocol (MCP) Gateway, a transparent proxy service that enables unified HTTP access to multiple MCP servers. The gateway supports containerized MCP servers and HTTP-based MCP servers. The gateway provides protocol translation, server isolation, authentication, and health monitoring capabilities.

This section describes the status of this document at the time of publication. This is a draft specification and may be updated, replaced, or made obsolete by other documents at any time.

This document is governed by the GitHub Agentic Workflows project specifications process.

  1. Introduction
  2. Conformance
  3. Architecture
  4. Configuration
  5. Protocol Behavior
  6. Server Isolation
  7. Authentication
  8. Health Monitoring
  9. Error Handling
  10. Compliance Testing

The MCP Gateway serves as a protocol translation layer between MCP clients expecting HTTP-based communication and MCP servers running in containers or accessible via HTTP. It enables:

  • Protocol Translation: Converting between containerized stdio servers and HTTP transports
  • Unified Access: Single HTTP endpoint for multiple MCP servers
  • Server Isolation: Enforcing boundaries between server instances through containerization
  • Authentication: Token-based access control
  • Health Monitoring: Service availability endpoints

The gateway requires that stdio-based MCP servers MUST be containerized. Direct command execution (stdio+command without containerization) is NOT supported because it cannot provide the necessary isolation and portability guarantees.

This specification covers:

  • Gateway configuration format and semantics
  • Protocol translation behavior
  • Server lifecycle management
  • Authentication mechanisms
  • Health monitoring interfaces
  • Error handling requirements

This specification does NOT cover:

  • Model Context Protocol (MCP) core protocol semantics
  • Individual MCP server implementations
  • Client-side MCP implementations
  • User interfaces or interactive features (e.g., elicitation)

The gateway MUST be designed for:

  • Headless Operation: No user interaction required during runtime
  • Fail-Fast Behavior: Immediate failure with diagnostic information
  • Forward Compatibility: Graceful rejection of unknown configuration features
  • Security: Isolation between servers and secure credential handling

A conforming MCP Gateway implementation is one that satisfies all MUST, REQUIRED, and SHALL requirements in this specification.

A partially conforming MCP Gateway implementation is one that satisfies all MUST requirements but MAY lack support for optional features marked with SHOULD or MAY.

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.

Implementations MUST support:

  • Level 1 (Required): Basic proxy functionality, stdio transport, configuration parsing
  • Level 2 (Standard): HTTP transport, authentication, health endpoints
  • Level 3 (Complete): All optional features including variable expressions, timeout configuration

┌─────────────────────────────────────────────────────────┐
│ MCP Client │
│ (HTTP Transport) │
└──────────────────────┬──────────────────────────────────┘
│ HTTP/JSON-RPC
┌─────────────────────────────────────────────────────────┐
│ MCP Gateway │
│ ┌───────────────────────────────────────────────────┐ │
│ │ Authentication & Authorization Layer │ │
│ └───────────────────────────────────────────────────┘ │
│ ┌───────────────────────────────────────────────────┐ │
│ │ Protocol Translation Layer │ │
│ └───────────────────────────────────────────────────┘ │
│ ┌───────────────────────────────────────────────────┐ │
│ │ Server Isolation & Lifecycle Management │ │
│ └───────────────────────────────────────────────────┘ │
└──────┬──────────────┬──────────────┬───────────────────┘
│ │ │
│ stdio │ HTTP │ stdio
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ MCP │ │ MCP │ │ MCP │
│ Server │ │ Server │ │ Server │
│ 1 │ │ 2 │ │ N │
└─────────┘ └─────────┘ └─────────┘

The gateway MUST support the following transport mechanisms:

  • stdio (containerized): MCP servers running in containers with standard input/output based communication
  • HTTP: Direct HTTP-based MCP servers

The gateway MUST translate all upstream transports to HTTP for client communication.

Stdio-based MCP servers MUST be containerized. The gateway SHALL NOT support direct command execution without containerization (stdio+command) because:

  1. Containerization provides necessary process isolation and security boundaries
  2. Containers enable reproducible environments across different deployment contexts
  3. Container images provide versioning and dependency management
  4. Containerization ensures portability and consistent behavior

Direct command execution of stdio servers (e.g., command: "node server.js" without a container) is explicitly NOT SUPPORTED by this specification.

The gateway operates in a headless mode:

  1. Configuration is provided via stdin (JSON format)
  2. Secrets are provided via environment variables
  3. Startup output is written to stdout (rewritten configuration)
  4. Error messages are written to stdout as error payloads
  5. HTTP server accepts client requests on configured port

The gateway MUST accept configuration via stdin in JSON format conforming to the MCP configuration file schema.

{
"mcpServers": {
"server-name": {
"container": "string",
"entrypointArgs": ["string"],
"env": {
"VAR_NAME": "value"
},
"type": "stdio" | "http",
"url": "string"
}
},
"gateway": {
"port": 8080,
"apiKey": "string",
"domain": "string",
"startupTimeout": 30,
"toolTimeout": 60
}
}

Each server configuration MUST support:

FieldTypeRequiredDescription
containerstringConditional*Container image for the MCP server (required for stdio servers)
entrypointArgsarray[string]NoArguments passed to container entrypoint (container only)
envobjectNoEnvironment variables for the server process
typestringNoTransport type: “stdio” or “http” (default: “stdio”)
urlstringConditional**HTTP endpoint URL for HTTP servers

*Required for stdio servers (containerized execution)
**Required for HTTP servers

Note: The command field is NOT supported. Stdio servers MUST use the container field to specify a containerized MCP server. Direct command execution is not supported by this specification.

The optional gateway section configures gateway-specific behavior:

FieldTypeDefaultDescription
portinteger8080HTTP server port
apiKeystring(none)API key for authentication
domainstringlocalhostGateway domain (localhost or host.docker.internal)
startupTimeoutinteger30Server startup timeout in seconds
toolTimeoutinteger60Tool invocation timeout in seconds

Configuration values MAY contain variable expressions using the syntax:

"${VARIABLE_NAME}"

The gateway MUST:

  1. Detect variable expressions in configuration values
  2. Replace expressions with values from process environment variables
  3. FAIL IMMEDIATELY if a referenced variable is not defined
  4. Log the undefined variable name to stdout as an error payload
  5. Exit with non-zero status code

Configuration:

{
"mcpServers": {
"github": {
"container": "ghcr.io/github/github-mcp-server:latest",
"env": {
"GITHUB_TOKEN": "${GITHUB_PERSONAL_ACCESS_TOKEN}"
}
}
}
}

If GITHUB_PERSONAL_ACCESS_TOKEN is not set in the environment:

Error: undefined environment variable referenced: GITHUB_PERSONAL_ACCESS_TOKEN
Required by: mcpServers.github.env.GITHUB_TOKEN

The gateway MUST reject configurations containing unrecognized fields at the top level with an error message indicating:

  • The unrecognized field name
  • The location in the configuration
  • A suggestion to check the specification version

The gateway MUST validate:

  • Required fields are present
  • Field types match expected types
  • Value constraints are satisfied (e.g., port ranges)
  • Mutually exclusive fields are not both present

If configuration is invalid, the gateway MUST:

  1. Write a detailed error message to stdout as an error payload including:
    • The specific validation error
    • The location in the configuration (JSON path)
    • Suggested corrective action
  2. Exit with status code 1
  3. NOT start the HTTP server
  4. NOT initialize any MCP servers

For complete details on the Model Context Protocol, see the Model Context Protocol Specification.

The gateway MUST expose the following HTTP endpoints:

POST /mcp/{server-name}
GET /health

Request Format:

POST /mcp/{server-name} HTTP/1.1
Content-Type: application/json
Authorization: {apiKey}
{
"jsonrpc": "2.0",
"method": "string",
"params": {},
"id": "string|number"
}

Response Format:

HTTP/1.1 200 OK
Content-Type: application/json
{
"jsonrpc": "2.0",
"result": {},
"id": "string|number"
}

Error Response:

HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"jsonrpc": "2.0",
"error": {
"code": -32603,
"message": "Internal error",
"data": {}
},
"id": "string|number"
}

The gateway MUST:

  1. Extract server name from URL path
  2. Validate server exists in configuration
  3. Route request to appropriate backend server
  4. Translate protocols if necessary (stdio ↔ HTTP)
  5. Return response to client

For containerized stdio-based servers, the gateway MUST:

  1. Start the container on first request (lazy initialization)
  2. Write JSON-RPC request to container’s stdin
  3. Read JSON-RPC response from container’s stdout
  4. Return HTTP response to client
  5. Maintain container for subsequent requests
  6. Buffer partial responses until complete JSON is received

The gateway SHALL NOT support non-containerized command execution. All stdio servers MUST be containerized.

For HTTP-based servers, the gateway MUST:

  1. Forward the JSON-RPC request to the server’s URL
  2. Apply any configured headers or authentication
  3. Return the server’s response to the client
  4. Handle HTTP-level errors appropriately

The gateway SHOULD NOT modify:

  • Tool names
  • Tool parameters
  • Tool return values
  • Method signatures

This ensures transparent proxying without name mangling or schema transformation.

The gateway SHOULD enforce startupTimeout for server initialization:

  1. Start timer when server container is launched
  2. Wait for server ready signal (stdio) or successful health check (HTTP)
  3. If timeout expires, kill server container and return error
  4. Log timeout error with server name and elapsed time

The gateway SHOULD enforce toolTimeout for individual tool invocations:

  1. Start timer when RPC request is sent to server
  2. Wait for complete response
  3. If timeout expires, return timeout error to client
  4. Log timeout with server name, method, and elapsed time

After successful initialization, the gateway MUST:

  1. Write a complete MCP server configuration to stdout
  2. Include gateway connection details:
    {
    "mcpServers": {
    "server-name": {
    "type": "http",
    "url": "http://{domain}:{port}/mcp/server-name",
    "headers": {
    "Authorization": "{apiKey}"
    }
    }
    }
    }
  3. Write configuration as a single JSON document
  4. Flush stdout buffer
  5. Continue serving requests

This allows clients to dynamically discover gateway endpoints.


For stdio servers, the gateway MUST:

  1. Launch each server in a separate container
  2. Maintain isolated stdin/stdout/stderr streams
  3. Prevent cross-container communication
  4. Terminate containers on gateway shutdown

All stdio-based MCP servers MUST be containerized to ensure:

  • Process Isolation: Each container provides a separate process namespace
  • Resource Isolation: Containers enforce CPU, memory, and filesystem boundaries
  • Network Isolation: Containers provide isolated network namespaces
  • Security Boundaries: Container runtimes enforce security policies and capabilities

The gateway SHALL NOT support non-containerized process execution for stdio servers.

The gateway MUST ensure:

  • Each server has isolated environment variables within its container
  • File descriptors are not shared between containers
  • Network sockets are not shared (for HTTP servers)
  • Container failures do not affect other containers

The gateway MUST NOT:

  • Allow servers to access each other’s configuration
  • Share authentication credentials between servers
  • Expose server implementation details to clients
  • Allow cross-server tool invocations

When gateway.apiKey is configured, the gateway MUST:

  1. Require Authorization: {apiKey} header on all RPC requests
  2. Reject requests with missing or invalid tokens (HTTP 401)
  3. Reject requests with malformed Authorization headers (HTTP 400)
  4. NOT log API keys in plaintext

The gateway SHOULD support temporary API keys:

  1. Generate a random API key on startup if not provided
  2. Include key in stdout configuration output

The following endpoints MUST NOT require authentication:

  • /health

GET /health HTTP/1.1

Response:

{
"status": "healthy" | "unhealthy",
"servers": {
"server-name": {
"status": "running" | "stopped" | "error",
"uptime": 12345
}
}
}

The gateway SHOULD:

  1. Periodically check server health (every 30 seconds)
  2. Restart failed containerized stdio servers automatically
  3. Mark HTTP servers unhealthy if unreachable
  4. Include health status in /health response
  5. Update readiness based on critical server status

If any configured server fails to start, the gateway MUST:

  1. Write detailed error to stdout as an error payload including:
    • Server name
    • Container image or URL attempted
    • Error message from server container
    • Environment variable status
    • Stdout/stderr from failed container
  2. Exit with status code 1
  3. NOT start the HTTP server

For runtime errors, the gateway MUST:

  1. Log errors to stdout as error payloads with:
    • Timestamp
    • Server name
    • Request ID
    • Error details
  2. Return JSON-RPC error response to client
  3. Continue serving other requests
  4. Attempt to restart failed containerized stdio servers

JSON-RPC errors MUST follow this structure:

{
"jsonrpc": "2.0",
"error": {
"code": -32000,
"message": "Server error",
"data": {
"server": "server-name",
"detail": "Specific error information"
}
},
"id": "request-id"
}

Error codes:

  • -32700: Parse error
  • -32600: Invalid request
  • -32601: Method not found
  • -32603: Internal error
  • -32000 to -32099: Server errors

The gateway SHOULD:

  1. Continue serving healthy servers when others fail
  2. Return specific errors for unavailable servers
  3. Attempt automatic recovery for transient failures
  4. Provide clear client feedback about server status

A conforming implementation MUST pass the following test categories:

  • T-CFG-001: Valid stdio server configuration
  • T-CFG-002: Valid HTTP server configuration
  • T-CFG-003: Variable expression resolution
  • T-CFG-004: Undefined variable error detection
  • T-CFG-005: Unknown field rejection
  • T-CFG-006: Missing required field detection
  • T-CFG-007: Invalid type detection
  • T-CFG-008: Port range validation
  • T-PTL-001: Stdio request/response cycle
  • T-PTL-002: HTTP passthrough
  • T-PTL-003: Tool signature preservation
  • T-PTL-004: Concurrent request handling
  • T-PTL-005: Large payload handling
  • T-PTL-006: Partial response buffering
  • T-ISO-001: Container isolation verification
  • T-ISO-002: Environment isolation verification
  • T-ISO-003: Credential isolation verification
  • T-ISO-004: Cross-container communication prevention
  • T-ISO-005: Container failure isolation
  • T-AUTH-001: Valid token acceptance
  • T-AUTH-002: Invalid token rejection
  • T-AUTH-003: Missing token rejection
  • T-AUTH-004: Health endpoint exemption
  • T-AUTH-005: Token rotation support
  • T-TMO-001: Startup timeout enforcement
  • T-TMO-002: Tool timeout enforcement
  • T-TMO-003: Timeout error messaging
  • T-TMO-004: Partial response timeout
  • T-TMO-005: Concurrent timeout handling
  • T-HLT-001: Health endpoint availability
  • T-HLT-002: Liveness probe accuracy
  • T-HLT-003: Readiness probe accuracy
  • T-HLT-004: Server status reporting
  • T-HLT-005: Automatic restart behavior
  • T-ERR-001: Startup failure reporting
  • T-ERR-002: Runtime error handling
  • T-ERR-003: Invalid request handling
  • T-ERR-004: Server crash recovery
  • T-ERR-005: Error message quality
RequirementTest IDLevelStatus
Configuration parsingT-CFG-*1Required
Variable expressionsT-CFG-003, T-CFG-0043Optional
Stdio transportT-PTL-0011Required
HTTP transportT-PTL-0022Standard
AuthenticationT-AUTH-*2Standard
Timeout handlingT-TMO-*3Optional
Health monitoringT-HLT-*2Standard
Server isolationT-ISO-*1Required
Error handlingT-ERR-*1Required

Implementations SHOULD provide:

  1. Automated test runner
  2. Test result reporting in standard format (e.g., TAP, JUnit)
  3. Test fixtures for common scenarios
  4. Performance benchmarks
  5. Conformance report generation

{
"mcpServers": {
"example": {
"container": "ghcr.io/example/mcp-server:latest",
"entrypointArgs": ["--verbose"],
"env": {
"API_KEY": "${MY_API_KEY}"
}
}
},
"gateway": {
"port": 8080,
"apiKey": "gateway-secret-token"
}
}
{
"mcpServers": {
"local-server": {
"container": "ghcr.io/example/python-mcp:latest",
"entrypointArgs": ["--config", "/app/config.json"],
"type": "stdio"
},
"remote-server": {
"type": "http",
"url": "https://api.example.com/mcp"
}
},
"gateway": {
"port": 8080,
"startupTimeout": 60,
"toolTimeout": 120
}
}
{
"mcpServers": {
"github": {
"container": "ghcr.io/github/github-mcp-server:latest",
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
}
}
}
}
CodeNameDescription
-32700Parse errorInvalid JSON received
-32600Invalid requestInvalid JSON-RPC request
-32601Method not foundMethod does not exist
-32602Invalid paramsInvalid method parameters
-32603Internal errorInternal JSON-RPC error
-32000Server errorGeneric server error
-32001Server unavailableServer not responding
-32002Server timeoutServer response timeout
-32003Authentication failedInvalid or missing credentials
  • API keys MUST NOT be logged
  • Environment variables MUST be isolated per server
  • Secrets SHOULD be cleared from memory after use
  • Gateway SHOULD support TLS/HTTPS
  • Server URLs SHOULD be validated
  • Cross-origin requests SHOULD be restricted
  • Rate limiting SHOULD be implemented
  • Server containers SHOULD run with minimal privileges
  • Resource limits SHOULD be enforced (CPU, memory, file descriptors)
  • Temporary files SHOULD be cleaned up
  • Container monitoring SHOULD detect anomalies
  • Container images SHOULD be signed and verified
  • Containers SHOULD use read-only root filesystems where possible

  • [RFC 2119] Key words for use in RFCs to Indicate Requirement Levels
  • [JSON-RPC 2.0] JSON-RPC 2.0 Specification
  • [MCP] Model Context Protocol Specification
  • [MCP-Config] MCP Configuration Format
  • [HTTP/1.1] Hypertext Transfer Protocol — HTTP/1.1

  • Initial specification release
  • Configuration format definition
  • Protocol behavior specification
  • Compliance test framework

Copyright © 2026 GitHub, Inc. All rights reserved.