MCP Google Ads

Model Context Protocol · Google Ads API v24+

Run Google Ads
straight from Claude.

An MCP server that connects Claude to your Google Ads accounts — reads, reporting, keyword research and Search-campaign creation, with an embedded OAuth login. Status: LIVE.

37 tools · embedded OAuth · multi-tenant · free

REST httpx · no gRPC Hexagonal architecture Writes born PAUSED Reads via GAQL validateOnly dry-run Multi-tenant on Vercel OAuth Authorization Server REST httpx · no gRPC Hexagonal architecture Writes born PAUSED Reads via GAQL validateOnly dry-run Multi-tenant on Vercel OAuth Authorization Server
What it is

Your Google Ads, driven in natural language

MCP Google Ads is a Model Context Protocol server that gives Claude real access to your accounts — not a chatbot that guesses, but typed calls against the Google Ads REST API (v24+).

Real connection

Claude talks to your account

List campaigns, pull spend and conversion reports, research keywords and build Search campaigns — all by chatting with Claude. The Google login is OAuth2, embedded in the flow.

Architecture

Hexagonal, ports-and-adapters

Domain, application and infrastructure kept apart; a pure async httpx client, no gRPC. The same core runs local over stdio (single-tenant) or multi-tenant on Vercel.

Status

LIVE in production

Multi-tenant deploy at gamcp.vercel.app — tokens in Supabase, cache in Upstash, and we are the OAuth Authorization Server. Local mode keeps the refresh token in a 0600 file.

What it already does

The complete tool catalog

37 tools grouped by function — from auth to GAQL reporting, from keyword research to the Search funnel that's born paused. Everything below is already implemented and live.

Auth

4 tools
  • google_loginConnect a Google account (browser consent); stores the refresh token.
  • google_submit_callbackFinish login by submitting the redirected callback URL.
  • google_token_statusReports whether the stored credential is valid, its scopes and expiry.
  • google_refresh_tokenMints a fresh access token from the stored refresh token.

Reads & reporting (GAQL)

11 tools
  • list_accessible_customersLists the Google Ads accounts the credential can access.
  • list_campaignsLists campaigns in an account.
  • list_ad_groupsLists ad groups.
  • list_adsLists ads.
  • get_insightsSynchronous report: spend, impressions, clicks, conversions.
  • run_insights_reportLarger report over a date range.
  • get_search_termsSearch terms that triggered the ads.
  • get_recommendationsGoogle's optimization recommendations, filterable by type.
  • generate_keyword_ideasKeyword research: volume, competition, bids.
  • list_conversion_actionsLists the account's conversion actions.
  • get_conversion_tagsRetrieves the gtag / event snippets for a conversion.

Writes — Search funnel

6 · born PAUSED
  • create_campaign_budgetCreate a daily budget (in currency units).
  • create_campaignCreate a Search campaign bound to a budget.
  • create_ad_groupCreate an ad group under a campaign.
  • add_keywordsAdd keywords to an ad group.
  • create_responsive_search_adCreate an RSA (3–15 headlines ≤30 / 2–4 descriptions ≤90).
  • create_search_campaignComposite: budget → campaign → ad group → targeting → keywords → RSA in one call.

Writes — targeting & negatives

3 tools
  • add_geo_targetingAdd geo-target criteria to a campaign.
  • add_age_targetingAdd age-range criteria to an ad group.
  • add_negative_keywordsAdd negative keywords at campaign or ad-group level.

Writes — extensions (assets)

5 tools
  • create_sitelinksAttach sitelink assets to a campaign.
  • create_calloutsAttach callout assets (≤25 chars each).
  • create_structured_snippetAttach a structured-snippet asset (header + values).
  • create_callAttach a call asset (phone + region).
  • create_promotionAttach a promotion asset.

Writes — conversions, status & recs

6 · confirm=true
  • create_conversion_actionCreate a conversion action (returns its tag snippets).
  • update_campaign_statusSet a campaign active/paused/archived (destructive, needs confirm).
  • pause_campaignPause a campaign (destructive, needs confirm).
  • update_ad_group_statusSet an ad group active/paused/archived (destructive, needs confirm).
  • update_ad_statusSet an ad active/paused/archived (destructive, needs confirm).
  • apply_recommendationsApply Google recommendations by resource name (needs confirm).

There's also an MCP prompt analyze_account_performance for guided reporting.

Write safety model

Claude doesn't spend your money on its own

Writing to Google Ads touches real money. So every write goes through explicit guardrails — you're always in control of what becomes spend.

Creations born PAUSED

Nothing spends until you explicitly activate it. Every campaign, ad group and ad is created paused.

Status needs confirm=true

Changing status is destructive. Without confirm, the tool returns a preview and makes no HTTP call.

preview=true = dry-run

Runs a server-side validateOnly: validates the operation without persisting anything. Check before running for real.

No auto-rollback

The funnel is non-atomic: on a mid-way failure it returns the resources already created (PAUSED) and where it stopped — it deletes nothing.

Money in units

Budgets are given in currency units (20.0 = $20/day) and converted to micros in the use case. No cents confusion.

Scope whitelist

The credential only accesses what you authorized in the OAuth consent — and google_token_status shows exactly which scopes are active.

How to connect

Up and running in minutes

Two paths: hosted (recommended, zero setup) and local stdio (for single-tenant devs). Both end in the same place — Claude operating your account.

Recommended

Hosted — gamcp.vercel.app

Add the MCP server as a connector in Claude and log in. Nothing to install; we handle the developer token and the OAuth tokens.

  1. Add the connector. In Claude.ai → Settings → Connectors → Add custom connector, paste the MCP server URL. In Claude Code, use the command below.
    # Claude Code
    claude mcp add --transport http \
      google-ads https://gamcp.vercel.app
  2. Log in to Google. Run the google_login tool — it opens browser consent and stores your refresh token securely.
  3. Confirm. Run google_token_status to validate the credential and list_accessible_customers to see your accounts. Ready to operate.
Advanced

Local stdio — single-tenant

Run the server on your machine. The refresh token lives in a local 0600 file; you use your own MCC developer token.

  1. Install. Create the environment and install dependencies.
    python -m venv venv
    venv/bin/pip install -e ".[dev]"
    cp .env.example .env.local
  2. Configure credentials. Fill .env.local: GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, GOOGLE_ADS_DEVELOPER_TOKEN and NGROK_URL (public tunnel for the OAuth callback).
  3. Run and log in. Start the server and connect your account.
    PYTHONPATH=src venv/bin/python \
      -m mcp_google_ads
    # then, in Claude: google_login

Frequently asked questions

Still have a question? Write to bruno@b2tech.io.

How much does it cost?
The MCP Google Ads server is free. You only need a Google Ads account and, in local mode, a developer token from your MCC.
Is it safe? Can Claude spend money on its own?
No. Every creation is born PAUSED — it never spends until you explicitly activate it. Status changes are destructive and require confirm=true; without confirm, the tool returns a preview and makes no HTTP call.
Do I need a developer token?
In local stdio mode, yes — it comes from your Google Ads MCC API Center. On the hosted deploy (gamcp.vercel.app) the platform token is already configured; you just OAuth-log in your account.
Multi-tenant — where do my tokens live?
On the hosted deploy, refresh tokens live in Supabase and the cache in Upstash; we are the OAuth Authorization Server. In local mode, the refresh token sits in a 0600 file on your machine (single-tenant).
Which accounts can I access?
The accounts the logged-in credential can access. list_accessible_customers lists them all, and the manager/login-customer is auto-resolved per credential at google_login.
What is preview=true?
It's a server-side dry-run (validateOnly): it validates the operation without persisting anything. Handy to check a write before running it for real.
Local or hosted — which should I pick?
Hosted (gamcp.vercel.app) is the fast path: zero setup, just add it as a connector in Claude and log in. Local stdio is single-tenant, for devs who want everything on their own machine with the refresh token in a 0600 file.
Start now

Stop tab-switching.
Ask Claude and it runs Google Ads.

Reads, reporting, keyword research and Search campaigns — with embedded OAuth and writes that are born paused. Free and live.

37 tools · embedded OAuth2 · multi-tenant on Vercel