MCP Gateway
Un gateway de proxy inverso para gestionar y acceder a múltiples servidores MCP a través de un único punto de entrada, desplegable mediante Docker.
Documentación
MCP Gateway
Descripción
El gateway MCP es un servidor proxy inverso que reenvía solicitudes de clientes al servidor MCP o utiliza todos los servidores MCP bajo el gateway a través de un portal unificado.
Soporta dos protocolos de transporte (conmutables al inicio):
- SSE (predeterminado, transporte MCP heredado)
- HTTP Streamable (especificación MCP
2025-03-26)
Características
- Desplegar múltiples servidores MCP
- Conectarse al servidor MCP
- Usar el gateway para llamar a servidores MCP
- Obtener los flujos SSE de todos los servidores MCP
- Obtener las herramientas de todos los servidores MCP
- Endpoint agregado HTTP Streamable con gestión de sesiones mediante el encabezado
Mcp-Session-Id - Agregación dinámica de capacidades (el gateway solo anuncia capacidades que al menos un MCP descendente soporta)
- Autenticación de servidor de recursos MCP OAuth 2.1 con descubrimiento de metadatos de recursos protegidos
Instalación
- extraer el paquete de github
docker pull ghcr.io/lucky-aeon/mcp-gateway:latest
- construir la imagen docker usted mismo
docker build -t mcp-gateway .
Uso
ejecutar el contenedor docker de github
docker run -d --name mcp-gateway -p 8080:8080 ghcr.io/lucky-aeon/mcp-gateway
ejecutar el contenedor docker construido por usted mismo
docker run -d --name mcp-gateway -p 8080:8080 mcp-gateway
Configuración
El gateway lee config.json del directorio de configuración (por defecto ./vm cuando está presente, de lo contrario .). Un ejemplo mínimo:
{
"LogLevel": 0,
"Bind": "[::]:8080",
"Auth": {
"Enabled": true,
"AuthorizationServers": ["https://auth.example.com"],
"TokenIssuer": "https://auth.example.com",
"TokenJWKSURI": "https://auth.example.com/.well-known/jwks.json",
"TokenAudience": "http://localhost:8080/stream",
"RequiredScopes": ["mcp:read"],
"ScopesSupported": ["mcp:read"]
},
"GatewayProtocol": "all",
"McpServiceMgrConfig": {
"McpServiceRetryCount": 3
}
}
Campos clave:
| Campo | Predeterminado | Descripción |
|---|---|---|
Bind | [::]:8080 | Dirección de escucha del servidor. |
GatewayProtocol | all | Protocolos expuestos del gateway: all, sse, o streamhttp. También se puede sobrescribir mediante la bandera --protocol. |
Auth.Enabled | true | Si se debe aplicar autenticación. Establezca false para uso MCP local sin autenticación. |
Auth.ApiKey | 123456 | Token de inicio de sesión de API de gestión de clave única heredado; no se usa como autenticación MCP. |
Auth.Mode | single-key | single-key o saas. El modo SaaS usa cuentas de MCP Gateway y inicio de sesión con contraseña. |
Auth.AuthorizationServers | vacío | URLs opcionales de emisores OAuth externos. Vacío en modo SaaS significa que el gateway se anuncia a sí mismo como servidor de autorización. |
Auth.TokenIssuer | primer servidor de autorización | Reclamación iss esperada para tokens de acceso OAuth MCP. |
Auth.TokenJWKSURI | descubierto del emisor | URL de JWKS utilizada para verificar tokens de acceso JWT. |
Auth.TokenIntrospectionURL | vacío | Endpoint de introspección RFC 7662 para tokens de acceso opacos. Si se establece, se usa introspección en lugar de JWKS. |
Auth.TokenAudience | URL del recurso solicitado | Reclamación aud esperada. Configure al indicador de recurso MCP utilizado por su servidor de autorización. |
Auth.RequiredScopes | vacío | Ámbitos requeridos para solicitudes MCP y anunciados en WWW-Authenticate. |
Auth.ScopesSupported | vacío | Ámbitos anunciados en Metadatos de Recursos Protegidos. |
SessionGCInterval | 10s | Intervalo para la recolección de basura de sesiones proxy inactivas. |
ProxySessionTimeout | 1m | Tiempo de espera para sesiones proxy inactivas antes de la recolección de basura. |
McpServiceMgrConfig.McpServiceRetryCount | 3 | Reintentos máximos para un servicio MCP fallido antes de marcarlo como failed. |
Selección del protocolo del gateway
Establezca GatewayProtocol en config.json:
{ "GatewayProtocol": "all" }
O pase la bandera CLI (tiene prioridad):
./mcp-gateway --protocol=streamhttp
Valores válidos: all (predeterminado), sse, o streamhttp.
Autenticación
Cuando Auth.Enabled es true, cada solicitud de protocolo MCP debe presentar un token Bearer:
Authorization: Bearer <access-token>
El gateway ya no trata api_key, sessionId, Mcp-Session-Id, o X-Session-Id como credenciales de autenticación. Mcp-Session-Id sigue siendo un identificador de sesión de transporte y debe enviarse junto con el token Bearer en solicitudes HTTP Streamable autenticadas.
Para el descubrimiento OAuth MCP, el gateway expone Metadatos de Recursos Protegidos OAuth:
GET /.well-known/oauth-protected-resource
GET /.well-known/oauth-protected-resource/stream
Las solicitudes MCP no autorizadas devuelven 401 con un desafío WWW-Authenticate: Bearer ... resource_metadata="..." cuando el descubrimiento OAuth está disponible. Para desarrollo local sin autenticación, establezca Auth.Enabled a false.
En Auth.Mode = "saas" sin Auth.AuthorizationServers externo, el gateway usa su propio sistema de cuentas para el inicio de sesión MCP. El descubrimiento anuncia el origen del gateway como servidor de autorización y expone:
GET /.well-known/oauth-authorization-server
POST /oauth/token
POST /oauth/register
/oauth/token acepta grant_type=password codificado en formulario con username/password y devuelve el mismo JWT del gateway utilizado por /api/v1/auth/login. Configure Auth.AuthorizationServers solo cuando desee Keycloak, Auth0 u otro proveedor OAuth externo.
Los clientes MCP basados en navegador también pueden usar el endpoint de autorización anunciado:
GET /oauth/authorize
El endpoint de autorización integrado muestra un formulario de inicio de sesión de cuenta del Gateway y completa el flujo de código de autorización OAuth, incluido PKCE.
/oauth/register implementa registro dinámico mínimo de clientes para clientes como MCP Inspector.
API
Desplegar
soporta: uvx, npx. o url sse
POST /deploy HTTP/1.1
Host: localhost:8080
Content-Type: application/json
{
"mcpServers": {
"time": {
"url": "http://mcp-server:8080", // url 和 command 二选一
"command": "uvx", // url 和 command 二选一
"args": ["mcp-server-time", "--local-timezone=America/New_York"], // 可选,command 的参数
"env": { // 可选,环境变量
"KEY1": "VALUE1",
"KEY2": "VALUE2"
}
}
}
}
Usar MCP (Modo SSE)
Disponible cuando
GatewayProtocolesall(predeterminado) osse.
GET SSE
GET /{mcp-server-name}/sse HTTP/1.1
Host: localhost:8080
POST Mensaje
POST /{mcp-server-name}/message HTTP/1.1
Host: localhost:8080
Content-Type: application/json
{
"method": "tools/call",
"params": {
"name": "get_current_time",
"arguments": {
"timezone": "Asia/Seoul"
}
},
"jsonrpc": "2.0",
"id": 2
}
Usar Gateway (Modo SSE)
Disponible cuando
GatewayProtocolesall(predeterminado) osse.
La diferencia entre el gateway y la conexión directa a MCP es que solo necesita interactuar con el gateway, y el gateway reenviará automáticamente las solicitudes al servidor MCP correspondiente. Al llamar, debe agregar el contenido mcpServerName antes del método, para identificar de qué servidor MCP proviene la solicitud.
GET SSE
GET /sse HTTP/1.1
Host: localhost:8080
Aquí el sse es el flujo SSE de todos los servidores MCP bajo todo el gateway.
Cuando el cliente se suscribe al sse, el gateway crea una conexión SSE para cada servidor MCP y combina todos los flujos SSE de los servidores MCP.
En todos los resultados de tools/call en la respuesta, se agrega el contenido mcpServerName antes del método, para identificar de qué servidor MCP proviene el resultado.
POST Mensaje
POST /message HTTP/1.1
Host: localhost:8080
Content-Type: application/json
{
"method": "tools/call",
"params": {
"name": "{mcp-server-name}-get_current_time",
"arguments": {
"timezone": "Asia/Seoul"
}
},
"jsonrpc": "2.0",
"id": 2
}
Obtener todas las herramientas bajo el gateway
POST /message HTTP/1.1
Host: localhost:8080
Content-Type: application/json
{
"method": "tools/list",
"jsonrpc": "2.0",
"id": 1
}
# SSE 响应 message event
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [
{
"name": "{mcpServerName}-get_current_time",
"description": "Get current time in a specific timezones",
"inputSchema": {
"type": "object",
"properties": {
"timezone": {
"type": "string",
"description": "IANA timezone name (e.g., 'America/New_York', 'Europe/London'). Use 'America/New_York' as local timezone if no timezone provided by the user."
}
},
"required": [
"timezone"
]
}
},
{
"name": "{mcpServerName}-convert_time",
"description": "Convert time between timezones",
"inputSchema": {
"type": "object",
"properties": {
"source_timezone": {
"type": "string",
"description": "Source IANA timezone name (e.g., 'America/New_York', 'Europe/London'). Use 'America/New_York' as local timezone if no source timezone provided by the user."
},
"time": {
"type": "string",
"description": "Time to convert in 24-hour format (HH:MM)"
},
"target_timezone": {
"type": "string",
"description": "Target IANA timezone name (e.g., 'Asia/Tokyo', 'America/San_Francisco'). Use 'America/New_York' as local timezone if no target timezone provided by the user."
}
},
"required": [
"source_timezone",
"time",
"target_timezone"
]
}
}
]
}
}
Usar Gateway (Modo HTTP Streamable)
Disponible cuando
GatewayProtocolesall(predeterminado) ostreamhttp.Implementa el transporte HTTP Streamable MCP definido en la especificación
2025-03-26. El gateway expone un único endpoint agregado/streamque aceptaPOST,GETyDELETE. Los identificadores de sesión se transportan en el encabezado HTTPMcp-Session-Id.
1. Establecer una sesión (initialize)
POST /stream HTTP/1.1
Host: localhost:8080
Authorization: Bearer <access-token>
Accept: application/json, text/event-stream
Content-Type: application/json
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-03-26",
"capabilities": {},
"clientInfo": {"name": "my-client", "version": "1.0.0"}
}
}
Respuesta:
HTTP/1.1 200 OK
Content-Type: application/json
Mcp-Session-Id: 7782f2f9-563c-4379-b961-df06e49e54c0
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2025-03-26",
"serverInfo": {"name": "mcp-gateway", "version": "1.0.0"},
"capabilities": { /* OR-merged from all downstream MCP servers */ },
"instructions": "MCP Gateway aggregates multiple MCP servers. Tools are namespaced as <serverName>_<toolName>."
}
}
Conserve el Mcp-Session-Id devuelto y envíelo en cada solicitud posterior.
2. Completar el protocolo de enlace (notification)
POST /stream HTTP/1.1
Host: localhost:8080
Authorization: Bearer <access-token>
Content-Type: application/json
Mcp-Session-Id: 7782f2f9-563c-4379-b961-df06e49e54c0
{"jsonrpc": "2.0", "method": "notifications/initialized"}
Respuesta: 202 Accepted (cuerpo vacío).
3. Llamar herramientas o listar recursos
POST /stream HTTP/1.1
Host: localhost:8080
Authorization: Bearer <access-token>
Accept: application/json, text/event-stream
Content-Type: application/json
Mcp-Session-Id: 7782f2f9-563c-4379-b961-df06e49e54c0
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "{mcp-server-name}_get_current_time",
"arguments": {"timezone": "Asia/Seoul"}
}
}
Los nombres de herramientas agregados siguen el patrón <serverName>_<toolName>, misma regla que en el modo gateway SSE.
La respuesta llega de forma síncrona en el cuerpo de la respuesta HTTP:
{"jsonrpc": "2.0", "id": 2, "result": { /* ... */ }}
Las notificaciones (mensajes JSON-RPC sin id) se responden con 202 Accepted y se reenvían de forma asíncrona.
4. Suscribirse a eventos iniciados por el servidor (opcional)
GET /stream HTTP/1.1
Host: localhost:8080
Authorization: Bearer <access-token>
Accept: text/event-stream
Mcp-Session-Id: 7782f2f9-563c-4379-b961-df06e49e54c0
El gateway mantiene la conexión abierta y emite tramas event: message para solicitudes y notificaciones JSON-RPC de servidor → cliente (por ejemplo, actualizaciones de progreso, mensajes de registro). Las respuestas JSON-RPC nunca se envían aquí — se devuelven en la respuesta HTTP de la solicitud POST /stream original.
Las líneas que comienzan con : son comentarios de mantenimiento de conexión SSE y pueden ignorarse.
5. Cerrar la sesión
DELETE /stream HTTP/1.1
Host: localhost:8080
Authorization: Bearer <access-token>
Mcp-Session-Id: 7782f2f9-563c-4379-b961-df06e49e54c0
Respuesta: 200 OK.
Paso directo de servidor único
En modo HTTP Streamable también puede acceder directamente a un servidor MCP individual:
POST /{mcp-server-name} HTTP/1.1
GET /{mcp-server-name} HTTP/1.1
El gateway reenvía la solicitud al endpoint message del MCP objetivo. La gestión de sesiones en este modo es responsabilidad del servidor descendente.
Conexión con MCP Inspector
- En Inspector seleccione Tipo de Transporte:
Streamable HTTP. - URL:
http://localhost:8080/stream. - Complete el flujo OAuth en su servidor de autorización y proporcione
Authorization: Bearer <access-token>. - Haga clic en Conectar. El Inspector maneja el intercambio
Mcp-Session-Idautomáticamente.