BQ Agent Gateway
by durjoi
README.md
# BQ Agent Gateway
A read-only MCP server that connects Claude to BigQuery with layered guardrails
against dangerous and expensive SQL.
## What it blocks
**Static AST validation** (parsed with `sqlglot`, not regex):
- Anything that isn't a `SELECT` (no `INSERT`/`UPDATE`/`DELETE`/`MERGE`/DDL)
- `SELECT *` and `table.*` (but `COUNT(*)` is fine)
- `CROSS JOIN` and implicit cartesian products (comma joins with no `ON`)
- Multiple statements in one call (blocks `SELECT 1; DROP TABLE ...`)
- Queries referencing datasets outside an allowlist
- Missing `LIMIT` (auto-injected by default) and over-large `LIMIT`s
**BigQuery cost gate:**
- A dry-run estimates bytes scanned *before* running; over-threshold queries are rejected
- Execution sets `maximum_bytes_billed` as a hard server-side cap, so even a
mis-estimate can't overspend — BigQuery kills the job instead
- Row count and wall-clock timeout are capped
## Tools exposed
`list_datasets`, `list_tables`, `describe_table`, `estimate_query_cost`, `run_query`.
## Setup
```bash
pip install -r requirements.txt # or: uv pip install -r requirements.txt
cp .env.example .env # then edit values
# Auth: either set GOOGLE_APPLICATION_CREDENTIALS to a service-account key,
# or run:
gcloud auth application-default login
```
Give the service account only what it needs:
`roles/bigquery.dataViewer` + `roles/bigquery.jobUser`. The dataViewer role
cannot mutate data, so the read-only guarantee is enforced at the IAM layer too,
not just in code.
## Run
```bash
# stdio (for Claude Desktop)
python server.py
# or HTTP
fastmcp run server.py --transport http --port 8000
```
## Register with Claude Desktop
Edit `claude_desktop_config.json`
(macOS: `~/Library/Application Support/Claude/`,
Windows: `%APPDATA%\Claude\`):
```json
{
"mcpServers": {
"bq-agent-gateway": {
"command": "python",
"args": ["/absolute/path/to/bq-agent-gateway/server.py"],
"env": {
"BQ_PROJECT": "my-gcp-project",
"GOOGLE_APPLICATION_CREDENTIALS": "/absolute/path/to/key.json",
"BQ_ALLOWED_DATASETS": "analytics,prod_reporting",
"BQ_MAX_BYTES_SCANNED_GIB": "5"
}
}
}
}
```
Restart Claude Desktop; the BigQuery tools appear in the tools menu.
## Design notes / defense in depth
The guardrails are structured as independent layers so a bypass of one doesn't
defeat the rest:
1. **IAM** — read-only service account can't write regardless of SQL.
2. **AST validation** — shape checks that regex can't do reliably.
3. **Dry-run cost gate** — the real budget protection for BigQuery.
4. **`maximum_bytes_billed`** — hard cap enforced by BigQuery itself.
5. **Row/time caps** — bound the response size and latency.
Toggle any static rule via env vars (see `.env.example`) without touching code.
```
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues