BigQuery MCP Server
README.md
# BigQuery MCP Server
A Model Context Protocol (MCP) server that enables LLMs to interact with Google BigQuery. Built with **FastMCP** (Python) and designed for ephemeral cloud environments where only environment variables are available (no file-based credentials).
---
## Features
| Tool | Description |
|---|---|
| `bq_list_datasets` | List all datasets in the configured project |
| `bq_list_tables` | List tables in a dataset with row counts and size in MB |
| `bq_get_schema` | Get the full schema of a table (columns, types, descriptions) |
| `bq_dry_run` | Validate SQL and estimate query cost (~$6.25/TB) |
| `bq_run_query` | Execute SQL and return results (auto-appends LIMIT 1000 if missing) |
---
## Project Structure
```
bigquery-mcp-server/
├── src/
│ ├── server.py # Entry point — starts the MCP server
│ ├── constants.py # Global constants (BigQuery config, limits)
│ ├── tools/
│ │ └── bigquery.py # All 5 BigQuery tools
│ └── services/
│ ├── bigquery_client.py # BigQuery client factory + row serialization
│ └── error_handler.py # Centralized BigQuery error handling
├── main.py # Root-level entry point wrapper
├── Dockerfile # Multi-stage Docker build
├── docker-compose.yml # Server + MCP Inspector
├── docker-compose.dev.yml # Dev mode with hot-reload
├── mcp.json # MCP client configuration
├── pyproject.toml # Project metadata and dependencies
└── requirements.txt # Pip-compatible dependencies
```
---
## Environment Variables
| Variable | Required | Default | Description |
|---|---|---|---|
| `BIGQUERY_PROJECT_ID` | Yes | — | GCP project ID (e.g. `my-project-123`) |
| `BIGQUERY_SERVICE_ACCOUNT_JSON_CONTENT` | Yes | — | Raw JSON string of the service account key |
| `BIGQUERY_LOCATION` | No | `US` | BigQuery dataset region |
| `TRANSPORT` | No | `stdio` | Transport mode: `stdio` or `http` |
| `PORT` | No | `8000` | HTTP server port |
| `HOST` | No | `127.0.0.1` | HTTP server bind address |
### Authentication
This server authenticates using a **service account JSON provided directly via environment variable** — no file paths, no `gcloud` CLI.
1. Create a service account in the GCP Console with at least:
- **BigQuery Data Viewer** (`roles/bigquery.dataViewer`)
- **BigQuery Job User** (`roles/bigquery.jobUser`)
2. Generate a JSON key for the service account
3. Set the full JSON string as `BIGQUERY_SERVICE_ACCOUNT_JSON_CONTENT`
```bash
export BIGQUERY_PROJECT_ID="my-project-123"
export BIGQUERY_SERVICE_ACCOUNT_JSON_CONTENT='{"type":"service_account","project_id":"...","private_key":"...","client_email":"...","...":"..."}'
```
---
## Quick Start
### Option A — uvx (Recommended)
No manual install needed. `uvx` downloads the package from PyPI, creates an isolated environment, and runs the server:
```bash
uvx bigquery-mcp-server
```
For MCP clients (Claude Code, Cursor, etc.), configure the server in your client's MCP config:
```json
{
"mcpServers": {
"bigquery-mcp": {
"command": "uvx",
"args": ["bigquery-mcp-server"],
"env": {
"BIGQUERY_PROJECT_ID": "my-project-123",
"BIGQUERY_SERVICE_ACCOUNT_JSON_CONTENT": "{ ... }"
}
}
}
}
```
> **Note:** Env vars must be passed explicitly via the `env` block in your MCP client config.
### Option B — Local (virtualenv)
```bash
# Create virtual environment and install
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e .
# Set credentials (or use a .env file)
export BIGQUERY_PROJECT_ID="my-project-123"
export BIGQUERY_SERVICE_ACCOUNT_JSON_CONTENT='{ ... }'
# Run in stdio mode
python main.py
# Or HTTP mode (for MCP Inspector)
TRANSPORT=http python main.py
```
### Option C — Docker
```bash
# Set env vars in a .env file or export them, then:
docker compose up --build
# Open MCP Inspector at http://localhost:6274
# Connect to: http://mcp-server:8000/mcp (Streamable HTTP)
```
### Option D — Dev mode with hot-reload
```bash
docker compose -f docker-compose.dev.yml up --build
# In another terminal:
npx @modelcontextprotocol/inspector
# Connect to: http://localhost:8000/mcp (Streamable HTTP)
```
---
## Testing with MCP Inspector CLI
```bash
# List all tools
npx @modelcontextprotocol/inspector --cli \
--config mcp.json --server bigquery-mcp \
--method tools/list
# List datasets
npx @modelcontextprotocol/inspector --cli \
--config mcp.json --server bigquery-mcp \
--method tools/call --tool-name bq_list_datasets
# List tables in a dataset
npx @modelcontextprotocol/inspector --cli \
--config mcp.json --server bigquery-mcp \
--method tools/call --tool-name bq_list_tables \
--tool-arg 'params={"dataset": "my_dataset"}'
# Get table schema
npx @modelcontextprotocol/inspector --cli \
--config mcp.json --server bigquery-mcp \
--method tools/call --tool-name bq_get_schema \
--tool-arg 'params={"dataset": "my_dataset", "table": "my_table"}'
# Dry run a query
npx @modelcontextprotocol/inspector --cli \
--config mcp.json --server bigquery-mcp \
--method tools/call --tool-name bq_dry_run \
--tool-arg 'params={"sql": "SELECT * FROM my_dataset.my_table"}'
# Run a query
npx @modelcontextprotocol/inspector --cli \
--config mcp.json --server bigquery-mcp \
--method tools/call --tool-name bq_run_query \
--tool-arg 'params={"sql": "SELECT * FROM my_dataset.my_table LIMIT 10"}'
```
---
## Connect to Claude Code
Using uvx (recommended):
```bash
claude mcp add bigquery-mcp uvx -- bigquery-mcp-server
```
Or add to `~/.claude/mcp.json`:
```json
{
"mcpServers": {
"bigquery-mcp": {
"command": "uvx",
"args": ["bigquery-mcp-server"],
"env": {
"BIGQUERY_PROJECT_ID": "my-project-123",
"BIGQUERY_SERVICE_ACCOUNT_JSON_CONTENT": "{ ... }"
}
}
}
}
```
---
## Transports
| Transport | How to activate | When to use |
|---|---|---|
| **stdio** | `TRANSPORT=stdio python -m src.server` | Claude Code, Cursor, local integration |
| **HTTP** | `TRANSPORT=http python -m src.server` | MCP Inspector, remote servers |
---
## Safety Features
- **Auto LIMIT**: `bq_run_query` automatically appends `LIMIT 1000` if no LIMIT clause is detected, preventing accidental large data transfers
- **Dry run**: `bq_dry_run` validates SQL and estimates cost before execution
- **Input validation**: All tool inputs validated with Pydantic v2
- **Error handling**: BigQuery exceptions (403, 404, 400, etc.) are caught and returned as human-readable strings — the server never crashes
- **Type serialization**: Dates, datetimes, decimals, and bytes are automatically converted to JSON-safe types
---
## References
- [FastMCP Docs](https://gofastmcp.com)
- [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk)
- [MCP Inspector](https://github.com/modelcontextprotocol/inspector)
- [MCP Protocol Docs](https://modelcontextprotocol.io)
- [BigQuery Python Client](https://cloud.google.com/python/docs/reference/bigquery/latest)
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues