Metabase

официальный

Официальный MCP-сервер Metabase для поиска данных, построения запросов на семантическом уровне и визуализации результатов через MCP-клиенты.

Что можно делать с Metabase MCP?

  • Поиск и получение контента — Попросите ассистента найти вопросы, дашборды или модели в Metabase с помощью инструмента search, а затем получить подробности через get_content.
  • Выполнение запросов и визуализация результатов — Поручите ассистенту выполнять структурированные запросы через execute_query или необработанный SQL с помощью execute_sql, а затем отображать результаты в виде интерактивных графиков с использованием visualize_query.
  • Создание и управление дашбордами — Дайте указание ассистенту создавать или обновлять дашборды и их макеты с помощью dashboard_write или дублировать существующий контент в коллекции через duplicate_content.
  • Настройка оповещений и подписок — Попросите ассистента создавать запланированные оповещения для сохраненных вопросов с помощью alert_write или настраивать email-подписки на дашборды через subscription_write.
  • Изучение иерархии данных — Направьте ассистента на просмотр баз данных, схем, таблиц и полей через browse_data или на структурную навигацию по коллекциям с помощью browse_collection.

Документация

Сервер MCP Metabase

Metabase включает встроенный сервер Model Context Protocol (MCP), который позволяет AI-клиентам подключаться напрямую к экземпляру Metabase. Он использует https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#streamable-http и опирается на Agent API Metabase, предоставляя инструменты для поиска, навигации, выполнения запросов, визуализации и создания/обновления контента — всё в рамках прав доступа подключающегося пользователя.

Конечная точка

Сервер MCP доступен по адресу:

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

Устаревший путь /api/mcp по-прежнему работает как псевдоним для существующих клиентов, но /api/metabase-mcp является каноническим URL для публикации.

Подключение клиента

Укажите любому MCP-совместимому клиенту конечную точку /api/metabase-mcp. Например, с Claude Code:

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

Для Claude Desktop создайте пользовательский коннектор, используя тот же URL.

Для Cursor откройте Settings > MCP и добавьте новый сервер с типом streamable-http и URL:

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

Аутентификация

MCP-клиенты аутентифицируются через OAuth 2.0. Metabase запускает собственный встроенный OAuth-сервер — внешний провайдер не требуется.

Процесс первого подключения:

  1. Клиент обнаруживает OAuth-конечные точки Metabase.
  2. Клиент регистрируется в Metabase.
  3. Пользователь перенаправляется в Metabase для входа и одобрения подключения.
  4. Клиент получает токен доступа с правами пользователя Metabase.

Сессии на основе браузера (cookie-аутентификация), API-ключи и токены mb:full не имеют MCP-области, поэтому они могут подключаться, но не могут вызывать инструменты с ограниченной областью.

Области

Токены доступа ограничены по областям, чтобы определить, какие инструменты может использовать клиент:

ОбластьПредоставляемые инструменты
agent:content:readbrowse_collection, browse_data, get_content, get_parameter_values, glossary, learn, search и ресурс данных catalog://metabase/fields (см. Ресурсы)
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

Инструмент соответствует только точной области из таблицы. Подстановочный знак, такой как * или agent:*, и маркер ::unrestricted не являются MCP-областями, поэтому они не предоставляют ни одного инструмента.

Эти области ограничивают только поверхность MCP. Ни одна REST-конечная точка не может объявить одну из них как свой :scope, поэтому новый токен, выданный MCP-клиенту, не предоставляет ничего в REST API.

В метаданных защищённого ресурса scopes_supported и в scope запроса 401 перечислены все области из таблицы, поэтому новое подключение запрашивает все из них. Некоторые клиенты не повышают права после 403: ручное переподключение из настроек коннектора Claude регистрирует новый клиент и запрашивает ровно то, что перечислено. Когда там был указан только базовый набор, такое переподключение никогда не предлагало запись, raw SQL или доставку, и у пользователя не было способа их предоставить (ENG-11089). Метаданные сервера авторизации также рекламируют все из них.

Базовый набор (agent:content:read agent:query:run) заблокирован на экране согласия: когда клиент запрашивает одну из этих областей, пользователь не может снять с неё отметку. agent:query:run входит в базовый набор, чтобы диаграммы никогда не требовали повышения прав. Claude Desktop повторяет вызов инструмента после повышения прав через сессию, которая не объявляет поддержку MCP Apps, поэтому повышенная область visualize_query отклоняется, и её диаграмма никогда не встраивается.

Вызов инструмента или чтение ресурса данных, для которого у токена нет области, отклоняется с HTTP 403 и запросом WWW-Authenticate: Bearer error="insufficient_scope", чей scope перечисляет v2-области, уже имеющиеся у токена, плюс требуемую, чтобы клиент мог повысить права. Каждый инструмент также объявляет свою область в securitySchemes, что является черновиком SEP-1488, поддерживаемым ChatGPT. Это не часть MCP 2025-03-26 (версии, которую сообщает этот сервер) или финальной спецификации инструментов 2026-07-28, поэтому другие клиенты обнаруживают отсутствующую область из 403. Внутри JSON-RPC-пакета отказ является внутриполосной ошибкой -32600 вместо этого. Чтения UI-оболочки никогда не запрашивают повышения прав: см. Ресурсы.

Метаданные защищённого ресурса OAuth доступны по адресу:

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

На экране согласия каждая область, запрошенная клиентом, изначально отмечена, а базовые области также заблокированы. Только оставшиеся отмеченными области предоставляются, и только для токена, который выпускает эта авторизация. Снятие отметки никогда не затрагивает токен, который уже есть у приложения. Область, оставленная без отметки, не запоминается Metabase. Последующий 403 может вызвать ещё одно повышение прав у клиентов, которые его поддерживают. Другим клиентам может потребоваться ручная повторная авторизация. Каждый запрос error_description завершается примечанием о том, что пользователь должен предоставить разрешение на экране согласия.

Некоторые клиенты заменяют error_description из 403 своим собственным текстом, поэтому в результате initialize поля instructions объясняют ошибки области и модели: ошибка аутентификации обычно означает отсутствующее разрешение, а не истёкший вход, модель должна назвать неудавшийся инструмент или ресурс и требуемое разрешение, а пользователь предоставляет его, переподключившись и оставив разрешение отмеченным на экране согласия. Инструкции представляют собой одну статическую строку, одинаковую для всех вызывающих: нет списка разрешений для конкретного подключения.

Доступ к инструментам по группам

В экземплярах Enterprise с функцией ai_controls администратор может сузить поверхность по группам разрешений в Admin > AI > Usage controls > MCP tools access (показывается, когда сервер MCP включён, с провайдером LLM или без него). Каждая группа имеет строку в mcp_group_permission, указывающую, могут ли её участники подключаться вообще, и, по имени инструмента, явное значение администратора "yes" или "no"; инструмент без записи принимает значение по умолчанию, объявленное его автором, поэтому каждый deftool несёт обязательное :default-access со значением :allowed или :denied, и инструмент, выпущенный позже, получает ровно это значение по умолчанию в каждой группе, пока администратор не переопределит его. Записи привязаны к имени инструмента, поэтому переименование инструмента требует :renamed-from с его прежними именами (сохранённая запись под прежним именем всё ещё действует, и API администратора показывает её под текущим именем), или автор принимает, что выбор каждого администратора для него отбрасывается; metabase.mcp.v2.tool-names-test фиксирует актуальные имена, чтобы ни то, ни другое не произошло случайно. Эффективная политика пользователя — это tool_access каждой его группы, чья строка включает MCP: MCP включён, когда существует любая такая группа, и инструмент разрешён, когда любая из этих групп разрешает его. Строки решают это сами по себе, и они также фиксируют режим разрешений: простой режим (Administrators, All Users и All tenant users) или режим уровня групп (все остальные группы), который является состоянием, в котором у All Users нет строки. Переключатель удаляет строки групп, скрываемых новым режимом, и заполняет группы, которые он включает при входе и не имеющие строки (Data Analysts при входе в режим уровня групп, All Users и All tenant users при выходе из него), а PUT отклоняет группу, скрываемую текущим режимом, поэтому ни один запрос не читает кэшированный режим. Политика применяется поверх областей OAuth в tools/list и tools/call (v2/registry.clj), и пользователь, чьи группы не дают доступа, отклоняется на initialize и на resources/read (для сессий, открытых до отключения MCP) с ошибкой, называющей исправление. Инструменты только для приложений (_meta {:ui {:visibility ["app"]}}, т.е. refresh_ui_credential) не отображаются на странице администратора: они разрешены, пока политика разрешает любой инструмент MCP Apps. Суперпользователи и внутренние вызывающие никогда не сужаются; OSS разрешает всё. В Enterprise сохранённые строки применяются даже без функции ai_controls (истёкший или непроверяемый токен сохраняет ограничения, настроенные администратором); функция ограничивает только страницу администратора и API. Резолвер — это permissions.clj (defenterprise, реализация EE в metabase-enterprise.mcp.permissions), а API администратора — это /api/ee/ai-controls/mcp-permissions.

Доступные инструменты

Сгенерировано из реестра v2 (deftool). Область, указанная здесь, — это то, что реестр проверяет перед запуском инструмента; некоторые обработчики проверяют дополнительную область, когда узнают, что делает вызов — agent:sql:run, когда источник разрешается в нативный SQL (question_write), и agent:query:run для выполнения, которое откладывает оповещение или подписка (alert_write, subscription_write). Эти отказы несут тот же запрос 403 insufficient_scope. tools/list показывает каждый инструмент независимо от того, что содержит токен, и токен без области не может его вызвать.

ИнструментОбласть действияОписание
alert_writeagent:delivery:writeСоздать или обновить оповещение: уведомление, отправляемое по расписанию, когда результаты сохранённого вопроса соответствуют условию.
bookmark_contentagent:content:writeДобавить или удалить закладку на контенте для вызывающего пользователя — тот же список избранного, который показывает боковая панель Metabase.
browse_collectionagent:content:readПросматривать коллекции структурно — один единый идентификатор для каждого раздела: числовой id, 21-символьный entity_id, «root» (переопределяемый для каждого пространства имён) или «trash» (архивированный контент, только в режиме элементов).
browse_dataagent:content:readПросматривать иерархию данных: базы данных → схемы → таблицы → поля.
collection_writeagent:content:writeСоздать, переименовать, переместить, архивировать или восстановить коллекцию — папки, содержащие вопросы, панели мониторинга, модели и документы.
dashboard_writeagent:content:writeСоздать или обновить панель мониторинга и изменить её макет с помощью упорядоченных операций.
document_writeagent:content:writeСоздать или обновить документ.
duplicate_contentagent:content:writeСкопировать вопрос, панель мониторинга или документ в коллекцию — дешевле и безопаснее, чем читать оригинал и создавать его заново, и это сохраняет всё, что опускают проекции чтения.
execute_queryagent:query:runСтандартный способ ответить на вопрос из данных: проверить и выполнить структурированный (MBQL) запрос, возвращая строки плюс query_handle.
execute_sqlagent:sql:runЗапасной вариант: выполнить сырую SQL-строку против базы данных, возвращая строки плюс query_handle.
get_contentagent:content:readПолучить контент по {type, id} — типизированное чтение для всего, что найдено через поиск или browse_collection.
get_parameter_valuesagent:content:readПолучить допустимые значения для одного фильтра на панели мониторинга или сохранённом вопросе, чтобы фильтровать по реальным значениям, а не угадывать.
glossaryagent:content:readНайти бизнес-термин так, как его определяет этот экземпляр Metabase; имена определённых терминов указаны в описании самого инструмента.
learnagent:content:readПрочитать документацию по задачам (навыкам) этого сервера для диалектов записи, которые схемы не могут полностью описать.
measure_writeagent:content:writeСоздать или обновить меру: именованное, переиспользуемое MBQL-агрегирование, привязанное к одной таблице, на которое ссылаются в агрегировании другого запроса как ["measure", id].
metric_writeagent:content:writeСоздать или обновить метрику: сохранённое, переиспользуемое агрегирование, которое живёт в коллекции и может быть запрошено само по себе или использовано в других запросах.
question_writeagent:content:writeСоздать, обновить или архивировать сохранённый вопрос или модель.
refresh_ui_credentialagent:query:runОбновить ограниченный учётные данные, используемые приложением Metabase MCP.
render_drill_throughagent:query:runОтрисовать визуализацию drill-through, в которую только что перешёл пользователь.
run_saved_questionagent:query:runВыполнить сохранённый вопрос (карточку) по числовому id или entity_id, возвращая строки встроенно.
searchagent:content:readНайти контент по всему экземпляру Metabase по релевантности.
segment_writeagent:content:writeСоздать или обновить сегмент: именованный, переиспользуемый MBQL-фильтр, привязанный к одной таблице, на который ссылаются из фильтров других запросов.
subscription_writeagent:delivery:writeСоздать или обновить подписку на панель мониторинга — запланированная доставка целой панели, например.
visualize_queryagent:query:runВизуализировать запрос как интерактивную диаграмму или таблицу, отрисованную встроенно в разговоре.

execute_query возвращает row_limit строк за вызов (по умолчанию 100, максимум 2000) — это размер страницы, а не ограничение на результат. Усечённая страница сообщает truncated: true и, когда у запроса есть полный порядок, next_cursor для передачи обратно как cursor для следующей страницы, пока не придёт страница с truncated: false. Запрос, которому нужны только первые N строк, несёт limit: N в своём этапе (с order-by); сервер расходует этот лимит по страницам, поэтому последняя страница приходит полной без курсора, и пагинация завершается сама.

Ресурсы

Сервер предоставляет MCP ресурсы, чтобы клиенты могли получать дополнительный контент по URI без раздувания описаний инструментов.

URI ресурсаОбласть действияОписание
ui://metabase/visualize-query.htmlagent:query:run (только учётные данные UI)Оболочка iframe MCP Apps, на которую visualize_query указывает способному клиенту.
ui://metabase/render-drill-through.htmlagent:query:run (только учётные данные UI)Оболочка, на которую указывает render_drill_through.
catalog://metabase/fieldsagent:content:readТочечные пути, которые каждый тип контента принимает в аргументах fields.

Каждый ресурс перечислен независимо от областей действия токена. Ресурс данных, такой как каталог полей, читается только токеном, имеющим его область действия; в противном случае чтение получает вызов 403 insufficient_scope, описанный в разделе Области действия. Оболочка UI читается любым токеном, потому что хост MCP Apps читает оболочку инструмента вместе с вызовом инструмента, и если бы это чтение было отклонено, хост не перешёл бы к следующему шагу после 403 от вызова инструмента. Оболочки не несут данных. Оболочка, прочитанная токеном без области действия оболочки, никогда не создаёт учётные данные UI. Данные диаграммы ограничены вызовом инструмента и refresh_ui_credential (оба agent:query:run), которые iframe нуждается до того, как сможет запросить что-либо. Неизвестный URI — это ошибка -32602 «Ресурс не найден».

Пакеты навыков доставляются через инструмент learn, а не как ресурсы.

Навигация по сущностям выполняется с помощью инструментов get_content и browse_*, а не схемы URI; ресурсы ui:// выше существуют только для того, чтобы клиент, который может отрисовать iframe, имел что монтировать.

Поддерживаемые методы JSON-RPC

МетодОписание
initializeИнициализировать MCP-соединение. Возвращает возможности сервера и ID сессии.
notifications/initializedУведомление клиента о завершении инициализации.
tools/listСписок доступных инструментов, независимо от областей действия токена.
tools/callВызвать инструмент с аргументами.
resources/listСписок доступных ресурсов, независимо от областей действия токена.
resources/readПрочитать ресурс по URI; ресурс данных требует свою область действия. Требуется сессия.
pingПинг поддержания соединения.

Запросы можно отправлять по отдельности или как JSON-RPC пакет. Сервер отвечает в формате JSON или SSE в зависимости от заголовка Accept.

Архитектура

Реализация находится в следующих файлах:

  • transport.clj - HTTP-транспорт. Разбирает JSON-RPC запросы, проверяет аутентификацию и заголовки сессии, применяет проверки происхождения (защита от DNS-ребдинга) и направляет к соответствующему методу. Поддерживает как JSON, так и SSE форматы ответов.

  • v2/api.clj - Обработчик поверхности инструментов. Связывает транспорт с реестрами инструментов и ресурсов v2 и определяет диспетчеризацию методов (tools/list, tools/call, resources/list, resources/read, ping).

  • v2/registry.clj - Реестр инструментов v2. Инструменты саморегистрируются через deftool; реестр проверяет области действия, валидирует аргументы, выполняет вызовы и записывает использование.

  • scope.clj - Логика сопоставления областей действия. Только точные совпадения: подстановочные знаки, nil-области и sentinel ::unrestricted не соответствуют ничему.

Поток запроса

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

Дополнительное чтение