Content
# metabase-mcp
Query your Metabase with AI agents. No API key. No admin begging. Just vibes and a cookie.
---
## The problem
The [official Metabase MCP](https://www.metabase.com/docs/master/ai/mcp) wants an API key or your username/password. Cool in theory. Not so cool if your company won't give you one.
But you *can* log into Metabase in a browser. Which means you have a session cookie. Which means you have everything you need.
That's this.
## Wait, should you even use this?
Honest answer: **if you have an API key or username/password, just use the [official Metabase MCP](https://www.metabase.com/docs/master/ai/mcp).** It's proper, supported, and won't expire on you mid-conversation. Newer versions of Metabase also support Google login natively via the official MCP.
This project is for the rest of us: the people whose company guards API keys like they're nuclear launch codes and treats every Metabase upgrade request like a 6-month procurement process.
**You'll love this if:**
- Your org controls Metabase and you don't have credentials beyond your browser login
- Your Metabase version doesn't support the official MCP's Google login yet
- You'd rather fish a cookie out of DevTools than write another Jira ticket
- You want to query data with AI and get on with your life
**You should know:**
| The good | The not-so-good |
|---|---|
| Works with just a browser login | Cookies expire, you'll re-paste it occasionally |
| Inherits your exact Metabase permissions | If using a session file, the token is stored in plaintext on disk (optional, you can pass it inline instead) |
| Zero setup on the Metabase side | If your session logs out, so does the MCP |
## What it can do
| Tool | What it does |
|---|---|
| `list_databases` | List all connected databases |
| `list_collections` | List all collections (folders) |
| `list_collection_items` | List questions, dashboards, and sub-collections inside a collection |
| `list_cards` | List all saved questions |
| `get_card` | Get details of a specific question |
| `create_card` | Create a new saved question in a collection |
| `run_card` | Execute a saved question and return results |
| `list_dashboards` | List all dashboards |
| `get_dashboard` | Get a dashboard with its card layout |
| `list_tables` | List tables, optionally filtered by database |
| `search` | Search across questions, dashboards, collections, and tables |
| `execute_query` | Run an ad-hoc query against any connected database |
## Prerequisites
- Go 1.25.5+
- A Metabase instance you can log into
## Install
```bash
go install github.com/Naveen-chava/metabase-mcp@latest
```
This puts the binary in `~/go/bin/`. Make sure that's in your `$PATH`:
```bash
export PATH="$PATH:$(go env GOPATH)/bin"
```
**Or build from source:**
```bash
git clone https://github.com/Naveen-chava/metabase-mcp
cd metabase-mcp
go install .
```
## Getting your session cookie
This is the one slightly sneaky step.
1. Open Metabase in your browser and log in
2. Open DevTools → **Application** → **Cookies** → select your Metabase domain
3. Find `metabase.SESSION` and copy its value
That's your cookie. Treat it like a password; it grants the same access as your login session.
> If the MCP starts throwing 401s, your session expired. Grab a fresh cookie and you're back.
## Configuration
| Variable | Required | Description |
|---|---|---|
| `METABASE_URL` | Yes | Base URL of your Metabase instance |
| `METABASE_SESSION` | One of these two | Session cookie value, read once at startup |
| `METABASE_SESSION_FILE` | One of these two | Path to a file containing the cookie, read on every request so rotating is just overwriting the file |
**Inline (quick start):**
```bash
METABASE_URL=https://metabase.company.com \
METABASE_SESSION=your-cookie \
./metabase-mcp
```
**Via file (recommended, no restart when your cookie expires):**
```bash
echo "your-cookie" > ~/.metabase-session
METABASE_URL=https://metabase.company.com \
METABASE_SESSION_FILE=~/.metabase-session \
./metabase-mcp
```
To rotate a stale cookie, just overwrite the file. No restart needed; the next request picks it up automatically.
> The server expands `~` and `$HOME` in the session file path, so `~/.metabase-session` works everywhere.
## Claude Desktop
Add this to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
```json
{
"mcpServers": {
"metabase": {
"command": "metabase-mcp",
"env": {
"METABASE_URL": "https://metabase.company.com",
"METABASE_SESSION_FILE": "~/.metabase-session"
}
}
}
}
```
Restart Claude Desktop. Done.
## Claude Code
```bash
claude mcp add metabase metabase-mcp -s user -e METABASE_URL=https://metabase.company.com -e METABASE_SESSION_FILE=~/.metabase-session
```
> Run as a single line. Backslash continuations can introduce invisible characters when copied from some terminals or browsers.
## Cursor
Add to `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (project-level):
```json
{
"mcpServers": {
"metabase": {
"command": "metabase-mcp",
"env": {
"METABASE_URL": "https://metabase.company.com",
"METABASE_SESSION_FILE": "~/.metabase-session"
}
}
}
}
```
Restart Cursor and verify the server is connected under **Settings → MCP**.
## Example prompts
- _"What databases are connected to Metabase?"_
- _"Show me all tables in the Analytics DB"_
- _"What's in my personal collection?"_
- _"Run the 'Daily Active Users' question"_
- _"Search for anything related to revenue"_
- _"Run this SQL on the Analytics DB: SELECT count(\*) FROM orders WHERE created\_at > now() - interval 7 day"_
- _"Query the orders collection in MongoDB and group revenue by category"_
- _"Create a saved question that shows top customers by spend"_
## Project structure
```
metabase-mcp/
├── main.go # Startup, env vars, wires everything together
└── internal/
├── metabase/ # Metabase API client
│ ├── client.go # HTTP client with cookie auth
│ ├── types.go # API types
│ ├── databases.go
│ ├── collections.go
│ ├── cards.go
│ ├── dashboards.go
│ ├── tables.go
│ ├── search.go
│ ├── query.go
│ └── tests/ # HTTP-level tests (package metabase_test)
└── tools/ # MCP tool handlers
├── client.go # MetabaseClient interface
├── register.go # One place to add/remove tools
├── helpers.go # Shared utilities
├── databases.go
├── collections.go
├── cards.go
├── dashboards.go
├── tables.go
├── search.go
├── query.go
└── tests/ # Handler tests with mock client (package tools_test)
```
## Running tests
```bash
go test ./...
```