metabase-mcp
README.md
# metabase-mcp
A Model Context Protocol (MCP) server for Metabase, designed to run in Claude Code via stdio transport.
## Features
- **`execute` tool** — Run SQL queries or saved Metabase cards; results returned inline as a formatted table
- **`export` tool** — Same as execute, but writes results to CSV or XLSX
- **Read-only mode** — Blocks mutating SQL keywords and comment-injection by default
- **DB whitelist** — Restricts queries to an explicit list of allowed database IDs
- **Audit log** — Appends a JSON line per tool call to a local log file
## Setup
### 1. Install dependencies
```bash
cd metabase-mcp
npm install
```
### 2. Configure environment
```bash
cp .env.example .env
chmod 600 .env
```
Edit `.env` and fill in your values:
| Variable | Description |
|---|---|
| `METABASE_URL` | Base URL of your Metabase instance (no trailing slash) |
| `METABASE_API_KEY` | Metabase API key (Settings → Admin → API Keys) |
| `METABASE_ALLOWED_DB_IDS` | Comma-separated list of allowed database IDs (e.g. `1,2,3`). Leave empty to allow all. |
| `METABASE_READ_ONLY_MODE` | `true` (default) blocks INSERT/UPDATE/DELETE/DROP/etc. and comment syntax |
| `AUDIT_LOG_PATH` | Path to the audit log file (default: `./audit.log`) |
| `EXPORT_DIRECTORY` | Directory where export files are written (default: `./exports`) |
### 3. Build
```bash
npm run build
```
### 4. Add to Claude Code
```bash
claude mcp add metabase-mcp -- node /absolute/path/to/metabase-mcp/build/index.js
```
Replace `/absolute/path/to/metabase-mcp` with the actual path on your machine.
## Tool reference
### `execute`
Run a SQL query or saved card and get results inline.
```json
{
"mode": "sql",
"database_id": 1,
"query": "SELECT id, name FROM users LIMIT 10",
"row_limit": 100
}
```
```json
{
"mode": "card",
"card_id": 42,
"card_parameters": [],
"row_limit": 50
}
```
### `export`
Write results to a file.
```json
{
"mode": "sql",
"database_id": 1,
"query": "SELECT * FROM orders",
"format": "csv",
"filename": "orders_export"
}
```
```json
{
"mode": "card",
"card_id": 7,
"format": "xlsx"
}
```
## Security model
- **Authentication**: API key via `X-API-KEY` header only. No email/password fallback.
- **DB whitelist**: If `METABASE_ALLOWED_DB_IDS` is set, any query targeting an unlisted database is blocked before any network call is made.
- **Read-only mode**: Rejects SQL containing `INSERT`, `UPDATE`, `DELETE`, `DROP`, `TRUNCATE`, `ALTER`, `CREATE`, `GRANT`, `REVOKE` (whole-word match) and comment syntax (`--`, `/*`, `*/`).
- **Path traversal**: Export filenames are sanitized and the resolved path is checked to ensure it stays within `EXPORT_DIRECTORY`.
## Error categories
| Category | Meaning |
|---|---|
| `AUTH_ERROR` | API key rejected by Metabase |
| `SECURITY_ERROR` | Blocked by read-only mode or DB whitelist |
| `VALIDATION_ERROR` | Bad input or missing env vars |
| `METABASE_ERROR` | Metabase API returned an error |
| `EXPORT_ERROR` | File write failure |
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues