mcp-oauth2-proxy
Um servidor MCP stdio local que faz proxy para um servidor MCP HTTP remoto protegido por OAuth2.
Documentação
mcp-oauth2-proxy
Um servidor MCP stdio local que faz proxy para um servidor MCP HTTP remoto protegido por OAuth2. Integre-o ao Claude Desktop, Cursor, VS Code Copilot ou qualquer outro cliente MCP — faça login uma vez no navegador — pronto.
MCP client ─stdio (JSON-RPC)─▶ mcp-oauth2-proxy ─HTTP+SSE + Bearer─▶ upstream MCP server
│
└─ OAuth2 token endpoint (IdP)
Documentação
Este README é um início rápido. A documentação completa está na wiki.
| Página | O que contém |
|---|---|
| Primeiros passos | Instalação, primeira execução, integração com um cliente. |
| Configuração | Todos os campos e variáveis de ambiente. |
| Concessões e tokens OAuth2 | Concessões, login interativo, ciclo de vida do token e cache. |
| Descoberta | Descoberta de endpoints RFC 9728 / RFC 8414. |
| Segurança | Modelo de ameaças e defesas integradas. |
| Hosts remotos (encaminhamento de porta SSH) | Como fazer login quando o proxy é executado remotamente. |
| Solução de problemas | Problemas comuns e FAQ. |
| Arquitetura · Bridge · OAuth2 internals | Como funciona internamente. |
| Contribuição e lançamentos | Configuração de desenvolvimento, testes, processo de release. |
Conteúdo
- Recursos
- Como funciona
- Requisitos
- Instalação
- Início rápido
- Integre a um cliente MCP
- Configuração
- Segurança
- Desenvolvimento
- Fora do escopo
- Licença
Recursos
- Fluxo interativo
authorization_code+ PKCE com um listener de callback local no navegador — sem copiar/colar códigos manualmente. - Cache de refresh token em disco (AES‑256‑GCM,
0600), para o navegador abrir apenas uma vez por máquina. - Concessão
client_credentialspara uso headless / service-to-service. - Descoberta RFC 9728 + RFC 8414 dos endpoints de token e autorização a partir do upstream — geralmente sem necessidade de configuração OAuth.
- Renovação proativa de token com margem de tempo, eliminação de duplicidade em voo e loop 401 → invalidar → tentar novamente.
- Suporte upstream Streamable-HTTP: respostas JSON de disparo único, SSE
text/event-stream, e o canal opcional de notificações do servidor de longa duração. HonraMcp-Session-Id. - Logs apenas em stderr (pino) com redação de tokens, segredos e cabeçalhos
Authorization— o stdout permanece um canal JSON-RPC limpo.
Como funciona
- Descoberta. Opcionalmente, busca metadados RFC 9728/8414 para preencher
tokenUrl,authorizationUrlescope. - Gerenciador de tokens. Envolve o
Grantconfigurado com cache, margem de renovação, eliminação de duplicidade em voo e invalidação por 401. - Pré-busca. Chama
getToken()uma vez na inicialização para que o fluxo interativo do navegador (se necessário) aconteça antes da primeira mensagem MCP. - Bridge. Para cada linha JSON-RPC do stdin, faz POST para
upstream.urlcom um tokenBearer; respostas JSON de disparo único tornam-se uma linha no stdout, respostas SSE uma linha por evento. Um401disparainvalidate()e uma única tentativa de repetição. - Stream do servidor. Após
initialize, opcionalmente mantém aberto um canalGET text/event-streampara notificações iniciadas pelo servidor.
Para os detalhes internos completos, consulte as páginas da wiki Arquitetura, Bridge Internals e OAuth2 Internals.
Requisitos
- Node.js 20+
- Um servidor MCP protegido por OAuth2 que fale o transporte MCP HTTP Streamable.
- Um cliente OAuth2 registrado no seu IdP. Para o fluxo interativo, registre
http://127.0.0.1:53682/callbackcomo URI de redirecionamento (ou o que você definir emOAUTH2_CALLBACK_PORT).
Instalação
Não é necessário instalar nada — os clientes MCP podem iniciar o proxy diretamente via npx:
npx -y mcp-oauth2-proxy
Para desenvolvimento com uma cópia local:
git clone https://github.com/ChengleiYuan/mcp-oauth2-proxy.git
cd mcp-oauth2-proxy
npm install
npm run build
Início rápido
Login interativo (recomendado para usuários finais)
UPSTREAM_URL=https://mcp.example.com/mcp \
OAUTH2_GRANT=authorization_code \
OAUTH2_CLIENT_ID=<your-client-id> \
npx -y mcp-oauth2-proxy
Na primeira execução, o proxy descobre os endpoints OAuth, abre o navegador para um login PKCE, captura o código em http://127.0.0.1:53682/callback, armazena em cache o refresh token (criptografado) no diretório de configuração do SO e inicia o bridge. Execuções posteriores reutilizam o token em cache silenciosamente. Detalhes: Concessões e tokens OAuth2.
Headless / conta de serviço
UPSTREAM_URL=https://mcp.example.com/mcp \
OAUTH2_GRANT=client_credentials \
OAUTH2_TOKEN_URL=https://idp.example.com/oauth2/token \
OAUTH2_CLIENT_ID=my-service \
OAUTH2_CLIENT_SECRET='…' \
OAUTH2_SCOPE='mcp:read mcp:write' \
npx -y mcp-oauth2-proxy
Integre a um cliente MCP
{
"mcpServers": {
"remote-oauth2-mcp": {
"command": "npx",
"args": ["-y", "mcp-oauth2-proxy"],
"env": {
"UPSTREAM_URL": "https://mcp.example.com/mcp",
"OAUTH2_GRANT": "authorization_code",
"OAUTH2_CLIENT_ID": "<your-client-id>"
}
}
}
}
Em hosts Windows que não resolvem shims de .cmd (então command: "npx" falha ao iniciar), use a forma explícita:
{
"command": "cmd",
"args": ["/c", "npx", "-y", "mcp-oauth2-proxy"]
}
Caminhos no bloco env devem ser absolutos e usar barras normais em todas as plataformas.
Configuração
O proxy pode ser configurado por um arquivo JSON (MCP_PROXY_CONFIG), por variáveis de ambiente, ou por uma combinação — variáveis de ambiente sobrescrevem valores do arquivo e o resultado mesclado é validado. Exemplo mínimo de arquivo:
{
"upstream": { "url": "https://mcp.example.com/mcp" },
"oauth2": {
"grant": "authorization_code",
"clientId": "my-client",
"scope": "mcp:read mcp:write"
}
}
Veja config.example.json para uma amostra mais completa.
Variáveis de ambiente mais usadas:
| Variável de ambiente | Mapeia para |
|---|---|
UPSTREAM_URL | upstream.url |
OAUTH2_GRANT | oauth2.grant |
OAUTH2_CLIENT_ID | oauth2.clientId |
OAUTH2_CLIENT_SECRET | oauth2.clientSecret |
OAUTH2_TOKEN_URL | oauth2.tokenUrl |
OAUTH2_SCOPE | oauth2.scope |
LOG_LEVEL | log.level |
Referência completa: todos os campos, padrões e variáveis de ambiente estão documentados na página da wiki Configuração. A descoberta automática de endpoints é abordada em Descoberta. Executando o proxy em uma máquina remota? Veja Hosts remotos (encaminhamento de porta SSH). Enfrentando um problema? Veja Solução de problemas.
Segurança
- Os tokens são obtidos pelo próprio proxy; o cabeçalho
Authorizationdo upstream é sempre definido pelo proxy, nunca repassado do cliente. - Tokens de acesso vivem apenas em memória. Refresh tokens são armazenados em cache criptografados (AES‑256‑GCM, modo de arquivo de chave
0600) — obfuscação honesta contra leituras casuais de disco, não uma proteção contra um processo rodando como o mesmo usuário do SO. http://em texto claro para hosts não loopback é rejeitado na inicialização (sobrescreva comALLOW_INSECURE_HTTP=true);https://e loopbackhttp://são sempre permitidos. O listener de callback interativo valida o cabeçalhoHostpara impedir rebinding de DNS.- Todos os logs vão para stderr com tokens, segredos e cabeçalhos
Authorizationredigidos; o stdout é reservado para JSON-RPC.
Modelo de ameaças completo e defesas: Segurança.
Desenvolvimento
npm install
npm run build # compile TS to dist/
npm run dev # tsx watch
npm test # vitest (unit + integration)
O teste de integração inicia um endpoint de token OAuth2 simulado e um upstream MCP simulado no mesmo processo e conduz o bridge real através de streams PassThrough — sem necessidade de rede. A estrutura do projeto, a estratégia de testes completa e o processo de release automatizado estão documentados em Contribuição e lançamentos.
Fora do escopo
- Múltiplos servidores MCP upstream por processo
- Armazenamento de refresh token com suporte a chaveiro do SO (DPAPI / Keychain / libsecret)
- Concessões mTLS / JWT-bearer / device-code / ROPC
- Transporte de entrada HTTP / SSE (este é um servidor MCP stdio)