Metabase

offiziell

Offizieller Metabase MCP-Server zum Durchsuchen von Daten, Erstellen von Abfragen auf der semantischen Ebene und Visualisieren von Ergebnissen über MCP-Clients.

Was kann man mit Metabase MCP machen?

  • Suche und Inhaltsabruf — Bitten Sie Ihren Assistenten, Fragen, Dashboards oder Modelle in Metabase mit dem search-Tool zu finden und anschließend Details mit get_content abzurufen.
  • Abfragen ausführen und Ergebnisse visualisieren — Lassen Sie Ihren Assistenten strukturierte Abfragen über execute_query oder rohes SQL mit execute_sql ausführen und die Ergebnisse dann mit visualize_query als interaktive Diagramme darstellen.
  • Dashboards erstellen und verwalten — Weisen Sie Ihren Assistenten an, Dashboards und deren Layouts mit dashboard_write zu erstellen oder zu aktualisieren, oder vorhandene Inhalte über duplicate_content in Sammlungen zu duplizieren.
  • Alarme und Abonnements einrichten — Bitten Sie Ihren Assistenten, geplante Alarme für gespeicherte Fragen mit alert_write zu erstellen oder Dashboard-E-Mail-Abonnements mit subscription_write zu konfigurieren.
  • Datenhierarchie erkunden — Leiten Sie Ihren Assistenten an, Datenbanken, Schemas, Tabellen und Felder über browse_data zu durchsuchen oder Sammlungen strukturell mit browse_collection zu navigieren.

Dokumentation

Metabase MCP Server

Metabase enthält einen integrierten Model Context Protocol (MCP)-Server, der es KI-Clients ermöglicht, sich direkt mit einer Metabase-Instanz zu verbinden. Er verwendet den Streamable HTTP Transport und baut auf der Agent API von Metabase auf, um Werkzeuge für die Suche, Navigation, Abfrage, Visualisierung und Erstellung/Aktualisierung von Inhalten bereitzustellen – alles eingeschränkt auf die Berechtigungen des verbundenen Benutzers.

Endpunkt

Der MCP-Server ist verfügbar unter:

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

Der veraltete /api/mcp-Pfad funktioniert weiterhin als Alias für bestehende Clients, aber /api/metabase-mcp ist die kanonische URL, die beworben werden sollte.

Verbinden eines Clients

Richten Sie einen beliebigen MCP-kompatiblen Client auf den /api/metabase-mcp-Endpunkt aus. Zum Beispiel mit Claude Code:

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

Für Claude Desktop erstellen Sie einen benutzerdefinierten Connector mit derselben URL.

Für Cursor öffnen Sie Einstellungen > MCP und fügen Sie einen neuen Server mit dem Typ streamable-http und der URL hinzu:

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

Authentifizierung

MCP-Clients authentifizieren sich über OAuth 2.0. Metabase führt einen eigenen eingebetteten OAuth-Server – kein externer Anbieter ist erforderlich.

Der Ablauf für eine Erstverbindung:

  1. Der Client ermittelt die OAuth-Endpunkte von Metabase.
  2. Der Client registriert sich bei Metabase.
  3. Der Benutzer wird zu Metabase weitergeleitet, um sich anzumelden und die Verbindung zu genehmigen.
  4. Der Client erhält ein Zugriffstoken, das auf die Metabase-Berechtigungen des Benutzers beschränkt ist.

Browserbasierte Sitzungen (Cookie-Authentifizierung), API-Schlüssel und mb:full-Tokens haben keinen MCP-Geltungsbereich, sodass sie sich verbinden, aber kein eingeschränktes Werkzeug aufrufen können.

Geltungsbereiche

Zugriffstokens sind eingeschränkt, um zu begrenzen, welche Werkzeuge ein Client verwenden kann:

GeltungsbereichGewährte Werkzeuge
agent:content:readbrowse_collection, browse_data, get_content, get_parameter_values, glossary, learn, search und die catalog://metabase/fields-Datenressource (siehe Ressourcen)
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

Ein Werkzeug entspricht nur dem exakten Geltungsbereich in der Tabelle. Ein Platzhalter wie * oder agent:* und das ::unrestricted-Sentinel sind keine MCP-Geltungsbereiche und gewähren daher kein Werkzeug.

Diese Geltungsbereiche begrenzen nur die MCP-Oberfläche. Kein REST-Endpunkt darf einen davon als seinen :scope deklarieren, sodass ein neues Token, das an einen MCP-Client ausgegeben wird, nichts auf der REST-API gewährt.

Die scopes_supported der Metadaten der geschützten Ressource und die scope der 401-Herausforderung listen alle Geltungsbereiche in der Tabelle auf, sodass eine neue Verbindung nach allen fragt. Einige Clients stufen nach einem 403 nicht hoch: Eine manuelle Neuverbindung über die Connector-Einstellungen von Claude registriert einen neuen Client und fragt genau nach dem, was diese auflisten. Wenn sie nur den Basisumfang auflisteten, bot diese Neuverbindung nie Schreibvorgänge, rohes SQL oder Zustellung an, und der Benutzer hatte keine Möglichkeit, sie zu gewähren (ENG-11089). Die Metadaten des Autorisierungsservers werben ebenfalls für alle.

Der Basisumfang (agent:content:read agent:query:run) ist auf dem Zustimmungsbildschirm gesperrt: Wenn ein Client einen davon anfordert, kann der Benutzer ihn nicht abwählen. agent:query:run ist im Basisumfang enthalten, sodass Diagramme nie eine Hochstufung benötigen. Claude Desktop wiederholt ein Werkzeug nach einer Hochstufung über eine Sitzung, die keine MCP-Apps-Unterstützung deklariert, sodass ein hochgestuftes visualize_query verweigert wird und sein Diagramm nie eingebettet wird.

Ein Werkzeugaufruf oder eine Datenressourcen-Leseoperation, für die dem Token ein Geltungsbereich fehlt, wird mit HTTP 403 und einer WWW-Authenticate: Bearer error="insufficient_scope"-Herausforderung verweigert, deren scope die v2-Geltungsbereiche auflistet, die das Token bereits besitzt, plus den erforderlichen, sodass ein Client hochstufen kann. Jedes Werkzeug deklariert seinen Geltungsbereich auch in securitySchemes, was der Entwurf SEP-1488 ist, der von ChatGPT unterstützt wird. Er ist nicht Teil von MCP 2025-03-26 (der Version, die dieser Server meldet) oder der endgültigen Tools-Spezifikation von 2026-07-28, sodass andere Clients den fehlenden Geltungsbereich stattdessen aus der 403 entdecken. Innerhalb eines JSON-RPC-Batches ist die Verweigerung stattdessen ein In-Band--32600-Fehler. UI-Shell-Lesevorgänge werden nie herausgefordert: siehe Ressourcen.

Die Metadaten der geschützten OAuth-Ressource sind verfügbar unter:

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

Auf dem Zustimmungsbildschirm ist jeder vom Client angeforderte Geltungsbereich standardmäßig angekreuzt, und die Basis-Geltungsbereiche sind ebenfalls gesperrt. Nur die angekreuzten Geltungsbereiche werden gewährt, und nur für das Token, das diese Autorisierung prägt. Ein Abwählen berührt nie ein Token, das die App bereits besitzt. Ein nicht angekreuzter Geltungsbereich wird von Metabase nicht gespeichert. Ein späteres 403 kann bei Clients, die es unterstützen, eine weitere Hochstufung auslösen. Andere Clients erfordern möglicherweise eine manuelle Neuautorisierung. Die error_description jeder Herausforderung endet mit einem Hinweis, dass der Benutzer die Berechtigung auf dem Zustimmungsbildschirm gewähren muss.

Mehrere Clients ersetzen die error_description der 403 durch ihren eigenen Text, sodass die instructions des initialize-Ergebnisses dem Modell ebenfalls Geltungsbereichsfehler erklären: Ein Authentifizierungsfehler bedeutet normalerweise eine fehlende Berechtigung und keinen abgelaufenen Login, das Modell sollte das fehlgeschlagene Werkzeug oder die Ressource und die erforderliche Berechtigung benennen, und der Benutzer gewährt sie, indem er sich neu verbindet und die Berechtigung auf dem Zustimmungsbildschirm angekreuzt lässt. Die Anweisungen sind ein statischer String, derselbe für jeden Aufrufer: Es gibt keine verbindungsspezifische Berechtigungsliste.

Gruppenbasierter Werkzeugzugriff

Auf Enterprise-Instanzen mit der ai_controls-Funktion kann ein Administrator die Oberfläche pro Berechtigungsgruppe unter Admin > KI > Nutzungssteuerung > MCP-Toolzugriff eingrenzen (angezeigt, wann immer der MCP-Server aktiv ist, mit oder ohne LLM-Anbieter). Jede Gruppe hat eine Zeile in mcp_group_permission, die angibt, ob ihre Mitglieder sich überhaupt verbinden dürfen, und pro Werkzeugname die explizite "yes" oder "no" des Administrators; ein Werkzeug ohne Eintrag übernimmt den Standard, den sein Autor deklariert hat, sodass jedes deftool eine erforderliche :default-access von :allowed oder :denied trägt und ein später veröffentlichtes Werkzeug genau diesen Standard in jeder Gruppe erhält, bis ein Administrator ihn überschreibt. Einträge sind nach Werkzeugnamen verschlüsselt, sodass das Umbenennen eines Werkzeugs :renamed-from mit seinen früheren Namen erfordert (ein gespeicherter Eintrag unter einem früheren Namen gilt weiterhin und die Admin-API präsentiert ihn unter dem aktuellen Namen), oder der Autor akzeptiert, dass jede Administratorwahl dafür verworfen wird; metabase.mcp.v2.tool-names-test fixiert die Live-Namen, sodass keines von beidem versehentlich passiert. Die effektive Richtlinie eines Benutzers ist die tool_access jeder seiner Gruppen, deren Zeile MCP aktiviert: MCP ist aktiv, wenn eine solche Gruppe existiert, und ein Werkzeug ist erlaubt, wenn eine dieser Gruppen es mit Ja auflöst. Die Zeilen allein entscheiden darüber, und sie zeichnen auch den Berechtigungsmodus auf: einfacher Modus (Administratoren, Alle Benutzer und Alle Mandantenbenutzer) oder Gruppenmodus (jede andere Gruppe), was der Zustand ist, in dem Alle Benutzer keine Zeile hat. Ein Schalter löscht die Zeilen der Gruppen, die der neue Modus ausblendet, und initialisiert die Gruppen, die er beim Eintritt aktiviert und die keine Zeile haben (Datenanalysten beim Eintritt in den Gruppenmodus, Alle Benutzer und Alle Mandantenbenutzer beim Verlassen), und PUT verweigert eine Gruppe, die der aktuelle Modus ausblendet, sodass keine Anfrage einen gecachten Modus liest. Die Richtlinie wird zusätzlich zu den OAuth-Geltungsbereichen in tools/list und tools/call (v2/registry.clj) angewendet, und ein Benutzer, dessen Gruppen keinen Zugriff gewähren, wird bei initialize und bei resources/read (für Sitzungen, die vor dem Deaktivieren von MCP geöffnet wurden) mit einem Fehler verweigert, der die Lösung benennt. Nur-App-Werkzeuge (_meta {:ui {:visibility ["app"]}}, d. h. refresh_ui_credential) sind nicht auf der Admin-Seite: Sie sind erlaubt, solange die Richtlinie ein MCP-Apps-Werkzeug erlaubt. Superuser und interne Aufrufer werden nie eingeschränkt; OSS erlaubt alles. Auf Enterprise werden die gespeicherten Zeilen auch ohne die ai_controls-Funktion durchgesetzt (ein abgelaufenes oder nicht verifizierbares Token behält die Einschränkungen, die ein Administrator konfiguriert hat); die Funktion schaltet nur die Admin-Seite und API frei. Der Resolver ist permissions.clj (defenterprise, EE-Implementierung in metabase-enterprise.mcp.permissions) und die Admin-API ist /api/ee/ai-controls/mcp-permissions.

Verfügbare Werkzeuge

Generiert aus dem v2-Registry (deftool). Der hier genannte Geltungsbereich ist der, den das Registry vor der Ausführung des Werkzeugs prüft; einige Handler prüfen einen weiteren Geltungsbereich, sobald sie wissen, was der Aufruf tut – agent:sql:run, wenn eine Quelle zu nativem SQL aufgelöst wird (question_write), und agent:query:run für die Ausführung, die eine Warnung oder ein Abonnement verschiebt (alert_write, subscription_write). Diese Verweigerungen tragen dieselbe 403-insufficient_scope-Herausforderung. tools/list zeigt jedes Werkzeug, was auch immer das Token enthält, und ein Token, dem der Geltungsbereich fehlt, darf es möglicherweise nicht aufrufen.

ToolGeltungsbereichBeschreibung
alert_writeagent:delivery:writeErstellen oder Aktualisieren eines Alarms: eine Benachrichtigung, die nach einem Zeitplan gesendet wird, wenn die Ergebnisse einer gespeicherten Frage eine Bedingung erfüllen.
bookmark_contentagent:content:writeLesezeichen für Inhalte für den aufrufenden Benutzer hinzufügen oder entfernen – dieselbe markierte/Favoriten-Liste, die die Metabase-Seitenleiste anzeigt.
browse_collectionagent:content:readSammlungen strukturell durchsuchen – eine einheitliche ID über jede Partition: eine numerische ID, eine 21-stellige entity_id, „root“ (pro Namespace neu verwurzelt) oder „trash“ (archivierte Inhalte, nur im Elementmodus).
browse_dataagent:content:readDie Datenhierarchie durchsuchen: Datenbanken → Schemas → Tabellen → Felder.
collection_writeagent:content:writeEine Sammlung erstellen, umbenennen, verschieben, archivieren oder wiederherstellen – die Ordner, die Fragen, Dashboards, Modelle und Dokumente enthalten.
dashboard_writeagent:content:writeEin Dashboard erstellen oder aktualisieren und sein Layout mit geordneten Operationen bearbeiten.
document_writeagent:content:writeEin Dokument erstellen oder aktualisieren.
duplicate_contentagent:content:writeEine Frage, ein Dashboard oder ein Dokument in eine Sammlung kopieren – günstiger und sicherer als das Original zu lesen und neu zu erstellen, und es bewahrt alles, was die Lese-Projektionen auslassen.
execute_queryagent:query:runDer Standardweg, eine Frage aus Daten zu beantworten: eine strukturierte (MBQL) Abfrage validieren und ausführen, die Zeilen plus einen query_handle zurückgibt.
execute_sqlagent:sql:runNotausstieg: eine rohe SQL-Zeichenfolge gegen eine Datenbank ausführen, die Zeilen plus einen query_handle zurückgibt.
get_contentagent:content:readInhalte nach {type, id} abrufen – der typisierte Lesevorgang für alles, was über Suche oder browse_collection gefunden wurde.
get_parameter_valuesagent:content:readDie gültigen Werte für einen Filter auf einem Dashboard oder einer gespeicherten Frage abrufen, damit Sie mit echten Werten filtern, statt zu raten.
glossaryagent:content:readEinen Geschäftsbegriff nachschlagen, wie diese Metabase-Instanz ihn definiert; die definierten Begriffsnamen reiten auf der eigenen Beschreibung des Tools.
learnagent:content:readDie Aufgabendokumentation (Skills) dieses Servers für die Schreib-Dialekte lesen, die die Schemas nicht vollständig beschreiben können.
measure_writeagent:content:writeEin Maß erstellen oder aktualisieren: eine benannte, wiederverwendbare MBQL-Aggregation, die an eine Tabelle angehängt ist und in der Aggregation einer anderen Abfrage als ["measure", id] referenziert wird.
metric_writeagent:content:writeEine Metrik erstellen oder aktualisieren: eine gespeicherte, wiederverwendbare Aggregation, die in einer Sammlung lebt und eigenständig abgefragt oder aus anderen Abfragen referenziert werden kann.
question_writeagent:content:writeEine gespeicherte Frage oder ein Modell erstellen, aktualisieren oder archivieren.
refresh_ui_credentialagent:query:runDie bereichsbezogene Anmeldeinformation aktualisieren, die von einer Metabase MCP App verwendet wird.
render_drill_throughagent:query:runDie Drill-through-Visualisierung rendern, in die der Benutzer gerade navigiert ist.
run_saved_questionagent:query:runEine gespeicherte Frage (Karte) nach numerischer ID oder entity_id ausführen und Zeilen inline zurückgeben.
searchagent:content:readInhalte in der gesamten Metabase-Instanz nach Relevanz finden.
segment_writeagent:content:writeEin Segment erstellen oder aktualisieren: ein benannter, wiederverwendbarer MBQL-Filter, der an eine Tabelle angehängt ist und aus den Filtern anderer Abfragen referenziert wird.
subscription_writeagent:delivery:writeEin Dashboard-Abonnement erstellen oder aktualisieren – geplante Zustellung eines gesamten Dashboards, z. B.
visualize_queryagent:query:runEine Abfrage als interaktives Diagramm oder Tabelle visualisieren, inline im Gespräch gerendert.

execute_query gibt row_limit Zeilen pro Aufruf zurück (Standard 100, maximal 2000) – eine Seitengröße, keine Begrenzung des Ergebnisses. Eine abgeschnittene Seite meldet truncated: true und, wenn die Abfrage eine Gesamtordnung hat, ein next_cursor, das als cursor für die nächste Seite zurückgegeben wird, bis eine Seite mit truncated: false eintrifft. Eine Abfrage, die nur ihre ersten N Zeilen möchte, trägt limit: N in ihrer Stufe (mit einem order-by); der Server verbraucht dieses Limit über Seiten hinweg, sodass die letzte Seite vollständig ohne Cursor zurückkommt und die Paginierung von selbst endet.

Ressourcen

Der Server stellt MCP-Ressourcen bereit, sodass Clients zusätzliche Inhalte per URI abrufen können, ohne die Tool-Beschreibungen aufzublähen.

Ressourcen-URIGeltungsbereichBeschreibung
ui://metabase/visualize-query.htmlagent:query:run (nur UI-Anmeldedaten)Die MCP-Apps-iframe-Shell, auf die visualize_query einen fähigen Client verweist.
ui://metabase/render-drill-through.htmlagent:query:run (nur UI-Anmeldedaten)Die Shell, auf die render_drill_through verweist.
catalog://metabase/fieldsagent:content:readDie Punktpfade, die jeder Inhaltstyp in fields-Argumenten akzeptiert.

Jede Ressource wird unabhängig von den Bereichen des Tokens aufgelistet. Eine Datenressource, wie der Feldkatalog, wird nur von einem Token gelesen, das ihren Bereich hält; andernfalls erhält der Lesevorgang die 403-insufficient_scope-Herausforderung, die unter Geltungsbereiche beschrieben ist. Eine UI-Shell wird von jedem Token gelesen, weil ein MCP-Apps-Host die Shell eines Tools zusammen mit dem Tool-Aufruf liest, und wenn dieser Lesevorgang verweigert würde, würde der Host nach dem 403 des Tool-Aufrufs nicht einspringen. Die Shells tragen keine Daten. Eine Shell, die von einem Token ohne den Bereich der Shell gelesen wird, erstellt nie eine UI-Anmeldedaten. Die Diagrammdaten sind durch den Tool-Aufruf und durch refresh_ui_credential (beide agent:query:run) geschützt, die der iframe benötigt, bevor er etwas abfragen kann. Eine unbekannte URI ist ein -32602-Fehler „Ressource nicht gefunden“.

Skill-Pakete werden über das learn-Tool statt als Ressourcen geliefert.

Die Entitätsnavigation erfolgt mit den get_content- und browse_*-Tools statt mit einem URI-Schema; die ui://-Ressourcen oben existieren nur, damit ein Client, der einen iframe rendern kann, etwas zum Einbinden hat.

Unterstützte JSON-RPC-Methoden

MethodeBeschreibung
initializeDie MCP-Verbindung initialisieren. Gibt Serverfähigkeiten und eine Sitzungs-ID zurück.
notifications/initializedClient-Benachrichtigung, dass die Initialisierung abgeschlossen ist.
tools/listVerfügbare Tools auflisten, unabhängig von den Bereichen des Tokens.
tools/callEin Tool mit Argumenten aufrufen.
resources/listVerfügbare Ressourcen auflisten, unabhängig von den Bereichen des Tokens.
resources/readEine Ressource per URI lesen; eine Datenressource benötigt ihren Bereich. Erfordert eine Sitzung.
pingKeepalive-Ping.

Anfragen können einzeln oder als JSON-RPC-Batch gesendet werden. Der Server antwortet mit JSON oder SSE, abhängig vom Accept-Header.

Architektur

Die Implementierung befindet sich in diesen Dateien:

  • transport.clj – Der HTTP-Transport. Analysiert JSON-RPC-Anfragen, validiert Authentifizierungs- und Sitzungsheader, erzwingt Origin-Prüfungen (DNS-Rebinding-Schutz) und leitet an die entsprechende Methode weiter. Unterstützt sowohl JSON- als auch SSE-Antwortformate.

  • v2/api.clj – Der Tool-Oberflächen-Handler. Verbindet den Transport mit den v2-Tool- und Ressourcen-Registries und definiert die Methodenverteilung (tools/list, tools/call, resources/list, resources/read, ping).

  • v2/registry.clj – Die v2-Tool-Registry. Tools registrieren sich selbst über deftool; die Registry prüft Bereiche, validiert Argumente, leitet Aufrufe weiter und zeichnet die Nutzung auf.

  • scope.clj – Bereichsabgleichslogik. Nur exakte Übereinstimmungen: Platzhalter, nil-Bereiche und das ::unrestricted-Sentinel stimmen mit nichts überein.

Anfrageablauf

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

Weiterführende Lektüre