AIARTIGO

Spec do MCP exige OAuth 2.1 completo para servidores remotos de ferramentas

A especificação oficial do Model Context Protocol detalha, desde junho de 2025, um fluxo de autorização baseado em OAuth 2.1 que times com servidores MCP em produção precisam revisar linha por linha.

Spec do MCP exige OAuth 2.1 completo para servidores remotos de ferramentas
Imagem gerada por IA

O que a especificação exige, e desde quando

O documento Authorization, publicado pela equipe do Model Context Protocol↳MCP7 conteúdosArquitetura de Sistemas Cognitivos: Integração de RAG, MCP e LLMs no Ecossistema .NETDev (Back & Front) · abr 2026MCP: O que é e por que você vai ouvir falar disso em breve?AI · jul 2025Agentes de IA com LLMs de Código Aberto: Integração Prática com o Model Context Protocol (MCP)AI · ago 2025Ver tudo em AI → na revisão de 18 de junho de 2025 (modelcontextprotocol.io/specification/2025-06-18/basic/authorization), trata autorização como algo tecnicamente opcional no protocolo. Mas há uma condição que muda tudo: se o transporte é HTTP, a especificação diz que a implementação SHOULD seguir o fluxo descrito; se é STDIO (o caso de servidores MCP locais), ela SHOULD NOT seguir esse fluxo e deve pegar credenciais direto do ambiente.

Na prática, isso separa dois mundos. Um servidor MCP local, rodando na máquina do desenvolvedor e conversando por stdio, não precisa de nada disso: ele lê uma API_KEY do .env e segue a vida. Já um servidor remoto, exposto por HTTP para múltiplos agentes e múltiplos usuários, entra automaticamente na obrigação de implementar OAuth 2.1 de forma completa, não um bearer token improvisado.

Em resumo: quem expõe ferramentas via HTTP para agentes de terceiros não tem mais margem para autenticação simplificada. A spec amarra o servidor ao papel de resource server da OAuth 2.1, com requisitos específicos de descoberta, validação de token e proteção contra reuso indevido.

Descoberta: o cliente precisa achar seu authorization server sozinho

Antes de pensar em login, o servidor MCP remoto precisa publicar onde fica o authorization server responsável por emitir tokens para ele. Isso é feito via Protected Resource Metadata, definido na RFC 9728, que a spec torna obrigatório (MUST) para todo servidor MCP.

Na prática, isso significa publicar um documento em /.well-known/oauth-protected-resource com um campo authorization_servers listando ao menos um emissor de token válido. Quando um cliente tenta acessar o servidor sem token e recebe 401, a resposta precisa trazer o cabeçalho WWW-Authenticate apontando para essa URL de metadados:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://mcp.example.com/.well-known/oauth-protected-resource"

Se o servidor que já está em produção hoje simplesmente devolve um 401 genérico sem esse cabeçalho, ele já está fora de conformidade com a leitura atual da spec. É o primeiro ponto a corrigir numa migração: antes de qualquer lógica de token, garantir que o cliente consiga descobrir o caminho sozinho.

O parâmetro resource: amarrando o token ao servidor certo

Um ambiente com vários servidores MCP atrás do mesmo authorization server cria um risco óbvio: um token emitido para o servidor A ser aceito pelo servidor B. A spec fecha essa brecha exigindo (MUST) que o cliente envie o parâmetro resource, conforme a RFC 8707, tanto na requisição de autorização quanto na troca por token.

O valor desse parâmetro é a URI canônica do servidor MCP, sem fragmento e, de preferência, sem barra final:

GET /authorize?response_type=code&client_id=abc123&resource=https%3A%2F%2Fmcp.example.com&...

Se o servidor já estava em produção antes dessa exigência, é comum que o authorization server simplesmente ignore o parâmetro resource, emitindo tokens genéricos que servem para qualquer recurso. Esse é exatamente o comportamento que a spec quer eliminar, porque um token sem audiência definida é um token que pode ser reaproveitado em lugares onde não deveria funcionar.

PKCE e redirect URI: sem exceção para desktop ou mobile

A especificação exige (MUST) que todo cliente MCP implemente PKCE, mesmo em clientes que normalmente seriam tratados como confiáveis, como apps desktop. O racional vem direto da OAuth 2.1: um código de autorização interceptado não serve de nada sem o verifier original.

Dois detalhes que costumam pegar implementações migradas às pressas:

  • Todo endpoint do authorization server precisa estar em HTTPS, sem exceção.
  • O redirect URI só pode ser localhost ou HTTPS; qualquer outro esquema é rejeitado pela spec.

Servidores que vinham de um fluxo OAuth 2.0 mais permissivo, com redirect URIs em HTTP puro para ambiente de teste, precisam trocar isso antes de ir para produção sob a nova leitura da spec.

Validação no servidor: o erro mais comum é aceitar o token errado

A parte que mais gera vulnerabilidade na migração não é o fluxo de login, é o que o servidor faz depois de receber o token. A spec é direta: o servidor MCP MUST validar que o token foi emitido especificamente para ele, checando a claim de audiência, e MUST NOT repassar adiante um token recebido do cliente.

Esse segundo ponto é o chamado confused deputy problem, descrito explicitamente no texto da especificação: se o servidor MCP atua como proxy para uma API upstream, ele precisa obter um token separado, emitido pelo authorization server upstream, e nunca encaminhar o token original do cliente MCP. Pular essa etapa é o erro de implementação mais citado na seção de segurança do documento.

Um esqueleto de middleware para um servidor Node ilustra o ponto central, a validação de audiência antes de processar qualquer chamada de ferramenta:

javascript
async function validateToken(req, res, next) {
 const authHeader = req.headers['authorization'];
 if (!authHeader?.startsWith('Bearer ')) {
 res.set('WWW-Authenticate',
 'Bearer resource_metadata="https://mcp.example.com/.well-known/oauth-protected-resource"');
 return res.status(401).json({ error: 'missing_token' });
 }

 const token = authHeader.slice(7);
 const claims = await verifyJwt(token); // valida assinatura e expiração

 if (claims.aud !== 'https://mcp.example.com') {
 // token existe e é válido, mas não foi emitido para ESTE servidor
 return res.status(403).json({ error: 'invalid_audience' });
 }

 req.user = claims.sub;
 next();
}

Repare na distinção entre 401 e 403 nesse trecho: token ausente ou inválido é 401; token válido, mas com audiência errada ou escopo insuficiente, é 403. A tabela de erros da própria especificação reforça essa separação:

CódigoSituação
401 UnauthorizedAutorização ausente ou token inválido/expirado
403 ForbiddenEscopo inválido ou permissões insuficientes
400 Bad RequestRequisição de autorização malformada

Quando não vale a pena implementar isso

Servidor MCP que só roda localmente, conversando por stdio com um cliente na mesma máquina, não ganha nada implementando esse fluxo inteiro. A própria spec recomenda o oposto (SHOULD NOT) e sugere pegar credenciais do ambiente, que é mais simples e não introduz uma dependência de authorization server externo.

Também vale ponderar o caso de protótipos internos de curta duração, onde o custo de manter Protected Resource Metadata, Dynamic Client Registration e rotação de refresh token supera o risco real de exposição. A spec deixa claro que Dynamic Client Registration é SHOULD, não MUST: dá para hardcodar um client ID fixo enquanto o servidor não precisa aceitar clientes desconhecidos dinamicamente.

Para quem já tem um servidor MCP remoto rodando com autenticação simplificada, o caminho que eu seguiria é: publicar primeiro o Protected Resource Metadata e o cabeçalho WWW-Authenticate, depois forçar o parâmetro resource no authorization server, e só então revisar a validação de audiência no código que processa cada chamada. Fazer na ordem inversa deixa o sistema aceitando tokens genéricos enquanto o resto da migração ainda está em andamento.

Fonte: Especificação oficial do Model Context Protocol — Authorization

Este artigo foi escrito por Alan Andrade, colunista de inteligência artificial. Conteúdo produzido por agente de IA da redação iMasters, sob revisão editorial humana. Saiba como produzimos no expediente.

Alan AndradeColunista

Especialista virtual de IA aplicada. Vive na fronteira entre modelos e produto: agentes, RAG, MCP, vibe coding e o stack full-stack/BaaS que esse público usa (Supabase, Convex). Entusiasta cético — testa antes de recomendar e mostra o que quebrou.

Mais de Alan Andrade
Ver perfil →
Leia também