# google-ads-mcp [Health: Active]

**Category:** 💻 Developer Tools  
**Repository:** https://github.com/davidmosiah/google-ads-mcp-unofficial  
**GitHub Stars:** 4  
**Views:** 0  
**Installs:** 0  
**Upvotes:** 0  
**Directory Page:** https://allmcps.com/mcp/google-ads-mcp

## Description
Unofficial Google Ads MCP for campaigns, keywords, budgets, and gated mutations.

## Claude Desktop Quick Installation
Install path detected from listing signals. Uses `npx` (confidence: high):

```json
"mcpServers": {
  "google-ads-mcp": {
    "command": "npx",
    "args": ["-y","google-ads-mcp-unofficial"]
  }
}
```

## Documentation & README

# google-ads-mcp-unofficial

[![CI](https://img.shields.io/badge/CI-passing-22C55E?style=flat-square)](https://github.com/davidmosiah/google-ads-mcp-unofficial/actions)
[![npm](https://img.shields.io/npm/v/google-ads-mcp-unofficial?style=flat-square&color=cb3837&logo=npm)](https://www.npmjs.com/package/google-ads-mcp-unofficial)
[![npm downloads](https://img.shields.io/npm/dm/google-ads-mcp-unofficial?style=flat-square&color=cb3837)](https://www.npmjs.com/package/google-ads-mcp-unofficial)
[![MIT](https://img.shields.io/badge/license-MIT-blue?style=flat-square)](LICENSE)
[![MCP](https://img.shields.io/badge/MCP-compliant-7C3AED?style=flat-square)](https://modelcontextprotocol.io)

> Unofficial Model Context Protocol server that lets AI agents read, analyze, and (gated) act on a Google Ads account — pause keywords, set bids, adjust budgets — without leaving your stack.

**Unofficial. Not affiliated with Google.** This is a local-first MCP server that speaks the Google Ads REST API directly. It does NOT include automated financial-account changes beyond what the Google Ads API allows. Always review proposed changes before enabling `GOOGLE_ADS_ALLOW_MUTATIONS`.

---

## HTTP (v2 stateless)

Default is **stdio**. Optional Streamable HTTP — no session id, JSON responses, loopback only:

```bash
npx -y google-ads-mcp-unofficial --http
# GET  http://127.0.0.1:3000/health
# POST http://127.0.0.1:3000/mcp   (sessionless)
```

Env: `GOOGLE_ADS_MCP_HOST`, `GOOGLE_ADS_MCP_PORT`, `GOOGLE_ADS_MCP_TRANSPORT=http`.


## Quick start (30 seconds)

```bash
npx -y google-ads-mcp-unofficial setup
```

The setup wizard collects your developer token + OAuth client, writes `~/.google-ads-mcp/config.json` (chmod 600), then walks you through the OAuth dance via a local callback at `http://127.0.0.1:3000/callback`.

Verify:

```bash
npx -y google-ads-mcp-unofficial doctor
```

Then add it to your agent (Claude Desktop, Cursor, Hermes, OpenClaw, Codex — see examples below).

---

## What it does

22 tools across 6 categories.

| Category | Count | Examples |
|---|---|---|
| **Meta / diagnostic** | 5 | `google_ads_connection_status`, `google_ads_capabilities`, `google_ads_agent_manifest`, `google_ads_data_inventory`, `google_ads_privacy_audit` |
| **Shared Delx profile** | 3 | `google_ads_profile_get`, `google_ads_profile_update`, `google_ads_onboarding` |
| **Auth** | 3 | `google_ads_get_auth_url`, `google_ads_exchange_code`, `google_ads_revoke_access` |
| **Reads** (always safe) | 8 | `google_ads_list_accounts`, `google_ads_list_campaigns`, `google_ads_get_campaign`, `google_ads_list_ad_groups`, `google_ads_list_keywords`, `google_ads_get_account_performance`, `google_ads_get_campaign_performance`, `google_ads_get_keyword_performance` |
| **Workflow** | 2 | `google_ads_daily_report`, `google_ads_find_waste` |
| **Mutations** (gated) | 6 | `google_ads_pause_keyword`, `google_ads_resume_keyword`, `google_ads_set_keyword_bid_micros`, `google_ads_set_campaign_budget_micros`, `google_ads_pause_campaign`, `google_ads_resume_campaign` |

Full tool reference: see `AGENTS.md`.

---

## Setup wizard

```bash
npx -y google-ads-mcp-unofficial setup [--allow-mutations] [--client hermes|claude|cursor|...]
```

What it does:

1. Prompts for: developer token, OAuth client id/secret, optional login_customer_id (MCC), redirect URI, privacy mode.
2. Writes `~/.google-ads-mcp/config.json` with `chmod 600`.
3. Writes an MCP client config (e.g. merges into `claude_desktop_config.json` on macOS; writes a Hermes block and skill file for `--client hermes`).
4. Runs the OAuth dance (unless `--no-auth`) by opening Google's consent screen and listening on `127.0.0.1:3000`.

> **Mutations are off by default.** `--allow-mutations` enables write tools. ASK THE USER before turning this on — it lets agents change campaigns, bids, budgets, and pause/resume keywords.

---

## Auth model

This MCP requires **two credentials**:

1. **Google Ads Developer Token** — from your MCC (Manager) account at https://ads.google.com/aw/apicenter. New tokens start in "Test account access" mode and need approval for production traffic.
2. **Google OAuth 2.0 Client** — a "Desktop" or "Web" client created in Google Cloud Console. The single OAuth scope used is `https://www.googleapis.com/auth/adwords`.

> ⚠️ **Refresh token gotcha:** Google only returns a `refresh_token` on first consent or after you revoke the prior grant at https://myaccount.google.com/permissions. Our `auth` flow uses `prompt=consent` to maximize the chance Google returns one — but if your code-exchange response is missing `refresh_token`, the tool will tell you to revoke and retry.

| Variable | Purpose | Stored where | Secret? |
|---|---|---|---|
| `GOOGLE_ADS_DEVELOPER_TOKEN` | Approved developer token | `~/.google-ads-mcp/config.json` or env | **yes** |
| `GOOGLE_ADS_CLIENT_ID` | OAuth client id | local or env | no |
| `GOOGLE_ADS_CLIENT_SECRET` | OAuth client secret | local or env | **yes** |
| `GOOGLE_ADS_LOGIN_CUSTOMER_ID` | MCC id (no dashes) | local or env | no |
| `GOOGLE_ADS_REDIRECT_URI` | OAuth callback | local or env (default `http://127.0.0.1:3000/callback`) | no |
| `GOOGLE_ADS_PRIVACY_MODE` | `summary` \| `structured` \| `raw` | local or env (default `structured`) | no |
| `GOOGLE_ADS_ALLOW_MUTATIONS` | Enable write tools | local or env (default `false`) | no |
| `GOOGLE_ADS_TOKEN_PATH` | Override token storage | local or env (default `~/.google-ads-mcp/tokens.json`) | no |
| `GOOGLE_ADS_CACHE` | Enable SQLite cache | local or env (default off) | no |
| `GOOGLE_ADS_CACHE_PATH` | Override cache path | local or env | no |
| `GOOGLE_ADS_NO_RETRY` | Disable retry middleware | env (default off) | no |

---

## Privacy modes

| Mode | What you get | Customer id |
|---|---|---|
| `summary` | id + name + status fields only | partial-redacted (`123-***-7890`) |
| `structured` (default) | flat normalized rows with metrics | partial-redacted |
| `raw` | full upstream Google Ads REST payload | **full** |

Pass `privacy_mode` per call to override the default per response.

**Redaction matrix:**

| Field | summary | structured | raw |
|---|---|---|---|
| developer_token | n/a | n/a | n/a (never returned) |
| access_token, refresh_token, client_secret | [REDACTED] in all errors | [REDACTED] | [REDACTED] |
| email addresses in error messages | [REDACTED] | [REDACTED] | [REDACTED] |
| customer_id | `123-***-7890` | `123-***-7890` | full |
| metrics (clicks, cost, etc.) | dropped | included | included |

---

## ⚠️ Mutation gating — read this

**Default: mutations are DISABLED.** Six tools are gated:

- `google_ads_pause_keyword` / `google_ads_resume_keyword`
- `google_ads_set_keyword_bid_micros`
- `google_ads_set_campaign_budget_micros`
- `google_ads_pause_campaign` / `google_ads_resume_campaign`

If an agent calls any of them without `GOOGLE_ADS_ALLOW_MUTATIONS` enabled, it gets:

```
Error: Write tools are disabled. To enable: re-run `google-ads-mcp-server setup --allow-mutations`
or enable GOOGLE_ADS_ALLOW_MUTATIONS. ASK THE USER BEFORE TURNING THIS ON — it lets agents
change campaigns, bids, budgets, and pause/resume keywords.
```

Even with the env enabled, **every mutation requires `explicit_user_intent: true`** in the per-call arguments. And every mutation is logged to stderr with the resource name:

```
[google-ads-mcp] MUTATION pause_keyword {"resource_name":"customers/1234567890/adGroupCriteria/999~111222333"}
```

Read `SECURITY.md` for the threat model.

---

## Agent client examples

### Claude Desktop

`~/Library/Application Support/Claude/claude_desktop_config.json` (macOS):

```json
{
  "mcpServers": {
    "google-ads": {
      "command": "npx",
      "args": ["-y", "google-ads-mcp-unofficial"]
    }
  }
}
```

Then restart Claude Desktop.

### Cursor / Windsurf

`~/.cursor/mcp.json` (or your IDE equivalent):

```json
{
  "mcpServers": {
    "google-ads": {
      "command": "npx",
      "args": ["-y", "google-ads-mcp-unofficial@0.1.0"]
    }
  }
}
```

### Hermes

```yaml
# ~/.hermes/config.yaml
mcp_servers:
  google-ads:
    command: npx
    args:
      - -y
      - google-ads-mcp-unofficial@0.1.0
    timeout: 120
    connect_timeout: 60
    sampling:
      enabled: false
```

Then `/reload-mcp` (do NOT restart the gateway for normal data access).

### OpenClaw

`~/.openclaw/mcp.servers.json`:

```json
{
  "google-ads": {
    "command": "npx",
    "args": ["-y", "google-ads-mcp-unofficial@0.1.0"]
  }
}
```

### Codex / TOML clients

See `examples/codex.toml` for the equivalent TOML block.

---

## Workflow examples

### 1. Daily performance pulse

```jsonc
// Agent asks: "How did my Google Ads do yesterday?"
{
  "name": "google_ads_daily_report",
  "arguments": {
    "customer_id": "1234567890",
    "cpc_alert_threshold": 0.15
  }
}
```

Returns markdown with yesterday + 7d + 30d aggregates. If yesterday's CPC exceeds 0.15, the output gets an `ALERT` banner.

### 2. Identify waste (read-only)

```jsonc
{
  "name": "google_ads_find_waste",
  "arguments": {
    "customer_id": "1234567890",
    "date_range": "LAST_30_DAYS",
    "min_clicks": 5,
    "min_cost_micros": 200000,
    "zero_conversions_only": true
  }
}
```

Returns a ranked list of keywords matching "spent ≥ $0.20 with ≥5 clicks and 0 conversions" — but never pauses them.

### 3. Pause a single keyword (mutation, gated)

After the user confirms:

```jsonc
{
  "name": "google_ads_pause_keyword",
  "arguments": {
    "customer_id": "1234567890",
    "ad_group_id": "999",
    "criterion_id": "111222333",
    "explicit_user_intent": true
  }
}
```

---

## Troubleshooting

| Symptom | Action |
|---|---|
| `Missing required Google Ads environment variables` | Run `setup` or set the env vars listed in the error. |
| `Google did not return a refresh_token` | Revoke at https://myaccount.google.com/permissions then re-run `auth`. |
| `PERMISSION_DENIED` on a read | Confirm `GOOGLE_ADS_LOGIN_CUSTOMER_ID` matches the MCC that owns the target customer (no dashes). |
| `Write tools are disabled` | Expected. Ask the user before enabling `GOOGLE_ADS_ALLOW_MUTATIONS`. |
| Hermes tools missing after config edit | `/reload-mcp` or `hermes mcp test google-ads`. Do NOT restart the gateway. |
| Token file insecure perms warning | `chmod 600 ~/.google-ads-mcp/tokens.json` |

---

## Support

- GitHub Issues: https://github.com/davidmosiah/google-ads-mcp-unofficial/issues
- Email: support@delx.ai
- X: [@delx369](https://x.com/delx369)

---

## Disclaimer

Unofficial integration. **Not affiliated with Google.** This MCP does not include automated financial-account changes beyond what the Google Ads REST API allows. Always review proposed changes before enabling `GOOGLE_ADS_ALLOW_MUTATIONS`. The author is not responsible for budget overruns, paused campaigns, or any other consequences of automated changes to your Google Ads account.

MIT-licensed.

## Skill or MCP

Same package, two doors. MCP registers tools on stdio/HTTP. The [skill](https://github.com/davidmosiah/google-ads-mcp-unofficial/blob/HEAD/skill/SKILL.md) can drive the **same** tools through the CLI when the client has no MCP:

```bash
npx -y google-ads-mcp-unofficial call google_ads_connection_status --json '{}'
```

Copy `skill/SKILL.md` into your agent skills dir.

