---
title: "Google Analytics MCP: Setup for Cursor, Claude, Codex"
slug: "google-analytics-mcp-cursor-claude-codex-setup"
published: "2026-06-22"
updated: "2026-06-24"
validated: "2026-06-24"
categories:
  - "Tools"
tags:
  - "Google Analytics MCP"
  - "analytics-mcp"
  - "GA4 setup"
  - "pipx analytics-mcp"
  - "service account GA4"
  - "OAuth ADC GA4"
  - "Cursor MCP configuration"
  - "Claude Code MCP"
  - "Codex MCP"
  - "analytics.readonly scope"
  - "Google Analytics Data API"
  - "GA4 Viewer access"
llm-intent: "reference"
audience-level: "intermediate"
framework-versions:
  - "python@3.10+"
  - "pipx@1.x"
  - "analytics-mcp@latest"
  - "gcloud@latest"
  - "Google Analytics Data API v1 (GA4)"
  - "Google Analytics Admin API v1"
status: "stable"
llm-purpose: "Google Analytics MCP enables Cursor, Claude Code, and Codex to query GA4. Learn pipx install, service-account and OAuth configs, verify Viewer access…"
llm-prereqs:
  - "Access to analytics-mcp"
  - "Access to pipx"
  - "Access to Python 3.10+"
  - "Access to Google Cloud Console"
  - "Access to gcloud CLI"
llm-outputs:
  - "Completed outcome: Google Analytics MCP enables Cursor, Claude Code, and Codex to query GA4. Learn pipx install, service-account and OAuth configs, verify Viewer access…"
---

**Summary Triples**
- (analytics-mcp, install, pipx run analytics-mcp (run anywhere with Python/pipx; keeps environment isolated))
- (GA4 read access, required scope, analytics.readonly (used by the MCP to run reports and list properties))
- (Service account, access setup, Create service account -> add as principal to GA4 property with Viewer role -> download JSON key -> set GOOGLE_APPLICATION_CREDENTIALS)
- (OAuth (developer user auth), alternative auth, Create OAuth client in Google Cloud -> use interactive login with analytics-mcp -> uses analytics.readonly)
- (Verify server, sanity checks, Run get_account_summaries and run_report endpoints to confirm property listing and queries)
- (Client configs, differs per client, Cursor, Claude Code and Codex each require updating their MCP client config to point to your analytics-mcp URL/port)
- (Permissions errors, common cause, User/service-account lacks Viewer access on the GA4 property or wrong property ID used in requests)
- (Realtime and funnel reports, supported endpoints, analytics-mcp exposes run_realtime_report, run_funnel_report, run_report, and admin endpoints)
- (Deployment, options, Run analytics-mcp locally for development or host on a server; adjust client configs accordingly)
- (Buildwithmatija repo, provides, Example client patches and a script that applies Cursor, Claude Code, and Codex configs together (used by the author))

### {GOAL}
Google Analytics MCP enables Cursor, Claude Code, and Codex to query GA4. Learn pipx install, service-account and OAuth configs, verify Viewer access…

### {PREREQS}
- Access to analytics-mcp
- Access to pipx
- Access to Python 3.10+
- Access to Google Cloud Console
- Access to gcloud CLI

### {STEPS}
1. Enable GA4 Admin and Data APIs
2. Choose credentials path (Service Account)
3. Choose credentials path (OAuth/ADC)
4. Smoke-test analytics-mcp with pipx
5. Add MCP server config for Cursor
6. Register analytics-mcp for Claude and Codex
7. Use repo setup script (optional)
8. Verify GA4 Viewer access and run reports

<!-- llm:goal="Google Analytics MCP enables Cursor, Claude Code, and Codex to query GA4. Learn pipx install, service-account and OAuth configs, verify Viewer access…" -->
<!-- llm:prereq="Access to analytics-mcp" -->
<!-- llm:prereq="Access to pipx" -->
<!-- llm:prereq="Access to Python 3.10+" -->
<!-- llm:prereq="Access to Google Cloud Console" -->
<!-- llm:prereq="Access to gcloud CLI" -->
<!-- llm:output="Completed outcome: Google Analytics MCP enables Cursor, Claude Code, and Codex to query GA4. Learn pipx install, service-account and OAuth configs, verify Viewer access…" -->

# Google Analytics MCP: Setup for Cursor, Claude, Codex
> Google Analytics MCP enables Cursor, Claude Code, and Codex to query GA4. Learn pipx install, service-account and OAuth configs, verify Viewer access…
Matija Žiberna · 2026-06-22

If you have a GA4 property and want Cursor, Claude Code, or Codex to query it directly, connect the [official Google Analytics MCP server](https://github.com/googleanalytics/google-analytics-mcp) (`analytics-mcp`). Access is read-only through the `analytics.readonly` scope, so the agent can run reports and list properties but never touch your configuration or your data. The setup is the same `pipx run analytics-mcp` process everywhere; only the client config file changes between Cursor, Claude Code, and Codex.

I run this server across all three clients on the buildwithmatija repo, and Google's own README only documents the Gemini and Claude Code paths. This guide adds the Cursor and Codex configs I use day to day, plus a setup script that patches all three at once if you're working in this repo.

## What the server gives you

The tools are backed by the [Google Analytics Admin API](https://developers.google.com/analytics/devguides/config/admin/v1) and [Google Analytics Data API](https://developers.google.com/analytics/devguides/reporting/data/v1):

| Tool | Purpose |
|------|---------|
| `get_account_summaries` | List GA accounts and properties your credentials can access |
| `get_property_details` | Return metadata for a property (timezone, currency, etc.) |
| `list_google_ads_links` | List Google Ads account links for a property |
| `run_report` | Run standard GA4 reports (dimensions, metrics, date ranges) |
| `run_funnel_report` | Run funnel reports |
| `get_custom_dimensions_and_metrics` | List custom dimensions and metrics on a property |
| `run_realtime_report` | Realtime activity, typically the last 30 minutes (GA360 properties can report up to 60 minutes) |

## Two things you need before you start

Keep these separate in your head, because mixing them up is where most setups stall:

1. **A Google Cloud project** with the Admin API and Data API enabled.
2. **GA4 Viewer access** for whichever identity you authenticate with. Enabling the APIs in GCP grants nothing in GA4 on its own. You still have to add that identity inside GA4's own access management screen.

You'll also need Python 3.10+, [pipx](https://pipx.pypa.io/stable/#install-pipx) to run `analytics-mcp` in an isolated environment, and one auth path: a service account JSON for headless setups, or OAuth through Application Default Credentials for local dev. The [Google Cloud SDK](https://cloud.google.com/sdk/docs/install) is optional and only needed for the OAuth path.

## Step 1: Enable the APIs

In [Google Cloud Console](https://console.cloud.google.com/), enable the [Admin API](https://console.cloud.google.com/apis/library/analyticsadmin.googleapis.com) and [Data API](https://console.cloud.google.com/apis/library/analyticsdata.googleapis.com) on your project, or run:

```bash
# File: terminal
gcloud config set project YOUR_GCP_PROJECT_ID
gcloud services enable analyticsadmin.googleapis.com analyticsdata.googleapis.com
```

This step only touches GCP. GA4 access still happens in Step 5.

## Step 2: Set up credentials

Pick one of these two paths. Don't run both.

### Option A: Service account JSON (headless setups)

This is the fastest path for a server, but it produces a long-lived key file. Store it outside version control, restrict its permissions, and rotate it the moment you suspect it's exposed. Google's own README favors [service account impersonation](https://cloud.google.com/docs/authentication/use-service-account-impersonation) over a downloaded key for production use, and that's worth following once you move past local testing.

1. In GCP, go to **IAM & Admin → Service Accounts → Create service account** (for example, `analytics-mcp-reader`).
2. Under **Keys → Add key → JSON**, download the file somewhere gitignored, like `keys/gc-service-key.json`.
3. In **GA4 → Admin → Property access management**, add the service account email (`…@….iam.gserviceaccount.com`) as **Viewer**.
4. Point `GOOGLE_APPLICATION_CREDENTIALS` at that file:

```bash
# File: terminal
export GOOGLE_APPLICATION_CREDENTIALS="/absolute/path/to/service-account.json"
```

You'll reuse this same path in every client config below.

### Option B: OAuth user credentials (local development)

1. Create an [OAuth desktop client](https://support.google.com/cloud/answer/15549257) in GCP and download the client JSON, for example `oauth-client.json`.
2. Log in with Application Default Credentials, scoped to read-only analytics access:

```bash
# File: terminal
gcloud config set project YOUR_GCP_PROJECT_ID
gcloud services enable analyticsadmin.googleapis.com analyticsdata.googleapis.com

gcloud auth application-default login \
  --scopes https://www.googleapis.com/auth/analytics.readonly,https://www.googleapis.com/auth/cloud-platform \
  --client-id-file=/absolute/path/to/oauth-client.json
```

3. gcloud prints the path to the credentials it saved:

```text
Credentials saved to file: [/home/you/.config/gcloud/application_default_credentials.json]
```

That printed ADC path is what goes into `GOOGLE_APPLICATION_CREDENTIALS` for every client config. The OAuth client JSON from step 1 only exists to run the login command itself; once you've logged in, it has no further role in any config file. Your Google account also needs Viewer access on the GA4 property, granted inside GA4 directly.

## Step 3: Smoke-test the server

```bash
# File: terminal
pipx run analytics-mcp
```

You should see:

```text
Starting MCP Stdio Server: Google Analytics MCP Server
```

The process sits there waiting on stdio, which is normal for an MCP server. Ctrl+C to exit.

Three environment variables are required for every client:

| Variable | Purpose |
|----------|---------|
| `GOOGLE_APPLICATION_CREDENTIALS` | Path to the service account JSON or ADC file |
| `GOOGLE_PROJECT_ID` | Your GCP project ID |
| `GOOGLE_CLOUD_PROJECT` | Same project ID again |

A quick test with explicit env vars:

```bash
# File: terminal
GOOGLE_APPLICATION_CREDENTIALS="/absolute/path/to/credentials.json" \
GOOGLE_PROJECT_ID="YOUR_GCP_PROJECT_ID" \
GOOGLE_CLOUD_PROJECT="YOUR_GCP_PROJECT_ID" \
pipx run analytics-mcp
```

If `pipx` isn't on your PATH, use the full path, something like `/home/you/.local/bin/pipx`.

## Step 4: Wire it into each client

Every client uses the same command (`pipx`), the same args (`["run", "analytics-mcp"]`), and the same three env vars. Only the file format changes. Restart the client after editing its config.

### Cursor

Edit `.cursor/mcp.json` at your project root, or the global MCP settings inside Cursor:

```json
{
  "mcpServers": {
    "analytics-mcp": {
      "command": "/home/you/.local/bin/pipx",
      "args": ["run", "analytics-mcp"],
      "env": {
        "GOOGLE_APPLICATION_CREDENTIALS": "/absolute/path/to/credentials.json",
        "GOOGLE_PROJECT_ID": "YOUR_GCP_PROJECT_ID",
        "GOOGLE_CLOUD_PROJECT": "YOUR_GCP_PROJECT_ID"
      }
    }
  }
}
```

If you already have other servers configured, merge this entry into the existing `mcpServers` object rather than replacing the file.

Restart Cursor, then try:

```text
What can the analytics-mcp server do?
List my Google Analytics properties
```

### Claude Code

Add the same shape to `.mcp.json` at the repo root, or register it through the CLI:

```bash
# File: terminal
claude mcp add analytics-mcp \
  --scope user \
  -e "GOOGLE_APPLICATION_CREDENTIALS=/absolute/path/to/credentials.json" \
  -e "GOOGLE_PROJECT_ID=YOUR_GCP_PROJECT_ID" \
  -e "GOOGLE_CLOUD_PROJECT=YOUR_GCP_PROJECT_ID" \
  -- pipx run analytics-mcp
```

Start a new session and run the same verification prompts as above.

### Codex

Edit `~/.codex/config.toml` for a user-wide setup, or `.codex/config.toml` inside the project. Codex uses a `[mcp_servers.<name>]` table, per the [Codex MCP configuration docs](https://developers.openai.com/codex/mcp/):

```toml
# File: ~/.codex/config.toml
[mcp_servers.analytics-mcp]
command = "pipx"
args = ["run", "analytics-mcp"]

[mcp_servers.analytics-mcp.env]
GOOGLE_APPLICATION_CREDENTIALS = "/absolute/path/to/credentials.json"
GOOGLE_PROJECT_ID = "YOUR_GCP_PROJECT_ID"
GOOGLE_CLOUD_PROJECT = "YOUR_GCP_PROJECT_ID"
```

On a laptop using OAuth/ADC, point the credentials path at your ADC file:

```toml
GOOGLE_APPLICATION_CREDENTIALS = "/home/you/.config/gcloud/application_default_credentials.json"
```

Restart Codex, then ask:

```text
What can the analytics-mcp server do?
What are the most popular events in the last 30 days?
```

## A shortcut, if you're working in the buildwithmatija repo

This repo ships `scripts/setup-google-analytics-mcp.sh`, which patches `.cursor/mcp.json`, `.mcp.json`, and `~/.codex/config.toml` in a single run:

```bash
# File: terminal

# Service account JSON (headless / server)
./scripts/setup-google-analytics-mcp.sh keys/gc-service-key.json

# OAuth desktop client (browser login)
./scripts/setup-google-analytics-mcp.sh /path/to/oauth-client.json
```

In service account mode, it writes the key path straight into `GOOGLE_APPLICATION_CREDENTIALS`. In OAuth mode, it uses the client JSON only to run `gcloud auth application-default login`, then writes the resulting ADC path into the configs. The script prints the API enablement links and the service account email to add in GA4 when relevant. Restart Cursor, Claude Code, and Codex once it finishes. This script is specific to this repo; on any other machine, follow Steps 1 through 4 directly.

## Step 5: Confirm GA4 access for real

This is the step people skip, and it's the most common reason the server connects but returns nothing. Enabling the GCP APIs never grants GA4 access by itself. Whatever identity you configured in Step 2 needs Viewer access inside GA4's own access management screen.

| Auth path | Who needs Viewer on the GA4 property |
|-----------|--------------------------------------|
| OAuth / ADC | Your Google account, the one used during `gcloud auth application-default login` |
| Service account JSON | The service account email (`…@….iam.gserviceaccount.com`) |

Add it under **GA4 → Admin → Property access management → +**, with role **Viewer**. Without this, `get_account_summaries` can return empty results or permission errors even when every GCP API shows as enabled.

## Verifying the setup

| Check | Expected result |
|-------|------------------|
| `pipx run analytics-mcp` | "Starting MCP Stdio Server…" |
| MCP tools visible in the client | `get_account_summaries`, `run_report`, and the rest |
| "List my Google Analytics properties" | Your property name and ID come back |
| `run_report` on a date range | Rows with actual metrics |

The first prompt worth running confirms access before you ask anything analytical:

```text
Use analytics-mcp to list the GA4 properties I can access. Then tell me which property ID I should use for my site.
```

A few more to try once that works:

```text
What can the analytics-mcp server do?
List my Google Analytics properties
What are the top 20 events in the last 90 days?
How many page views did /tools/cms-picker get in the last 30 days?
```

## Troubleshooting

| Symptom | Likely cause | Fix |
|---------|--------------|-----|
| MCP tools not listed in Cursor | Server didn't reload after a config change | Restart Cursor and validate the JSON in `.cursor/mcp.json` |
| `get_account_summaries` returns empty | The configured identity lacks GA4 Viewer | Add Viewer access for your Google account (OAuth) or the service account email |
| `403` / permission denied | APIs disabled, or the wrong GCP project ID | Enable the Admin and Data APIs, and check `GOOGLE_PROJECT_ID` |
| `pipx: command not found` | pipx isn't on PATH | Use the full path, e.g. `/home/you/.local/bin/pipx` |
| Auth works in the terminal but not in the IDE | The MCP process started before the config update | Fully restart the client and open a new session |
| Confusion right after OAuth login | The OAuth client JSON got used as the credentials path | Use the ADC path gcloud printed, not the OAuth client JSON |
| `Precondition check failed` in logs | Google auth boundary noise | Usually harmless if reports still return data |
| Report fails: "11 metrics" | The Data API caps requests at 10 metrics | Split the request into two `run_report` calls |
| Funnel fails on `pagePath` | The Funnel API doesn't support `pagePath` in steps | Use `pageLocation` with a CONTAINS filter |

## Security notes

Treat the credentials here the same way you'd treat any production secret. Never commit service account keys, OAuth client JSON, or ADC files to version control. Grant Viewer only on the GA4 property, never Editor or Administrator. Use a dedicated service account per environment rather than reusing one across projects. For production or CI, lean toward service account impersonation or workload identity instead of a long-lived downloaded key whenever your setup allows it.

## What this setup doesn't cover

This server reads GA4 data that already exists; it doesn't create it. It won't install GA4 tracking on your site, so you still need gtag, GTM, or an equivalent. It won't create custom events or mark key events inside GA4. Every tool is read-only, so nothing here writes back to your property, and none of it replaces the GA4 UI for complex explorations or exports. For funnel tracking, lead attribution, or conversion analysis, instrument those events in your application first. The MCP server can only read what GA4 has already collected.

## FAQ

**Does this MCP server work the same way across Cursor, Claude Code, and Codex?**
Yes. The underlying `analytics-mcp` process, the command, and the three environment variables are identical. Only the config file format changes: JSON for Cursor and Claude Code, TOML for Codex.

**Can this server modify my GA4 property or data?**
No. Access is scoped to `analytics.readonly`, so every tool listed here reads data without the ability to change configuration, events, or settings.

**Should I use a service account or OAuth?**
Service account JSON is the simpler choice for headless or server environments, since there's no browser login step. OAuth through Application Default Credentials fits local development better, especially if you're already authenticated with `gcloud` for other work.

**Why does `get_account_summaries` return nothing even though I enabled the APIs?**
GCP API enablement and GA4 property access are managed separately. Add the relevant identity, your Google account or your service account email, as Viewer inside GA4's own access management screen.

**Why did a report fail with a metrics limit error?**
The GA4 Data API allows a maximum of 10 metrics per `run_report` call. If you need more, split the request into two separate calls and combine the results yourself.

## Wrapping up

Once the server is wired into your client of choice, GA4 questions stop requiring a trip to the Analytics UI. You can ask for top events, page view counts on a specific path, or which properties a given credential can see, all from inside Cursor, Claude Code, or Codex. The setup is identical everywhere except for the config file format, and the one step that trips people up is GA4 Viewer access, which lives outside GCP entirely.

Let me know in the comments if you have questions, and subscribe for more practical development guides.

Thanks,
Matija

## LLM Response Snippet
```json
{
  "goal": "Google Analytics MCP enables Cursor, Claude Code, and Codex to query GA4. Learn pipx install, service-account and OAuth configs, verify Viewer access…",
  "responses": [
    {
      "question": "What does the article \"Google Analytics MCP: Setup for Cursor, Claude, Codex\" cover?",
      "answer": "Google Analytics MCP enables Cursor, Claude Code, and Codex to query GA4. Learn pipx install, service-account and OAuth configs, verify Viewer access…"
    }
  ]
}
```