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 e api_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 OAuth 2.1 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.dashboards.kobana.com.br. Ele chega por um de dois caminhos — o fluxo OAuth, feito pelo próprio cliente, ou um token pessoal que você cria na sua conta Kobana — e é verificado do mesmo jeito nos dois casos.
Authorization: Bearer eyJhbGciOiJSUzI1NiIs…
:::info Cada superfície tem a sua audience
Um token emitido para o MCP não vale na API REST (api.dashboards.*), e um token da API não vale aqui. É o que impede que o token entregue a um assistente seja reaproveitado contra a API — e o contrário.
:::
Dois jeitos de conectar
| Fluxo OAuth | Token pessoal | |
|---|---|---|
| Como você obtém | Cola a URL no cliente; ele abre o login da Kobana e você autoriza | Cria em Conta Kobana → Tokens e Acesso → Novo Token Pessoal: app Dashboard Mágico, uso MCP, recursos e acessos, validade |
| Como o cliente usa | Sozinho, depois da autorização | Você cola no cliente como Authorization: Bearer <token> |
| Validade | 30 minutos, renovado pelo cliente | De 7 dias a 1 ano, escolhida por você |
| Escopo | Só o nível de acesso — hoje, read | Os recursos e acessos que você marcou |
| Bom para | Claude, ChatGPT, IDEs e qualquer cliente com OAuth | Clientes sem suporte a OAuth, scripts e automações |
O token pessoal tem que ser criado com o uso MCP. Um token criado para API REST 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 (Claude, ChatGPT, uma IDE) faz tudo sozinho a partir da URL. Eles estão aqui para quando algo falhar no meio.
-
Desafio. Uma requisição sem token recebe
401com o desafio que todo resource server OAuth 2.1 deve mandar (RFC 9728):WWW-Authenticate: Bearer realm="kobana-dashboards-mcp",error="invalid_token",resource_metadata="https://mcp.dashboards.kobana.com.br/.well-known/oauth-protected-resource" -
Metadata do recurso. O cliente lê o documento apontado. Ele é público e não carrega segredo nenhum — só ponteiros:
curl https://mcp.dashboards.kobana.com.br/.well-known/oauth-protected-resource{"resource": "https://mcp.dashboards.kobana.com.br","authorization_servers": ["https://account.kobana.com.br"],"bearer_methods_supported": ["header"],"resource_documentation": "https://docs.dashboards.kobana.com.br"} -
Metadata do authorization server (RFC 8414), em
https://account.kobana.com.br/.well-known/oauth-authorization-server. -
Registro dinâmico do cliente (RFC 7591). O cliente se registra sozinho; a tela de consentimento avisa que ele não é um app verificado.
-
Autorização com PKCE e
resource(RFC 8707). Você faz login na Kobana, escolhe a organização (se tiver mais de uma) e autoriza. -
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 Dashboard Mágico recebe 403 unknown_organization.
Autorização: as permissões de quem autorizou
O que um chamador vê é mais estreito que o catálogo: as tools são filtradas pelas permissões de dashboard da pessoa que autorizou o cliente, naquela organização, resolvidas a cada requisição. O teto é sempre o que essa pessoa pode fazer na interface.
| Situação | Resultado |
|---|---|
| A pessoa não é membro da organização | Nega todas as tools (key_owner_not_member). Autorize de novo com uma conta que pertença à organização. |
| Vínculo ativo | As permissões e papéis da pessoa, aplicados tool a tool. owner e o curinga * liberam tudo; portal-users.* libera a família. |
| Vínculo suspenso, removido, ou sem nenhum papel | Nega todas as tools (membership_inactive). |
| A consulta de permissões falha | Nega todas as tools. Falha fechada. |
As permissões são lidas a cada chamada, então revogar um papel no dashboard vale já na tool seguinte, 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ódigo | Quem resolve |
|---|---|
insufficient_scope | Usar um token que alcance o recurso com o acesso pedido — por exemplo, um token pessoal com escrita nesse recurso. |
insufficient_permission | Um admin da organização, concedendo a permissão (o erro nomeia qual). |
membership_inactive | Reativar a pessoa — nenhuma permissão conserta um vínculo morto. |
key_owner_not_member | Autorizar 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 que o agente precisa. Um cliente autorizado por um analista somente-leitura expõe só as tools de leitura, faça o que fizer o modelo do outro lado. :::
Escopo do token
Além das permissões, o MCP aplica o escopo que o token carrega, no claim scope. As duas checagens se somam: uma tool só aparece se as duas deixarem. Leitura é tool de leitura, resource, prompt de leitura e completion; escrita é todo o resto, destrutivas incluídas.
Token com recursos — o caso do token pessoal. Os recursos definem até onde o token chega, e read/write valem só dentro deles:
| Escopo do token | Resultado |
|---|---|
dashboards/users dashboards/members read write | Lê e escreve usuários do portal e membros do time (com os papéis) — e nada mais |
dashboards/users read | Só lê usuários do portal |
dashboards/all read | Lê tudo, não escreve nada |
Um recurso fora dos dez grupos só é alcançável com dashboards/all. delete, import e export sozinhos não contam como escrita.
Token sem recursos — o caso do fluxo OAuth. Vale só o nível de acesso: leitura com read, write ou all; escrita com write ou all.
:::info Clientes conectados pelo fluxo OAuth ficam só com leitura
O authorization server concede apenas read a clientes registrados dinamicamente — Claude, ChatGPT, o MCP Inspector, IDEs. Para eles, o MCP lista só as tools de leitura, e uma tool que escreve volta insufficient_scope. Para um agente escrever hoje, use um token pessoal com acesso de escrita nos recursos de que ele precisa.
:::
A mesma regra vale na API REST, com o recurso tirado do caminho: um token sem acesso de escrita ao recurso recebe 403 insufficient_scope em qualquer método que não seja GET.
Revogação do token pessoal
Revogar um token pessoal na sua conta Kobana não corta o acesso na hora: o Dashboard Mágico verifica o token sozinho, sem consultar a Kobana a cada chamada, 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, suspenda ou remova o vínculo da pessoa na organização — as permissões são lidas a cada chamada e valem na hora.
Modos de falha
| HTTP | code | Causa |
|---|---|---|
| 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. |
| 401 | UNAUTHORIZED | Token ausente, malformado, inválido, expirado ou emitido para outro recurso (por exemplo, para a API REST). |
| 403 | unknown_organization | O token é válido, mas a organização que ele nomeia não existe no Dashboard Mágico. |
| 403 | FORBIDDEN | Origin fora da allowlist (origin_not_allowed). |
| 404 | NOT_FOUND | A requisição chegou por um host que não serve MCP. |
| 429 | TOO_MANY_REQUESTS | Limite de requisições atingido — veja Limite de requisições. |
| 503 | SERVICE_UNAVAILABLE | Não conseguimos falar com o authorization server para verificar o token. É 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.
Negativas 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
/mcp tem que ser alcançável só por mcp.dashboards.* — nunca pelo host do app, nunca pelo host da API, cujas distributions apontam para a mesma origin. Qualquer outro caminho responde 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 — é derivado 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.