CountLineage

Google Analytics MCP: connect Claude to GA4 and keep it read-only

AI for data and analytics · Facts checked 28 October 2026

The Google Analytics MCP server is an experimental, open-source server from Google's Analytics team, run locally with `pipx run analytics-mcp`. It works with Claude Desktop and Claude Code, not claude.ai. Its nine default tools read GA4 through the Admin and Data APIs; one write tool stays off unless you add `--allow-write`. Grant only the `analytics.readonly` scope and a Viewer role.

Google's Analytics MCP server runs on your machine, not Google's

Google's Analytics team publishes an MCP server for GA4 at googleanalytics/google-analytics-mcp, documented on Google for Developers. The README still calls it "Experimental". It ships on PyPI as analytics-mcp; version 0.8.0 came out on 22 October 2026 (checked 28 October 2026).

Unlike BigQuery, there's no hosted endpoint. Google Cloud's list of remote MCP servers has no Analytics entry, so this one runs locally over stdio, started by Claude on your computer. That means Claude Desktop or Claude Code. Custom connectors on claude.ai need a remote server URL, and Anthropic says local servers "aren't available in Cowork or claude.ai".

It wraps two Google APIs, the Admin API and the Data API, as ten tools. Nine are read-only and on by default:

Tool What it does Reads or writes
get_account_summaries Accounts and properties you can access Reads
get_property_details One property's settings Reads
list_google_ads_links Google Ads accounts linked to a property Reads
list_property_annotations Annotations on a property Reads
get_custom_dimensions_and_metrics The property's custom fields Reads
run_report A standard Data API report Reads
run_realtime_report Realtime activity Reads
run_funnel_report A funnel exploration Reads
run_conversions_report Conversions, cost and ROAS by channel or campaign Reads
create_property_annotation Adds an annotation Writes, only with --allow-write and the edit scope

Google's developer page says the server "cannot create, modify, or delete" Analytics settings. That holds for the default install. The README also lists an annotation tool, which stays hidden unless you start the server with --allow-write.

Connect it to Claude Desktop or Claude Code in six steps

You need Python 3.10 or later, pipx, a Google Cloud project you can enable APIs in, and access to the GA4 property. The steps follow Google's setup guide, Anthropic's Claude Code MCP docs and the MCP project's local server guide for Claude Desktop.

  1. Enable the APIs. In your Cloud project, turn on the Google Analytics Admin API and Data API: gcloud services enable analyticsadmin.googleapis.com analyticsdata.googleapis.com --project=YOUR_PROJECT_ID.
  2. Grant Viewer on the property. In GA4, give the account Claude will use the Viewer role on the property it should read. Nothing higher.
  3. Create credentials. Run gcloud auth application-default login with --scopes="https://www.googleapis.com/auth/analytics.readonly,https://www.googleapis.com/auth/cloud-platform". Google's guide has variants for your own OAuth client file and for impersonating a service account. Copy the path it prints after "Credentials saved to file".
  4. Add it to Claude Desktop. Open Settings > Developer > Edit Config and add a server to claude_desktop_config.json:
{
  "mcpServers": {
    "analytics-mcp": {
      "command": "/full/path/to/pipx",
      "args": ["run", "analytics-mcp"],
      "env": {
        "GOOGLE_APPLICATION_CREDENTIALS": "/Users/you/.config/gcloud/application_default_credentials.json",
        "GOOGLE_CLOUD_PROJECT": "your-project-id"
      }
    }
  }
}

Use absolute paths throughout. Google warns that ~ and $HOME don't expand in this file, and that desktop apps may not see your shell's PATH, so take the full path from which pipx. Quit Claude Desktop completely and reopen it.

  1. Or add it to Claude Code with one command: claude mcp add analytics-mcp --scope user -e GOOGLE_APPLICATION_CREDENTIALS=/path/to/credentials.json -e GOOGLE_CLOUD_PROJECT=your-project-id -- pipx run analytics-mcp. Check it with claude mcp list or /mcp.
  2. Test with a number you already know. Ask for last week's sessions for one property and compare it with the GA4 interface.

If it fails, the errors are specific. A 403 PERMISSION_DENIED usually means an API isn't enabled or the role is missing; ACCESS_NOT_CONFIGURED means the credentials have no quota project, which GOOGLE_CLOUD_PROJECT fixes.

The setupGA4 to Claude, with a check before it shipsData stays in GA4. Claude reads it through Google's local MCP server with a read-only scope and a Viewer role, and Count audits the answer before it's shared.
  1. Analytics
    • Google Analytics 4 · one property, Viewer role
    read with the analytics.readonly scope
  2. report through approved tools
  3. audit before it ships
  4. share
  5. Where it goes
    • Dashboard
    • Board pack
    • Slack thread

GA4 answers, with the working shown

Google's MCP server gives Claude your GA4 reports. Count shows which claims in the answer trace to a report, and which rest on a metric nobody checked.

Keep it read-only with the scope and the role, not the prompt

Three settings decide what Claude can do with your GA4 data, and none of them is the prompt.

  • The scope. analytics.readonly lets the credentials read reports and settings and nothing else. Write tools need analytics.edit as well, so leave it out.
  • The role. Viewer can see settings and data. Annotations need Marketer or Editor, so a Viewer account can't write even if someone adds --allow-write to the config later.
  • The flag. Without --allow-write, the annotation tool isn't offered to Claude at all.

Google's login command also requests the cloud-platform scope alongside the read-only one. That scope is broad: it covers whatever Google Cloud APIs the account can reach, and the credentials file sits on your disk. The cleaner set-up is a service account that holds Viewer on the GA4 property and little else, impersonated with the command in Google's guide.

Two more levers are worth using. GA4's data restrictions, No Cost Metrics and No Revenue Metrics, hide those metrics from a user across reports and explorations, which helps if Claude is being used by people who shouldn't see margins. And in Claude, approve tool calls one by one. Anthropic's advice is to "only click 'Allow always' when using a server and tool that you trust to run unsupervised".

Read-only also doesn't stop leaks. Don't run the GA4 server in the same session as a connector that reads inbound email or public tickets and can post somewhere. Our BigQuery MCP guide covers the incidents that taught people this.

What the GA4 MCP server can and can't reach

Every report goes through the Google Analytics Data API, so the server inherits that API's limits. They decide whether the answer covers all your data.

Limit What happens Source
Rows 10,000 by default; up to 250,000 per request with limit, more by paging with offset Data API basics
Quota, standard property 200,000 tokens a day, 40,000 an hour, 14,000 per project per property per hour, 10 concurrent requests Data API quotas
Quota, Analytics 360 2,000,000 a day, 400,000 an hour, 140,000 per project per property per hour Data API quotas
Sampling May apply once a query needs more than 10 million events (standard) About data sampling
Thresholds Rows withheld to protect individuals, mainly with demographic data or narrow date ranges About data thresholds
(other) Low-volume dimension values grouped into one row Data API response metadata

Most requests cost 10 tokens or fewer, Google says, but long date ranges, many dimensions and high-cardinality fields like pagePath cost more. Ask Claude to set return_property_quota if a session is heavy.

What it can reach: anything you can build from the Data API's dimensions and metrics, your custom definitions, the realtime view, funnels and the conversions report. The conversions tool is narrower than it looks. It accepts only 12 dimensions, such as sessionSourceMedium and campaignName, and metrics like cost, conversions and ROAS by conversion date or by interaction date.

What it can't reach: individual events, user journeys row by row, or any field the API doesn't expose. It answers with aggregates GA4 has already computed, and that's the main reason to look at the BigQuery export below.

Prompts that make Claude say which GA4 numbers it used

Each of these pins the definition, asks Claude to name the exact API fields and makes it report the response metadata. The property ID is illustrative.

Map the property first:

Using the analytics-mcp tools, list the properties I can access. For property
123456789, give its time zone, currency, and any custom dimensions and metrics.
Don't run any reports yet.

Ask for a metric with the field names fixed:

Report sessions, activeUsers and totalUsers for property 123456789 for
September 2026, by sessionDefaultChannelGroup. Name every dimension and metric
you request. After the table, tell me rowCount, and whether the response said
subjectToThresholding, dataLossFromOtherRow or included samplingMetadatas.

Explain a change without guessing:

Conversions from paid search fell from August to September. Use
run_conversions_report with LAST_CLICK, then again with DATA_DRIVEN, by
campaignName. Show both. If the two models disagree about which campaign
caused the drop, say so rather than choosing one.

Catch a truncated result:

Before you answer, compare rowCount with the number of rows returned. If
rowCount is larger, page through with offset or aggregate further, and
run it again.

The last prompt matters most with pagePath or landingPage, where 10,000 rows can run out fast.

Where Claude misreads GA4 numbers

The API returns correct numbers. The mistakes come when Claude picks the wrong one or describes it loosely.

Users isn't one metric. GA4 has totalUsers (anyone who logged an event), activeUsers (engaged users) and newUsers. The interface's "Users" is active users, so a summary that adds up total users won't match the report your team looks at. Google also notes that new users can exceed active users.

Sessions and users answer different questions. sessionSource is the source that started a session; firstUserSource is the one that first brought the user. A question like "which channel drives sign-ups" has different answers depending on which Claude reaches for, and it rarely says. Ask it to name the field. The same goes for rates: sessionKeyEventRate and userKeyEventRate have different denominators. Our conversion rate guide covers why that matters.

Attribution moves. The conversions report takes an attribution model, data-driven or last click, and gives different credit under each. Data-driven credit can be reattributed for up to 7 days after a conversion, so last week's figures can shift when you ask again. Google retired first click, linear, time decay and position-based models in November 2023, so if Claude offers one, it's remembering, not reading. For spend metrics, see return on ad spend.

Thresholds and (other) hide rows silently. Withheld rows don't show up as zeros. They're missing, and totals across rows come out low. The response says so in subjectToThresholding and dataLossFromOtherRow, but Claude won't mention either unless you ask.

(not set) is a tagging fault, not a channel. Google defines it as "a placeholder name that Analytics uses when it hasn't received any information for a dimension". On source and medium it usually means a missing session_start; on Google Ads rows, an unlinked account, auto-tagging switched off or broken UTMs. Claude may describe it as a traffic source. It's a fix for whoever owns your tags.

Unique counts are estimates. For unsampled reports, Google uses HyperLogLog++ to estimate distinct counts such as users and sessions. Small differences between the API, the interface and BigQuery are normal.

When to use the BigQuery export instead

The MCP server suits questions GA4 already answers: traffic by channel, a funnel, last month's conversions. Switch to the GA4 BigQuery export, queried through Google's BigQuery MCP server, when you need any of these:

  • Raw events. The export holds "all the raw, unsampled event data", one row per event, so you can rebuild a user's path or define a session your own way.
  • Joins. Revenue from your billing system, plan from your CRM or cost from another ad platform. GA4 can't join to tables it doesn't hold.
  • Bigger questions. No Data API token quota and no sampling. BigQuery's MCP server caps results at 3,000 rows, though, so ask Claude to aggregate in SQL.

It has its own catches. Standard properties have a daily export limit of 1 million events, and the export pauses if you keep going over. Streaming export has no event limit but is best-effort and billed at $0.05 per gigabyte. Data from Google signals isn't exported. Once data has been exported, Google says, "you cannot re-export it". And data starts arriving within 24 hours of linking; Google's set-up page describes no backfill of earlier days, so link the export before the day you need it.

Expect the export not to match the interface exactly. You're writing the session and user logic in SQL, and GA4 isn't. That's the point, and also the risk: Claude's SQL becomes the definition.

Two minutes with the tool calls before you share the number

Claude Desktop and Claude Code both show each tool call. Expand them before you trust the answer.

  1. Which tool ran? run_report for standard questions, run_conversions_report for attribution. If create_property_annotation appears, the server was started with --allow-write; find out why.
  2. Read the request. Check the property ID, the date range (in the property's time zone) and the exact dimensions and metrics. totalUsers and activeUsers aren't interchangeable.
  3. Check the metadata. rowCount higher than the rows returned means truncation. subjectToThresholding, dataLossFromOtherRow or samplingMetadatas mean the total is incomplete or estimated.
  4. Open the same report in GA4 and compare one figure.
  5. Ask: "Which numbers came from a tool result, and which did you calculate afterwards?" Ratios Claude works out from two reports are where small errors creep in. Our guide to checking AI answers has more.

For a number going into a board pack, Count makes this systematic. Connect Count's MCP server to Claude alongside the GA4 server and ask it to audit the answer. It returns a link to a canvas with every claim labelled (Citation, Assumption, Model knowledge, Hallucination) and a reasoning chain under each, showing the reports and calculations it rests on. A conversion rate built on total users when your team uses active users shows up in the chain, not in a footnote.

Questions people ask

Is there an official Google Analytics MCP server?

Yes. Google's Analytics team maintains googleanalytics/google-analytics-mcp on GitHub, documented on Google for Developers and published on PyPI as analytics-mcp. The README labels it experimental. It runs locally; Google doesn't host a remote endpoint for it as it does for BigQuery.

How do I connect Claude to GA4?

Enable the Analytics Admin and Data APIs, give your account Viewer on the property, create credentials with gcloud auth application-default login and the analytics.readonly scope, then add pipx run analytics-mcp to Claude Desktop's config file or with claude mcp add in Claude Code.

Can the Google Analytics MCP server change my GA4 settings?

Not by default. Nine of its ten tools are read-only. The tenth, create_property_annotation, appears only when the server runs with --allow-write and the credentials carry the analytics.edit scope. A Viewer role blocks it too.

Does the GA4 MCP server work on claude.ai?

No. It's a local server, and claude.ai custom connectors need a remote MCP URL. Use Claude Desktop or Claude Code.

Should I use the GA4 MCP server or the BigQuery export?

Use the MCP server for questions GA4's reports already answer. Use the BigQuery export, through Google's BigQuery MCP server, when you need raw events, joins to other data or results without sampling and row limits.

Sources

  1. Google for Developers: Try the Google Analytics MCP server (checked 28 October 2026)
  2. GitHub: googleanalytics/google-analytics-mcp README and source (checked 28 October 2026)
  3. PyPI: analytics-mcp release history (0.8.0, 22 October 2026)
  4. Google Cloud: Supported products for remote MCP (checked 28 October 2026)
  5. Google Analytics Data API: Quotas
  6. Google Analytics Data API: Basics (pagination)
  7. Google Analytics Data API: ResponseMetaData
  8. Google Analytics Data API: API dimensions and metrics
  9. Google Analytics Help: About data sampling
  10. Google Analytics Help: About data thresholds
  11. Google Analytics Help: What the value (not set) means
  12. Google Analytics Help: Understand user metrics
  13. Google Analytics Help: Get started with attribution
  14. Google Analytics Help: Access and data-restriction management
  15. Google Analytics Help: BigQuery Export
  16. Google Analytics Help: Set up BigQuery Export
  17. Claude Code docs: Connect Claude Code to tools via MCP (checked 28 October 2026)
  18. Model Context Protocol: Connect to local MCP servers (Claude Desktop)
  19. Anthropic Help Centre: Getting started with custom connectors using remote MCP (checked 28 October 2026)

Early access

Count Lineage isn't ready to download yet.

Count Lineage is coming to Claude Desktop in the next few weeks. Leave your work email and we'll send you the download the day it's ready.

Where should Lineage go after Claude? Optional

One email when it's ready. No newsletter.