You can wire Claude straight into BigQuery with MCP, and once you do, "export a CSV and paste it into chat" stops being your workflow.

Here's the practical setup, and the parts the quick tutorials skip.

What the BigQuery MCP server does

Claude doesn't talk to BigQuery directly. It talks to a BigQuery MCP server, and the server holds the connection and exposes a few tools: run a query, list tables, describe a schema.

Concretely, you type a question, Claude calls run_query with SQL it wrote, the server executes it under your service account, and the rows come back into the chat. Claude never sees the key.

That separation is the whole point, and it's what lets you reason about safety.

What you need first

A GCP project with BigQuery, and a service account scoped to the job: BigQuery Data Viewer and Job User on the specific dataset, not project-wide owner.

Enable the BigQuery API on the project, and note the dataset location you'll query, US or EU, because a mismatched location is the first error most setups hit.

Then an MCP client like Claude Desktop, and a BigQuery MCP server. Google's MCP Toolbox for Databases supports BigQuery, and there are community npm servers that do the same.

The config

You point the client at the server in its config file. In Claude Desktop that's claude_desktop_config.json:

{
  "mcpServers": {
    "bigquery": {
      "command": "npx",
      "args": ["-y", "your-bigquery-mcp-server",
               "--project-id", "your-project",
               "--location", "US"],
      "env": {
        "GOOGLE_APPLICATION_CREDENTIALS": "/path/to/service-account.json"
      }
    }
  }
}

Restart the client so it picks up the server.

Give it the right tools, not all of them

A good BigQuery MCP server lets you choose which tools are live. Turn on run_query, list_tables, and describe_schema. Leave anything that writes, creates, or drops switched off.

Read-only tools plus a read-only service account is belt and braces, and that's exactly the posture you want when the caller is a model.

Point it at modeled tables, not raw exports

The raw GA4 export is where models write confident nonsense, thanks to nested fields and event scope. If you have clean sessions and metrics tables from Dataform or dbt, expose those instead.

Claude answers far better over a tidy layer than over events_YYYYMMDD, because the hard modeling work is already done.

Test it before you trust it

Ask Claude to list the datasets, then run a small bounded query on one table. If it returns real rows and names the tool it used, the connection works.

Then ask a question that needs a join across two tables. If it wires the join correctly and the number reconciles with a figure you already know, you're in business.

Scope access with an authorized view

If you don't want the model to see every column, put an authorized view over the sensitive tables and grant the service account access to the view, not the base table. The model queries the view and never touches the raw PII underneath.

This is the difference between "Claude can read our warehouse" and "Claude can read the three views we decided are safe," and it's worth the extra ten minutes.

Cost is the failure mode nobody plans for

Set maximum_bytes_billed on the server so a careless query fails instead of scanning a terabyte. A dry run first, to show the bytes a query would read, is cheap insurance.

Watch the query logs for the first week. You're looking for the accidental full-table scan, not for anything malicious. Start with one dataset and two or three views; you can widen access later, but you can't un-leak a table the model already read into a chat.

Once the server is in place, Claude queries BigQuery directly and you stop shuttling CSVs by hand. Just remember the server carries your access, so scope it like an account, not like a chat toy.

Want a stronger data analyst role or a raise? Grab the FREE Product Analyst Playbook and get the exact roadmap to your next offer.