Skip to main content
Glama
itsshreyanshhere

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 |