Google Ads MCP
by v-p3truk
README.md
# Google Ads MCP — with write operations
An MCP server that lets Claude (or any MCP client) **read _and_ change** a Google Ads account.
This is a rebuilt fork of [cohnen/mcp-google-ads](https://github.com/cohnen/mcp-google-ads).
The original is query-only — it exposes 12 read tools and cannot modify anything. Google's own
[googleads/google-ads-mcp](https://github.com/googleads/google-ads-mcp) is read-only too: it wraps GAQL
search and resource metadata, with no mutate operations at all.
So if you want an agent that actually *manages* campaigns — pauses ads, updates budgets, pushes negative
keywords — neither of those will do it. This fork adds that layer.
**What's different from upstream:**
- **16 write tools** built on a shared `_mutate()` helper (upstream had none)
- **Google Ads API v19 → v24** (v19 and v20 are deprecated)
- Credentials are read from `.env` everywhere — no hardcoded secrets, and `.gitignore` actually
covers them (upstream's last entry was glued together by a missing newline, so it matched nothing)
- Helper scripts: OAuth re-authorization, a standalone GAQL runner for debugging
## Tools
**Read** — `run_gaql`, `execute_gaql_query` (arbitrary GAQL), `get_campaign_performance`,
`get_ad_performance`, `get_ad_creatives`, `get_image_assets`, `download_image_asset`, `get_asset_usage`,
`analyze_image_assets`, `get_account_currency`, `list_accounts`, `list_resources`
**Write** — `create_campaign`, `create_ad_group`, `create_rsa_ad`, `add_keywords`, `update_keyword_status`,
`add_negative_keywords`, `remove_negative_keywords`, `create_shared_negative_set`, `add_to_shared_negative_set`,
`attach_shared_set_to_campaign`, `update_campaign_status`, `update_ad_status`, `update_campaign_budget`,
`update_campaign_geo_targeting`, `add_sitelink_extensions`, `add_callout_extensions`
**Not covered** — keyword/ad-group level bids, bidding strategies, Performance Max assets, audiences,
ad scheduling. Do those in the UI, or extend `_mutate()`.
## What you need
1. **Google Ads developer token** — MCC account → Tools → API Center. A fresh token starts at *Test*
level, which only sees test accounts; request Basic access to work against live accounts.
2. **OAuth client ID + secret** — Google Cloud Console → create a project → enable the Google Ads API →
APIs & Services → Credentials → Create OAuth client ID → type **Desktop app**.
3. **Refresh token** — you don't get this by hand; `reauth.py` generates it (step 3 below).
## Setup
```bash
python3 -m venv .venv && ./.venv/bin/pip install -r requirements.txt
cp .env.example .env # fill in the developer token and OAuth pair from above
./.venv/bin/python reauth.py # opens a browser for consent, writes client_secret.json
```
Then point your MCP client at it:
```json
{
"mcpServers": {
"google-ads": {
"type": "stdio",
"command": "/absolute/path/to/.venv/bin/python",
"args": ["/absolute/path/to/google_ads_server.py"],
"env": { "GOOGLE_ADS_AUTH_TYPE": "oauth" }
}
}
}
```
Everything else is picked up from `.env` — the server loads it via `python-dotenv`.
## Helper scripts
| File | Purpose |
|------|---------|
| `reauth.py` | get or refresh the OAuth refresh token when it expires |
| `gaql_rest.py` | run a GAQL query straight over REST, bypassing MCP — handy for debugging |
| `pause_ads.py` | example: bulk-pause ads by ID |
| `gaql-google-ads-query-language.mdc` | GAQL syntax cheatsheet |
## Secrets
They live in `.env` and `client_secret.json` only. Both are gitignored — don't commit them.
If you add your own scripts, pull values with `os.getenv()`; never inline them.
## License
MIT, inherited from [cohnen/mcp-google-ads](https://github.com/cohnen/mcp-google-ads)
(Copyright © 2025 Ernesto Cohnen — ixigo). See [LICENSE](LICENSE). Modifications © 2026 Vlad Petruk.
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues