Metabase

oficial

Servidor MCP oficial do Metabase para pesquisar dados, criar consultas na camada semântica e visualizar resultados por meio de clientes MCP.

O que você pode fazer com Metabase MCP?

  • Pesquisar e recuperar conteúdo — Peça ao seu assistente para encontrar perguntas, painéis ou modelos no Metabase usando a ferramenta search e, em seguida, busque os detalhes com get_content.
  • Executar consultas e visualizar resultados — Faça seu assistente executar consultas estruturadas via execute_query ou SQL bruto com execute_sql e, depois, renderize os resultados como gráficos interativos usando visualize_query.
  • Criar e gerenciar painéis — Instrua seu assistente a criar ou atualizar painéis e seus layouts com dashboard_write, ou duplicar conteúdo existente em coleções via duplicate_content.
  • Configurar alertas e assinaturas — Peça ao seu assistente para criar alertas agendados para perguntas salvas com alert_write ou configurar assinaturas de e-mail de painéis usando subscription_write.
  • Explorar a hierarquia de dados — Direcione seu assistente para navegar por bancos de dados, esquemas, tabelas e campos através de browse_data, ou navegue por coleções estruturalmente com browse_collection.

Documentação

Servidor MCP do Metabase

O Metabase inclui um servidor integrado de Model Context Protocol (MCP) que permite que clientes de IA se conectem diretamente a uma instância do Metabase. Ele usa o transporte HTTP Streamable e se baseia na Agent API do Metabase para expor ferramentas de busca, navegação, consulta, visualização e criação/atualização de conteúdo — tudo limitado às permissões do usuário conectado.

Endpoint

O servidor MCP está disponível em:

https://{your-metabase.example.com}/api/metabase-mcp

O caminho legado /api/mcp ainda funciona como um alias para clientes existentes, mas /api/metabase-mcp é a URL canônica a ser divulgada.

Conectando um cliente

Aponte qualquer cliente compatível com MCP para o endpoint /api/metabase-mcp. Por exemplo, com o Claude Code:

claude mcp add metabase https://{your-metabase.example.com}/api/metabase-mcp --transport streamable-http

Para o Claude Desktop, crie um conector personalizado usando a mesma URL.

Para o Cursor, abra Configurações > MCP e adicione um novo servidor com o tipo definido como streamable-http e a URL:

https://{your-metabase.example.com}/api/metabase-mcp

Autenticação

Os clientes MCP autenticam via OAuth 2.0. O Metabase executa seu próprio servidor OAuth incorporado — nenhum provedor externo é necessário.

O fluxo para uma primeira conexão:

  1. O cliente descobre os endpoints OAuth do Metabase.
  2. O cliente se registra no Metabase.
  3. O usuário é redirecionado para o Metabase para fazer login e aprovar a conexão.
  4. O cliente recebe um token de acesso limitado às permissões do usuário no Metabase.

Sessões baseadas em navegador (autenticação por cookie), chaves de API e tokens mb:full não possuem escopo MCP, portanto podem se conectar, mas não podem chamar nenhuma ferramenta com escopo.

Escopos

Os tokens de acesso têm escopos que limitam quais ferramentas um cliente pode usar:

EscopoFerramentas que concede
agent:content:readbrowse_collection, browse_data, get_content, get_parameter_values, glossary, learn, search e o recurso de dados catalog://metabase/fields (consulte Recursos)
agent:content:writebookmark_content, collection_write, dashboard_write, document_write, duplicate_content, measure_write, metric_write, question_write, segment_write
agent:delivery:writealert_write, subscription_write
agent:query:runexecute_query, refresh_ui_credential, render_drill_through, run_saved_question, visualize_query
agent:sql:runexecute_sql

Uma ferramenta corresponde apenas ao escopo exato na tabela. Um curinga como * ou agent:*, e o sentinel ::unrestricted, não são escopos MCP, portanto não concedem nenhuma ferramenta.

Esses escopos controlam apenas a superfície MCP. Nenhum endpoint REST pode declarar um deles como seu :scope, portanto um novo token emitido para um cliente MCP não concede nada na API REST.

O scopes_supported dos metadados do recurso protegido e o scope do desafio 401 listam todos os escopos da tabela, portanto uma nova conexão solicita todos eles. Alguns clientes não fazem step-up após um 403: uma reconexão manual nas configurações do conector do Claude registra um novo cliente e solicita exatamente o que essas listas indicam. Quando listavam apenas o escopo básico, essa reconexão nunca oferecia escrita, SQL bruto ou entrega, e o usuário não tinha como concedê-los (ENG-11089). Os metadados do servidor de autorização também divulgam todos eles.

O escopo básico (agent:content:read agent:query:run) está bloqueado na tela de consentimento: quando um cliente solicita um desses, o usuário não pode desmarcá-lo. agent:query:run está no escopo básico para que os gráficos nunca precisem de step-up. O Claude Desktop tenta novamente uma ferramenta após um step-up em uma sessão que não declara suporte a MCP Apps, portanto um visualize_query com step-up é recusado e seu gráfico nunca é incorporado.

Uma chamada de ferramenta ou leitura de recurso de dados para a qual o token não possui escopo é recusada com HTTP 403 e um desafio WWW-Authenticate: Bearer error="insufficient_scope" cujo scope lista os escopos v2 que o token já possui mais o necessário, para que um cliente possa fazer step-up. Cada ferramenta também declara seu escopo em securitySchemes, que é o rascunho SEP-1488, suportado pelo ChatGPT. Ele não faz parte do MCP 2025-03-26 (a versão que este servidor reporta) nem da especificação final de ferramentas de 2026-07-28, portanto outros clientes descobrem o escopo ausente pelo 403. Dentro de um lote JSON-RPC, a recusa é um erro -32600 in-band em vez disso. Leituras de shell de UI nunca são desafiadas: consulte Recursos.

Os metadados de recurso protegido OAuth estão disponíveis em:

/.well-known/oauth-protected-resource/api/metabase-mcp

Na tela de consentimento, todo escopo solicitado pelo cliente começa marcado, e os escopos básicos também estão bloqueados. Apenas os escopos que permanecem marcados são concedidos, e somente para o token que esta autorização emite. Desmarcar nunca afeta um token que o aplicativo já possui. Um escopo deixado desmarcado não é lembrado pelo Metabase. Um 403 posterior pode acionar outro step-up em clientes que o suportam. Outros clientes podem exigir reautorização manual. O error_description de cada desafio termina com uma nota de que o usuário deve conceder a permissão na tela de consentimento.

Vários clientes substituem o error_description do 403 por seu próprio texto, portanto o instructions do resultado initialize também explica falhas de escopo ao modelo: um erro de autenticação geralmente significa uma permissão ausente em vez de um login expirado, o modelo deve nomear a ferramenta ou recurso que falhou e a permissão que ele exige, e o usuário a concede reconectando e deixando a permissão marcada na tela de consentimento. As instruções são uma única string estática, a mesma para todos os chamadores: não há lista de permissões por conexão.

Acesso a ferramentas por grupo

Em instâncias Enterprise com o recurso ai_controls, um administrador pode restringir a superfície por grupo de permissões em Admin > IA > Controles de uso > Acesso a ferramentas MCP (exibido sempre que o servidor MCP está ativo, com ou sem um provedor de LLM). Cada grupo tem uma linha em mcp_group_permission indicando se seus membros podem se conectar e, por nome de ferramenta, o "yes" ou "no" explícito do administrador; uma ferramenta sem entrada assume o padrão declarado por seu autor, portanto todo deftool carrega um :default-access obrigatório de :allowed ou :denied, e uma ferramenta lançada posteriormente recebe exatamente esse padrão em todos os grupos até que um administrador o substitua. As entradas são indexadas por nome de ferramenta, portanto renomear uma ferramenta exige :renamed-from com seus nomes anteriores (uma entrada armazenada sob um nome anterior ainda se aplica e a API de administração a apresenta sob o nome atual), ou o autor aceita que a escolha de cada administrador para ela seja descartada; metabase.mcp.v2.tool-names-test fixa os nomes ativos para que nenhum dos dois aconteça por acidente. A política efetiva de um usuário é o tool_access de cada grupo seu cuja linha habilita MCP: o MCP está ativo quando qualquer grupo desse tipo existe, e uma ferramenta é permitida quando qualquer um desses grupos a resolve como sim. As linhas sozinhas decidem isso, e também registram o modo de permissão: modo simples (Administradores, Todos os usuários e Todos os usuários de tenant) ou modo de nível de grupo (todos os outros grupos), que é o estado em que Todos os usuários não tem linha. Um interruptor exclui as linhas dos grupos que o novo modo oculta e semeia os grupos que ele habilita na entrada que não têm linha (Analistas de dados ao entrar no modo de nível de grupo, Todos os usuários e Todos os usuários de tenant ao sair dele), e PUT recusa um grupo que o modo atual oculta, portanto nenhuma solicitação lê um modo em cache. A política é aplicada além dos escopos OAuth em tools/list e tools/call (v2/registry.clj), e um usuário cujos grupos não concedem acesso é recusado em initialize e em resources/read (para sessões abertas antes de o MCP ser desativado) com um erro nomeando a correção. Ferramentas somente de aplicativo (_meta {:ui {:visibility ["app"]}}, ou seja, refresh_ui_credential) não estão na página de administração: elas são permitidas enquanto a política permitir qualquer ferramenta de MCP Apps. Superusuários e chamadores internos nunca são restringidos; OSS permite tudo. No Enterprise, as linhas armazenadas são aplicadas mesmo sem o recurso ai_controls (um token expirado ou não verificável mantém as restrições que um administrador configurou); o recurso apenas controla a página e a API de administração. O resolvedor é permissions.clj (defenterprise, implementação EE em metabase-enterprise.mcp.permissions) e a API de administração é /api/ee/ai-controls/mcp-permissions.

Ferramentas disponíveis

Geradas a partir do registro v2 (deftool). O escopo nomeado aqui é o que o registro verifica antes de a ferramenta ser executada; alguns manipuladores verificam um escopo adicional quando sabem o que a chamada faz — agent:sql:run quando uma fonte resolve para SQL nativo (question_write) e agent:query:run para a execução que um alerta ou assinatura adia (alert_write, subscription_write). Essas recusas carregam o mesmo desafio 403 insufficient_scope. tools/list mostra todas as ferramentas, independentemente do que o token possui, e um token sem o escopo não pode chamá-la.

FerramentaEscopoDescrição
alert_writeagent:delivery:writeCriar ou atualizar um alerta: uma notificação enviada em um agendamento quando os resultados de uma pergunta salva atendem a uma condição.
bookmark_contentagent:content:writeAdicionar ou remover um marcador em conteúdo para o usuário que está chamando — a mesma lista de favoritos/estrelados que a barra lateral do Metabase mostra.
browse_collectionagent:content:readNavegar por coleções estruturalmente — um id uniforme sobre cada partição: um id numérico, um entity_id de 21 caracteres, "root" (re-enraizado por namespace) ou "trash" (conteúdo arquivado, somente no modo de itens).
browse_dataagent:content:readNavegar pela hierarquia de dados: bancos de dados → esquemas → tabelas → campos.
collection_writeagent:content:writeCriar, renomear, mover, arquivar ou restaurar uma coleção — as pastas que guardam perguntas, dashboards, modelos e documentos.
dashboard_writeagent:content:writeCriar ou atualizar um dashboard e editar seu layout com operações ordenadas.
document_writeagent:content:writeCriar ou atualizar um documento.
duplicate_contentagent:content:writeCopiar uma pergunta, dashboard ou documento para uma coleção — mais barato e mais seguro do que ler o original e recriá-lo, e preserva tudo o que as projeções de leitura deixam de fora.
execute_queryagent:query:runA forma padrão de responder a uma pergunta a partir de dados: validar e executar uma consulta estruturada (MBQL), retornando linhas mais um query_handle.
execute_sqlagent:sql:runSaída de emergência: executar uma string SQL bruta contra um banco de dados, retornando linhas mais um query_handle.
get_contentagent:content:readBuscar conteúdo por {type, id} — a leitura tipada para qualquer coisa encontrada via busca ou browse_collection.
get_parameter_valuesagent:content:readBuscar os valores válidos para um filtro em um dashboard ou pergunta salva, para que você filtre com valores reais em vez de adivinhar.
glossaryagent:content:readConsultar um termo de negócio conforme definido nesta instância do Metabase; os nomes dos termos definidos acompanham a própria descrição da ferramenta.
learnagent:content:readLer a documentação de tarefas (skills) deste servidor para os dialetos de escrita que os esquemas não conseguem descrever completamente.
measure_writeagent:content:writeCriar ou atualizar uma medida: uma agregação MBQL nomeada e reutilizável anexada a uma tabela, referenciada dentro da agregação de outra consulta como ["measure", id].
metric_writeagent:content:writeCriar ou atualizar uma métrica: uma agregação salva e reutilizável que vive em uma coleção e pode ser consultada por conta própria ou referenciada a partir de outras consultas.
question_writeagent:content:writeCriar, atualizar ou arquivar uma pergunta salva ou modelo.
refresh_ui_credentialagent:query:runAtualizar a credencial com escopo usada por um MCP App do Metabase.
render_drill_throughagent:query:runRenderizar a visualização de drill-through para a qual o usuário acabou de navegar.
run_saved_questionagent:query:runExecutar uma pergunta salva (card) por id numérico ou entity_id, retornando linhas inline.
searchagent:content:readEncontrar conteúdo em toda a instância do Metabase por relevância.
segment_writeagent:content:writeCriar ou atualizar um segmento: um filtro MBQL nomeado e reutilizável anexado a uma tabela, referenciado a partir dos filtros de outras consultas.
subscription_writeagent:delivery:writeCriar ou atualizar uma assinatura de dashboard — entrega agendada de um dashboard inteiro, por exemplo.
visualize_queryagent:query:runVisualizar uma consulta como um gráfico interativo ou tabela, renderizado inline na conversa.

execute_query retorna row_limit linhas por chamada (padrão 100, máximo 2000) — um tamanho de página, não um limite no resultado. Uma página truncada reporta truncated: true e, quando a consulta tem uma ordem total, um next_cursor para passar de volta como cursor para a próxima página, até que uma página chegue com truncated: false. Uma consulta que quer apenas suas primeiras N linhas carrega limit: N em seu estágio (com um order-by); o servidor gasta esse limite ao longo das páginas, então a última página volta completa sem cursor e a paginação termina por si só.

Recursos

O servidor expõe recursos do MCP para que clientes possam buscar conteúdo complementar por URI sem inflar as descrições das ferramentas.

URI do recursoEscopoDescrição
ui://metabase/visualize-query.htmlagent:query:run (somente credencial de UI)O shell iframe dos MCP Apps para o qual visualize_query aponta um cliente capaz.
ui://metabase/render-drill-through.htmlagent:query:run (somente credencial de UI)O shell para o qual render_drill_through aponta.
catalog://metabase/fieldsagent:content:readOs caminhos de pontos que cada tipo de conteúdo aceita nos argumentos de fields.

Todo recurso é listado independentemente dos escopos do token. Um recurso de dados, como o catálogo de campos, é lido apenas por um token que possua seu escopo; caso contrário, a leitura recebe o desafio 403 insufficient_scope descrito em Escopos. Um shell de UI é lido por qualquer token, porque um host de MCP Apps lê o shell de uma ferramenta junto com a chamada da ferramenta, e se essa leitura fosse recusada, o host não subiria de nível após o 403 da chamada da ferramenta. Os shells não carregam dados. Um shell lido por um token sem o escopo do shell nunca gera uma credencial de UI. Os dados do gráfico são protegidos pela chamada da ferramenta e por refresh_ui_credential (ambos agent:query:run), que o iframe precisa antes de poder consultar qualquer coisa. Uma URI desconhecida é um erro -32602 "Recurso não encontrado".

Os pacotes de skills são entregues por meio da ferramenta learn em vez de como recursos.

A navegação de entidades é feita com as ferramentas get_content e browse_* em vez de um esquema de URI; os recursos ui:// acima existem apenas para que um cliente que possa renderizar um iframe tenha algo para montar.

Métodos JSON-RPC suportados

MétodoDescrição
initializeInicializar a conexão MCP. Retorna capacidades do servidor e um ID de sessão.
notifications/initializedNotificação do cliente de que a inicialização está completa.
tools/listListar ferramentas disponíveis, independentemente dos escopos do token.
tools/callChamar uma ferramenta com argumentos.
resources/listListar recursos disponíveis, independentemente dos escopos do token.
resources/readLer um recurso por URI; um recurso de dados precisa do seu escopo. Requer uma sessão.
pingPing de keepalive.

As solicitações podem ser enviadas individualmente ou como um lote JSON-RPC. O servidor responde com JSON ou SSE dependendo do cabeçalho Accept.

Arquitetura

A implementação vive nestes arquivos:

  • transport.clj - O transporte HTTP. Analisa solicitações JSON-RPC, valida autenticação e cabeçalhos de sessão, aplica verificações de origem (proteção contra rebinding de DNS) e despacha para o método apropriado. Suporta tanto formatos de resposta JSON quanto SSE.

  • v2/api.clj - O manipulador da superfície de ferramentas. Conecta o transporte aos registros de ferramentas e recursos v2 e define o despacho de métodos (tools/list, tools/call, resources/list, resources/read, ping).

  • v2/registry.clj - O registro de ferramentas v2. As ferramentas se auto-registram via deftool; o registro verifica escopos, valida argumentos, despacha chamadas e registra o uso.

  • scope.clj - Lógica de correspondência de escopo. Somente correspondências exatas: curingas, escopos nulos e o sentinela ::unrestricted não correspondem a nada.

Fluxo de solicitação

MCP client
  -> POST /api/metabase-mcp (JSON-RPC)
  -> Origin + session validation
  -> Auth: OAuth bearer token or browser session
  -> Scope check against requested tool
  -> Synthetic request to Agent API endpoint
  -> Response materialized as MCP content
  -> JSON or SSE back to client

Leitura adicional