# Google Ads MCP: an MCP server by Scalably

Canonical: https://scalably.io/mcp/google-ads-mcp
Source: https://github.com/scalably-io/google-ads-mcp
Registry: https://registry.modelcontextprotocol.io/v0.1/servers/io.scalably%2Fgoogle-ads-mcp/versions/1.0.1
Provenance: derived from `container/tools/google-ads-mcp/server.py` at `ef174fc3` (2026-08-31) in the private ScalablyAI repository
Integrity: sha256 of the raw README served at https://scalably.io/mcp/google-ads-mcp.md is fe7b16cce59c64cba3a24fd46bd99eb069245681fb279bb13a89113350e7912a. Verify: curl -s https://scalably.io/mcp/google-ads-mcp.md | shasum -a 256
This is the machine-readable representation of the page at the canonical URL. Same facts, denser format.

## Direct answer
Google Ads MCP: GAQL queries, resources, recommendations, keyword ideas, change history. 11 tools.

GAQL reporting, keyword planning and change history for paid accounts.

## Install
- Claude Code: `claude mcp add google-ads \
  -e GOOGLE_ADS_DEVELOPER_TOKEN=your-token \
  -e GOOGLE_ADS_CLIENT_ID=your-client-id \
  -e GOOGLE_ADS_CLIENT_SECRET=your-client-secret \
  -e GOOGLE_ADS_REFRESH_TOKEN=your-refresh-token \
  -e GOOGLE_ADS_LOGIN_CUSTOMER_ID=1234567890 \
  -- uvx scalably-google-ads-mcp`
- Codex: `codex mcp add google-ads \
  --env GOOGLE_ADS_DEVELOPER_TOKEN=your-token \
  --env GOOGLE_ADS_CLIENT_ID=your-client-id \
  --env GOOGLE_ADS_CLIENT_SECRET=your-client-secret \
  --env GOOGLE_ADS_REFRESH_TOKEN=your-refresh-token \
  --env GOOGLE_ADS_LOGIN_CUSTOMER_ID=1234567890 \
  -- uvx scalably-google-ads-mcp`
- Claude Desktop: download `google-ads-mcp.mcpb` from the latest GitHub release and open it.

## Environment
| Variable | Required | Secret | Purpose |
|---|---|---|---|
| `GOOGLE_ADS_DEVELOPER_TOKEN` | yes | yes | Google Ads API developer token from the Ads API Center |
| `GOOGLE_ADS_CLIENT_ID` | yes | no | OAuth2 client_id for a Desktop-app credential |
| `GOOGLE_ADS_CLIENT_SECRET` | yes | yes | OAuth2 client_secret paired with the client_id |
| `GOOGLE_ADS_REFRESH_TOKEN` | yes | yes | Long-lived OAuth2 refresh_token for the adwords scope |
| `GOOGLE_ADS_LOGIN_CUSTOMER_ID` | yes | no | 10-digit customer ID of the manager account (MCC) |
| `GOOGLE_ADS_API_VERSION` | no | no | Google Ads API version to target, default set by the server |
| `GOOGLE_ADS_LOG_LEVEL` | no | no | Log level, default WARNING |
| `GOOGLE_ADS_USE_PROTO_PLUS` | no | no | Use proto-plus message types, default true |

## Tools
| Tool | Description |
|---|---|
| `google_ads_list_accessible_customers` | List every customer_id the OAuth user has direct access to |
| `google_ads_list_customer_clients` | Walk the MCC hierarchy and return every child account |
| `google_ads_query` | Run a GAQL query against a specific customer account |
| `google_ads_describe_resource` | Schema (fields, metrics, segments) for a GAQL resource |
| `google_ads_list_resources` | Return the full catalog of GAQL resources |
| `google_ads_recommendations` | Read Google's optimization recommendations for a customer account |
| `google_ads_keyword_ideas` | Generate keyword ideas with search volume, competition and CPC estimates |
| `google_ads_keyword_historical_metrics` | Historical monthly search-volume and competition metrics for specific keywords |
| `google_ads_keyword_forecast_metrics` | Forecast KPIs for a proposed keyword plan |
| `google_ads_change_events` | Audit trail of who changed what, last 30 days |
| `google_ads_change_status` | Lightweight last-modified change tracker per resource |

## Setup
This is the heaviest setup in the gallery: expect up to two days waiting on developer token approval. One set of credentials, rooted at a manager account (MCC), can read any customer account linked under it, so there is no per-client configuration beyond linking an account to the MCC.

1. **Google Ads developer token.** Sign in at ads.google.com under your manager account, go to Tools and Settings, API Center, and apply for a developer token. A new token starts on the Explorer access level, which Google grants after a review that can take a few days; discovery, query and recommendation tools work there. Basic access (a separate application) is needed for higher quotas and may be needed for the keyword-planning tools.
2. **Google Cloud OAuth client.** In a Google Cloud project, enable the Google Ads API, then create an OAuth client ID of type Desktop app under APIs and Services, Credentials. Note the client ID and client secret, and add the `https://www.googleapis.com/auth/adwords` scope to the OAuth consent screen.
3. **Refresh token.** Generate a refresh token once, as an admin user of the manager account, using Google's `oauth2l` tool or the `generate_user_credentials.py` example shipped with the `google-ads` Python library. Save the refresh token; it does not expire from normal use.
4. **Login customer ID.** Use the 10-digit customer ID of the manager account itself (no hyphens) as `GOOGLE_ADS_LOGIN_CUSTOMER_ID`. Any client account accepts an invite to link under this manager account in its own Google Ads UI, after which `google_ads_list_customer_clients` sees it.

## Limits
`google_ads_query` responses are capped at 64 MB per call by the Google Ads API; split large date ranges across calls. `KeywordPlanIdeaService` (keyword ideas, historical metrics, forecasts) is rate-limited to 1 query per second and may require Basic Access if you get a permission error on the Explorer tier. `google_ads_change_events` covers up to 30 days back; `google_ads_change_status` covers up to 14 days back. `metrics.cost_micros` and other `*_micros` fields are 1 unit = $0.000001; `google_ads_query` emits a matching `*_units` field alongside when `convert_micros` is true (the default).

## Reply shape
Every tool returns JSON with `status` (`succeeded`, `partial`, `no_op`), `operation`, `summary`, `target`, `result`, `proof`, `warnings`, `recovery`. Failures surface as a tool error whose text is `google_ads_request_failed: <message> <hint>`. `proof.apiVersion` names the Google Ads API version used. `proof.microsConverted` is set on `google_ads_query`. A `partial` status means the result hit its configured bound (`max_rows`, `page_size` or `limit`); `recovery.nextAction` says how to continue.

## Reliability
- CI: https://github.com/scalably-io/google-ads-mcp/actions/workflows/validate.yml
- Release 1.0.1
- Verified 2026-08-31
- Each of ours started as an internal ScalablyAI MCP server. We stripped the internal envelope, the auth wrapper and client dispatch that only make sense inside our own platform, and kept the tool surface. Every release runs through a clean-install CI job, publishes under the io.scalably namespace with trusted publishing so no long-lived token ever leaves our CI, and registers on the official MCP registry.

## Related
- Read more: [AI agents for SEO: 5,329 tasks at 98% over four months](https://scalably.io/blog/ai-agents-for-seo), [How to build an MCP server in Python (production guide)](https://scalably.io/blog/how-to-build-mcp-server-python)
