Provider REST API

Analytics

Connect Claude to Metabase

Browse saved questions, dashboards and database metadata, run a saved card, and query a database. Toolspoke puts 11 of its actions behind one MCP endpoint that Claude, Cursor, and Codex all speak.

Connection
Provider REST API
Authentication
API key
Actions exposed
11
Cost per call (typical)
1 credit
Adapter
Maintained by Toolspoke

Connected in three steps

  1. 1

    Install Metabase

    Open the marketplace in your workspace, add Metabase to the project your agents work in, and it appears on the gateway immediately.

  2. 2

    Connect the credential

    Authenticate with api key. Where to get one, and what it has to be able to reach, is the next section.

  3. 3

    Point your agent at the gateway

    Give your client one address, https://toolspoke.com/mcp. Claude Code takes it as a command, Claude and Claude Desktop add it as a custom connector, and Cursor, Codex and VS Code each read it from a config file of their own.

.mcp.json
{
  "mcpServers": {
    "toolspoke": {
      "type": "http",
      "url": "https://toolspoke.com/mcp"
    }
  }
}

One block covers every tool you have installed. Metabase shows up in the client as soon as your policy allows it, and so does everything else you install later.

Where the address goes, per client

Claude Code

Run it in your project, then /mcp to sign in

claude mcp add --transport http toolspoke https://toolspoke.com/mcp
Claude and Claude Desktop

Settings, then Connectors, then Add custom connector

https://toolspoke.com/mcp
Cursor

~/.cursor/mcp.json, or .cursor/mcp.json for one project

{ "mcpServers": { "toolspoke": { "url": "https://toolspoke.com/mcp" } } }
Codex

~/.codex/config.toml

[mcp_servers.toolspoke]
url = "https://toolspoke.com/mcp"
VS Code

.vscode/mcp.json, or the MCP: Add Server command

{ "servers": { "toolspoke": { "type": "http", "url": "https://toolspoke.com/mcp" } } }

What Metabase asks for

API key. You provide it once, when you install the connector. Toolspoke encrypts it at rest and decrypts it only for the length of a single call, and the gateway attaches it to the outbound request itself, so it is never part of the arguments an agent sends.

API keyRequired
Metabase → gear icon → Admin → Settings → Authentication → API keys → Create API key. The key inherits the permissions of the group you pick, so pick a group with the access you actually want to hand over - a read-only group is the usual answer. The key is shown once. Needs Metabase 0.49 or newer; earlier versions have no API keys at all.
mb_…
Instance URLRequired
The root URL of your Metabase, with no trailing /api - this connector adds that itself. Metabase Cloud and a self-hosted install are both fine.
https://metabase.example.com

What Claude can do in Metabase

11 actions, each one declared and named by the connector rather than discovered at runtime. A workspace policy grants a person all of them, a hand-picked selection, everything on the read side, everything on the write side, or none.

Reads
10Reads
Writes
1Writes
Destructive
0Destructive

Reads

10

Fetches data and changes nothing.

  • list_databases

    List the databases this Metabase is connected to, with each one's id, name and engine. Start here: the database id is what run_native_query and get_database_metadata take, and this is the cheapest call that proves the API key works and says what it can see - which is why it is the connection test. Connection details come back with secrets already masked by Metabase, and this connector adds no operation that could unmask them.

  • get_database_metadata

    Fetch one database's full schema as Metabase understands it: every table, and for each table every field with its type, its semantic type and its display name. This is the map to read before writing SQL for run_native_query, because it names the tables and columns as they actually exist. It can be a very large response on a wide warehouse - pass skip_fields to get tables only, then use get_table_query_metadata for the one table you care about.

  • list_tables

    List every table Metabase knows about, across all connected databases, with each one's id, name, schema and database. Use it to find a table id for get_table_query_metadata when you do not want to pull a whole database's metadata. On an instance connected to a large warehouse this is a long list, so prefer get_database_metadata with skip_fields when you already know which database you mean.

  • get_table_query_metadata

    Fetch one table's fields as they matter for querying: name, base type, semantic type, whether each field is a foreign key and what it points at. This is the precise version of get_database_metadata for a single table, and the right call before writing a join. Fields an admin marked sensitive are withheld unless include_sensitive_fields is set, which is Metabase's own choice about them and is left off by default here.

  • list_cards

    List the saved questions in this Metabase - what its own API calls cards - with each one's id, name, collection, database and query definition. This is the catalogue of analysis somebody has already written and reviewed, and it is nearly always the better answer than writing new SQL. The id is what get_card and run_card_query take. `f` narrows the list; "mine" is the questions the API key's own user owns, which for a key is rarely what you want.

  • get_card

    Fetch one saved question by id, with its full query definition, its visualisation settings, its collection and the parameters it accepts. Read this before run_card_query so you know which parameter ids that question takes and what they mean. Ids come from list_cards or from search.

  • run_card_query

    Run a saved question and return its result rows. This is a genuine read and is classified as one: the statement being executed was written and saved by a person in Metabase, the caller cannot change it, and all this operation supplies is values for the parameters that question already declares. That is the whole difference from run_native_query, which sends SQL a caller wrote and is a write. Reach for this first - a saved question is reviewed, cached and permissioned, and running one avoids writing SQL at all. Get the parameter ids from get_card; each entry needs the `id` of a parameter the card declares plus the `value` to use.

  • list_dashboards

    List the dashboards in this Metabase with their ids and names. Metabase itself marks this route as kept only for backwards compatibility and no longer uses it in its own interface, so treat what it returns as a plain list and prefer search with models set to ["dashboard"] when you need collections, ownership or last-edited information alongside the names. Note that `f` here accepts only all, mine or archived - a much smaller set than list_cards takes.

  • get_dashboard

    Fetch one dashboard by id, with every card on it, how those cards are laid out, and the filters the dashboard declares. This is how you find which saved questions a dashboard is built from - take their ids and run them with run_card_query. Ids come from list_dashboards or from search.

  • search

    Search everything in this Metabase by name - questions, dashboards, models, collections, tables and databases - and get back what each hit is, where it lives and its id. This is the fastest way from "the revenue dashboard" to an id, and it is the recommended way to list dashboards with their context. `models` narrows what kinds of thing come back and is repeated once per kind. Metabase pages this route with limit and offset, and defaults to 50 results when either is given.

Writes

1

Creates or updates something on the other side.

  • run_native_query

    Send a SQL statement to one of the connected databases and return the result rows. CLASSIFIED A WRITE ON PURPOSE, and this is not a mistake to correct later: /api/dataset is the same endpoint for SELECT, INSERT, UPDATE and DDL, Metabase offers no read-only mode to open the connection in, and nothing on this side can tell which of those a caller sent - the same reasoning that makes connectors/supabase.json's `query` and connectors/bigquery.json's run_query writes. If this install should only ever read, give its API key a Metabase group whose database permission is read-only; the classification stops a read-only grant reaching this at all. Prefer run_card_query when a saved question already answers the question. Always put a LIMIT in the statement - the rows come back verbatim. Call get_database_metadata first to get table and column names right.

What it will not do

Enforced by the gateway rather than left to convention, which is why each of these can be stated flatly.

It cannot call anything else
The 11 actions above are the whole of it. A call to any other name is refused before it reaches Metabase rather than forwarded on, and connecting your account does not add to the list: it is fixed by the connector, not discovered at run time.
Nothing here deletes
This connector writes to Metabase, but nothing in it deletes or permanently alters anything.
It reaches no further than your credential
Toolspoke holds no access to Metabase of its own. Every call carries the credential you stored and nothing besides, so whatever that credential cannot reach, this connector cannot reach either.
It never hears from Metabase
Nothing is pushed to it. There is no webhook, no subscription and no polling, so this connector cannot notice by itself that something changed in Metabase. An agent has to ask.
It does not smooth over provider limits
Toolspoke does not retry, queue or back off around Metabase's own rate limits. A call that Metabase refuses comes back to the agent as a failed call.

Before you connect it

What can Claude do in Metabase?

11 named actions: 10 that only read and 1 that write. They include list_databases, get_database_metadata and list_tables. Nothing outside that list is reachable: the connector declares each operation by name rather than proxying whatever an agent asks for.

What credentials does the Metabase connector need?

API key. The connector asks for api key and instance url. Values are encrypted at rest and attached to the outbound request by the gateway, so they are never part of the arguments an agent sends and never reach the audit log.

Does the Metabase connector work with Cursor and Codex, or only Claude?

Any client that speaks MCP, and every one of them gets the same 11 actions. There is a single address, https://toolspoke.com/mcp. Claude Code adds it with claude mcp add --transport http, Claude and Claude Desktop take it as a custom connector in settings, Cursor reads it from .cursor/mcp.json, Codex from ~/.codex/config.toml, and VS Code from .vscode/mcp.json. Each of them signs in to the gateway itself, so there is no key to paste.

What does the Metabase connector not do?

The 11 actions above are the whole of it. A call to any other name is refused before it reaches Metabase rather than forwarded on, and connecting your account does not add to the list: it is fixed by the connector, not discovered at run time. This connector writes to Metabase, but nothing in it deletes or permanently alters anything. Toolspoke holds no access to Metabase of its own. Every call carries the credential you stored and nothing besides, so whatever that credential cannot reach, this connector cannot reach either. Nothing is pushed to it. There is no webhook, no subscription and no polling, so this connector cannot notice by itself that something changed in Metabase. An agent has to ask. Toolspoke does not retry, queue or back off around Metabase's own rate limits. A call that Metabase refuses comes back to the agent as a failed call.

Can I limit which actions an agent can call?

Yes, in two places. The project switches Metabase's actions on and off one at a time, for everyone in the project at once, and the screen groups them by read, write and destructive so turning off everything that deletes is one click. An individual agent key can then be narrowed further, to particular toolkits in a project and to particular actions in a toolkit. Whatever it was granted, a key never reaches a project its owner cannot.

What gets recorded when an agent calls Metabase?

Every attempt, with the agent that made it and the person that agent belongs to, the full request payload, the response payload, the status, the duration, and the credits spent. Values whose key names a secret are masked out before the record is shown to anyone. An operation the connector marks as not retained never has its response body written at all, so the gateway keeps no second copy of what was read.