Fluxo OAuth 2.1 do MCP explicado: CIMD ou DCR com exemplos
O fluxo OAuth 2.1 do MCP, passo a passo, desde o desafio 401 e as consultas de metadados até o PKCE e a validação do token. Veja JSON real para Client ID Metadata Documents e Dynamic Client Registration, uma tabela lado a lado e as verificações de segurança que cada abordagem exige.
Um cliente MCP que quer chamar um servidor protegido enfrenta um problema de confiança já na primeira requisição. O servidor nunca viu esse cliente, e o servidor de autorização por trás dele também nunca ouviu falar dele. A especificação de autorização do MCP resolve isso com OAuth 2.1, e a parte que mais mudou no último ano é a forma como um cliente obtém seu client_id. Client ID Metadata Documents (CIMD) entraram na revisão 2025-11-25 como um mecanismo de registro recomendado, e a revisão 2026-07-28 marca o Dynamic Client Registration (DCR) como obsoleto. Este artigo acompanha o fluxo OAuth 2.1 do MCP desde a primeira resposta 401 até a primeira chamada de ferramenta autorizada, mostra requisições e respostas reais para os dois caminhos de registro e termina com uma regra simples para escolher entre eles.
Por que o MCP precisa de OAuth 2.1
Imagine a recepção de um hotel. Você mostra seu documento uma vez, a recepção confirma quem você é e você sai com um cartão de quarto que abre o seu quarto e mais nada. O OAuth segue o mesmo padrão. O servidor de autorização é a recepção, o token de acesso é o cartão do quarto, e o servidor MCP é a porta que confere o cartão. A porta nunca vê o seu passaporte, e um cartão do quarto 412 não abre o quarto 518.
A autorização é opcional no MCP, mas as regras ficam rígidas assim que você a ativa. Servidores baseados em HTTP DEVERIAM seguir a especificação de autorização, enquanto servidores stdio NÃO DEVERIAM fazer isso e, em vez disso, leem as credenciais do ambiente. Veja o que a especificação torna obrigatório:
PKCE com o método S256. Os clientes também devem verificar se o servidor de autorização anuncia code_challenge_methods_supported e recusar continuar se o campo estiver ausente.
Metadados de recurso protegido (RFC 9728). O servidor MCP os publica, e o cliente os usa para encontrar o servidor de autorização correto.
Indicadores de recurso (RFC 8707). Os clientes enviam um parâmetro resource tanto na requisição de autorização quanto na requisição de token.
Bearer tokens em um cabeçalho. O cabeçalho Authorization: Bearer vai em toda requisição HTTP, e os tokens nunca aparecem na query string.
Validação de audiência. Um servidor MCP aceita apenas tokens emitidos para ele mesmo.
Os quatro atores
Todo fluxo deste artigo envolve as mesmas quatro partes. Mantenha-as claras e o restante fica fácil de acompanhar.
Ator
Papel no OAuth
Exemplo típico
Usuário
Dono do recurso
Uma pessoa aprovando o acesso em um navegador
Cliente MCP
Cliente OAuth
Um app de desktop com IA, uma IDE, um agente de linha de comando
Servidor MCP
Servidor de recursos
https://mcp.example.com/mcp
Servidor de autorização
Emite tokens
Auth0, Okta, Microsoft Entra ID ou um serviço próprio
💡 O servidor MCP e o servidor de autorização podem estar na mesma implantação ou pertencer a duas empresas diferentes. Um client ID só tem significado para o servidor de autorização que o emitiu ou aceitou, então um cliente nunca deve presumir que um ID funciona em todo lugar.
O fluxo do 401 ao token
O handshake é uma cadeia curta de requisições HTTP simples. Você pode acompanhar cada uma no terminal, o que torna a depuração bem menos misteriosa do que as siglas sugerem.
O desafio 401
O cliente envia uma requisição MCP sem token. O servidor recusa e informa ao cliente onde procurar:
O parâmetro scope é a dica do servidor sobre o menor privilégio necessário para esta requisição. Se o parâmetro resource_metadata estiver ausente, o cliente recorre a URLs conhecidas, primeiro /.well-known/oauth-protected-resource/mcp (com o caminho inserido) e depois a versão na raiz.
Duas consultas de metadados
O cliente busca o documento de metadados de recurso protegido e lê qual servidor de autorização usar:
Em seguida, pede ao servidor de autorização que se descreva, tentando primeiro /.well-known/oauth-authorization-server e depois o /.well-known/openid-configuration do OpenID Connect. O issuer presente na resposta precisa coincidir com a URL que o cliente usou para montar a requisição, ou o documento é descartado. Uma resposta típica tem esta aparência:
Dois campos dessa resposta decidem como o cliente se registra: client_id_metadata_document_supported (CIMD) e registration_endpoint (DCR). Voltaremos aos dois.
PKCE e o parâmetro de recurso
Com um client_id em mãos, o cliente gera um verificador PKCE de uso único, calcula o hash dele e abre o navegador. Ele também registra o issuer esperado para conferir a resposta depois.
GET https://auth.example.com/authorize?response_type=code
&client_id=https%3A%2F%2Fapp.example.com%2Foauth%2Fclient-metadata.json
&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fcallback
&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
&code_challenge_method=S256
&resource=https%3A%2F%2Fmcp.example.com%2Fmcp
&scope=files%3Aread
&state=xyz123
O valor resource é a URI canônica do servidor MCP. Os clientes DEVEM enviá-lo mesmo quando o servidor de autorização o ignora, porque é isso que permite vincular um token a um servidor específico.
Troca do código e uso do token
O usuário aprova, e o navegador volta para a URI de redirecionamento com um code, o state e, idealmente, um parâmetro iss. A revisão 2026-07-28 acrescenta uma verificação de emissor da RFC 9207: se iss estiver presente, o cliente o compara com o emissor registrado antes de enviar o código para qualquer lugar. Isso bloqueia ataques de troca de contexto (mix-up), em que um servidor de autorização hostil tenta capturar códigos destinados a um servidor legítimo.
Depois vem a requisição de token, que comprova a posse do verificador PKCE:
A resposta traz o token de acesso, e daí em diante toda requisição ao servidor MCP inclui Authorization: Bearer <access-token>. Se mais tarde o token não tiver um escopo necessário, o servidor responde 403 com error="insufficient_scope", e o cliente autoriza novamente com a união dos escopos antigos e novos.
DCR: como funciona e onde quebra
O Dynamic Client Registration vem da RFC 7591. A ideia é simples: antes do primeiro login, o cliente envia seus dados a um registration_endpoint e recebe de volta um client_id novo. Nenhuma pessoa preenche um formulário. Durante anos essa foi a principal forma de integrar automaticamente um cliente desconhecido, e por isso o MCP adotou o mecanismo no início.
Uma requisição de registro
Veja uma troca realista para um cliente MCP de desktop:
Repare em application_type. Desde a revisão 2026-07-28, os clientes DEVEM definir esse campo. Servidores que falam OpenID Connect tratam um valor ausente como web, e esse padrão pode rejeitar URIs de redirecionamento localhost.
Por que os servidores têm dificuldade com ele
O DCR funciona, mas transfere uma carga grande para o servidor de autorização:
Um endpoint público de escrita. Qualquer pessoa na internet pode criar registros, então você precisa de limites de taxa, expiração e tarefas de limpeza.
Um registro por pareamento. Cada cliente se registra separadamente em cada servidor de autorização e precisa armazenar o resultado com segurança, indexado por issuer. Quando o servidor de autorização muda, o cliente precisa se registrar de novo.
Nomes que ninguém verificou. A tela de consentimento mostra o client_name que quem se registrou digitou, então um aplicativo hostil pode se chamar como quiser.
Crescimento do banco de dados. Milhares de instalações de um mesmo cliente popular viram milhares de registros que todos significam a mesma coisa.
Esses custos são o motivo pelo qual a especificação agora aponta novas implementações para outro caminho.
CIMD: a URL é o client ID
Pense em um passaporte. Ninguém pede ao agente de fronteira que memorize você antecipadamente. Você entrega um documento, e o agente o confere com a autoridade emissora. O CIMD inverte o registro do mesmo jeito. O cliente publica um documento JSON em uma URL HTTPS estável, e essa URL é o client_id. O servidor de autorização lê o documento quando vê a URL pela primeira vez, então não há nada para registrar antecipadamente.
O documento de metadados
As regras para o cliente são curtas. O client_id precisa usar https e incluir um caminho, o documento deve conter client_id, client_name e redirect_uris, e o client_id dentro do arquivo precisa coincidir com a URL de onde ele foi servido, caractere por caractere. O exemplo da própria especificação tem esta aparência:
Quando chega uma requisição de autorização com uma URL no formato client_id, o servidor de autorização segue uma rotina fixa:
Busque o documento com um GET HTTPS simples.
Confirme que é um JSON válido e que contém os campos obrigatórios.
Confirme que o client_id no arquivo é exatamente igual à URL.
Confirme que o redirect_uri na requisição corresponde a um dos listados no arquivo.
Armazene o resultado em cache, respeitando os cabeçalhos de cache HTTP.
Mostre ao usuário o client_name e o nome do host de redirecionamento na tela de consentimento.
Um esboço mínimo dos passos 1 a 3 em TypeScript, escrito para clareza e não para uso em produção:
async function loadClient(clientId: string) {
const url = new URL(clientId);
if (url.protocol !== "https:" || url.pathname === "/") throw new Error("invalid_client");
await assertPublicHost(url.hostname); // reject private, loopback and link-local addresses
const res = await fetch(url, { redirect: "error", signal: AbortSignal.timeout(5000) });
const doc = await res.json();
if (doc.client_id !== clientId) throw new Error("invalid_client");
if (!doc.client_name || !Array.isArray(doc.redirect_uris)) throw new Error("invalid_client");
return doc;
}
Anunciando suporte a CIMD
O servidor de autorização anuncia o recurso em seus metadados com "client_id_metadata_document_supported": true. Os clientes que o encontram usam a URL deles como client_id e pulam o registro por completo. Como o ID é uma URL pública, ele também é portátil: o mesmo cliente pode conversar com outro servidor de autorização amanhã sem se registrar de novo.
CIMD ou DCR lado a lado
Pergunta
CIMD
DCR
Status na especificação em 2026-07-28
Recomendado (DEVE)
Obsoleto, mantido por compatibilidade (PODE)
Quem armazena o registro do cliente
O cliente o hospeda, o servidor o armazena em cache
O servidor de autorização o armazena
Formato do client_id
Uma URL, como https://app.example.com/oauth/client-metadata.json
Uma string opaca, como s6BhdRkqt3
Precisa de um endpoint de registro
Não
Sim, anunciado como registration_endpoint
Trabalho antes do primeiro login
Nenhum para o cliente
Um POST por servidor de autorização
Portável entre servidores de autorização
Sim
Não, registrar de novo para cada emissor
Principal risco
SSRF durante a busca, falsificação de localhost
Abuso de endpoint aberto, registros inúteis
Como um servidor anuncia o recurso
client_id_metadata_document_supported
registration_endpoint
Um cliente que suporta todas as opções DEVE escolher nesta ordem:
Usar os dados de cliente pré-registrados, se tiver algum para este servidor.
Usar CIMD se o servidor de autorização anunciar suporte.
Recorrer ao DCR se existir um registration_endpoint.
Pedir ao usuário que digite os dados do cliente manualmente.
💡 O pré-registro continua sendo a melhor opção quando você o tem. Se você controla tanto o cliente quanto o servidor de autorização, um client_id fixo pula todas as consultas acima.
Verificações de segurança que você não pode pular
Passar do DCR para o CIMD não elimina o risco. Ele move o risco para outros lugares, e cada um precisa de um responsável.
SSRF na busca
Com o CIMD, um visitante anônimo decide qual URL o seu servidor vai requisitar. Aponte client_id para https://169.254.169.254/latest/meta-data/ ou para um painel administrativo interno, e um buscador descuidado vira um proxy para dentro da sua rede. Resolva primeiro o nome do host e rejeite faixas privadas, de loopback e de link-local. Defina um timeout curto, limite o tamanho da resposta e seja rigoroso com os redirecionamentos.
Redirecionamentos para localhost
Um documento de metadados não pode provar que um processo escutando em localhost:3000 pertence ao cliente nomeado no arquivo. Qualquer programa local pode reivindicar essa porta. Por isso, o servidor de autorização DEVE exibir o nome do host de redirecionamento na tela de consentimento, DEVERIA avisar quando todas as URIs de redirecionamento forem localhost e PODE exigir uma atestação extra para obter maior garantia. As próprias URIs de redirecionamento devem corresponder exatamente, nunca por prefixo ou padrão.
Audiência e repasse de token
O servidor MCP é o último portão, e precisa conferir o cartão, não apenas dar uma olhada nele. Valide a assinatura, a expiração, os escopos e, acima de tudo, a audiência. Um token emitido para outro serviço deve ser rejeitado com um 401. Se o seu servidor MCP chamar uma API upstream, ele precisa de um token separado para essa API, emitido pelo servidor de autorização dessa API. Repassar o token do cliente se chama repasse de token (token passthrough), e a especificação o proíbe expressamente.
Uma lista curta de verificação para fixar ao lado do seu monitor:
Sirva todo endpoint de autorização sobre HTTPS e permita apenas redirecionamentos HTTPS ou localhost.
Mantenha os tokens de acesso de curta duração e rotacione os refresh tokens para clientes públicos.
Use e verifique o parâmetro state.
Valide iss quando ele estiver presente, antes de trocar o código.
Inclua em um único desafio todos os escopos necessários para uma operação, para que o usuário não passe por telas de aprovação repetidas.
Escolhendo uma estratégia
A decisão é menos dramática do que o debate sugere. Dê prioridade ao CIMD, mantenha o DCR como ponte e seja honesto sobre de que lado da mesa você está.
Se você administra um servidor MCP
Publique os metadados de recurso protegido de qualquer forma. Escolha um servidor de autorização que suporte CIMD e, se o seu ainda não suportar, mantenha o DCR ativado com limites de requisição e expiração, em vez de bloquear todos os clientes. Coloque um scope no seu desafio WWW-Authenticate, responda com 403 e insufficient_scope quando um token não tiver o escopo necessário, e verifique a audiência em toda requisição.
Se você desenvolve um cliente MCP
Hospede seu documento de metadados em uma URL que você vai manter por anos, porque a URL é a sua identidade. Leia os metadados do servidor de autorização e depois escolha um caminho de registro no código:
Quando você de fato recorrer ao DCR, armazene as credenciais vinculadas ao issuer, defina application_type: "native" para apps de desktop e de linha de comando, e nunca as reutilize com outro servidor de autorização.
Experimente no PicassoIA
Seja qual for o lado do handshake que você construir, vai escrever bastante JSON, fixtures de teste e documentação. Um modelo de linguagem capaz acelera isso, e o PicassoIA hospeda vários. Veja um jeito rápido de usar o Claude Sonnet 5 como revisor do seu documento de metadados:
Cole o seu client-metadata.json e os metadados do servidor de autorização do seu provedor.
Peça uma verificação com checklist: "Confira este documento com as regras do CIMD: client_id igual à URL, https com caminho, campos obrigatórios presentes, redirect_uris exatas. Liste cada falha."
Peça que a saída venha como tabela com regra, resultado e correção, para que a resposta seja fácil de colar em um pull request.
Para uma segunda opinião, rode o mesmo prompt no GPT 5.6 Sol ou faça uma passada rápida com o Gemini 3.5 Flash, e compare as falhas que cada um encontra.
💡 Os modelos revisam documentos bem, mas não substituem um teste real. Execute seu fluxo contra um servidor de autorização de homologação antes de publicar.
Documentação precisa de imagens tanto quanto precisa de JSON. Uma imagem de destaque, um fundo de diagrama ou um card para redes sociais tornam um post sobre OAuth muito mais fácil de compartilhar, e o PicassoIA foi feito exatamente para isso. Resultados fotorrealistas vêm de prompts específicos: nomeie a lente, a direção da luz e as texturas da cena. Experimente algo como "uma recepcionista de hotel deslizando um cartão de quarto sobre um balcão de mármore, lente de 50mm, luz suave de janela vindo da direita, granulação de filme" e veja o que aparece. Desenvolvedores também podem acessar os modelos de imagem e vídeo do PicassoIA pela API do PicassoIA e por conexões MCP, então o mesmo prompt pode rodar a partir do seu próprio agente.
Pronto para criar os seus próprios visuais? Abra o PicassoIA, escolha um modelo e comece a experimentar seu primeiro prompt hoje mesmo.