MCP Gateway
Um gateway de proxy reverso para gerenciar e acessar múltiplos servidores MCP através de um único ponto de entrada, implantável via Docker.
Documentação
MCP Gateway
Descrição
O gateway MCP é um servidor proxy reverso que encaminha solicitações de clientes para o servidor MCP ou usa todos os servidores MCP sob o gateway através de um portal unificado.
Suporta dois protocolos de transporte (alternáveis na inicialização):
- SSE (padrão, transporte MCP legado)
- Streamable HTTP (especificação MCP
2025-03-26)
Recursos
- Implantar vários servidores MCP
- Conectar ao servidor MCP
- Usar o gateway para chamar servidores MCP
- Obter todos os fluxos SSE dos servidores MCP
- Obter todas as ferramentas dos servidores MCP
- Endpoint agregado Streamable HTTP com gerenciamento de sessão via cabeçalho
Mcp-Session-Id - Agregação dinâmica de capacidades (o gateway anuncia apenas capacidades que pelo menos um MCP downstream suporta)
- Autenticação de servidor de recursos MCP OAuth 2.1 com descoberta de metadados de recursos protegidos
Instalação
- baixar pacote do github
docker pull ghcr.io/lucky-aeon/mcp-gateway:latest
- construir imagem docker manualmente
docker build -t mcp-gateway .
Uso
executar contêiner docker do github
docker run -d --name mcp-gateway -p 8080:8080 ghcr.io/lucky-aeon/mcp-gateway
executar contêiner docker de construção manual
docker run -d --name mcp-gateway -p 8080:8080 mcp-gateway
Configuração
O gateway lê config.json do diretório de configuração (padrão é ./vm quando presente, caso contrário .). Um exemplo 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 principais:
| Campo | Padrão | Descrição |
|---|---|---|
Bind | [::]:8080 | Endereço de escuta do servidor. |
GatewayProtocol | all | Protocolos expostos do gateway: all, sse ou streamhttp. Também pode ser substituído via flag --protocol. |
Auth.Enabled | true | Se deve impor autenticação. Defina false para uso MCP local sem autenticação. |
Auth.ApiKey | 123456 | Token de login legado de chave única da API de gerenciamento; não usado como autenticação MCP. |
Auth.Mode | single-key | single-key ou saas. O modo SaaS usa contas MCP Gateway e login por senha. |
Auth.AuthorizationServers | vazio | URLs opcionais de emissor OAuth externo. Vazio no modo SaaS significa que o gateway se anuncia como servidor de autorização. |
Auth.TokenIssuer | primeiro servidor de autorização | Reivindicação iss esperada para tokens de acesso OAuth MCP. |
Auth.TokenJWKSURI | descoberto do emissor | URL JWKS usada para verificar tokens de acesso JWT. |
Auth.TokenIntrospectionURL | vazio | Endpoint de introspecção RFC 7662 para tokens de acesso opacos. Se definido, a introspecção é usada em vez de JWKS. |
Auth.TokenAudience | URL do recurso solicitado | Reivindicação aud esperada. Configure para o indicador de recurso MCP usado pelo seu servidor de autorização. |
Auth.RequiredScopes | vazio | Escopos necessários para solicitações MCP e anunciados em WWW-Authenticate. |
Auth.ScopesSupported | vazio | Escopos anunciados nos Metadados de Recursos Protegidos. |
SessionGCInterval | 10s | Intervalo para coleta de lixo de sessões de proxy ociosas. |
ProxySessionTimeout | 1m | Tempo limite para sessões de proxy ociosas antes da coleta de lixo. |
McpServiceMgrConfig.McpServiceRetryCount | 3 | Máximo de tentativas para um serviço MCP com falha antes de marcá-lo como failed. |
Selecionando o protocolo do gateway
Defina GatewayProtocol em config.json:
{ "GatewayProtocol": "all" }
Ou passe a flag CLI (tem precedência):
./mcp-gateway --protocol=streamhttp
Valores válidos: all (padrão), sse ou streamhttp.
Autenticação
Quando Auth.Enabled é true, toda solicitação de protocolo MCP deve apresentar um token Bearer:
Authorization: Bearer <access-token>
O gateway não trata mais api_key, sessionId, Mcp-Session-Id ou X-Session-Id como credenciais de autenticação. Mcp-Session-Id permanece um identificador de sessão de transporte e deve ser enviado junto com o token Bearer em solicitações Streamable HTTP autenticadas.
Para descoberta OAuth MCP, o gateway expõe Metadados de Recursos Protegidos OAuth:
GET /.well-known/oauth-protected-resource
GET /.well-known/oauth-protected-resource/stream
Solicitações MCP não autorizadas retornam 401 com um desafio WWW-Authenticate: Bearer ... resource_metadata="..." quando a descoberta OAuth está disponível. Para desenvolvimento local sem autenticação, defina Auth.Enabled como false.
Em Auth.Mode = "saas" sem Auth.AuthorizationServers externo, o gateway usa seu próprio sistema de contas para login MCP. A descoberta anuncia a origem do gateway como servidor de autorização e expõe:
GET /.well-known/oauth-authorization-server
POST /oauth/token
POST /oauth/register
/oauth/token aceita grant_type=password codificado em formulário com username/password e retorna o mesmo JWT do gateway usado por /api/v1/auth/login. Configure Auth.AuthorizationServers apenas quando quiser Keycloak, Auth0 ou outro provedor OAuth externo.
Clientes MCP baseados em navegador também podem usar o endpoint de autorização anunciado:
GET /oauth/authorize
O endpoint de autorização integrado renderiza um formulário de login de conta do Gateway e completa o fluxo de código de autorização OAuth, incluindo PKCE.
/oauth/register implementa registro dinâmico mínimo de cliente para clientes como MCP Inspector.
API
Implantar
suporte: uvx, npx. ou 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)
Disponível quando
GatewayProtocoléall(padrão) ousse.
GET SSE
GET /{mcp-server-name}/sse HTTP/1.1
Host: localhost:8080
POST Message
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)
Disponível quando
GatewayProtocoléall(padrão) ousse.
A diferença entre o gateway e a conexão direta com o MCP é que você só precisa interagir com o gateway, que encaminhará automaticamente a solicitação para o servidor MCP correspondente. Ao chamar, você precisa adicionar o conteúdo mcpServerName antes do método, identificando de qual servidor MCP a solicitação vem.
GET SSE
GET /sse HTTP/1.1
Host: localhost:8080
Aqui, o SSE é o fluxo SSE de todos os servidores MCP sob o gateway.
Quando o cliente assina o SSE, o gateway cria uma conexão SSE para cada servidor MCP e combina todos os fluxos SSE dos servidores MCP em um só.
Em todos os resultados de tools/call na resposta, o conteúdo mcpServerName é adicionado antes do método, identificando de qual servidor MCP o resultado vem.
POST Message
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
}
Obter todas as ferramentas sob o 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 Streamable HTTP)
Disponível quando
GatewayProtocoléall(padrão) oustreamhttp.Implementa o transporte Streamable HTTP MCP definido na especificação
2025-03-26. O gateway expõe um único endpoint agregado/streamque aceitaPOST,GETeDELETE. Os identificadores de sessão são transportados no cabeçalho HTTPMcp-Session-Id.
1. Estabelecer uma sessão (inicializar)
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"}
}
}
Resposta:
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>."
}
}
Mantenha o Mcp-Session-Id retornado e envie-o em cada solicitação subsequente.
2. Completar o handshake (notificação)
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"}
Resposta: 202 Accepted (corpo vazio).
3. Chamar ferramentas ou 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"}
}
}
Os nomes de ferramentas agregados seguem o padrão <serverName>_<toolName>, mesma regra do modo gateway SSE.
A resposta chega de forma síncrona no corpo da resposta HTTP:
{"jsonrpc": "2.0", "id": 2, "result": { /* ... */ }}
Notificações (mensagens JSON-RPC sem id) são respondidas com 202 Accepted e encaminhadas de forma assíncrona.
4. Assinar eventos iniciados pelo 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
O gateway mantém a conexão aberta e emite quadros event: message para solicitações e notificações JSON-RPC do servidor para o cliente (por exemplo, atualizações de progresso, mensagens de log). Respostas JSON-RPC nunca são enviadas aqui — elas são retornadas na resposta HTTP da solicitação POST /stream original.
Linhas que começam com : são comentários de keepalive SSE e podem ser ignoradas.
5. Fechar a sessão
DELETE /stream HTTP/1.1
Host: localhost:8080
Authorization: Bearer <access-token>
Mcp-Session-Id: 7782f2f9-563c-4379-b961-df06e49e54c0
Resposta: 200 OK.
Passagem direta de servidor único
No modo Streamable HTTP, você também pode acessar um servidor MCP individual diretamente:
POST /{mcp-server-name} HTTP/1.1
GET /{mcp-server-name} HTTP/1.1
O gateway encaminha a solicitação para o endpoint message do MCP de destino. O gerenciamento de sessão neste modo é responsabilidade do servidor downstream.
Conectando com o MCP Inspector
- No Inspector, selecione Tipo de Transporte:
Streamable HTTP. - URL:
http://localhost:8080/stream. - Complete o fluxo OAuth no seu servidor de autorização e forneça
Authorization: Bearer <access-token>. - Clique em Conectar. O Inspector lida com a troca
Mcp-Session-Idautomaticamente.