Google Ads MCP Worker
Google Ads MCP Worker
Google Ads MCP server on a Cloudflare Worker. Same shape as mcp-gsc: TypeScript, REST via fetch, no Google client library.
Reimplementation of FGRibreau/mcp-google-ads (Rust, API v23) on API v25
Auth: OAuth2 refresh token. The Google Ads API does not accept service accounts, so the GSC JWT approach does not apply here
Transports: Streamable HTTP (
/mcp) and legacy SSE (/sse)
Writes are unguarded. No dry-run, no budget ceiling, no bid-increase cap, no two-step confirmation, no audit log. Every mutation tool applies immediately to whichever account
customer_idpoints at.create_campaign,create_ad_groupandcreate_responsive_search_addefault toPAUSED, but that is a default you can override, not a lock. Point this at a test account until you trust the setup.
Setup
1. Google Ads developer token
Manager (MCC) account → Tools & Settings → API Center → apply for a developer token. Until Basic Access is approved the token only works against test accounts.
2. OAuth client
Google Cloud Console → pick/create a project → enable the Google Ads API.
APIs & Services → Credentials → Create credentials → OAuth client ID → Desktop app.
Note the client ID and client secret.
3. Refresh token
npm install --legacy-peer-deps
npm run token -- <CLIENT_ID> <CLIENT_SECRET>Opens a browser, asks for the adwords scope, prints GOOGLE_ADS_REFRESH_TOKEN.
Sign in as a Google account that has access to the Ads account you want to manage.
4. Deploy
npx wrangler secret put GOOGLE_ADS_DEVELOPER_TOKEN
npx wrangler secret put GOOGLE_ADS_CLIENT_ID
npx wrangler secret put GOOGLE_ADS_CLIENT_SECRET
npx wrangler secret put GOOGLE_ADS_REFRESH_TOKEN
npx wrangler secret put MCP_AUTH_TOKEN # any long random string: openssl rand -hex 32
npm run deploySet the non-secret defaults in wrangler.jsonc:
Var | Meaning |
| Default account, digits only. Tools take |
| Your MCC id, sent as |
| Defaults to |
Local dev: copy .dev.vars.example to .dev.vars, then npm run dev.
5. Connect a client
claude mcp add --transport http gads https://gads-mcp.<your-subdomain>.workers.dev/mcp \
--header "Authorization: Bearer <MCP_AUTH_TOKEN>"Claude Desktop / stdio-only clients:
{
"mcpServers": {
"gads": {
"command": "npx",
"args": [
"mcp-remote",
"https://gads-mcp.<your-subdomain>.workers.dev/mcp",
"--header",
"Authorization: Bearer <MCP_AUTH_TOKEN>"
]
}
}
}Then call health_check — it reports OAuth status, developer token presence, and the accounts reachable.
Tools
46 tools. Every customer-scoped tool takes an optional customer_id.
Read (21)
Tool | What |
| Auth status, API version, configured accounts |
| Accessible accounts (with names when an MCC is configured) |
| Currency, time zone, auto-tagging, test-account flag |
| Any GAQL query; |
| Campaign metrics by cost |
| Ad group metrics |
| Ad metrics with RSA headlines/descriptions and approval status |
| Keyword metrics with match type, quality score, bid |
| Actual queries — the negative keyword source |
| Campaign / ad group / shared-set negatives |
| Metrics by location |
| Metrics by device |
| Change events (API retains 30 days) |
| Assets and their attachment level |
| Disapproved and limited ads with policy topics |
| Conversion actions with category, counting, lookback |
| Google's recommendations plus impact estimates |
| Place name → geo target constant id |
| Keyword ideas from seeds and/or a URL |
| Volume/competition for a fixed keyword list |
| Forecast for a hypothetical campaign |
Write (25)
Tool | What |
| Daily budget, shared or not |
| Campaign + optional budget in one call |
| Name, status, budget, dates, bidding strategy |
| Ad groups and default CPC |
| Positive keywords, bids, final URLs |
| Campaign or ad group negatives |
| RSA with pinning; length limits checked before sending |
| Pause / enable / remove anything by resource name |
| Target or exclude locations, with bid modifiers |
| Presence vs presence-or-interest |
| Dayparting windows and bid modifiers |
| Audiences |
| Sitelinks, callouts, snippets, text, images |
| Conversion setup, primary/secondary |
| Portfolio strategies |
| Act on Google's suggestions |
| Raw mutate on any resource collection — covers everything above |
| Atomic |
mutate and mutate_batch are the escape hatches: anything Google adds, or any resource with no named tool
(shared sets, user lists, asset groups, experiments, labels), goes through them without a code change.
Both accept validate_only if you want a manual dry run.
Checks
npm run typecheck # tsc --noEmit
npm test # pure-logic selfcheck: micros, dates, resource names, bidding payloadsNotes
Money is passed in currency units (
25.5) and converted to micros internally.Mutate payloads use
YYYYMMDDdates; reporting usesYYYY-MM-DD. Tools takeYYYY-MM-DDeverywhere and convert.updateMaskuses snake_case field names — relevant if you hand-write operations formutate.Access tokens are cached per Worker isolate; refresh tokens do not expire unless revoked or unused for 6 months.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/ambo-sk/mcp-google-ads'
If you have feedback or need assistance with the MCP directory API, please join our Discord server