Content
# Metabase MCP Server
Let AI assistants (Claude, Cursor, etc.) directly operate your Metabase - query databases, execute SQL, manage dashboards, and question cards.
## Quick Start
### Method 1: Docker (Recommended)
```bash
docker run -d \
-p 8000:8000 \
-e METABASE_URL=https://metabase.example.com \
-e METABASE_API_KEY=mb_xxxx \
--name metabase-mcp \
docker.cnb.cool/debug.icu/mcp/metabase:latest
```
Then fill in the connection address in your MCP client (see "Connection Configuration" below).
### Method 2: Download Binary
Download the binary file for your platform from [Releases](../../releases) and run it directly:
```bash
# HTTP mode (for remote client connection, default)
METABASE_URL=https://metabase.example.com \
METABASE_API_KEY=mb_xxxx \
./metabase-mcp --transport http
# stdio mode (for Claude Desktop / Claude Code and other local clients)
METABASE_URL=https://metabase.example.com \
METABASE_API_KEY=mb_xxxx \
./metabase-mcp --transport stdio
```
## Connection Configuration
### Claude Code (stdio mode)
Use the `claude mcp add` command to register with one click, supporting project-level and global scopes.
**Using `METABASE_CREDENTIALS` (Recommended, avoid plaintext)**
First, generate base64url-encoded credentials:
```bash
# API Key
echo -n 'apikey:mb_xxxx' | base64 | tr '+/' '-_' | tr -d '='
# Email + Password
echo -n 'alice@example.com:password' | base64 | tr '+/' '-_' | tr -d '='
```
Then register the MCP server:
```bash
# Register to the current project (configuration saved in project .mcp.json)
claude mcp add metabase \
-e METABASE_URL=https://metabase.example.com \
-e METABASE_CREDENTIALS=YXBpa2V5Om1iX3h4eHg \
-- /path/to/metabase-mcp --transport stdio
# Register as globally available (shared by all projects)
claude mcp add metabase --scope user \
-e METABASE_URL=https://metabase.example.com \
-e METABASE_CREDENTIALS=YXBpa2V5Om1iX3h4eHg \
-- /path/to/metabase-mcp --transport stdio
```
**Using plaintext credentials**
```bash
# API Key
claude mcp add metabase \
-e METABASE_URL=https://metabase.example.com \
-e METABASE_API_KEY=mb_xxxx \
-- /path/to/metabase-mcp --transport stdio
# Email + Password
claude mcp add metabase \
-e METABASE_URL=https://metabase.example.com \
-e METABASE_USER_EMAIL=alice@example.com \
-e METABASE_PASSWORD=your-password \
-- /path/to/metabase-mcp --transport stdio
```
Verify if it takes effect after registration:
```bash
claude mcp list
claude mcp get metabase
```
### Claude Code (HTTP mode, connect to remote server)
```bash
# Using API Key
claude mcp add metabase --transport http \
"http://apikey:mb_xxxx@your-server:8000/mcp"
# Using email + password (@ needs to be encoded as %40)
claude mcp add metabase --transport http \
"http://alice%40example.com:password@your-server:8000/mcp"
```
### Claude Desktop (stdio mode)
Edit `claude_desktop_config.json`:
```json
{
"mcpServers": {
"metabase": {
"command": "/path/to/metabase-mcp",
"args": ["--transport", "stdio"],
"env": {
"METABASE_URL": "https://metabase.example.com",
"METABASE_CREDENTIALS": "YXBpa2V5Om1iX3h4eHg"
}
}
}
}
```
### Claude Desktop / Cursor (HTTP mode, connect to remote server)
Fill in the connection URL in the client, with credentials directly written in the URL:
```
# Using API Key (Recommended)
http://apikey:mb_xxxx@your-server:8000/mcp
# Using email + password (@ needs to be encoded as %40)
http://alice%40example.com:password@your-server:8000/mcp
```
> **Multi-user scenario**: One server instance can serve multiple users simultaneously, and each user can fill in their own credentials in the URL without interfering with each other.
### Other credential passing methods
If the client does not support carrying authentication information in the URL, you can use:
**HTTP request header**
```
X-Metabase-Api-Key: mb_xxxx
# Or email + password:
X-Metabase-Email: alice@example.com
X-Metabase-Password: your-password
# Optional: override the default Metabase address on the server
X-Metabase-Url: https://other-metabase.example.com
```
**URL path encoding** (applicable to clients that can only fill in ordinary URLs)
```bash
# Generate credential token
echo -n 'alice@example.com:password' | base64 | tr '+/' '-_' | tr -d '='
# → YWxpY2VAZXhhbXBsZS5jb206cGFzc3dvcmQ
# Connection URL
http://your-server:8000/YWxpY2VAZXhhbXBsZS5jb206cGFzc3dvcmQ/mcp
```
## Available Tools
After connection, AI assistants can use the following tools:
### Database Exploration
| Tool | Function |
|------|------|
| `list_databases` | List all connected databases |
| `list_tables` | List all tables in a specified database |
| `get_table_fields` | View field/column definitions of a table |
### Data Query
| Tool | Function |
|------|------|
| `execute_query` | Execute native SQL queries on a specified database |
### Saved Questions
| Tool | Function |
|------|------|
| `list_cards` | List all saved questions |
| `get_card` | View details of a question |
| `execute_card` | Run a saved question and return results |
| `create_card` | Create a new question card |
### Collections
| Tool | Function |
|------|------|
| `list_collections` | List all collections |
| `get_collection_items` | Browse contents within a collection |
| `create_collection` | Create a new collection |
### Dashboards
| Tool | Function |
|------|------|
| `list_dashboards` | List all dashboards |
| `get_dashboard` | View dashboard details (including card list) |
| `create_dashboard` | Create a new dashboard |
| `update_dashboard` | Modify dashboard information |
| `add_card_to_dashboard` | Add a question card to a dashboard |
| `update_dashboard_card` | Adjust the position/size of a card on a dashboard |
| `remove_card_from_dashboard` | Remove a card from a dashboard |
## Configuration Items
All configurations are set through environment variables, supporting `.env` files (refer to `.env.example`).
| Variable | Default Value | Description |
|------|--------|------|
| `METABASE_URL` | — | **Required**. Metabase instance address, e.g., `https://metabase.example.com` |
| `METABASE_CREDENTIALS` | — | base64url-encoded credentials (recommended). Format described below, priority higher than the following three items |
| `METABASE_API_KEY` | — | Plaintext API Key |
| `METABASE_USER_EMAIL` | — | Plaintext email (used with `METABASE_PASSWORD`) |
| `METABASE_PASSWORD` | — | Plaintext password |
| `METABASE_HTTP_PROXY` | — | HTTP proxy address used to access Metabase (leave blank to ignore proxy and system `HTTP_PROXY` environment variable) |
| `TRANSPORT` | `http` | Transport mode: `http` or `stdio` |
| `HOST` | `0.0.0.0` | HTTP listening address |
| `PORT` | `8000` | HTTP listening port |
| `MCP_PATH` | `/mcp` | MCP endpoint path |
| `CLIENT_CACHE_TTL` | `3600` | Cache duration (seconds) for each user connection |
### METABASE_CREDENTIALS Format
base64url-encode `apikey:<key>` or `<email>:<password>` (without padding):
```bash
# API Key
echo -n 'apikey:mb_xxxx' | base64 | tr '+/' '-_' | tr -d '='
# Email + Password
echo -n 'alice@example.com:password' | base64 | tr '+/' '-_' | tr -d '='
```
## CLI Mode
In addition to the MCP server, this tool provides two independent CLI subcommands that can be used directly without MCP.
### query — Execute Local SQL Files
Read query statements from local SQL files, execute through Metabase API, and save results as JSONL files.
```bash
# Single SQL file
metabase-mcp query -db 1 report.sql
# Batch execute multiple SQL files
metabase-mcp query -db 1 -o ./data queries/*.sql
# Read SQL from stdin
cat report.sql | metabase-mcp query -db 1 -
# Custom output file name
metabase-mcp query -db 1 -f result.jsonl report.sql
# Specify a named instance
metabase-mcp query --instance hz -db 1 report.sql
```
| Parameter | Description |
|------|------|
| `-db, --database <id>` | **Required**. Target database ID |
| `-o, --output <dir>` | Output directory (default current directory) |
| `-f, --filename <name>` | Output file name (only single-file mode; default taken from SQL file name) |
| `-i, --instance <name>` | Named Metabase instance (see below), leave blank to use the default instance |
### download — Download Card / Dashboard Data
```bash
# Download a single Card
metabase-mcp download -c 456 -o ./data
# Download an entire Dashboard (each Card in a separate file)
metabase-mcp download -d 123 -o ./data
# Specify a named instance
metabase-mcp download --instance sg -d 123 -o ./data
```
| Parameter | Description |
|------|------|
| `-d, --dashboard <id>` | Dashboard ID (export all Cards) |
| `-c, --card <id>` | Single Card/Question ID |
| `-o, --output <dir>` | Output directory (default current directory) |
| `-f, --filename <name>` | Output file name (only single Card mode) |
| `-i, --instance <name>` | Named Metabase instance (see below), leave blank to use the default instance |
### Multiple Instances
Configure multiple named instances through the `METABASE_INSTANCES` environment variable or the `instances` section of the configuration file. The CLI can use `--instance <name>` to select the target instance; if not specified, the default instance (i.e., the configuration corresponding to `METABASE_URL`) is used.
```bash
export METABASE_INSTANCES=hz,sg
export METABASE_HZ_URL=https://hz.metabase.example.com
export METABASE_HZ_API_KEY=mb_xxxx
export METABASE_SG_URL=https://sg.metabase.example.com
export METABASE_SG_API_KEY=mb_yyyy
metabase-mcp query --instance hz -db 1 report.sql
```
## Docker Compose Example
```yaml
services:
metabase-mcp:
image: docker.cnb.cool/debug.icu/mcp/metabase:latest
ports:
- "8000:8000"
environment:
METABASE_URL: https://metabase.example.com
METABASE_CREDENTIALS: YXBpa2V5Om1iX3h4eHg
restart: unless-stopped
```