Pular para o conteúdo principal

Autenticação

O servidor MCP aceita um Bearer token no cabeçalho Authorization, e nada além disso — sem cookie, sem certificado de cliente.

:::warning Nunca na URL Token na query string (?access_token=…, ou parâmetros como token, bearer, api_key e key) não autentica, mesmo acompanhado de um cabeçalho válido: a requisição responde 401 com error="invalid_request" no WWW-Authenticate. Um token na URL vaza em logs de proxy e CDN, no Referer e no histórico — a especificação de autorização do MCP e a RFC 6750 proíbem esse uso. :::

Esse token é um access token emitido pelo Authorization Server da Kobana (https://account.kobana.com.br), um JWT assinado em RS256 e emitido para este recurso: o aud dele é https://mcp.kadu.ia.br (em staging, https://mcp.staging.kadu.ia.br), e só ele — um token com mais de uma audience é recusado. O token chega por um de dois caminhos — o fluxo OAuth, feito pelo próprio cliente, ou um token pessoal que você cria na Conta Kobana — e é verificado do mesmo jeito nos dois casos, com a mesma checagem local de assinatura da API v1.

Authorization: Bearer eyJhbGciOiJSUzI1NiIs…

:::info Cada superfície tem a sua audience Um token emitido para o MCP não vale na API (api.kadu.ia.br), e um token da API não vale aqui. É o que impede que o token entregue a um assistente seja reaproveitado como credencial REST — e o contrário. :::

Dois jeitos de conectar​

Fluxo OAuthToken pessoal
Como você obtémCola a URL no cliente; ele abre o login da Conta Kobana e você autorizaCria no assistente de tokens da Conta Kobana, com o uso MCP, os recursos e acessos e a validade
Como o cliente usaSozinho, depois da autorização, renovando quando expiraVocê cola no cliente como Authorization: Bearer <token>
EscopoOs recursos e os níveis de acesso que você manteve marcados na tela de consentimentoOs recursos e acessos que você marcou
Bom paraClaude, ChatGPT, IDEs e qualquer cliente com OAuthClientes sem suporte a OAuth, scripts e automações

O token pessoal tem que ser criado com o uso MCP. Um token criado para a API tem a audience da API e é recusado aqui com 401 — e o contrário também vale.

O fluxo OAuth​

Você não executa nenhum destes passos: o cliente MCP faz tudo sozinho a partir da URL. Eles estão aqui para quando algo falhar no meio.

  1. Desafio. Uma requisição sem token recebe 401 com o desafio que todo resource server OAuth 2.1 deve mandar (RFC 9728):

    WWW-Authenticate: Bearer realm="kadu-mcp",
    error="invalid_token",
    resource_metadata="https://mcp.kadu.ia.br/.well-known/oauth-protected-resource"
  2. Metadata do recurso. O cliente lê o documento apontado. Ele é público e não carrega segredo nenhum — só ponteiros:

    curl https://mcp.kadu.ia.br/.well-known/oauth-protected-resource
    {
    "resource": "https://mcp.kadu.ia.br",
    "authorization_servers": ["https://account.kobana.com.br"],
    "bearer_methods_supported": ["header"],
    "scopes_supported": [
    "kadu/activities",
    "kadu/environments",
    "kadu/executions",
    "kadu/files",
    "kadu/memberships",
    "kadu/memories",
    "kadu/organizations",
    "kadu/repository",
    "kadu/roles",
    "kadu/schedules",
    "kadu/secrets",
    "kadu/system_events",
    "kadu/tasks",
    "kadu/todos",
    "kadu/usage",
    "kadu/users",
    "kadu/webhook_deliveries",
    "kadu/webhooks",
    "kadu/workspaces",
    "read",
    "write",
    "delete",
    "import",
    "export",
    "all"
    ],
    "resource_documentation": "https://api.kadu.ia.br/v1/docs"
    }

    kadu/all fica de fora de propósito: o curinga não é entregue a um cliente que se registrou sozinho.

  3. Metadata do Authorization Server (RFC 8414), em https://account.kobana.com.br/.well-known/oauth-authorization-server.

  4. Registro dinâmico do cliente (RFC 7591). O cliente se registra sozinho.

  5. Autorização com PKCE e resource (RFC 8707). Você faz login na Conta Kobana, escolhe a organização (se tiver mais de uma), revisa o que o cliente pede e autoriza.

  6. Token. O cliente troca o código por um access token de vida curta e passa a mandá-lo em toda requisição, renovando quando expira.

O token carrega quem você é (sub) e a organização que você autorizou (org). É o org que escopa os dados — nenhuma tool aceita organização como argumento. Um token cuja organização não existe no Kadu recebe 403 unknown_organization.

Autorização: o papel de quem autorizou​

O que um chamador vê é mais estreito que o catálogo: as tools são filtradas pelo papel da pessoa do token na organização — as mesmas permissões agent.<recurso>.<ação> do console e da API (veja Permissões). A tool exige exatamente a permissão da rota que ela espelha. O teto é sempre o que essa pessoa pode fazer no console.

SituaçãoResultado
A pessoa do token não é membro da organizaçãoNega todas as tools (not_a_member). Autorize de novo com uma conta que pertença à organização.
MembroAs permissões do papel, aplicadas tool a tool. Os curingas *, agent.* e agent.<recurso>.* valem como no console.
A consulta de permissões falhaNega todas as tools. Falha fechada.

Diferente da API, o MCP não tem token de integração sem pessoa: o token tem que levar a uma pessoa da organização (pelo sub ou pelo e-mail do token), senão nenhuma tool roda.

As permissões são relidas pelo menos a cada minuto, então mudar ou remover o papel de alguém vale em até um minuto, sem esperar o token expirar.

Uma tool que o chamador não pode rodar não é listada em tools/list. Quando tools/call recusa, o código diz quem resolve:

CódigoQuem resolve
insufficient_scopeVocê, autorizando de novo com o acesso que faltou — ou usando um token pessoal que alcance o recurso com o nível pedido.
insufficient_permissionUm administrador da organização, concedendo a permissão (o erro nomeia qual).
not_a_memberAutorizar de novo com uma conta que seja membro da organização.

:::tip Postura recomendada para agentes Autorize o cliente com uma conta que só tenha as permissões de que o agente precisa. Um cliente autorizado por alguém que só lê expõe só as tools de leitura, faça o que fizer o modelo do outro lado. :::

Escopo do token​

Além do papel, o MCP aplica o escopo que o token carrega, no claim scope, com a mesma gramática da API (veja Autenticação da API → Escopos). As duas checagens se somam: uma tool só aparece se as duas deixarem.

ToolExige
Leitura (*_list, *_get, kadu_usage_get…)O escopo do recurso (kadu/tasks)
Exclusão (*_delete)O escopo do recurso + delete
Qualquer outra alteração (criar, alterar, disparar, cancelar, continuar, sincronizar, reenviar, girar segredo)O escopo do recurso + write
kadu_me_getQualquer token válido

O recurso é o primeiro segmento da rota que a tool espelha: kadu_executions_logs_list é do recurso executions, e kadu_tasks_run exige kadu/tasks write. As aprovações por link (kadu_operation_approvals_*) são lidas com kadu/system_events. Um nível não substitui outro: write não exclui. Nenhuma tool exige import ou export.

Escopo do tokenResultado
kadu/executions kadu/todos read writeLê e altera execuções e pendências — cancela, continua e resolve — e nada mais
kadu/tasks kadu/executions writeLê, dispara e acompanha tarefas, sem excluir nada
read (sem nenhum kadu/…)Lê tudo, não escreve nada

:::info Clientes conectados pelo fluxo OAuth pedem todos os níveis — você escolhe quais conceder O documento /.well-known/oauth-protected-resource anuncia os recursos do Kadu e os seis níveis de acesso, e é isso que o cliente pede na tela de consentimento. Lá você desmarca o que não quer conceder: o token emitido traz só os recursos e os níveis que ficaram marcados, e o MCP lista só as tools que eles alcançam. Uma tool fora dele volta insufficient_scope, e a saída é autorizar de novo concedendo o acesso que faltou — por exemplo, delete para as tools de exclusão. :::

Revogação do token pessoal​

O Kadu verifica o token sozinho, pela assinatura, sem consultar a Conta Kobana a cada chamada: revogar um token pessoal lá não corta o acesso na hora, e ele continua aceito até a validade dele. Por isso:

  • escolha a validade mais curta que o uso permite;
  • marque só os recursos e acessos de que o agente precisa;
  • para cortar um agente imediatamente, remova o vínculo da pessoa com a organização ou troque o papel dela — vale em até um minuto.

Modos de falha​

HTTPcodeCausa
400-32022 (JSON-RPC)Versão do protocolo não suportada, no cabeçalho MCP-Protocol-Version ou no _meta; data.supported lista as que são. Veja Transporte.
401invalid_tokenToken ausente, malformado, inválido, emitido para outro recurso (por exemplo, para a API) ou com mais de uma audience no aud.
401token_expiredO token expirou. O cliente renova e tenta de novo.
401token_revokedO token foi revogado no Kadu.
401invalid_requestToken na query string — veja o aviso no topo da página.
403unknown_organizationO token é válido, mas a organização que ele nomeia não existe no Kadu.
403FORBIDDENOrigin fora da lista permitida (origin_not_allowed).
404NOT_FOUNDA requisição chegou por um host que não serve MCP.
413-32600 (JSON-RPC)Corpo acima de 1 MB.
429TOO_MANY_REQUESTSLimite de Requisições atingido, com Retry-After e X-RateLimit-* — veja Limite de Requisições.
503SERVICE_UNAVAILABLENão conseguimos verificar o token contra o Authorization Server. É do nosso lado: tente de novo depois do Retry-After.

Todo 401 carrega o desafio WWW-Authenticate acima, que manda o cliente de volta ao fluxo OAuth. O desafio diz sempre error="invalid_token" (ou invalid_request, para token na URL), como manda a RFC 6750; é o code do corpo que separa um token expirado (token_expired) dos demais. Tentativas com token recusado contam num limite por IP, e passado o limite a resposta vira 429.

Nenhuma resposta do MCP é cacheável: todas, inclusive as recusas, vêm com Cache-Control: no-store e Content-Security-Policy: default-src 'none'. A exceção é o documento /.well-known/oauth-protected-resource, público, com Cache-Control: public, max-age=300.

Negativas de escopo e de permissão não são erros HTTP: elas voltam como resultado de tool marcado isError, para que o modelo leia e reaja — veja Erros.

Host e borda​

O MCP só responde por mcp.kadu.ia.br — nunca pelo host do console, nunca pelo host da API, que apontam para a mesma aplicação. Por qualquer outro caminho a resposta é 404: o endpoint não anuncia que existe em outro lugar.

O identificador de recurso OAuth — e, portanto, a audience que o token precisa ter — vem da configuração do servidor, nunca do Host da requisição, para que um Host forjado não consiga apontar um cliente para outro identificador.