Skip to main content
Glama
yeswanthreddyk

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
```

Maintenance

ActivityStale
ResponsivenessNo issues