Skip to main content
Glama
devopsbrandmirchi

GA4 Analytics MCP V3

README.md
# GA4 Analytics MCP V3

True Model B connector: one MCP operator can own multiple independent Google OAuth connections. Each GA4 query is executed with the Google credential that has access to that property.

This is a new application. It does not modify V2 and does not use Firestore `(default)` (reserved for V1).

## Local development

```powershell
cd D:\MCP_Servers\Ga4McpV3
npm install
copy .env.example .env.local
# Fill secrets. Set FIRESTORE_DATABASE_ID=ga4-mcp-v3 (never (default)).
npm test
npm run dev
```

- App: `http://localhost:3000`
- MCP: `http://localhost:3000/mcp`
- Health: `http://localhost:3000/health`

## Claude Custom Connector

URL: `https://<v3-host>/mcp`

1. Claude starts MCP OAuth 2.1 (same V2 flow).
2. The first Google sign-in **bootstraps** an internal `operatorId`.
3. After that, connect additional Google Accounts from the connections page or `ga4_start_google_connection`.
4. The MCP JWT `sub` is always `operatorId`, never a Google OpenID `sub`.

## Connect a second or third Google Account

From Claude, call `ga4_start_google_connection` and open the returned URL. Or use **Connect another Google Account** on the connections page during authorize. Each authorization is an independent OAuth identity.

## Property routing

```text
property_id → this operator's ga4_properties row → connection_id → encrypted refresh token → GA4 API
```

The server never uses the current browser Google login, Claude email, or property name to pick a credential.

## Operator isolation

Operator A cannot load Operator B's connections by guessing a `connectionId`. Ownership is checked server-side on every sensitive operation.

## Cloud Run

```powershell
.\scripts\cloud-run-setup.ps1 -ProjectId YOUR_PROJECT_ID
.\scripts\cloud-run-deploy.ps1 -ProjectId YOUR_PROJECT_ID
.\scripts\cloud-run-set-env.ps1 `
  -ProjectId YOUR_PROJECT_ID `
  -AppBaseUrl https://YOUR_V3_CLOUD_RUN_URL `
  -GoogleClientId ... -GoogleClientSecret ... `
  -McpTokenSecret ... -OauthStateSecret ... -TokenEncryptionKey ...
```

Create a **named** Firestore database `ga4-mcp-v3` before first use. Use a separate Google OAuth web client from V1/V2.

## Docs

- [Firestore schema](docs/firestore.md)
- [OAuth flows](docs/oauth.md)
- [MCP tools](docs/mcp-tools.md)
- [Security](docs/security.md)
- [V2 vs V3](docs/v2-vs-v3.md)