Metabase

resmi

Server MCP resmi Metabase untuk mencari data, membangun kueri pada lapisan semantik, dan memvisualisasikan hasil melalui klien MCP.

Apa yang bisa Anda lakukan dengan Metabase MCP?

  • Mencari dan mengambil konten — Minta asisten Anda untuk menemukan pertanyaan, dasbor, atau model di seluruh Metabase menggunakan alat search, lalu ambil detailnya dengan get_content.
  • Menjalankan kueri dan memvisualisasikan hasil — Minta asisten Anda untuk menjalankan kueri terstruktur melalui execute_query atau SQL mentah dengan execute_sql, lalu render hasilnya sebagai bagan interaktif menggunakan visualize_query.
  • Membuat dan mengelola dasbor — Instruksikan asisten Anda untuk membuat atau memperbarui dasbor beserta tata letaknya dengan dashboard_write, atau duplikat konten yang ada ke dalam koleksi melalui duplicate_content.
  • Menyiapkan pemberitahuan dan langganan — Minta asisten Anda untuk membuat pemberitahuan terjadwal untuk pertanyaan tersimpan dengan alert_write atau konfigurasikan langganan email dasbor menggunakan subscription_write.
  • Menjelajahi hierarki data — Arahkan asisten Anda untuk menelusuri basis data, skema, tabel, dan kolom melalui browse_data, atau navigasikan koleksi secara struktural dengan browse_collection.

Dokumentasi

Server MCP Metabase

Metabase menyertakan server Model Context Protocol (MCP) bawaan yang memungkinkan klien AI terhubung langsung ke instance Metabase. Server ini menggunakan https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#streamable-http dan dibangun di atas Agent API Metabase untuk mengekspos alat untuk mencari, menavigasi, membuat kueri, memvisualisasikan, dan membuat/memperbarui konten - semuanya dibatasi oleh izin pengguna yang terhubung.

Endpoint

Server MCP tersedia di:

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

Jalur /api/mcp lama masih berfungsi sebagai alias untuk klien yang sudah ada, tetapi /api/metabase-mcp adalah URL kanonik yang perlu diiklankan.

Menghubungkan klien

Arahkan klien yang kompatibel dengan MCP ke endpoint /api/metabase-mcp. Misalnya, dengan Claude Code:

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

Untuk Claude Desktop, buat konektor khusus menggunakan URL yang sama.

Untuk Cursor, buka Settings > MCP dan tambahkan server baru dengan tipe diatur ke streamable-http dan URL:

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

Autentikasi

Klien MCP melakukan autentikasi melalui OAuth 2.0. Metabase menjalankan server OAuth tertanamnya sendiri - tidak diperlukan penyedia eksternal.

Alur untuk koneksi pertama kali:

  1. Klien menemukan endpoint OAuth Metabase.
  2. Klien mendaftarkan dirinya ke Metabase.
  3. Pengguna diarahkan ke Metabase untuk masuk dan menyetujui koneksi.
  4. Klien menerima token akses yang dibatasi oleh izin Metabase pengguna.

Sesi berbasis browser (autentikasi cookie), kunci API, dan token mb:full tidak memiliki cakupan MCP, sehingga mereka dapat terhubung tetapi tidak dapat memanggil alat yang dibatasi cakupan.

Cakupan

Token akses dibatasi untuk membatasi alat apa yang dapat digunakan klien:

CakupanAlat yang diberikan
agent:content:readbrowse_collection, browse_data, get_content, get_parameter_values, glossary, learn, search, dan sumber daya data catalog://metabase/fields (lihat Sumber Daya)
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

Sebuah alat hanya cocok dengan cakupan yang tepat di tabel. Wildcard seperti * atau agent:*, dan sentinel ::unrestricted, bukanlah cakupan MCP, sehingga mereka tidak memberikan alat apa pun.

Cakupan ini hanya menggerbang permukaan MCP. Tidak ada endpoint REST yang boleh mendeklarasikan salah satunya sebagai :scope-nya, sehingga token baru yang diterbitkan ke klien MCP tidak memberikan apa pun pada REST API.

scopes_supported dari metadata sumber daya yang dilindungi dan scope dari tantangan 401 keduanya mencantumkan setiap cakupan di tabel, sehingga koneksi baru meminta semuanya. Beberapa klien tidak melakukan step-up setelah 403: koneksi ulang manual dari pengaturan konektor Claude mendaftarkan klien baru dan meminta persis apa yang tercantum. Ketika mereka hanya mencantumkan baseline, koneksi ulang itu tidak pernah menawarkan penulisan, SQL mentah, atau pengiriman, dan pengguna tidak memiliki cara untuk memberikannya (ENG-11089). Metadata server otorisasi juga mengiklankan semuanya.

Baseline (agent:content:read agent:query:run) terkunci di layar persetujuan: ketika klien meminta salah satunya, pengguna tidak dapat menghapus centangnya. agent:query:run ada di baseline sehingga bagan tidak pernah memerlukan step-up. Claude Desktop mencoba ulang alat setelah step-up melalui sesi yang tidak mendeklarasikan dukungan MCP Apps, sehingga visualize_query yang di-step-up ditolak dan bagannya tidak pernah disematkan.

Panggilan alat atau pembacaan sumber daya data yang tokennya tidak memiliki cakupan ditolak dengan HTTP 403 dan tantangan WWW-Authenticate: Bearer error="insufficient_scope" yang scope-nya mencantumkan cakupan v2 yang sudah dimiliki token ditambah yang diperlukan, sehingga klien dapat melakukan step-up. Setiap alat juga mendeklarasikan cakupannya di securitySchemes, yang merupakan draf SEP-1488, didukung oleh ChatGPT. Ini bukan bagian dari MCP 2025-03-26 (versi yang dilaporkan server ini) atau spesifikasi alat final 2026-07-28, sehingga klien lain menemukan cakupan yang hilang dari 403 sebagai gantinya. Di dalam batch JSON-RPC, penolakan adalah kesalahan -32600 in-band sebagai gantinya. Pembacaan shell UI tidak pernah ditantang: lihat Sumber Daya.

Metadata sumber daya yang dilindungi OAuth tersedia di:

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

Di layar persetujuan, setiap cakupan yang diminta klien mulai dicentang, dan cakupan baseline juga terkunci. Hanya cakupan yang tetap dicentang yang diberikan, dan hanya untuk token yang dicetak oleh otorisasi ini. Penghapusan centang tidak pernah menyentuh token yang sudah dimiliki aplikasi. Cakupan yang tidak dicentang tidak diingat oleh Metabase. 403 berikutnya dapat memicu step-up lain di klien yang mendukungnya. Klien lain mungkin memerlukan otorisasi ulang manual. error_description setiap tantangan diakhiri dengan catatan bahwa pengguna harus memberikan izin di layar persetujuan.

Beberapa klien mengganti error_description dari 403 dengan teks mereka sendiri, sehingga hasil initialize instructions-nya menjelaskan kegagalan cakupan ke model juga: kesalahan autentikasi biasanya berarti izin yang hilang daripada login yang kedaluwarsa, model harus menyebutkan alat atau sumber daya yang gagal dan izin yang diperlukan, dan pengguna memberikannya dengan menghubungkan ulang dan membiarkan izin dicentang di layar persetujuan. Instruksinya adalah satu string statis, sama untuk setiap pemanggil: tidak ada daftar izin per koneksi.

Akses alat per grup

Pada instance Enterprise dengan fitur ai_controls, admin dapat mempersempit permukaan per grup izin di Admin > AI > Kontrol penggunaan > Akses alat MCP (ditampilkan setiap kali server MCP aktif, dengan atau tanpa penyedia LLM). Setiap grup memiliki baris di mcp_group_permission yang menyatakan apakah anggotanya dapat terhubung sama sekali dan, per nama alat, "yes" atau "no" eksplisit admin; alat tanpa entri mengambil default yang dideklarasikan pembuatnya, sehingga setiap deftool membawa :default-access wajib dari :allowed atau :denied dan alat yang dirilis kemudian mendapatkan default itu persis di setiap grup sampai admin menimpanya. Entri dikunci oleh nama alat, sehingga mengganti nama alat memerlukan :renamed-from dengan nama lamanya (entri tersimpan di bawah nama lama masih berlaku dan API admin menyajikannya di bawah nama saat ini), atau pembuat menerima bahwa pilihan setiap admin untuk itu dibuang; metabase.mcp.v2.tool-names-test mengunci nama langsung sehingga keduanya tidak terjadi secara tidak sengaja. Kebijakan efektif pengguna adalah tool_access dari setiap grup mereka yang barisnya mengaktifkan MCP: MCP aktif ketika grup semacam itu ada, dan alat diizinkan ketika salah satu grup tersebut menyelesaikannya menjadi ya. Baris-baris itu sendiri yang memutuskannya, dan mereka juga mencatat mode izin: mode sederhana (Administrator, Semua Pengguna, dan Semua pengguna penyewa) atau mode tingkat grup (setiap grup lainnya), yang merupakan keadaan di mana Semua Pengguna tidak memiliki baris. Sakelar menghapus baris grup yang disembunyikan mode baru dan mengisi grup yang diaktifkannya pada entri yang tidak memiliki baris (Analis Data saat memasuki mode tingkat grup, Semua Pengguna dan Semua pengguna penyewa saat meninggalkannya), dan PUT menolak grup yang disembunyikan mode saat ini, sehingga tidak ada permintaan yang membaca mode cache. Kebijakan diterapkan di atas cakupan OAuth di tools/list dan tools/call (v2/registry.clj), dan pengguna yang grupnya tidak memberikan akses ditolak di initialize dan di resources/read (untuk sesi yang dibuka sebelum MCP dimatikan) dengan kesalahan yang menyebutkan perbaikannya. Alat khusus aplikasi (_meta {:ui {:visibility ["app"]}}, yaitu refresh_ui_credential) tidak ada di halaman admin: mereka diizinkan selama kebijakan mengizinkan alat MCP Apps apa pun. Superuser dan pemanggil internal tidak pernah dipersempit; OSS mengizinkan semuanya. Di Enterprise, baris tersimpan ditegakkan bahkan tanpa fitur ai_controls (token yang kedaluwarsa atau tidak dapat diverifikasi tetap mempertahankan pembatasan yang dikonfigurasi admin); fitur hanya menggerbang halaman admin dan API. Resolver adalah permissions.clj (defenterprise, implementasi EE di metabase-enterprise.mcp.permissions) dan API admin adalah /api/ee/ai-controls/mcp-permissions.

Alat yang tersedia

Dihasilkan dari registri v2 (deftool). Cakupan yang disebutkan di sini adalah apa yang diperiksa registri sebelum alat berjalan; beberapa penangan memeriksa cakupan lebih lanjut setelah mereka tahu apa yang dilakukan panggilan - agent:sql:run ketika sumber diselesaikan ke SQL asli (question_write), dan agent:query:run untuk eksekusi yang ditunda oleh peringatan atau langganan (alert_write, subscription_write). Penolakan tersebut membawa tantangan 403 insufficient_scope yang sama. tools/list menunjukkan setiap alat apa pun yang dimiliki token, dan token yang tidak memiliki cakupan tidak boleh memanggilnya.

AlatCakupanDeskripsi
alert_writeagent:delivery:writeMembuat atau memperbarui peringatan: notifikasi yang dikirim sesuai jadwal ketika hasil pertanyaan tersimpan memenuhi suatu kondisi.
bookmark_contentagent:content:writeMenambah atau menghapus penanda pada konten untuk pengguna yang memanggil — daftar berbintang/favorit yang sama dengan yang ditampilkan sidebar Metabase.
browse_collectionagent:content:readMenjelajahi koleksi secara struktural — satu id seragam di setiap partisi: id numerik, entity_id 21 karakter, "root" (di-root ulang per namespace), atau "trash" (konten yang diarsipkan, hanya mode item).
browse_dataagent:content:readMenjelajahi hierarki data: database → skema → tabel → kolom.
collection_writeagent:content:writeMembuat, mengganti nama, memindahkan, mengarsipkan, atau memulihkan koleksi — folder yang menampung pertanyaan, dasbor, model, dan dokumen.
dashboard_writeagent:content:writeMembuat atau memperbarui dasbor dan mengedit tata letaknya dengan operasi terurut.
document_writeagent:content:writeMembuat atau memperbarui dokumen.
duplicate_contentagent:content:writeMenyalin pertanyaan, dasbor, atau dokumen ke dalam koleksi — lebih murah dan lebih aman daripada membaca yang asli lalu membuat ulang, dan ini mempertahankan semua yang tidak tercakup oleh proyeksi baca.
execute_queryagent:query:runCara default untuk menjawab pertanyaan dari data: memvalidasi dan mengeksekusi kueri terstruktur (MBQL), mengembalikan baris plus query_handle.
execute_sqlagent:sql:runJalur pelarian: mengeksekusi string SQL mentah terhadap database, mengembalikan baris plus query_handle.
get_contentagent:content:readMengambil konten berdasarkan {type, id} — pembacaan bertipe untuk apa pun yang ditemukan melalui pencarian atau browse_collection.
get_parameter_valuesagent:content:readMengambil nilai valid untuk satu filter pada dasbor atau pertanyaan tersimpan, sehingga Anda memfilter dengan nilai nyata alih-alih menebak.
glossaryagent:content:readMencari istilah bisnis sebagaimana didefinisikan oleh instance Metabase ini; nama istilah yang didefinisikan mengikuti deskripsi alat itu sendiri.
learnagent:content:readMembaca dokumen tugas (keterampilan) server ini untuk dialek penulisan yang tidak dapat dijelaskan sepenuhnya oleh skema.
measure_writeagent:content:writeMembuat atau memperbarui ukuran: agregasi MBQL bernama yang dapat digunakan ulang, dilampirkan ke satu tabel, direferensikan di dalam agregasi kueri lain sebagai ["measure", id].
metric_writeagent:content:writeMembuat atau memperbarui metrik: agregasi tersimpan yang dapat digunakan ulang, berada di koleksi, dan dapat dikueri sendiri atau direferensikan dari kueri lain.
question_writeagent:content:writeMembuat, memperbarui, atau mengarsipkan pertanyaan atau model tersimpan.
refresh_ui_credentialagent:query:runMenyegarkan kredensial tercakup yang digunakan oleh Aplikasi MCP Metabase.
render_drill_throughagent:query:runMerender visualisasi drill-through yang baru saja dinavigasi pengguna.
run_saved_questionagent:query:runMenjalankan pertanyaan tersimpan (kartu) berdasarkan id numerik atau entity_id, mengembalikan baris secara inline.
searchagent:content:readMenemukan konten di seluruh instance Metabase berdasarkan relevansi.
segment_writeagent:content:writeMembuat atau memperbarui segmen: filter MBQL bernama yang dapat digunakan ulang, dilampirkan ke satu tabel, direferensikan dari filter kueri lain.
subscription_writeagent:delivery:writeMembuat atau memperbarui langganan dasbor — pengiriman terjadwal untuk seluruh dasbor, mis.
visualize_queryagent:query:runMemvisualisasikan kueri sebagai bagan atau tabel interaktif, dirender inline dalam percakapan.

execute_query mengembalikan row_limit baris per panggilan (default 100, maks 2000) — ukuran halaman, bukan batas hasil. Halaman yang terpotong melaporkan truncated: true dan, ketika kueri memiliki urutan total, next_cursor untuk diteruskan kembali sebagai cursor untuk halaman berikutnya, hingga halaman tiba dengan truncated: false. Kueri yang hanya menginginkan N baris pertamanya membawa limit: N di tahapnya (dengan order-by); server menghabiskan batas itu di seluruh halaman, sehingga halaman terakhir kembali lengkap tanpa kursor dan paginasi berakhir dengan sendirinya.

Sumber Daya

Server mengekspos sumber daya MCP sehingga klien dapat mengambil konten tambahan berdasarkan URI tanpa memperbesar deskripsi alat.

URI Sumber DayaCakupanDeskripsi
ui://metabase/visualize-query.htmlagent:query:run (kredensial UI saja)Shell iframe Aplikasi MCP visualize_query yang ditunjuk oleh klien yang mampu.
ui://metabase/render-drill-through.htmlagent:query:run (kredensial UI saja)Shell yang render_drill_through tunjuk.
catalog://metabase/fieldsagent:content:readJalur titik yang diterima setiap jenis konten dalam argumen fields.

Setiap sumber daya terdaftar apa pun cakupan tokennya. Sumber daya data, seperti katalog kolom, hanya dibaca oleh token yang memegang cakupannya; jika tidak, pembacaan mendapatkan tantangan 403 insufficient_scope yang dijelaskan di bawah Scopes. Shell UI dibaca oleh token apa pun, karena host Aplikasi MCP membaca shell alat bersamaan dengan panggilan alat, dan jika pembacaan itu ditolak, host tidak akan naik setelah 403 panggilan alat. Shell tidak membawa data. Shell yang dibaca oleh token tanpa cakupan shell tidak pernah mencetak kredensial UI. Data bagan digerbang oleh panggilan alat dan oleh refresh_ui_credential (keduanya agent:query:run), yang dibutuhkan iframe sebelum dapat membuat kueri apa pun. URI yang tidak dikenal adalah kesalahan -32602 "Resource not found".

Paket keterampilan dikirim melalui alat learn daripada sebagai sumber daya.

Navigasi entitas dilakukan dengan alat get_content dan browse_* daripada skema URI; sumber daya ui:// di atas ada hanya agar klien yang dapat merender iframe memiliki sesuatu untuk dipasang.

Metode JSON-RPC yang didukung

MetodeDeskripsi
initializeMenginisialisasi koneksi MCP. Mengembalikan kemampuan server dan ID sesi.
notifications/initializedNotifikasi klien bahwa inisialisasi selesai.
tools/listMencantumkan alat yang tersedia, apa pun cakupan tokennya.
tools/callMemanggil alat dengan argumen.
resources/listMencantumkan sumber daya yang tersedia, apa pun cakupan tokennya.
resources/readMembaca sumber daya berdasarkan URI; sumber daya data memerlukan cakupannya. Memerlukan sesi.
pingPing keepalive.

Permintaan dapat dikirim secara individual atau sebagai batch JSON-RPC. Server merespons dengan JSON atau SSE tergantung pada header Accept.

Arsitektur

Implementasi berada di file-file ini:

  • transport.clj - Transport HTTP. Mengurai permintaan JSON-RPC, memvalidasi autentikasi dan header sesi, menegakkan pemeriksaan asal (perlindungan DNS rebinding), dan mengirim ke metode yang sesuai. Mendukung format respons JSON dan SSE.

  • v2/api.clj - Penangan permukaan alat. Menghubungkan transport ke registri alat + sumber daya v2 dan mendefinisikan pengiriman metode (tools/list, tools/call, resources/list, resources/read, ping).

  • v2/registry.clj - Registri alat v2. Alat mendaftar sendiri melalui deftool; registri memeriksa cakupan, memvalidasi argumen, mengirim panggilan, dan mencatat penggunaan.

  • scope.clj - Logika pencocokan cakupan. Hanya kecocokan tepat: wildcard, cakupan nil, dan sentinel ::unrestricted tidak cocok dengan apa pun.

Alur permintaan

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

Bacaan lebih lanjut