BigQuery MCP Server: Google's Remote Server vs. MCP Toolbox, Tested

On this page
There are two official ways to give an AI agent access to BigQuery through
the Model Context Protocol (MCP). Google runs a managed remote MCP server at
https://bigquery.googleapis.com/mcp, and the open-source
MCP Toolbox for Databases
(MCP Toolbox for short) runs the same kind of tools on your own machine or
server. Both let the agent list datasets, read table schemas and run SQL.
They differ in control. The Toolbox can restrict queries to an allowlist of
datasets and cap the bytes billed per query, while the remote server relies
on IAM and has no per-query cost cap.
We set up both on 6 November 2026 (MCP Toolbox 1.16.0, MCP Inspector
2.14.0), connected MCP Inspector, Claude Code and a small Python agent, and
let the agent answer seven business questions on the public
bigquery-public-data.thelook_ecommerce dataset. With clear instructions
the agent answered all seven correctly via the remote server and six via the
Toolbox. With a minimal prompt it had answered only four and five correctly.
The causes, a parser bug in the Toolbox, an invented number and an ambiguous
column, are described under "Pitfalls we hit".
What a BigQuery MCP server does
An MCP server exposes tools that an AI client can call. For BigQuery, the useful set is small:
- list the datasets and tables the caller may see,
- read a table's schema and description,
- run a SQL query and return the rows.
The SQL itself is written by the client. Claude Code, Codex, Gemini CLI or your own agent turns the user's question into SQL, calls the query tool and writes the answer. The server only executes and returns data, which keeps model costs with the client and lets you control access at one point. If MCP is new to you, our post on building an MCP server with FastMCP explains the protocol.
Two ways to connect an agent to BigQuery: MCP Toolbox on your own infrastructure or Google's managed remote MCP server
Every query runs as a normal BigQuery job, billed to a project you choose, under the identity the server uses: the token the client sends, or the Toolbox's own credentials. That makes the identity the most important design decision: whatever that service account or user may read, the agent may read.
Your options compared
| Option | Auth | Read-only and dataset scope | Per-query cost cap | Setup |
|---|---|---|---|---|
| Remote BigQuery MCP server (Google) | OAuth token of a user or service account, no API keys | execute_sql_readonly tool, IAM deny policy for write tools, dataset access only via IAM | none, only daily quotas | nothing to install |
| MCP Toolbox, prebuilt BigQuery tools | ADC, impersonation or the client's OAuth token | BIGQUERY_READONLY, no allowlist variable in the prebuilt config | BIGQUERY_MAXIMUM_BYTES_BILLED | one binary, environment variables |
MCP Toolbox, own tools.yaml | as above | readOnly, allowedDatasets, fixed SQL tools | maximumBytesBilled | one binary plus a YAML file |
| LucasHild/mcp-server-bigquery 0.3.3 | ADC or key file | dataset filter for listing only, queries are not restricted | none | uvx one-liner |
| ergut/mcp-bigquery-server 1.0.4 | ADC or key file | SELECT only (checked by dry run), optional column restrictions | 1 GB default, configurable | npx one-liner |
The rows for Google's options come from the official docs and our test; the
community servers from their READMEs and source code. LucasHild's
execute-query tool runs whatever SQL it receives, so read-only access
depends entirely on the permissions of the identity.
Our recommendation:
- For a developer who wants to explore data from Claude Code, Cursor or Gemini CLI: the remote server. Nothing to run, and IAM already knows who may see what.
- For an agent that runs unattended or serves many users: the MCP Toolbox
with your own
tools.yaml, a dataset allowlist and a bytes cap, or fixed SQL tools only. - Community servers are fine for a quick local test, but they add a third party between your agent and your warehouse without adding controls that Google's options lack.
Step 1: a dedicated service account
Do not let an agent run with your own account. Create a service account that
can run query jobs in a billing project and read only the datasets it needs.
These are the commands we ran (replace PROJECT_ID and the e-mail address):
Our test used a public dataset, which every account can read. For your own data, grant BigQuery Data Viewer on each dataset instead of the whole project. The BigQuery DCL reference shows the SQL form:
For a service account the grantee is "serviceAccount:<email>". Dataset-level
grants are the only dataset allowlist the remote server has, so they matter.
Instead of downloading a key file, mint a token that is valid for one hour:
Both servers accept this token as Authorization: Bearer ....
Option A: Google's remote BigQuery MCP server
The remote server needs no installation. According to the
docs it is
enabled together with the BigQuery API, uses Streamable HTTP, and requires
roles/mcp.toolUser plus the usual BigQuery roles. It offers nine tools:
list_dataset_ids, get_dataset_info, list_table_ids, get_table_info,
execute_sql_readonly, execute_sql, get_query_results, cancel_job and
get_job. All but execute_sql and cancel_job are marked read-only.
Google's client guide for Claude Code uses an OAuth client ID and secret
(the remote servers don't support dynamic client registration). For a
terminal setup, Claude Code's headersHelper is simpler: it runs a command at
connect time and sends its output as headers. This .mcp.json worked for us:
Claude Code reruns the helper on reconnect and after a 401 or 403, so the one-hour token is refreshed without manual steps.
Four things to know before you rely on it:
- Every query tool takes a
projectId, which is the billing project. Agents tend to pass the project that owns the data. With a public dataset that fails withUser does not have bigquery.jobs.create permission in project bigquery-public-data. In our first run, "Run every query with projectId PROJECT_ID" was not explicit enough; "Always pass projectId PROJECT_ID to execute_sql_readonly; it is the billing project" was. - There is no
maximumBytesBilledparameter. A single query can scan as much as the identity can read. The available brake is a custom quota such asQueryUsagePerUserPerDay, which is unlimited by default. execute_sql_readonlyrejects anything but SELECT (MCP execute_sql_readonly tool allows only SELECT statements.), but the agent can still callexecute_sql. Block it with an IAM deny policy on read-write MCP tools, as shown in Control MCP use with IAM, or with a tool filter in your client.- Results are limited to 3,000 rows and queries to three minutes by default.
Every job gets the label
goog-mcp-server: true, so you can find agent queries inINFORMATION_SCHEMA.JOBS.
Option B: MCP Toolbox with guardrails
The MCP Toolbox is a single Go binary. Version 1.16.0 was released on 5 November 2026:
For macOS, replace linux/amd64 with darwin/arm64. The quickest start is
the prebuilt BigQuery configuration, which the BigQuery
docs
describe for Claude Code, Cursor, VS Code and others. It exposes nine tools,
including execute_sql, forecast, analyze_contribution and
ask_data_insights, and is configured with environment variables such as
BIGQUERY_PROJECT, BIGQUERY_READONLY and BIGQUERY_MAXIMUM_BYTES_BILLED.
For an agent you want to control, write your own tools.yaml. This is the
file we used. The source carries the guardrails; the tools inherit them:
What the settings do:
readOnly: trueletsexecute_sqlrun only SELECT. The Toolbox dry-runs every query first and rejects other statement types.allowedDatasetsrejects queries that name tables outside the list, as well as statements it cannot analyze, such asCREATE FUNCTIONorEXECUTE IMMEDIATE. With a single dataset, it also becomes the default for the listing tools.maximumBytesBilledis passed to BigQuery with every job. A larger query fails before it is billed.useClientOAuth: truemakes the Toolbox use the token the client sends. Without it, the Toolbox uses Application Default Credentials (ADC), set up withgcloud auth application-default login; theimpersonateServiceAccountfield then switches to the service account.revenue_by_monthis a fixed, parameterized query. The agent supplies the year, never the SQL. In read-only mode such tools are hidden unless they are annotated withreadOnlyHint: true.kind: groupreplaces the olderkind: toolset. The group gets its own endpoint, here/mcp/analyst.
Start the server. By default it listens on 127.0.0.1:5000:
--config replaces the deprecated --tools-file, and clients connect via
Streamable HTTP at /mcp (or /mcp/analyst for the group). The old SSE
endpoint /mcp/sse is deprecated. At startup the Toolbox warns that
--allowed-origins and --allowed-hosts default to *. Set both when the
server is reachable from a browser or a network.
Test with MCP Inspector
MCP Inspector is the quickest way to see what an agent will see:
Version 2 starts with a server list. Choose "Add Servers", "Add manually",
transport streamable-http and the URL http://127.0.0.1:5000/mcp/analyst.
The Authorization header goes into the server's "Settings" under "Custom
Headers" (Inspector keeps secrets in the OS keychain). After connecting,
the Tools tab shows the four tools, each marked read-only. The description of
execute_sql already includes the allowlist, which the Toolbox adds itself:
MCP Inspector with the Toolbox's execute_sql tool, marked read-only, and a query against a dataset outside the allowlist
The query above reads a different public dataset, and the Toolbox refuses it before BigQuery runs anything:
MCP Inspector showing the Toolbox error: access to dataset bigquery-public-data.samples is not allowed
The fixed tool revenue_by_month takes only a year and returns one row per
month:
MCP Inspector showing monthly orders and revenue for 2025 returned by the revenue_by_month tool
A query over the 384 MB events table hits the 100 MB cap and is not billed:
Connect an agent
For Claude Code, the headersHelper configuration from option A works for
the Toolbox as well; only the URL changes to
http://127.0.0.1:5000/mcp/analyst. We asked Claude Code (Sonnet) for the
top five product categories by revenue in 2025, and it returned the correct
figures in three turns.
For your own application, a small Python agent with the OpenAI Agents SDK (0.24.0) is enough. This is the version we used for the test:
Run it with the token from step 1:
For the remote server, set MCP_URL to https://bigquery.googleapis.com/mcp and
add the billing project to the instructions ("Always pass projectId
PROJECT_ID to execute_sql_readonly").
Test results: seven business questions
We asked the same seven questions through both servers, first with a minimal
prompt (the first paragraph of the instructions above plus "Revenue means the
sum of order_items.sale_price"; for the remote server also "Run every query
with projectId PROJECT_ID"), then with the full instructions, the explicit
billing-project sentence and the date hint in the execute_sql description. The reference answers
come from our own SQL. The thelook data is regenerated regularly, so the
numbers will differ on another day.
| Question | Reference answer | Toolbox, run 1 → 2 | Remote server, run 1 → 2 |
|---|---|---|---|
| Orders in 2025, share cancelled or returned | 28,384, 24.9 % | correct → correct | wrong billing project, no answer → correct |
| Top five categories by revenue, completed orders 2025 | Jeans, Outerwear & Coats, Sweaters, Suits & Sport Coats, Swim | blocked by Toolbox → correct | correct → correct |
| Country with the most users, their average age | China, 33,738 users, 40.93 years | correct → correct | correct → correct |
| Average order value, completed orders Q4 2025 | 83.32 | correct → correct | correct → correct |
| Traffic source of most users with an order | Search, 56,031 | correct → correct | wrong table (Email) → correct |
| Department with the higher gross margin, 2025 | Women, 52.09 % vs. 51.84 % | blocked by Toolbox → correct | correct → correct |
| Browser used in the most sessions | Chrome, 340,268 sessions | invented 1,398,587 → events instead of sessions | correct → correct |
Run 2 in numbers:
| Server | Correct | Query jobs | Bytes processed | Bytes billed | Input tokens |
|---|---|---|---|---|---|
| MCP Toolbox | 6 of 7 | 8 (1 stopped by the cap) | 44 MB | 114 MB | 27,564 |
| Remote MCP server | 7 of 7 | 7 | 142 MB | 238 MB | 89,218 |
The whole test, both runs plus reference queries, billed about 1 GB in
BigQuery, a negligible amount. The remote server processed more
bytes because it answered the browser question, which needs 112 MB. It also
used three times as many input tokens for the same questions: its tool
descriptions are long, and get_table_info returns the full table resource
from the BigQuery API, while the Toolbox returns a compact schema.
Pitfalls we hit
The Toolbox allowlist rejects EXTRACT(YEAR FROM o.created_at). With
allowedDatasets set, Toolbox 1.16.0 parses table names from the SQL text
and reads the FROM inside EXTRACT as a table reference. The query then
fails with access to dataset 'pondhouse-docs.o' is not allowed, where o
is the table alias. EXTRACT(YEAR FROM created_at) without an alias works,
and so do date comparisons. Agents write the aliased form all the time: in
the first run, it broke two of seven questions. A hint in the tool
description fixed it. Fixed SQL tools (bigquery-sql) are not affected.
After a blocked query, the agent made up a number. The browser question ran into the 100 MB cap twice. The agent then answered "Chrome had the most sessions: 1,398,587", a number that appears in no query result. The correct value is 340,268. With the rule "never estimate or make up numbers", it instead counted events, which stays under the cap, and said so. That is better, but it still answered a slightly different question. Guardrails make queries fail, and your agent needs instructions for what to do then.
Ambiguous columns lead to plausible wrong answers. "Traffic source"
exists in users (how the customer was acquired) and in events (the source
of each visit). Through the remote server, the agent used events and
answered "Email" instead of "Search". The SQL was valid, and the answer
looked right. A one-line definition in the instructions fixed it. With
dozens of tables, you need such definitions systematically. Our post on
NVIDIA Auto Ontology shows a tool
that builds a semantic layer for text-to-SQL.
Small queries are billed at 10 MB. A query that read 1.3 MB of the
orders table was billed 10 MB (10,485,760 bytes). For many small agent
queries, bytes billed is the number that counts.
The Toolbox moves fast. Between version 0.7 (June 2025) and 1.16 the
config format, the CLI flags, the transport and toolset changed. Pin the
version and read the release notes before you update.
Security and cost checklist
- Give the agent its own service account: BigQuery Job User on the billing
project, BigQuery Data Viewer only on the datasets it needs, and
roles/mcp.toolUseronly if you use the remote server. - Use short-lived tokens through impersonation or Workload Identity instead of key files.
- Allow only read access:
readOnly: truein the Toolbox; with the remote server, an IAM deny policy for read-write tools. - Cap costs per query with
maximumBytesBilledin the Toolbox, and per day with the custom quotasQueryUsagePerDayandQueryUsagePerUserPerDay. - For production agents, prefer fixed parameterized tools over free SQL. The
Toolbox docs say
execute_sqlis meant for developer workflows with a human in the loop. - Make queries traceable: both servers label their jobs
(
goog-mcp-server: true, ormcp-toolbox-toolwith the tool type), so you can filter agent queries and their bytes billed inINFORMATION_SCHEMA.JOBS. For the remote server, enable Data Access audit logs for "Google Cloud MCP servers"; they are off by default. - Remember that query results go to the model provider. Keep sensitive columns out of reach with authorized views or column-level security.
Which BigQuery MCP server should you use?
Both servers answered business questions correctly once the agent had clear instructions. The remote server is the faster start and needs no infrastructure. You control it entirely through IAM, which is clean, but it cannot limit what a single query costs. The MCP Toolbox needs a process you operate, and in return gives you the controls an unattended agent should have: dataset allowlist, read-only mode, bytes cap and fixed SQL tools. Its allowlist parser still has rough edges, so test it with the SQL your agent actually writes.
In both cases, quality depends less on the server than on the agent's instructions and the clarity of your schema. If you want to go further with BigQuery, our posts on vector search in BigQuery and Vertex AI Agent Builder cover the neighboring building blocks.
We help companies in Austria, Germany and Switzerland give AI agents safe access to their own data, from the identity setup to evaluating the answers. If you are planning such an agent, our AI consulting is a good place to start.
Interested in building high-quality AI agent systems?
We prepared a comprehensive guide based on cutting-edge research for how to build robust, reliable AI agent systems that actually work in production. This guide covers:
- Understanding the 14 systematic failure modes in multi-agent systems
- Evidence-based best practices for agent design
- Structured communication protocols and verification mechanisms



