Skip to content

Connect Metabase to Claude: Build Reports & Audit Data Usage

Learn how to connect Metabase to Claude using a managed MCP server. Execute SQL, audit dashboards, and build AI-driven data ops workflows without custom code.

Roopendra Talekar Roopendra Talekar · · 11 min read

If your team needs to connect Metabase to Claude to automate data exploration, audit user permissions, or generate new business intelligence dashboards, you need a Model Context Protocol (MCP) server. This server acts as the translation layer between Claude's tool calls and the complex Metabase REST API.

You can either build and maintain this infrastructure yourself—handling token lifecycles, translating JSON schemas into tool definitions, and managing pagination—or use a managed integration platform like Truto to dynamically generate a secure, authenticated MCP server URL.

If your team uses ChatGPT, check out our companion guide on connecting Metabase to ChatGPT or explore our broader architectural overview on connecting Metabase to AI Agents.

Giving a Large Language Model (LLM) read and write access to a BI tool like Metabase is an engineering challenge. Metabase is fundamentally a query orchestration engine. Its API does not just expose CRUD operations; it exposes raw SQL execution endpoints, highly nested layout schemas for dashboards, and its own proprietary query language (MBQL). Exposing this safely to an LLM requires strict schema boundaries and error handling.

This guide breaks down exactly how to use Truto to generate a secure, managed MCP server for Metabase, connect it natively to Claude, and execute complex reporting workflows using natural language.

The Engineering Reality of the Metabase API

A custom MCP server is a self-hosted integration layer. While the open MCP standard provides a predictable way for models to discover tools over JSON-RPC 2.0, the reality of implementing it against Metabase's API is painful. Metabase is built to translate user interface interactions into complex database queries, and its API structure reflects that legacy.

If you decide to build a custom Metabase MCP server, here are the specific integration challenges you will face:

The MBQL versus SQL Divide When users click around the Metabase UI to build a report, Metabase generates an abstract JSON payload known as Metabase Query Language (MBQL). Many of the core /api/dataset and /api/card endpoints expect queries in MBQL, not SQL. If you want an LLM to build a saved question in Metabase, the LLM cannot just send a SELECT * FROM users string. You have to either force the LLM to learn and write valid MBQL (which leads to high hallucination rates) or build translation layers that proxy raw SQL into native query objects. Metabase recently introduced the /api/agent namespace specifically for AI operations, but you must correctly map these disparate endpoints into unified MCP tool calls.

Massive, Nested Layout Schemas Updating a Metabase Dashboard is not a simple patch operation. Dashboards consist of nested grids, "dashcards", parameter mappings, and visualization settings. Fetching a dashboard via GET /api/dashboard/:id returns a massive JSON payload. If Claude decides it wants to "remove an unused card from the Sales Dashboard," your MCP server must fetch the full layout, find the correct dashcard, recalculate the grid positioning (size, row, column), and PUT the entire structure back. Exposing this directly to an LLM usually results in corrupted dashboard grids. A properly architected MCP server must provide highly constrained, abstracted tools for layout modification.

Strict Rate Limiting and Long-Running Queries Metabase sits on top of your actual data warehouse. When you execute an ad-hoc query via the API, that request blocks until the warehouse returns the data. If the query takes 45 seconds, the HTTP request hangs for 45 seconds.

A crucial architectural note on how Truto handles this: Truto does not retry, throttle, or apply automatic backoff on rate limit or timeout errors. When Metabase rejects a request with an HTTP 429 (or times out due to query length), Truto passes that exact error back to the caller. Truto normalizes the upstream rate limit data into standard ratelimit-limit, ratelimit-remaining, and ratelimit-reset headers per the IETF specification. The caller—in this case, your MCP client or Claude—is strictly responsible for implementing exponential backoff.

Creating the Metabase MCP Server

Rather than hand-coding tool definitions and managing JSON-RPC translation yourself, Truto dynamically derives MCP tools from the connected Metabase integration's resources and documentation records.

Each server is scoped to a single integrated account and secured via a cryptographic token in the URL. You can provision this server through the Truto UI or programmatically via the API.

Method 1: Via the Truto UI

For IT admins or one-off workflows, generating the server in the dashboard takes seconds.

  1. Navigate to the Integrated Accounts page in your Truto dashboard and select your connected Metabase account.
  2. Click the MCP Servers tab.
  3. Click Create MCP Server.
  4. Select your configuration options (e.g., name the server "Metabase Data Ops", filter to read methods only, or apply tags).
  5. Copy the generated MCP Server URL (e.g., https://api.truto.one/mcp/a1b2c3d4e5f6...). This URL contains the secure hash needed for authentication.

Method 2: Via the Truto API

For engineering teams building multi-tenant AI agents, you can generate MCP servers programmatically for your users.

Send a POST request to /integrated-account/:id/mcp with your desired filtering configuration. This securely stores the token in Truto's KV infrastructure for low-latency validation and returns a ready-to-use URL.

curl -X POST https://api.truto.one/admin/integrated-accounts/{integrated_account_id}/mcp \
  -H "Authorization: Bearer <YOUR_TRUTO_API_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Claude BI Agent",
    "config": {
      "methods": ["read", "custom"], 
      "require_api_token_auth": false
    }
  }'

The response returns the secure URL you will pass to Claude:

{
  "id": "mcp-abc-123",
  "name": "Claude BI Agent",
  "config": { "methods": ["read", "custom"] },
  "expires_at": null,
  "url": "https://api.truto.one/mcp/a1b2c3d4e5f6..."
}

Connecting the MCP Server to Claude

Once you have your Truto MCP URL, you can plug it directly into Claude. Because Truto acts as an SSE (Server-Sent Events) transport layer for JSON-RPC messages, you don't have to install local Python or Node.js packages.

Method A: Via the Claude UI

If you are using Claude Desktop (or ChatGPT's custom connectors):

  1. Open the Claude Desktop application.
  2. Navigate to Settings → Integrations (or Developer Settings depending on your tier).
  3. Click Add MCP Server.
  4. Provide a name (e.g., "Metabase") and paste the Truto MCP URL.
  5. Click Add. Claude will instantly handshake with the server, negotiate capabilities, and pull down the list of available Metabase tools.

Method B: Via the Config File (claude_desktop_config.json)

If you prefer declarative configuration, you can update Claude's configuration file directly. Because Truto provides an SSE endpoint, you will use the @modelcontextprotocol/server-sse CLI to bridge the standard I/O to Truto's remote server.

  1. Open your configuration file:
    • Mac: ~/Library/Application Support/Claude/claude_desktop_config.json
    • Windows: %APPDATA%\Claude\claude_desktop_config.json
  2. Add the Metabase server block:
{
  "mcpServers": {
    "metabase": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-sse",
        "https://api.truto.one/mcp/a1b2c3d4e5f6..."
      ]
    }
  }
}

Save the file and restart Claude Desktop. The model will now have native access to your Metabase data warehouse.

Hero Tools for Metabase

Truto dynamically derives dozens of proxy tools from Metabase's API documentation. Here are the 6 highest-leverage tools your AI agent should use when interacting with Metabase.

1. Execute SQL Directly (create_a_metabase_agent_execute_sql)

This tool allows the LLM to run ad-hoc SQL queries against a connected database without saving a card first. This leverages Metabase's agent API to execute raw queries and return row counts, execution time, and column metadata alongside the data array.

Usage note: You must know the database_id. If the query returns a massive dataset, Claude may struggle to render the full context window. Instruct the model to always use LIMIT clauses.

"Find the database ID for our production PostgreSQL cluster, then write and execute a SQL query to find the top 10 users by total session duration over the last 30 days."

Before hallucinating a new query, Claude should always check if a report already exists. This tool uses Metabase's semantic and term-based search to find tables, models, metrics, saved questions, and dashboards.

Usage note: The LLM can use this to resolve plain-text entity names into exact IDs before attempting to fetch dashboard layouts or execute saved cards.

"Search Metabase for any existing dashboards or saved questions related to 'Churn Analysis' or 'Retention'. If you find one, list its ID and name."

3. Save a New Report (create_a_metabase_agent_question)

Once Claude has formulated a correct SQL query and verified the data, it can persist it into the Metabase UI as a "Saved Question" (Card) so human users can view it.

Usage note: You must pass a properly constructed query payload. The LLM can first use create_a_metabase_agent_construct_native_query to serialize the raw SQL into a base64-encoded format, and then pass that payload into this tool to save it.

"Take the active user query we just tested, format it as a native query payload, and save it as a new question named '30-Day Active Users' in my personal collection."

4. Fetch Dashboard Definitions (get_single_metabase_dashboard_by_id)

This tool retrieves the complete configuration for a single dashboard, including its dashcards, tabs, parameters, and layout grid coordinates.

Usage note: This returns a very large, deeply nested JSON object. Claude should use this to audit which cards belong to which dashboards, or to understand the parameter mappings for dashboard filters before attempting to update them.

"Fetch the dashboard configuration for dashboard ID 45. Give me a bulleted list of all the cards currently placed on this dashboard, including their names and underlying question IDs."

5. Audit User Access (list_all_metabase_users)

Allows the LLM to pull the full directory of Metabase users. It returns fields like id, email, first_name, and last_name.

Usage note: By default, this endpoint only returns active users. It is highly effective for cross-referencing access against an HRIS or SSO provider to catch shadow IT.

"List all active Metabase users. Cross-reference their email domains, and flag any user that does not have an '@ourcompany.com' email address."

6. Revoke User Access (delete_a_metabase_user_by_id)

Despite the HTTP DELETE verb, this tool disables a user account in Metabase (preventing login) rather than permanently deleting the relational data tied to their created cards.

Usage note: Requires administrator permissions. Best used in automated offboarding workflows.

"Disable the Metabase user account for employee ID 1042 immediately."

(To view the complete inventory of available Metabase tools, query schemas, and return types, visit the Truto Metabase integration reference.)

Workflows in Action

Giving an AI agent access to a BI tool transforms how non-technical users interact with data. Here is how Claude executes multi-step workflows using the tools provided by the MCP server.

Scenario 1: Self-Serve SQL Exploration and Report Generation

A Product Manager needs a new metric tracking dashboard but doesn't know SQL. They ask Claude to figure out the schema, test the query, and save the report.

"I need a report showing the number of failed Stripe payments grouped by error code for the last week. Figure out which database and tables have this data, test the query, and save it as a new question."

How the agent executes this:

  1. Calls metabase_agents_search with the query "stripe payments" to discover the correct database_id and table schemas.
  2. Calls create_a_metabase_agent_execute_sql with a drafted SQL query, iterating if the database engine throws syntax errors.
  3. Calls create_a_metabase_agent_construct_native_query to wrap the validated SQL into Metabase's required serialized format.
  4. Calls create_a_metabase_agent_question to save the formatted query as "Stripe Payment Failures by Error Code" in the root collection.

Claude then replies to the PM confirming the report is available in the UI.

sequenceDiagram
    participant User as User
    participant Claude as "Claude Desktop"
    participant MCP as "Truto MCP"
    participant MB as "Metabase"

    User->>Claude: "Create a report on Stripe failures"
    Claude->>MCP: Call metabase_agents_search
    MCP->>MB: GET /api/search
    MB-->>MCP: Returns tables
    MCP-->>Claude: Schema context
    Claude->>MCP: Call create_a_metabase_agent_execute_sql
    MCP->>MB: POST /api/agent/v1/execute-sql
    MB-->>MCP: Results & Column metadata
    MCP-->>Claude: Validated data
    Claude->>MCP: Call create_a_metabase_agent_question
    MCP->>MB: POST /api/agent/v1/question
    MB-->>MCP: Card ID
    MCP-->>Claude: Success
    Claude-->>User: "Report is saved in Metabase!"

Scenario 2: Dashboard Auditing and Cleanup

A Data Engineer wants to clean up stale reports that are slowing down the instance and cluttering the UI.

"Fetch the 'Q3 Exec Review' dashboard. Check if any of the underlying cards haven't been viewed in the last 6 months. If they are stale, remove them from the dashboard."

How the agent executes this:

  1. Calls metabase_agents_search to resolve "Q3 Exec Review" to a dashboard_id.
  2. Calls get_single_metabase_dashboard_by_id to retrieve the massive dashboard layout object, extracting the dashcards array.
  3. Iterates over the card_id list and analyzes their metadata (or calls an activity API if available) to determine staleness.
  4. Modifies the JSON layout to drop the stale dashcards, recalculates the grid positioning if prompted, and calls update_a_metabase_dashboard_by_id to push the cleaned layout back to Metabase.

Scenario 3: Automated User Offboarding

An IT administrator receives a termination notice and asks the agent to immediately secure the data warehouse.

"An employee with the email jsmith@company.com has left. Find their Metabase account and disable it. Also, list any personal API keys they generated."

How the agent executes this:

  1. Calls list_all_metabase_users and filters the response in-memory for jsmith@company.com to grab the user_id.
  2. Calls delete_a_metabase_user_by_id with that ID to disable the user's login access.
  3. Calls list_all_metabase_api_keys to cross-reference keys owned by the user (or assigned to a group the user belonged to) and alerts the IT admin to revoke them via delete_a_metabase_api_key_by_id if necessary.

Security and Access Control

Giving an AI agent access to your production BI environment is risky. Metabase holds the keys to your underlying data warehouse. Truto's MCP architecture provides several layers of security to lock down what the model can do:

  • Method Filtering (config.methods): Restrict an MCP server to strictly read-only operations. By setting methods: ["read"], you guarantee the LLM can query data (get, list) but is physically blocked at the proxy layer from calling create, update, or delete endpoints.
  • Tag Filtering (config.tags): Metabase endpoints are grouped by resource. You can filter the MCP server to only expose tools tagged with "users" or "dashboards", keeping the model away from sensitive administrative settings like "databases" or "ldap".
  • Dual-Layer Authentication (require_api_token_auth): By default, an MCP server authenticates via the secure token embedded in its URL. By enabling require_api_token_auth: true, the calling client must also pass a valid Truto session token or API key in the Authorization header, meaning possession of the URL alone is useless.
  • Time-to-Live (expires_at): For temporary workflows—like granting a contractor agent access to audit your dashboards—you can set an absolute expiration date. Cloudflare KV automatically evicts the token when it expires, cutting off access instantly.

Moving Data Operations to Natural Language

Connecting Metabase to Claude via MCP turns your AI agent into an autonomous data analyst. Instead of forcing PMs and marketers to learn MBQL, navigate nested schemas, or wait on Data Engineering to build a simple report, they can prompt Claude to do the heavy lifting.

By leveraging Truto's managed MCP servers, you bypass the friction of building OAuth flows, maintaining custom JSON-RPC middleware, and keeping pace with Metabase API changes. You generate the URL, configure Claude, and immediately begin orchestrating data at scale.

FAQ

How do I connect Metabase to Claude Desktop?
You can connect Metabase to Claude using a Model Context Protocol (MCP) server. Generate a managed MCP server URL in Truto, and paste it into Claude Desktop's custom connector settings, or configure it via the claude_desktop_config.json file using the SSE transport command.
Can Claude execute raw SQL queries against my Metabase databases?
Yes. By exposing tools like create_a_metabase_agent_execute_sql, Claude can write and execute raw SQL queries against your connected databases. Truto handles the schema mapping and API authentication required to pass the request to Metabase.
How does Truto handle Metabase rate limits?
Truto does not absorb, retry, or throttle rate limits. If Metabase returns an HTTP 429, Truto passes the error back to the caller while normalizing upstream rate limit info into standard headers (ratelimit-limit, ratelimit-remaining, ratelimit-reset). The client calling the MCP server must implement its own exponential backoff.
Is it safe to give an AI agent access to my Metabase instance?
Yes, if configured correctly. You can scope your Metabase MCP server to read-only operations using method filtering, restrict it to specific tags, or require dual-layer authentication where the caller must provide a valid Truto API token in addition to the secure MCP URL.

More from our Blog