google-ads-mcp
# google-ads-mcp
A read-only [MCP](https://modelcontextprotocol.io) server for the Google Ads API.
It exposes reporting tools (campaigns, ad groups, keywords, and raw GAQL
queries) so an MCP client (Claude Code, Claude Desktop, etc.) can query your
Google Ads account. There are no mutate/write tools — this server cannot
change campaigns, budgets, or bids.
## Tools
| Tool | Description |
| --- | --- |
| `list_accessible_customers` | List customer IDs accessible to the configured credentials. |
| `get_account_hierarchy` | List accounts under a manager (MCC) account. |
| `list_campaigns` | List campaigns and their settings (no metrics). |
| `get_campaign_performance` | Campaign-level metrics (impressions, clicks, cost, conversions). |
| `get_ad_group_performance` | Ad group-level metrics. |
| `get_keyword_performance` | Keyword-level metrics. |
| `run_gaql` | Run a raw read-only [GAQL](https://developers.google.com/google-ads/api/docs/query/overview) `SELECT` query. |
## Prerequisites
You need Google Ads API credentials:
1. A **developer token** from the Google Ads API Center (Tools & Settings →
API Center) on the manager account you'll authenticate with.
2. An OAuth2 **client ID / client secret** from a Google Cloud project with
the Google Ads API enabled.
3. A **refresh token** for a user with access to the target account(s). See
Google's [OAuth desktop flow guide](https://developers.google.com/google-ads/api/docs/oauth/desktop-app)
or run the helper script bundled with the `google-ads` Python library.
4. If you authenticate via a manager (MCC) account on behalf of a client
account, its `login_customer_id`.
## Setup
```bash
# from the repo root
pip install -e .
```
Configure credentials one of two ways:
**Option A: YAML file**
```bash
cp google-ads.yaml.example google-ads.yaml
# edit google-ads.yaml with your values
```
**Option B: environment variables**
```bash
cp .env.example .env
# edit .env, then export the variables into your shell environment
```
Either `google-ads.yaml` in the current directory, or the `GOOGLE_ADS_*`
environment variables, will be picked up automatically. Set
`GOOGLE_ADS_CONFIGURATION_FILE_PATH` to point at a YAML file in a different
location if you'd prefer.
## Running standalone
```bash
python -m google_ads_mcp
# or, after `pip install -e .`:
google-ads-mcp
```
The server communicates over stdio, per the MCP spec.
## Registering with an MCP client
**Claude Code** (project-level `.mcp.json`, or `claude mcp add`):
```json
{
"mcpServers": {
"google-ads": {
"command": "google-ads-mcp",
"env": {
"GOOGLE_ADS_CONFIGURATION_FILE_PATH": "/absolute/path/to/google-ads.yaml"
}
}
}
}
```
**Claude Desktop** (`claude_desktop_config.json`): same `mcpServers` entry as
above.
## Security notes
- This server only issues GAQL `SELECT` queries via `GoogleAdsService.SearchStream`.
GAQL has no `INSERT`/`UPDATE`/`DELETE` syntax, so there is no way to mutate
Google Ads data through these tools.
- Never commit `google-ads.yaml` or `.env` — both are gitignored. Treat your
developer token, OAuth client secret, and refresh token as credentials.
- `customer_id` and entity IDs are validated as numeric before being
interpolated into GAQL query strings.
TDQS
Scored across 7 tools
Each tool targets a distinct resource or action: account listing, hierarchy, campaign listing, and performance at campaign, ad group, and keyword levels, plus a raw query fallback. There is no overlap or ambiguity between them.
All tool names follow a consistent verb_noun pattern (list_, get_, run_) and use snake_case throughout. The verbs accurately reflect the operation, and the nouns clearly indicate the target resource.
With 7 tools, the server is well-scoped for a read-only Google Ads reporting use case. Each tool serves a clear purpose, and the count is neither too sparse nor overwhelming.
The surface covers account enumeration, hierarchy, campaign listing, and performance at three key levels, plus a generic GAQL escape hatch. Minor gaps like structured ad group or keyword listing exist, but run_gaql can fill them, so no dead ends remain.