The design assumes the thing asking the question might be a customer-facing bot, a third-party tool, or a document carrying an injection. So the answer is a tiny surface, a table allowlist enforced in the parser, and a cost ceiling that is a property of the deployment rather than something you hope the model respects.
A BigQuery server you deploy into your own Google Cloud project on Cloud Run, reached over HTTPS with an API key in a header. It exposes exactly two things — reading the schema of tables you have allowlisted, and running SELECT queries against them — and enforces that in the application rather than leaving it to IAM alone.
- Schema reads for the allowlisted tables, returned in a shape that is the same for one table or many
- SELECT queries, with DDL, DML, scripting, multi-statement bodies and procedural constructs rejected by the SQL parser
- A hard allowlist of dataset and table pairs: a qualified reference into a dataset you did not allow is refused, a bare name that exists in two allowed datasets is refused as ambiguous, and CTE names are correctly exempt
- A dry run before every query, so one that would scan more than your ceiling is rejected without a BigQuery job being created or a byte being billed
- A row cap that truncates results server-side before they reach a context window
- Token-bucket rate limiting with burst, plus separate concurrency limits for queries and metadata calls
- Cached schema lookups and dry runs, with an admin endpoint to invalidate them after a schema change
- Configuration entirely through environment variables, so adding a table is a redeploy rather than a config file
A Google Cloud project with Cloud Run, BigQuery, Secret Manager, Artifact Registry and IAM enabled, and a dedicated service account holding job-user on the project and data-viewer on each allowlisted dataset — nothing broader. Two keys, generated by you and stored in Secret Manager: one clients present on every request, one for the admin endpoint. Clients connect through an MCP proxy over streamable HTTP. Cloud Run scales to zero, which means near-nothing at idle and a few seconds of cold start on the first request unless you keep an instance warm. Deployment is regional, and the schema cache is per instance. What it deliberately does not do: no column-level masking, so allowlist an authorized view if your tables hold columns an agent should not see; no per-user attribution behind the shared key; no prompt-injection scanning; and no writes, ever.
Build from source — clone the repository and build it, then point your client at the binary
