Skip to main content
Glama
kwp-lab

Google Analytics MCP Server

by kwp-lab
README.md
# Google Analytics MCP Server

A Model Context Protocol (MCP) server that provides seamless access to Google Analytics 4 data through standard MCP interfaces. This tool allows LLM applications to easily query and analyze Google Analytics data without directly dealing with the complexities of the Google Analytics Data API.

## ✨ Features

- **🔐 Dual Authentication**: Support both Service Account and OAuth2 User Authorization
- **Real-time Data Access**: Get real-time analytics data for current active users and activity
- **Custom Reports**: Create comprehensive reports with custom dimensions and metrics
- **Quick Insights**: Predefined analytics insights for common use cases
- **Metadata Discovery**: Get available dimensions and metrics for your Google Analytics property
- **🔄 Auto Token Refresh**: Automatically refreshes expired OAuth2 access tokens
- **Smart Error Handling**: Detailed error messages with actionable solutions for permission issues
- **Standard MCP Interface**: Works with any MCP-compatible client

## Installation

```bash
npm install @toolsdk.ai/google-analytics-mcp
```

## Prerequisites

- Node.js >= 18.0.0
- Google Analytics 4 property
- Either:
  - **Service Account** credentials (default), OR
  - **OAuth2 tokens** from a user authorization flow

## 🔐 Authentication Modes

This MCP server supports two authentication modes, controlled by the `GOOGLE_AUTH_MODE` environment variable:

| Mode | Value | Description |
|------|-------|-------------|
| **Service Account** | `service_account` (default) | Use a GCP service account JSON key |
| **OAuth2** | `oauth2` | Use user-authorized OAuth2 tokens |

---

## Mode 1: Service Account (Default)

Use this mode for server-to-server authentication without user interaction.

### Setup Steps

1. **Create a Service Account** in Google Cloud Console
2. **Download the JSON key** file
3. **Grant access** to your GA4 property:
   - Go to Google Analytics → Admin → Property Access Management
   - Add the service account email (e.g., `xxx@project.iam.gserviceaccount.com`) with **Viewer** access

### Environment Variables

```env
# Optional: defaults to 'service_account'
GOOGLE_AUTH_MODE=service_account

# Option 1: Direct JSON string
GOOGLE_CREDENTIALS='{"type":"service_account","project_id":"...","private_key":"...","client_email":"..."}'

# Option 2: Path to JSON file
GOOGLE_CREDENTIALS_PATH=/path/to/service-account.json
```

### Claude Desktop Configuration

```json
{
  "mcpServers": {
    "google-analytics-mcp": {
      "command": "npx",
      "args": ["-y", "@toolsdk.ai/google-analytics-mcp"],
      "env": {
        "GOOGLE_AUTH_MODE": "service_account",
        "GOOGLE_CREDENTIALS_PATH": "/path/to/service-account.json"
      }
    }
  }
}
```

---

## Mode 2: OAuth2 User Authorization

Use this mode to access GA data on behalf of a user with their own permissions.

### Advantages

- ✅ Access the user's own GA properties without service account setup
- ✅ No need to add service accounts to GA property permissions
- ✅ Works with the user's existing Google account permissions

> ⚠️ **Important**: This MCP server does **NOT** include the OAuth2 authorization flow itself. You need to implement the OAuth2 consent flow separately to obtain the tokens.

### 1. Implement OAuth2 Authorization Flow (Your Responsibility)

You need to implement the OAuth2 authorization flow using libraries like:

- [`googleapis`](https://www.npmjs.com/package/googleapis) (Node.js)
- [`google-auth-library`](https://www.npmjs.com/package/google-auth-library) (Node.js)

Required OAuth2 scopes:
```
https://www.googleapis.com/auth/analytics.readonly
```

Example OAuth2 flow (simplified):
```javascript
import { google } from 'googleapis';

const oauth2Client = new google.auth.OAuth2(
  CLIENT_ID,
  CLIENT_SECRET,
  REDIRECT_URI
);

// Generate auth URL and redirect user
const authUrl = oauth2Client.generateAuthUrl({
  access_type: 'offline',  // Important: to get refresh_token
  scope: ['https://www.googleapis.com/auth/analytics.readonly']
});

// After user consent, exchange code for tokens
const { tokens } = await oauth2Client.getToken(code);

// Save tokens to tokens.json
fs.writeFileSync('tokens.json', JSON.stringify(tokens, null, 2));
```

### 2. tokens.json Format

After completing the OAuth2 flow, save the tokens in a `tokens.json` file:

```json
{
  "access_token": "ya29.a0AWY7CknXXX...",
  "refresh_token": "1//0eXXX...",
  "scope": "https://www.googleapis.com/auth/analytics.readonly",
  "token_type": "Bearer",
  "expiry_date": 1234567890000
}
```

| Field | Description | Required |
|-------|-------------|----------|
| `access_token` | The OAuth2 access token | ✅ Yes |
| `refresh_token` | The refresh token (for auto-renewal) | ⚠️ Recommended |
| `scope` | Authorized scopes | Optional |
| `token_type` | Token type (usually "Bearer") | Optional |
| `expiry_date` | Token expiration timestamp (ms) | ⚠️ Recommended |

### 3. Token Loading Priority

The MCP server loads OAuth2 tokens in the following order:

1. **Direct JSON string** via `GOOGLE_OAUTH2_TOKENS` environment variable
2. Path specified by `GOOGLE_OAUTH2_TOKEN_PATH` environment variable
3. `{current working directory}/tokens.json`
4. `{current working directory}/../tokens.json`
5. `{src directory}/../../tokens.json`

### 4. Environment Variables (OAuth2 Mode)

```env
GOOGLE_AUTH_MODE=oauth2

# Option 1: Direct JSON string
GOOGLE_OAUTH2_TOKENS='{"access_token":"ya29...","refresh_token":"1//0e...","expiry_date":1234567890000}'

# Option 2: Path to tokens.json
GOOGLE_OAUTH2_TOKEN_PATH=/path/to/your/tokens.json

# Optional: For automatic token refresh
GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your-client-secret
```

### Claude Desktop Configuration (OAuth2)

```json
{
  "mcpServers": {
    "google-analytics-mcp": {
      "command": "npx",
      "args": ["-y", "@toolsdk.ai/google-analytics-mcp"],
      "env": {
        "GOOGLE_AUTH_MODE": "oauth2",
        "GOOGLE_OAUTH2_TOKEN_PATH": "/path/to/your/tokens.json",
        "GOOGLE_CLIENT_ID": "your-client-id (optional)",
        "GOOGLE_CLIENT_SECRET": "your-client-secret (optional)"
      }
    }
  }
}
```

---

## ⚠️ Token Lifecycle Management (OAuth2 Mode)

### Access Token Expiration

- Google OAuth2 access tokens typically expire after **1 hour**
- The MCP server will automatically attempt to refresh tokens if `refresh_token` is provided

### Automatic Token Refresh

When configured with `GOOGLE_CLIENT_ID` and `GOOGLE_CLIENT_SECRET`, the server will:

1. Detect when the access token is expired
2. Use the `refresh_token` to obtain a new `access_token`
3. **Automatically save** the new tokens to `tokens.json`

### Refresh Token Considerations

> ⚠️ **Important Notes about Refresh Tokens:**

1. **Refresh tokens can expire or be revoked:**
   - If the user revokes access in their Google Account settings
   - If the refresh token is unused for 6 months (for non-verified apps)
   - If you've exceeded the limit of 100 refresh tokens per user per client

2. **Getting a refresh token:**
   - You only get a `refresh_token` on the **first** authorization
   - Use `access_type: 'offline'` in your auth URL
   - Use `prompt: 'consent'` to force re-consent and get a new refresh token

3. **Recommended practices:**
   - Always request `access_type: 'offline'` during OAuth2 flow
   - Store and protect the `refresh_token` securely
   - Implement re-authorization flow for when refresh tokens become invalid
   - Monitor for `invalid_grant` errors which indicate the refresh token is no longer valid

---

## Available Tools

### `analytics_report`
Get comprehensive Google Analytics data with custom dimensions and metrics. Can create any type of report.

Parameters:
- `propertyId` (string, required): Google Analytics property ID
- `startDate` (string, required): Start date (YYYY-MM-DD)
- `endDate` (string, required): End date (YYYY-MM-DD)
- `dimensions` (array, optional): Dimensions to query
- `metrics` (array, required): Metrics to query
- `dimensionFilter` (object, optional): Filter by dimension values
- `metricFilter` (object, optional): Filter by metric values
- `orderBy` (object, optional): Sort results by dimension or metric
- `limit` (number, optional): Limit number of results (default: 100)

### `realtime_data`
Get real-time analytics data for current active users and activity.

Parameters:
- `propertyId` (string, required): Google Analytics property ID
- `dimensions` (array, optional): Dimensions for real-time data
- `metrics` (array, optional): Real-time metrics (default: ['activeUsers'])
- `limit` (number, optional): Limit number of results (default: 50)

### `quick_insights`
Get predefined analytics insights for common use cases.

Parameters:
- `propertyId` (string, required): Google Analytics property ID
- `startDate` (string, required): Start date (YYYY-MM-DD)
- `endDate` (string, required): End date (YYYY-MM-DD)
- `reportType` (string, required): Type of quick insight report (overview, top_pages, traffic_sources, etc.)
- `limit` (number, optional): Limit number of results (default: 20)

### `get_metadata`
Get available dimensions and metrics for Google Analytics property.

Parameters:
- `propertyId` (string, required): Google Analytics property ID
- `type` (string, optional): Type of metadata to retrieve (dimensions, metrics, both)

### `search_metadata`
Search for specific dimensions or metrics by name or category.

Parameters:
- `propertyId` (string, required): Google Analytics property ID
- `query` (string, required): Search term to find dimensions/metrics
- `type` (string, optional): Type of metadata to search (dimensions, metrics, both)
- `category` (string, optional): Filter by category

## Error Handling

The server provides detailed error messages with actionable solutions based on the authentication mode:

**Service Account Mode:**
- Permission errors will prompt you to add the service account email to GA property access

**OAuth2 Mode:**
- Permission errors will suggest re-authorization
- Token errors will indicate refresh or re-authorization needs

## Environment Variables Summary

| Variable | Mode | Description |
|----------|------|-------------|
| `GOOGLE_AUTH_MODE` | Both | `service_account` (default) or `oauth2` |
| `GOOGLE_CREDENTIALS` | Service Account | JSON string of service account key |
| `GOOGLE_CREDENTIALS_PATH` | Service Account | Path to service account JSON file |
| `GOOGLE_OAUTH2_TOKENS` | OAuth2 | JSON string of OAuth2 tokens |
| `GOOGLE_OAUTH2_TOKEN_PATH` | OAuth2 | Path to tokens.json |
| `GOOGLE_CLIENT_ID` | OAuth2 | Client ID for token refresh |
| `GOOGLE_CLIENT_SECRET` | OAuth2 | Client secret for token refresh |

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## License

MIT

TDQS

A3.5/5.0

Scored across 5 tools

Disambiguation5/5

Each tool targets a distinct purpose: real-time data, comprehensive reports, metadata listing, predefined insights, and metadata search. No overlap, agent can easily differentiate.

Naming Consistency4/5

Mostly snake_case with descriptive names, but mixes verb-noun (get_metadata, search_metadata) with noun-noun (realtime_data, analytics_report) and adjective-noun (quick_insights). Minor inconsistency but still clear.

Tool Count5/5

5 tools is well-scoped for a Google Analytics server covering main data access needs: realtime, custom reports, metadata, insights, and search. Neither too few nor excessive.

Completeness5/5

Covers key Google Analytics data retrieval: real-time, custom reports via analytics_report (which can handle any dimensions/metrics), metadata listing, search, and predefined insights. No obvious gaps for a read-only analytics server.

Maintenance

ActivityInactive
ResponsivenessNo issues