Google Ads MCP Server
README.md
# Google Ads MCP Server
An MCP server that connects an MCP client (Claude Desktop, etc.) to the
**Google Ads API v23**. You log into your Google account once; after that every
tool operates on the ad accounts that login can access — read reporting and full
campaign management.
Built with the official `google-ads` Python client and `FastMCP`.
---
## What it can do
**Read**
| Tool | Purpose |
|------|---------|
| `google_ads_list_accessible_customers` | List the account IDs your login can access |
| `google_ads_search` | Run any GAQL query (the flexible workhorse) |
| `google_ads_list_campaigns` | Campaigns with status, channel type, budget |
| `google_ads_list_ad_groups` | Ad groups, optionally filtered to a campaign |
| `google_ads_get_performance` | Impressions, clicks, cost, conversions by account/campaign/ad group |
**Write / manage**
| Tool | Purpose |
|------|---------|
| `google_ads_create_campaign_budget` | Create a daily budget |
| `google_ads_create_campaign` | Create a campaign (PAUSED by default) |
| `google_ads_update_campaign_status` | Enable / pause / remove a campaign |
| `google_ads_update_campaign_budget` | Change a budget's daily amount |
| `google_ads_create_ad_group` | Create an ad group under a campaign |
> New campaigns are created **PAUSED** so nothing spends until you explicitly
> enable them. Money values are entered in normal currency units (the server
> converts to/from API "micros").
---
## Important: login alone is not enough
The Google Ads API can't authorize from a Google login by itself. Three things
are required, and the steps below get you all three:
1. **A developer token** — from your Google Ads manager account (one-time, may
need Google approval).
2. **An OAuth client** (client ID + secret) — from Google Cloud Console.
3. **A refresh token** — produced when *you* log in (`get_refresh_token.py`).
Once these sit in `.env`, the server works.
---
## Setup
### 0. Requirements
- Python 3.9+
- A Google Ads account, and access to a **manager (MCC) account** to get a
developer token.
### 1. Install dependencies
```bash
cd google-ads-mcp
python -m pip install -r requirements.txt
```
### 2. Get a developer token
Google Ads UI → **Tools → API Center** (must be a manager account). Copy the
developer token. A brand-new token starts in *test* mode (works only against
test accounts); apply for **Basic access** to use it on real accounts.
### 3. Create an OAuth client (Desktop app)
In [Google Cloud Console](https://console.cloud.google.com/):
1. Create/select a project.
2. **APIs & Services → Library →** enable **Google Ads API**.
3. **APIs & Services → Credentials → Create credentials → OAuth client ID**.
4. Application type: **Desktop app**. Copy the **client ID** and **client secret**.
(Add your Google account as a **Test user** on the OAuth consent screen if the
app is in "Testing".)
### 4. Log in to get your refresh token
```bash
python get_refresh_token.py
```
A browser opens — choose the Google account that has access to your Google Ads
account and approve. The script prints the refresh token and writes the client
ID/secret + refresh token into `.env`.
### 5. Fill in `.env`
Copy the template and complete the remaining values:
```bash
cp .env.example .env # Windows: copy .env.example .env
```
At minimum set:
```
GOOGLE_ADS_DEVELOPER_TOKEN=... # from step 2
GOOGLE_ADS_CLIENT_ID=... # from step 3 (also written by step 4)
GOOGLE_ADS_CLIENT_SECRET=... # from step 3 (also written by step 4)
GOOGLE_ADS_REFRESH_TOKEN=... # from step 4
# Manager accounts only:
GOOGLE_ADS_LOGIN_CUSTOMER_ID=... # your MCC id, 10 digits
# Optional convenience:
GOOGLE_ADS_DEFAULT_CUSTOMER_ID=... # the account most tools act on
```
### 6. Smoke-test
```bash
python -c "import server; print('server imports OK')"
```
Then verify credentials end-to-end (lists your accounts):
```bash
python -c "import asyncio, server; from server import ListCustomersInput; \
print(asyncio.run(server.google_ads_list_accessible_customers(ListCustomersInput())))"
```
### 7. Connect it to Claude Desktop
Edit `claude_desktop_config.json`
(macOS: `~/Library/Application Support/Claude/`, Windows:
`%APPDATA%\Claude\`) and add — using the **absolute path** to `server.py`:
```json
{
"mcpServers": {
"google-ads": {
"command": "python",
"args": ["/ABSOLUTE/PATH/TO/google-ads-mcp/server.py"]
}
}
}
```
The server reads `.env` from its own folder, so no secrets need to go in this
config. Restart Claude Desktop; the Google Ads tools will appear.
---
## Example prompts
- "List my Google Ads accounts."
- "Show campaign performance for the last 30 days."
- "Run GAQL: `SELECT campaign.name, metrics.clicks, metrics.cost_micros FROM campaign WHERE segments.date DURING LAST_7_DAYS ORDER BY metrics.clicks DESC`."
- "Create a $20/day budget called 'Summer', then a paused Search campaign 'Summer Sale' using it."
- "Pause campaign 1234567890."
---
## Manager (MCC) accounts
If your login is a manager account operating client accounts, set
`GOOGLE_ADS_LOGIN_CUSTOMER_ID` to the **manager** id, and pass the **client**
account id as `customer_id` (or set `GOOGLE_ADS_DEFAULT_CUSTOMER_ID`).
---
## Troubleshooting
| Symptom | Fix |
|---------|-----|
| `Missing Google Ads credentials: ...` | Fill the named vars in `.env`. |
| `invalid_grant` / RefreshError | Refresh token expired/revoked — re-run `get_refresh_token.py`. |
| `DEVELOPER_TOKEN_NOT_APPROVED` / token in test mode | Apply for Basic access, or use a test account. |
| `USER_PERMISSION_DENIED` | Login lacks access to that account, or `login_customer_id` is wrong/missing for MCC. |
| `CUSTOMER_NOT_FOUND` | Check the 10-digit `customer_id` (dashes are fine, they're stripped). |
| No refresh token returned | Revoke prior access at myaccount.google.com/permissions, re-run the login. |
---
## Security
- `.env` holds secrets and is git-ignored — never commit it.
- The developer token, OAuth secret, and refresh token together grant access to
your ad accounts; treat them like passwords.
- All write tools are annotated (`destructiveHint` on remove/pause) so clients
can warn before acting.
## Project layout
```
google-ads-mcp/
├── server.py # FastMCP server + all 10 tools
├── ads_client.py # credentials, client factory, error handling, helpers
├── get_refresh_token.py # one-time OAuth login -> refresh token
├── requirements.txt
├── .env.example # copy to .env and fill in
├── .gitignore
└── README.md
```
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues