DEV Community

Kulma Co
Kulma Co

Posted on

Using the GA4 MCP Server with Python: A Practical Guide

Using the GA4 MCP Server with Python: A Practical Guide

I've worked with Google Analytics for about seven years. The Data API is a tool I reach for constantly, but writing a one-off query has always been more friction than the answer was worth. Spin up a notebook, find the credentials, look up the dimension names, build the request, format the output. By the time you have an answer, you've forgotten what you wanted to know.

The Model Context Protocol changes that math. With an MCP server in front of GA4, you can ask Claude or Cursor "what were my top traffic sources last week?" and get a real answer pulled from your actual property. No notebook. No request body. Just a question.

Here's how to set it up with Google's official MCP server, plus the pieces that tripped me up the first time.

What you'll need

  1. A GA4 property and its numeric Property ID (not the Measurement ID that starts with G-).
  2. Python 3.10 or higher.
  3. An MCP-compatible client. I'll show Claude Desktop; the config translates directly to Claude Code or Cursor.

Install the server

Google publishes the server as analytics-mcp. Use pipx to keep dependencies isolated:

pip install pipx
pipx ensurepath
pipx install analytics-mcp
Enter fullscreen mode Exit fullscreen mode

If you're on Windows with Miniconda like I am, pipx works fine, but make sure your MCP client points at the exact Python binary inside the env you installed into. I lost an hour the first time chasing a "module not found" error that was really a "wrong interpreter" error.

Authenticate

Install the Google Cloud CLI, then:

gcloud auth application-default login \
  --scopes https://www.googleapis.com/auth/analytics.readonly
Enter fullscreen mode Exit fullscreen mode

This writes credentials the MCP server reads automatically. For production or anything long-running, use a service account instead: create one in Google Cloud Console with the Analytics Data API enabled, download the JSON key, and grant the service account email Viewer access on your GA4 property in Admin → Property access management. The key file authenticates you to Google, but GA4 still needs to know that specific email is allowed to read your property. That second step is what catches most people.

Wire it into Claude Desktop

Edit claude_desktop_config.json (under ~/Library/Application Support/Claude/ on macOS, %APPDATA%\Claude\ on Windows):

{
  "mcpServers": {
    "analytics-mcp": {
      "command": "pipx",
      "args": ["run", "analytics-mcp"],
      "env": {
        "GOOGLE_APPLICATION_CREDENTIALS": "/full/path/to/your/key.json",
        "GOOGLE_PROJECT_ID": "your-gcp-project-id"
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Drop the GOOGLE_APPLICATION_CREDENTIALS line if you used gcloud auth instead of a service account.

Fully quit Claude Desktop and relaunch. Not just close the window. On Windows, check Task Manager. MCP servers only load on cold start.

Your first query

Open a new chat:

Using the analytics-mcp tools, list my Google Analytics accounts and properties.

Claude should call get_account_summaries and reply with your accounts. If you see the tool call, you're set. If Claude says it can't see any tools, the server isn't loading, which is almost always a bad path or an incomplete restart.

Then try a real report:

For property 123456789, what were the top 5 traffic sources by sessions over the last 14 days?

Claude calls run_report with sessionDefaultChannelGroup, sessions, and a 14-day window. Clean answer, ten seconds. The first time this worked for me I sat there a little stunned.

Gotchas worth knowing

Property ID, not Measurement ID. The number you want is the nine-digit one. Anything starting with G- gets you confusing empty results.

Scopes matter. If you ran gcloud auth without the analytics scope, errors won't clearly say "wrong scope." Re-run with the --scopes flag above.

Sampling is invisible. The server will happily return sampled data without flagging it. For weekly-traffic questions you'll never notice. For a small segment over a long window, sanity-check against the GA4 UI before quoting numbers in a meeting.

Realtime is a separate tool. run_realtime_report covers the last 30 minutes; run_report does everything else. If Claude reaches for the wrong one, redirect it.

Where this stops being enough

MCP is excellent for the question you remember to ask. For analytics work where you're already in a flow state ("did traffic actually change after this launch?"), it's a real time-saver.

But MCP is pull, not push. It assumes you remember to look. The pattern I keep seeing, in my own habits and at work, is that the people who most need GA4 insight are the ones least likely to open a chat window on a Monday morning and ask. They set up GA4, configure their goals, and never log in.

That's the gap I built Kulma to fill. Weekly email brief for GA4 properties: pulls your data on a schedule, surfaces what actually changed week over week, explains it in plain language, lands in your inbox Monday morning. Same kind of plain-English summary you'd get from a well-prompted MCP query, except you don't have to remember to ask.

I use both. MCP for the questions I want to chase down. Kulma for the baseline awareness that makes me know which questions to chase.

If you run into setup trouble, the two issues that get 90% of people are the wrong Python interpreter (especially on Windows) and the service account email not being added to the GA4 property. Check those first.

Top comments (0)