@theethosteam/google-ads-mcp
v0.1.0
Published
Read + write MCP server (and CLI) for Google Ads — GAQL reporting, campaign/budget/keyword CRUD with validate-only dry-runs and confirm gates, over OAuth + developer token. Runs via npx, locally or in cloud.
Downloads
175
Maintainers
Readme
@theethosteam/google-ads-mcp
Read + write MCP server (and CLI) for Google Ads — GAQL reporting plus
campaign/budget/keyword/ad CRUD, with hard money-safety rails. Plain REST
(no gRPC), runs via npx, locally or in cloud.
Part of The Ethos Team connectors
(ga4-mcp · gtm-mcp · gsc-mcp · google-ads-mcp).
Safety model (read this first)
Every mutating tool is a dry-run by default. Without confirm:true the
call runs with validate_only — Google fully validates the change and we
return a preview (including warnings like “⚠️ 3.2× budget increase” or
“shared budget affects 4 campaigns”) but nothing changes. Only
confirm:true executes. New campaigns, ad groups, keywords, and ads are
created PAUSED unless explicitly told otherwise.
Env vars
| Var | What |
|---|---|
| ADS_OAUTH_CLIENT_ID / ADS_OAUTH_CLIENT_SECRET | OAuth client (Desktop type) with the Google Ads API enabled |
| ADS_OAUTH_REFRESH_TOKEN | Mint with ads auth:url → approve → ads auth:exchange <code> |
| ADS_DEVELOPER_TOKEN | Google Ads → MCC → Admin → API Center |
| ADS_LOGIN_CUSTOMER_ID | The MCC id, digits only (e.g. 1751993391) |
| ADS_CUSTOMER_ID | (optional) default client account for calls that omit customerId |
| ADS_API_VERSION | (optional) override the pinned API version (default v24) |
auth:url requests the Ads and GA4/GSC/GTM scopes, so the one refresh
token it mints also works for the other three Ethos connectors (same OAuth
client, set it as their *_OAUTH_REFRESH_TOKEN).
MCP
{
"mcpServers": {
"google-ads": {
"command": "npx",
"args": ["-y", "@theethosteam/google-ads-mcp"],
"env": {
"ADS_OAUTH_CLIENT_ID": "${ADS_OAUTH_CLIENT_ID}",
"ADS_OAUTH_CLIENT_SECRET": "${ADS_OAUTH_CLIENT_SECRET}",
"ADS_OAUTH_REFRESH_TOKEN": "${ADS_OAUTH_REFRESH_TOKEN}",
"ADS_DEVELOPER_TOKEN": "${ADS_DEVELOPER_TOKEN}",
"ADS_LOGIN_CUSTOMER_ID": "${ADS_LOGIN_CUSTOMER_ID}",
"ADS_CUSTOMER_ID": "${ADS_CUSTOMER_ID}"
}
}
}
}Reads: ads_whoami, ads_list_accounts, ads_query (raw GAQL),
ads_overview, ads_campaigns, ads_ad_groups, ads_ads, ads_keywords,
ads_search_terms, ads_budgets, ads_recommendations,
ads_change_history, ads_conversions.
Writes (guarded): ads_set_{campaign,ad_group,ad,keyword}_status,
ads_update_budget, ads_update_bidding, ads_set_cpc_bid,
ads_add_keywords, ads_add_negative_keywords, ads_create_campaign,
ads_create_rsa, ads_apply_recommendation, ads_dismiss_recommendation,
ads_mutate (raw passthrough).
CLI
npx -y -p @theethosteam/google-ads-mcp ads auth:url
npx -y -p @theethosteam/google-ads-mcp ads whoami
npx -y -p @theethosteam/google-ads-mcp ads accounts # find a client's CID under the MCC
npx -y -p @theethosteam/google-ads-mcp ads search-terms -c 1234567890
npx -y -p @theethosteam/google-ads-mcp ads set-budget 123456 45.00 # dry-run preview
npx -y -p @theethosteam/google-ads-mcp ads set-budget 123456 45.00 --confirm # executesMulti-client
Every tool takes an optional customerId (dashes ok) and falls back to
ADS_CUSTOMER_ID. Onboarding a new client = finding their id with
ads_list_accounts and passing it per call — no new credentials needed as
long as the account is linked under the MCC.
