Skip to main content
Glama
Google Ads MCP Server

Google Ads MCP Server


๐Ÿ“Œ Contents

  1. Why this exists

  2. Features

  3. The safety check

  4. How it works

  5. What you can ask it

  6. Quick start

  7. Google Ads credentials

  8. Connect your AI client

  9. Configuration reference

  10. Tools

  11. Running it remotely

  12. Security

  13. Project structure

  14. Development

  15. Troubleshooting

  16. Roadmap

  17. Contributing

  18. Contributors

  19. License and attribution


Related MCP server: gads-write-mcp

๐Ÿ’ก Why this exists

Google Ads gives you a lot of power and a lot of screens. Checking last week's spend, finding wasted keywords, or setting up a Performance Max campaign can take many clicks โ€” and a single typo in a budget can cost real money.

This project is a Model Context Protocol (MCP) server: a small service that gives AI assistants a safe, well-defined set of Google Ads actions. You ask in plain language; the assistant uses the right tool; and anything that could spend money shows you a preview first and waits for your OK.

Without this

With this

Build reports by hand in the Ads UI

"Which campaigns spent the most last 30 days, and what was their ROAS?"

Hunt through search terms

"Show search terms with spend but no conversions this month"

Hope nobody mistypes a budget

Budget changes show $50 โ†’ $75/day, โ‰ˆ +$760/month and need your approval

Trust every AI client to ask first

The server itself refuses to apply risky changes without confirm=true


โœจ Features

Feature

Details

๐Ÿ“Š

Reporting

Campaign, ad group, keyword and search-term reports; account summaries; any read-only GAQL query

๐Ÿš€

Campaigns

Search, Display, Video, Demand Gen and Shopping โ€” created PAUSED by default

โšก

Performance Max

Full PMax setup in one call: budget, campaign, asset group, assets, audience signals

โœ๏ธ

Ads

Responsive search, responsive display, video and Demand Gen ads

๐Ÿ”‘

Keywords

Add, remove, re-bid and analyse keywords

๐Ÿ’ฐ

Budgets

Create, change and check budget use

๐Ÿข

Accounts

Accessible accounts and full MCC (manager) hierarchy

๐Ÿ›ก๏ธ

Safety check

Preview + confirm=true on 19 spend, launch and removal tools

๐Ÿšง

Spend limits

Optional hard caps on daily budget, % increase and CPC โ€” enforced even after confirmation

๐Ÿ”

Remote security

Bearer login, rate limiting, allowed hosts, secret-free /health

๐Ÿณ

Docker

Non-root image, credentials mounted at runtime, health check

๐Ÿงฉ

Claude plugin

/google-ads-setup command and a google-ads-manager skill that follows the safety workflow


๐Ÿ›ก๏ธ The safety check

Every tool that can start spend, raise spend, turn something on, or remove something works in two steps:

sequenceDiagram
    participant You
    participant AI as AI client
    participant S as MCP server
    participant G as Google Ads
    You->>AI: "Raise the Brand campaign budget to $75/day"
    AI->>S: update_budget(budget_id=โ€ฆ, amount=75)
    S->>G: read current budget ($50)
    S-->>AI: confirmation_required + preview<br/>$50 โ†’ $75 (+$25/day, โ‰ˆ +$760/month)<br/>nothing changed
    AI-->>You: shows the preview, asks to approve
    You->>AI: "Yes"
    AI->>S: update_budget(โ€ฆ, confirm=true)
    S->>G: apply change
    S-->>AI: success

What a preview looks like

{
  "success": false,
  "confirmation_required": true,
  "message": "Confirmation required. Nothing has been changed yet. โ€ฆ",
  "preview": {
    "tool": "update_budget",
    "summary": "Update budget 1234567",
    "current_state": { "daily_amount": 50.0 },
    "requested_changes": { "daily_amount": 75.0 },
    "financial_impact": "Daily budget changes from 50.00 to 75.00 (+25.00/day, about +760.00/month).",
    "reversible": true,
    "spend_limits": { "max_daily_budget": 500.0, "max_budget_increase_pct": 50.0, "max_cpc_bid": null }
  }
}

The rules

Action

What happens

Reading, reporting, GAQL

Runs instantly

Pausing anything

Runs instantly โ€” stopping spend is never delayed

Renaming

Runs instantly

Budgets, bids, creating or enabling campaigns / ad groups / ads, adding keywords, PMax creation

Preview first, then confirm=true

Removing campaigns, ad groups, ads, keywords or PMax assets

Preview first (marked not reversible), then confirm=true

Anything above a configured spend limit

Refused, even with confirm=true

Spend limits are optional environment variables โ€” see Configuration. They catch the "extra zero" mistake no matter who or what confirmed it.


๐Ÿงญ How it works

One Python server in src/google_ads_mcp/ serves every AI client. Folders under clients/ and docs/clients/ only explain how to launch or connect it. The full design is in ARCHITECTURE.md.


๐Ÿ’ฌ What you can ask it

Reporting

  • "How did my campaigns perform this week compared to last week?"

  • "Which keywords spent over $100 with no conversions in the last 30 days?"

  • "Show the search terms report for the Brand campaign."

  • "What's our budget utilisation for active campaigns?"

Building (you'll see a preview first)

  • "Create a paused Search campaign called Spring Sale with a $40/day budget."

  • "Add these 10 phrase-match keywords to ad group 12345."

  • "Write a responsive search ad for our landing page."

  • "Set up a Performance Max campaign for the new product line."

Changes

  • "Pause every campaign with CPA over $80." (runs immediately)

  • "Raise the Brand budget by 20%." (preview, then confirm)

  • "Remove the old Black Friday campaign." (preview, marked not reversible)


โšก Quick start

You need: Python 3.12+, uv (or Docker), a Google Ads developer token, and a GCP service account with access to your Ads account (details).

# 1. Get the code
git clone https://github.com/nexoradev-stack/google-ads-manager-ai-plugin.git
cd google-ads-manager-ai-plugin

# 2. Install
uv sync

# 3. Add credentials (never commit .env)
cp .env.example .env
#   edit: GOOGLE_ADS_DEVELOPER_TOKEN, GOOGLE_ADS_SERVICE_ACCOUNT_PATH,
#         GOOGLE_ADS_LOGIN_CUSTOMER_ID (if you use an MCC)
#   recommended: GOOGLE_ADS_MAX_DAILY_BUDGET=500

# 4. Run (local stdio โ€” what Claude Desktop, Cursor and Gemini CLI use)
uv run google-ads-mcp

Then connect your AI client and start with a read-only question such as "List my accessible Google Ads accounts."


๐Ÿ”‘ Google Ads credentials

Variable

Required

What it is

GOOGLE_ADS_DEVELOPER_TOKEN

โœ…

From the API Center in your Google Ads manager account

GOOGLE_ADS_SERVICE_ACCOUNT_PATH

โœ…

Path to the service-account JSON key

GOOGLE_ADS_LOGIN_CUSTOMER_ID

MCC only

Your manager (MCC) account ID

GOOGLE_ADS_CUSTOMER_ID

Default account when a tool call omits customer_id

GOOGLE_ADS_IMPERSONATED_EMAIL

Workspace only

User to impersonate with domain-wide delegation

Steps

  1. In Google Cloud, create a service account, enable the Google Ads API, and download its JSON key.

  2. Give the service account access to your Ads account: add its email as a user in Google Ads where your account supports it, or, for Workspace-owned accounts, enable domain-wide delegation and set GOOGLE_ADS_IMPERSONATED_EMAIL. Google's service account guide has the current options.

  3. Get a developer token from Tools โ†’ API Center in your manager account.

  4. Put the values in .env. Dashes in customer IDs are fine โ€” they're removed automatically.

If credentials are missing or wrong, the server still starts so offline tools (convert_micros, list_gaql_resources, get_field_metadata) keep working, and the log explains what's missing.


๐Ÿ”Œ Connect your AI client

Client

Local (stdio)

Remote (HTTP)

Guide

Claude (Desktop, Code, plugin)

โœ…

โœ…

docs/clients/claude.md

ChatGPT

โ€”

โœ… (HTTPS or Secure MCP Tunnel)

docs/clients/chatgpt.md

Gemini CLI

โœ…

โœ…

docs/clients/gemini.md

Cursor

โœ…

โœ…

docs/clients/cursor.md

{
  "mcpServers": {
    "google-ads": {
      "command": "uv",
      "args": ["run", "--directory", "/ABSOLUTE/PATH/TO/google-ads-manager-ai-plugin", "google-ads-mcp"]
    }
  }
}

Credentials are read from the .env file in that folder. Ready-made files: clients/.

{
  "mcpServers": {
    "google-ads": {
      "url": "https://ads-mcp.example.com/mcp",
      "headers": { "Authorization": "Bearer YOUR_MCP_HTTP_BEARER_TOKEN" }
    }
  }
}

Add this repository as a plugin marketplace in Claude, install google-ads-manager, then run /google-ads-setup. The bundled skill tells Claude to show every preview and ask before confirming.


โš™๏ธ Configuration reference

Spend limits (optional, recommended โ€” refused even after confirmation)

Variable

Example

Effect

GOOGLE_ADS_MAX_DAILY_BUDGET

500

No budget, campaign or PMax campaign above 500/day

GOOGLE_ADS_MAX_BUDGET_INCREASE_PCT

50

No single budget increase above +50%

GOOGLE_ADS_MAX_CPC_BID

20

No ad-group or keyword max-CPC bid above 20

Transport and remote protection

Variable

Default

Effect

MCP_TRANSPORT

stdio

stdio, streamable-http or sse

MCP_HOST / MCP_PORT

127.0.0.1 / 8000

Bind address for HTTP transports (PORT also works)

MCP_HTTP_BEARER_TOKEN

โ€”

Required Authorization: Bearer โ€ฆ on /mcp. Mandatory to bind a non-local address

MCP_ALLOWED_HOSTS

โ€”

Your public domain(s), comma-separated, for Host-header checks

MCP_RATE_LIMIT_MAX

120

Requests per window per client IP

MCP_RATE_LIMIT_WINDOW_SECONDS

60

Rate-limit window

MCP_ALLOW_UNAUTHENTICATED

false

Only behind a proxy that already authenticates users


๐Ÿงฐ Tools

47 tools in 9 areas. ๐ŸŸข read ยท ๐ŸŸก write (instant) ยท ๐Ÿ”ด gated (preview, then confirm=true)

Area

Tools

Accounts ๐ŸŸข

list_accessible_accounts ยท get_account_info ยท get_account_hierarchy

Campaigns

๐ŸŸข list_campaigns ยท get_campaign โ€” ๐Ÿ”ด create_campaign ยท update_campaign* ยท set_campaign_status* ยท remove_campaign

Ad groups

๐ŸŸข list_ad_groups ยท get_ad_group โ€” ๐Ÿ”ด create_ad_group* ยท update_ad_group* ยท set_ad_group_status*

Budgets

๐ŸŸข list_budgets ยท get_budget_utilization โ€” ๐Ÿ”ด create_budget ยท update_budget*

Ads

๐ŸŸข list_ads ยท get_ad_details โ€” ๐Ÿ”ด create_responsive_search_ad* ยท create_responsive_display_ad* ยท create_video_ad* ยท create_demand_gen_ad* ยท set_ad_status*

Keywords

๐ŸŸข list_keywords ยท get_keyword_performance โ€” ๐Ÿ”ด add_keywords ยท update_keyword_bid ยท remove_keyword

Performance Max

๐ŸŸข list_asset_groups ยท get_asset_group_details ยท get_asset_performance ยท get_pmax_placement_performance โ€” ๐ŸŸก add_assets_to_group ยท add_audience_signal โ€” ๐Ÿ”ด create_performance_max_campaign ยท remove_asset_from_group

Reporting ๐ŸŸข

execute_gaql ยท get_campaign_performance ยท get_ad_group_performance ยท get_search_terms_report ยท get_keyword_performance_report ยท get_account_performance_summary

Utilities ๐ŸŸข

list_gaql_resources ยท get_field_metadata ยท convert_micros

* Gated only for the risky case โ€” e.g. set_campaign_status gates ENABLED and REMOVED but pauses instantly; ads and ad groups created PAUSED with no bids run instantly. Exact rules per tool: docs/tools.md.


๐ŸŒ Running it remotely

ChatGPT (and any hosted setup) needs the HTTP transport.

export MCP_HTTP_BEARER_TOKEN="$(openssl rand -hex 32)"
export MCP_ALLOWED_HOSTS=ads-mcp.example.com
uv run google-ads-mcp --transport streamable-http --host 0.0.0.0 --port 8000
curl http://localhost:8000/health

Docker

export GOOGLE_ADS_DEVELOPER_TOKEN=...
export GOOGLE_ADS_LOGIN_CUSTOMER_ID=...
export GOOGLE_ADS_SERVICE_ACCOUNT_HOST_PATH=/absolute/path/to/service-account.json
export MCP_HTTP_BEARER_TOKEN="$(openssl rand -hex 32)"
export MCP_ALLOWED_HOSTS=ads-mcp.example.com
docker compose up --build

The service-account key is bind-mounted read-only โ€” never copied into the image. Put HTTPS in front (reverse proxy or platform ingress). The server refuses to start on a public address without a bearer token.

/health reports version, whether credentials are configured (never their values), whether login is on, and the active spend limits.


๐Ÿ” Security

  • Credentials come only from environment variables, .env or mounted secrets, and are never logged.

  • The server cannot change billing, user access or account permissions.

  • 19 risky tools need explicit confirmation; spend limits are enforced server-side.

  • Remote mode: constant-time bearer check, per-IP rate limit, Host allow-list, secret-free /health.

Report vulnerabilities privately โ€” see SECURITY.md.


๐Ÿ—‚๏ธ Project structure

google-ads-manager-ai-plugin/
โ”œโ”€โ”€ src/google_ads_mcp/          # โญ the one MCP server
โ”‚   โ”œโ”€โ”€ server.py                # FastMCP app, /health, CLI, transport startup
โ”‚   โ”œโ”€โ”€ safety.py                # confirmation gate + spend limits
โ”‚   โ”œโ”€โ”€ http_security.py         # bearer login, rate limit, allowed hosts
โ”‚   โ”œโ”€โ”€ client.py ยท config.py    # Google Ads client wrapper and settings
โ”‚   โ”œโ”€โ”€ annotations.py           # MCP tool hints (read-only / destructive โ€ฆ)
โ”‚   โ”œโ”€โ”€ helpers.py               # GAQL, micros, responses
โ”‚   โ””โ”€โ”€ tools/                   # 9 files, 47 tools
โ”œโ”€โ”€ tests/                       # 253 tests, Google Ads API fully mocked
โ”œโ”€โ”€ google-ads-manager/          # Claude plugin: command, skill, .mcp.json
โ”œโ”€โ”€ clients/ ยท docs/clients/     # per-client configs and guides
โ”œโ”€โ”€ docs/tools.md                # full tool catalog with risk levels
โ”œโ”€โ”€ assets/                      # banner + architecture (SVG source, PNG)
โ”œโ”€โ”€ Dockerfile ยท docker-compose.yml
โ”œโ”€โ”€ ARCHITECTURE.md ยท CHANGELOG.md ยท SECURITY.md ยท CONTRIBUTING.md
โ””โ”€โ”€ LICENSE ยท NOTICE

๐Ÿ› ๏ธ Development

uv sync --all-groups
uv run pytest -q              # 253 tests, no credentials needed
uv run google-ads-mcp --help
docker build -t google-ads-manager-ai-plugin:dev .

CI runs the tests on Python 3.12 and 3.13 and builds the Docker image on every push and pull request.


๐Ÿงฏ Troubleshooting

Symptom

Fix

Google Ads client is not available

Check the GOOGLE_ADS_* variables and that the key file path exists

confirmation_required: true

Expected โ€” review the preview and call again with confirm=true

blocked_by_spend_limit

A GOOGLE_ADS_MAX_* limit was hit; change the request or the limit

Refusing to listen on 0.0.0.0 without MCP_HTTP_BEARER_TOKEN

Set a bearer token, or bind to 127.0.0.1

401 on /mcp

Send Authorization: Bearer <token> from the client

421 Misdirected Request

Add your domain to MCP_ALLOWED_HOSTS

429 Rate limit exceeded

Wait Retry-After seconds or raise MCP_RATE_LIMIT_MAX

ChatGPT can't use stdio

Deploy streamable-http or use a Secure MCP Tunnel

Client can't start the server

Use absolute paths and make sure uv is on PATH


๐Ÿ—บ๏ธ Roadmap

Planned work is tracked as GitHub issues in four milestones:

Milestone

Focus

Highlights

v1.1 โ€” Hardening

Security and reliability

Validated GAQL inputs, validate_only dry-runs in previews, confirmation bound to the previewed request, linting, coverage, releases

v1.2 โ€” Reporting+

Better answers

Period comparisons, budget pacing, wasted-spend finder, Quality Score, change history, account health

v1.3 โ€” Campaign ops

More actions

Negative keywords, sitelinks and callouts, location targeting, bulk pause, conversions, image uploads, experiments

v2.0 โ€” Team scale

Running for a team

OAuth login, per-user access, audit log, account allow-list, read-only mode, account-wide spend cap

Good first contributions carry the good first issue label.


๐Ÿค Contributing

See CONTRIBUTING.md. The short version: put logic in src/google_ads_mcp/, keep tool names stable, route any spend/launch/removal tool through the safety gate, never gate pausing, and never commit credentials.


๐Ÿ‘ฅ Contributors

Contributor

Role

๐Ÿค–

Claude (Anthropic)

Safety gate, spend limits, remote security, tests, documentation, architecture

โŒจ๏ธ

Cursor

AI code editor โ€” implementation and refactoring


๐Ÿ“„ License and attribution

Licensed under the Apache License 2.0 โ€” see LICENSE.

This project is derived from google-ads-claude-plugin by Neelkant Ekbote (Apache-2.0). The required attribution and a summary of changes are in NOTICE.

Available Tools

47 tools
add_assets_to_groupA

Add assets to an existing asset group (batch link operation).

Args:
    customer_id: Google Ads customer ID.
    asset_group_id: Asset group ID.
    assets: List of asset dicts, each with:
        - asset_resource_name (str): Full asset resource name.
        - field_type (str): Asset field type -- 'HEADLINE', 'LONG_HEADLINE',
          'DESCRIPTION', 'BUSINESS_NAME', 'MARKETING_IMAGE',
          'SQUARE_MARKETING_IMAGE', 'LOGO', 'YOUTUBE_VIDEO', 'CALL_TO_ACTION_SELECTION'.

Example:
    assets=[
        {"asset_resource_name": "customers/123/assets/456", "field_type": "HEADLINE"},
        {"asset_resource_name": "customers/123/assets/789", "field_type": "MARKETING_IMAGE"},
    ]

Inputs: assets (required), customer_id (required), asset_group_id (required).

add_audience_signalA

Add audience or search theme signals to a PMax asset group.

Audience signals help Google's AI find the right customers. They're suggestions,
not hard targeting constraints.

Args:
    customer_id: Google Ads customer ID.
    asset_group_id: Asset group ID.
    audience_resource_name: Audience resource name (from audience manager).
    search_themes: List of search theme strings (keywords that describe your ideal customer).

Inputs: customer_id (required), asset_group_id (required), search_themes, audience_resource_name.

add_keywordsA

Add keywords to an ad group (batch operation).

Safety: new keywords are live immediately in an enabled ad group, so this
returns a preview first; call again with confirm=True. Refused if any
cpc_bid is above GOOGLE_ADS_MAX_CPC_BID.

Args:
    customer_id: Google Ads customer ID.
    ad_group_id: Ad group ID to add keywords to.
    keywords: List of keyword dicts, each with:
        - text (str): The keyword text.
        - match_type (str): 'EXACT', 'PHRASE', or 'BROAD'.
        - cpc_bid (float, optional): Max CPC bid in currency.

Example:
    keywords=[
        {"text": "buy shoes online", "match_type": "PHRASE", "cpc_bid": 1.50},
        {"text": "running shoes", "match_type": "BROAD"},
        {"text": "[red running shoes]", "match_type": "EXACT", "cpc_bid": 2.00},
    ]

Inputs: keywords (required), ad_group_id (required), customer_id (required), confirm.

convert_microsA
Read-only

Convert between micros and currency amounts.

Google Ads uses micros for monetary values: $1.00 = 1,000,000 micros.

Args:
    value: The value to convert.
    direction: 'to_micros' (currency to micros) or 'from_micros' (micros to currency).

Inputs: value (required), direction.

create_ad_groupA

Create a new ad group in a campaign.

Safety: creating an ENABLED ad group or setting a bid returns a preview
first; call again with confirm=True. A PAUSED ad group with no bid is
created immediately. Refused if cpc_bid is above GOOGLE_ADS_MAX_CPC_BID.

Args:
    customer_id: Google Ads customer ID.
    campaign_id: Campaign ID to create the ad group in.
    name: Ad group name.
    cpc_bid: Max CPC bid in currency (e.g., 2.50 for $2.50).
    target_cpa: Target CPA in currency (overrides campaign-level if set).
    ad_group_type: Ad group type -- 'SEARCH_STANDARD', 'DISPLAY_STANDARD',
        'VIDEO_TRUE_VIEW_IN_STREAM', 'VIDEO_BUMPER', etc.
    status: Initial status -- 'ENABLED' (default) or 'PAUSED'.
    confirm: Must be True to create an ENABLED ad group or one with bids.

Inputs: name (required), campaign_id (required), customer_id (required), status, +4 more.

create_budgetA

Create a new campaign budget.

Safety: returns a preview first. Call again with confirm=True to create it.
Refused if the amount is above GOOGLE_ADS_MAX_DAILY_BUDGET.

Args:
    customer_id: Google Ads customer ID.
    name: Budget name.
    amount: Daily budget amount in currency (e.g., 50.00 for $50/day).
    delivery_method: 'STANDARD' (spread evenly) or 'ACCELERATED'.
    explicitly_shared: If True, budget can be shared across multiple campaigns.
    confirm: Must be True to actually create the budget (after reviewing the preview).

Inputs: name (required), amount (required), customer_id (required), confirm, +2 more.

create_campaignA

Create a new campaign with a budget.

Creates both the campaign budget and campaign in a single atomic operation.
Campaign is created as PAUSED by default for safety.

Safety: returns a preview first; call again with confirm=True to create it.
Refused if budget_amount is above GOOGLE_ADS_MAX_DAILY_BUDGET.

Args:
    customer_id: Google Ads customer ID.
    name: Campaign name.
    budget_amount: Daily budget in currency (e.g., 50.00 for $50/day).
    channel_type: Campaign type -- 'SEARCH', 'DISPLAY', 'VIDEO', 'DEMAND_GEN', 'SHOPPING'.
    bidding_strategy: Bidding strategy -- 'MAXIMIZE_CONVERSIONS', 'MAXIMIZE_CONVERSION_VALUE',
        'MAXIMIZE_CLICKS', 'TARGET_SPEND', 'MANUAL_CPC', 'TARGET_CPA', 'TARGET_ROAS'.
    target_cpa: Target CPA in currency (required if bidding_strategy is TARGET_CPA).
    target_roas: Target ROAS as a decimal (e.g., 3.0 for 300% ROAS).
    network_settings: Optional dict with keys: target_google_search, target_search_network,
        target_content_network (all bool).
    start_date: Campaign start date (YYYY-MM-DD). Defaults to today.
    end_date: Optional campaign end date (YYYY-MM-DD).
    status: Initial status -- 'PAUSED' (default, recommended) or 'ENABLED'.
    confirm: Must be True to actually create the campaign (after reviewing the preview).

Inputs: name (required), customer_id (required), budget_amount (required), status, +8 more.

create_demand_gen_adA

Create a Demand Gen ad (serves on YouTube, Gmail, Discover).

Safety: an ENABLED ad returns a preview first; call again with confirm=True.
A PAUSED ad is created immediately.

Args:
    customer_id: Google Ads customer ID.
    ad_group_id: Ad group ID (must be in a Demand Gen campaign).
    headlines: 1-5 headlines (max 40 chars each).
    descriptions: 1-5 descriptions (max 90 chars each).
    marketing_images: Landscape image asset resource names.
    logo_images: Logo asset resource names.
    final_urls: Landing page URLs.
    business_name: Business name.
    call_to_action_text: Optional CTA text.
    status: Ad status -- 'ENABLED' (default) or 'PAUSED'.

Inputs: headlines (required), final_urls (required), ad_group_id (required), customer_id (required), +7 more.

create_performance_max_campaignA

Create a complete Performance Max campaign with budget, campaign, and asset group.

Creates everything in a single atomic batch operation using temporary IDs.
Campaign is created as PAUSED by default for safety.

Safety: returns a preview first; call again with confirm=True to create it.
Refused if budget_amount is above GOOGLE_ADS_MAX_DAILY_BUDGET.

PMax minimum requirements:
- 3+ headlines (max 30 chars each)
- 1+ long headlines (max 90 chars)
- 2+ descriptions (max 90 chars each)
- 1 business name
- Final URLs
- Image assets should be pre-uploaded (use asset resource names)

Args:
    customer_id: Google Ads customer ID.
    campaign_name: Campaign name.
    budget_amount: Daily budget in currency.
    asset_group_name: Name for the asset group.
    final_urls: Landing page URLs.
    headlines: 3-15 headlines (max 30 chars each).
    long_headlines: 1-5 long headlines (max 90 chars each).
    descriptions: 2-5 descriptions (max 90 chars each).
    business_name: Business name for the asset group.
    marketing_image_assets: Landscape image asset resource names (1200x628).
    square_image_assets: Square image asset resource names (1200x1200).
    logo_assets: Logo image asset resource names.
    youtube_video_assets: YouTube video asset resource names.
    bidding_strategy: 'MAXIMIZE_CONVERSIONS' or 'MAXIMIZE_CONVERSION_VALUE'.
    target_cpa: Target CPA (for maximize_conversions with target).
    target_roas: Target ROAS (for maximize_conversion_value with target).
    status: Initial status -- 'PAUSED' (default) or 'ENABLED'.
    confirm: Must be True to actually create the campaign (after reviewing the preview).

Inputs: headlines (required), final_urls (required), customer_id (required), descriptions (required), +14 more.

create_responsive_display_adA

Create a Responsive Display Ad for Display campaigns.

Safety: an ENABLED ad returns a preview first; call again with confirm=True.
A PAUSED ad is created immediately.

Args:
    customer_id: Google Ads customer ID.
    ad_group_id: Ad group ID (must be in a Display campaign).
    headlines: 1-5 short headlines (max 30 chars each).
    long_headline: Long headline (max 90 chars).
    descriptions: 1-5 descriptions (max 90 chars each).
    marketing_images: List of landscape image asset resource names (1200x628).
    square_marketing_images: List of square image asset resource names (1200x1200).
    logo_images: List of logo asset resource names.
    business_name: Business name (max 25 chars).
    final_urls: Landing page URLs.
    call_to_action_text: Optional CTA text.
    status: Ad status -- 'ENABLED' (default) or 'PAUSED'.

Inputs: headlines (required), final_urls (required), ad_group_id (required), customer_id (required), +9 more.

create_responsive_search_adA

Create a Responsive Search Ad (RSA) for Search campaigns.

Google will automatically test combinations of headlines and descriptions.

Safety: an ENABLED ad returns a preview first; call again with confirm=True.
A PAUSED ad is created immediately.

Args:
    customer_id: Google Ads customer ID.
    ad_group_id: Ad group ID (must be in a Search campaign).
    headlines: 3-15 headline strings (max 30 chars each).
    descriptions: 2-4 description strings (max 90 chars each).
    final_urls: List of landing page URLs (at least one required).
    path1: Optional display URL path 1 (max 15 chars).
    path2: Optional display URL path 2 (max 15 chars, requires path1).
    status: Ad status -- 'ENABLED' (default) or 'PAUSED'.

Inputs: headlines (required), final_urls (required), ad_group_id (required), customer_id (required), +5 more.

create_video_adA

Create a Video ad for Video campaigns (YouTube).

Safety: an ENABLED ad returns a preview first; call again with confirm=True.
A PAUSED ad is created immediately.

Args:
    customer_id: Google Ads customer ID.
    ad_group_id: Ad group ID (must be in a Video campaign).
    youtube_video_id: YouTube video ID (e.g., 'dQw4w9WgXcQ').
    final_urls: Landing page URLs.
    headline: Optional headline for the ad.
    description: Optional description.
    call_to_action_text: CTA button text (e.g., 'Learn More', 'Shop Now').
    ad_format: Video ad format -- 'IN_STREAM' (skippable), 'BUMPER' (6-sec non-skip),
        'IN_FEED' (discovery/in-feed).
    companion_banner_asset: Optional companion banner image asset resource name.
    status: Ad status -- 'ENABLED' (default) or 'PAUSED'.

Inputs: final_urls (required), ad_group_id (required), customer_id (required), youtube_video_id (required), +7 more.

execute_gaqlA
Read-only

Execute an arbitrary GAQL (Google Ads Query Language) query.

This is the most flexible tool -- use it for any read query not covered by other tools.
GAQL reference: https://developers.google.com/google-ads/api/docs/query/overview

Args:
    customer_id: Google Ads customer ID.
    query: Full GAQL query string (SELECT ... FROM ... WHERE ...).

Inputs: query (required), customer_id (required).

get_account_hierarchyB
Read-only

Get the MCC account hierarchy tree.

Lists all child accounts under the given MCC account.

Args:
    customer_id: MCC customer ID. Uses default if not provided.

Inputs: customer_id.

get_account_infoB
Read-only

Get details for a Google Ads account (name, currency, timezone, etc.).

Args:
    customer_id: Google Ads customer ID (e.g., '123-456-7890' or '1234567890').

Inputs: customer_id (required).

get_account_performance_summaryC
Read-only

Get account-level daily performance summary.

Args:
    customer_id: Google Ads customer ID.
    date_range: Date range (predefined or 'YYYY-MM-DD,YYYY-MM-DD').

Inputs: customer_id (required), date_range.

get_ad_detailsB
Read-only

Get full details of an ad (headlines, descriptions, URLs, assets).

Args:
    customer_id: Google Ads customer ID.
    ad_group_id: Ad group ID containing the ad.
    ad_id: Ad ID.

Inputs: ad_id (required), ad_group_id (required), customer_id (required).

get_ad_groupC
Read-only

Get details for a single ad group.

Args:
    customer_id: Google Ads customer ID.
    ad_group_id: Ad group ID.

Inputs: ad_group_id (required), customer_id (required).

get_ad_group_performanceC
Read-only

Get ad group performance metrics.

Args:
    customer_id: Google Ads customer ID.
    campaign_id: Optional -- filter to ad groups in this campaign.
    date_range: Date range (predefined or 'YYYY-MM-DD,YYYY-MM-DD').
    limit: Max rows (default 50).

Inputs: customer_id (required), limit, date_range, campaign_id.

get_asset_group_detailsB
Read-only

Get full details of an asset group including linked assets and signals.

Args:
    customer_id: Google Ads customer ID.
    asset_group_id: Asset group ID.

Inputs: customer_id (required), asset_group_id (required).

get_asset_performanceB
Read-only

Get asset-level performance labels (BEST, GOOD, LOW, etc.) for PMax.

Args:
    customer_id: Google Ads customer ID.
    campaign_id: Optional -- filter to a specific campaign.
    asset_group_id: Optional -- filter to a specific asset group.

Inputs: customer_id (required), campaign_id, asset_group_id.

get_budget_utilizationB
Read-only

Get budget vs actual spend for campaigns.

Shows how much of each campaign's budget has been utilized.

Args:
    customer_id: Google Ads customer ID.
    date_range: Date range (predefined or 'YYYY-MM-DD,YYYY-MM-DD').
    campaign_id: Optional -- filter to a single campaign.

Inputs: customer_id (required), date_range, campaign_id.

get_campaignC
Read-only

Get details for a single campaign.

Args:
    customer_id: Google Ads customer ID.
    campaign_id: The campaign ID.

Inputs: campaign_id (required), customer_id (required).

get_campaign_performanceA
Read-only

Get campaign performance metrics over a date range.

Args:
    customer_id: Google Ads customer ID.
    date_range: Date range -- use predefined (LAST_7_DAYS, LAST_30_DAYS, THIS_MONTH,
        LAST_MONTH, etc.) or custom 'YYYY-MM-DD,YYYY-MM-DD'.
    campaign_id: Optional -- filter to a single campaign.
    status_filter: Optional -- filter by status (ENABLED, PAUSED, REMOVED).
    limit: Max rows to return (default 50).

Inputs: customer_id (required), limit, date_range, campaign_id, +1 more.

get_field_metadataA
Read-only

Get selectable, filterable, and sortable fields for a GAQL resource.

Args:
    resource_type: Resource name (e.g., 'campaign', 'ad_group', 'ad_group_ad').
    customer_id: Customer ID (uses default if not provided).

Inputs: resource_type (required), customer_id.

get_keyword_performanceB
Read-only

Get keyword performance metrics for an ad group.

Args:
    customer_id: Google Ads customer ID.
    ad_group_id: Ad group ID.
    date_range: Date range (predefined or 'YYYY-MM-DD,YYYY-MM-DD').
    limit: Max rows (default 100).

Inputs: ad_group_id (required), customer_id (required), limit, date_range.

get_keyword_performance_reportB
Read-only

Get keyword-level performance metrics.

Args:
    customer_id: Google Ads customer ID.
    campaign_id: Optional campaign filter.
    ad_group_id: Optional ad group filter.
    date_range: Date range (predefined or 'YYYY-MM-DD,YYYY-MM-DD').
    limit: Max rows (default 100).

Inputs: customer_id (required), limit, date_range, ad_group_id, +1 more.

get_pmax_placement_performanceA
Read-only

Get PMax placement performance breakdown (Search, YouTube, Display, Discover, Gmail).

Args:
    customer_id: Google Ads customer ID.
    campaign_id: PMax campaign ID.
    date_range: Date range (predefined or 'YYYY-MM-DD,YYYY-MM-DD').

Inputs: campaign_id (required), customer_id (required), date_range.

get_search_terms_reportC
Read-only

Get search terms that triggered your ads.

Args:
    customer_id: Google Ads customer ID.
    campaign_id: Optional campaign filter.
    ad_group_id: Optional ad group filter.
    date_range: Date range (predefined or 'YYYY-MM-DD,YYYY-MM-DD').
    limit: Max rows (default 100).

Inputs: customer_id (required), limit, date_range, ad_group_id, +1 more.

list_accessible_accountsB
Read-only

List all Google Ads accounts accessible via current credentials.

Returns accounts accessible through the authenticated MCC or direct account.

Inputs: no named parameters.

list_ad_groupsA
Read-only

List ad groups in a campaign.

Args:
    customer_id: Google Ads customer ID.
    campaign_id: Campaign ID to list ad groups for.
    status_filter: Optional -- 'ENABLED', 'PAUSED', or 'REMOVED'.
    limit: Max ad groups to return (default 100).

Inputs: campaign_id (required), customer_id (required), limit, status_filter.

list_adsA
Read-only

List ads in an ad group with approval status.

Args:
    customer_id: Google Ads customer ID.
    ad_group_id: Ad group ID.
    status_filter: Optional -- 'ENABLED', 'PAUSED', or 'REMOVED'.
    limit: Max ads to return (default 50).

Inputs: ad_group_id (required), customer_id (required), limit, status_filter.

list_asset_groupsC
Read-only

List asset groups in a Performance Max campaign.

Args:
    customer_id: Google Ads customer ID.
    campaign_id: PMax campaign ID.

Inputs: campaign_id (required), customer_id (required).

list_budgetsC
Read-only

List campaign budgets in the account.

Args:
    customer_id: Google Ads customer ID.
    limit: Max budgets to return (default 100).

Inputs: customer_id (required), limit.

list_campaignsA
Read-only

List campaigns in a Google Ads account.

Args:
    customer_id: Google Ads customer ID.
    status_filter: Optional filter -- 'ENABLED', 'PAUSED', or 'REMOVED'.
    limit: Max campaigns to return (default 100).

Inputs: customer_id (required), limit, status_filter.

list_gaql_resourcesA
Read-only

List available GAQL FROM-clause resources for use with execute_gaql.

Returns commonly used resource names that can be queried via GAQL.

Inputs: no named parameters.

list_keywordsA
Read-only

List keywords in an ad group.

Args:
    customer_id: Google Ads customer ID.
    ad_group_id: Ad group ID.
    status_filter: Optional -- 'ENABLED', 'PAUSED', or 'REMOVED'.
    limit: Max keywords to return (default 200).

Inputs: ad_group_id (required), customer_id (required), limit, status_filter.

remove_asset_from_groupA
DestructiveIdempotent

Remove an asset from an asset group.

Safety: returns a preview first; call again with confirm=True to remove.

Args:
    customer_id: Google Ads customer ID.
    asset_group_id: Asset group ID.
    asset_resource_name: Full resource name of the asset to unlink.
    field_type: The field type of the asset link (e.g., 'HEADLINE', 'MARKETING_IMAGE').
    confirm_removal: Older name for confirm; either one set to True proceeds.
    confirm: Must be True to proceed (after reviewing the preview).

Inputs: field_type (required), customer_id (required), asset_group_id (required), asset_resource_name (required), +2 more.

remove_campaignA
DestructiveIdempotent

Soft-delete (remove) a campaign.

This is a destructive operation. The campaign will be set to REMOVED status.
Safety: returns a preview first; call again with confirm=True to remove.

Args:
    customer_id: Google Ads customer ID.
    campaign_id: Campaign ID to remove.
    confirm_removal: Older name for confirm; either one set to True proceeds.
    confirm: Must be True to proceed (after reviewing the preview).

Inputs: campaign_id (required), customer_id (required), confirm, confirm_removal.

remove_keywordA
DestructiveIdempotent

Remove a keyword from an ad group.

Safety: returns a preview first; call again with confirm=True to remove.

Args:
    customer_id: Google Ads customer ID.
    ad_group_id: Ad group ID containing the keyword.
    criterion_id: Keyword criterion ID to remove.
    confirm_removal: Older name for confirm; either one set to True proceeds.
    confirm: Must be True to proceed (after reviewing the preview).

Inputs: ad_group_id (required), customer_id (required), criterion_id (required), confirm, +1 more.

set_ad_group_statusA
DestructiveIdempotent

Set an ad group's status (enable, pause, or remove).

Safety: PAUSED applies immediately; ENABLED and REMOVED return a preview
first and need confirm=True.

Args:
    customer_id: Google Ads customer ID.
    ad_group_id: Ad group ID.
    status: New status -- 'ENABLED', 'PAUSED', or 'REMOVED'.
    confirm: Must be True to enable or remove.

Inputs: status (required), ad_group_id (required), customer_id (required), confirm.

set_ad_statusA
DestructiveIdempotent

Set an ad's status (enable, pause, or remove).

Safety: PAUSED applies immediately; ENABLED and REMOVED return a preview
first and need confirm=True.

Args:
    customer_id: Google Ads customer ID.
    ad_group_id: Ad group ID containing the ad.
    ad_id: Ad ID.
    status: New status -- 'ENABLED', 'PAUSED', or 'REMOVED'.

Inputs: ad_id (required), status (required), ad_group_id (required), customer_id (required), +1 more.

set_campaign_statusA
DestructiveIdempotent

Set a campaign's status (enable, pause, or remove).

Safety: PAUSED is applied immediately (it stops spend). ENABLED and REMOVED
return a preview first; call again with confirm=True to apply.

Args:
    customer_id: Google Ads customer ID.
    campaign_id: Campaign ID.
    status: New status -- 'ENABLED', 'PAUSED', or 'REMOVED'.
    confirm: Must be True to enable or remove.

Inputs: status (required), campaign_id (required), customer_id (required), confirm.

update_ad_groupA
Idempotent

Update an existing ad group.

Only provided fields will be updated.

Safety: bid changes, enabling and removing return a preview first; call
again with confirm=True. Renaming and pausing apply immediately. Refused if
cpc_bid is above GOOGLE_ADS_MAX_CPC_BID.

Args:
    customer_id: Google Ads customer ID.
    ad_group_id: Ad group ID to update.
    name: New ad group name.
    cpc_bid: New max CPC bid in currency.
    target_cpa: New target CPA in currency.
    status: New status -- 'ENABLED', 'PAUSED', or 'REMOVED'.
    confirm: Must be True to apply a gated change.

Inputs: ad_group_id (required), customer_id (required), name, status, +3 more.

update_budgetA
Idempotent

Update an existing campaign budget.

Safety: changing the amount or delivery method returns a preview first
(current vs new amount); call again with confirm=True to apply. Renaming
only is applied immediately. Refused if the new amount breaks
GOOGLE_ADS_MAX_DAILY_BUDGET or GOOGLE_ADS_MAX_BUDGET_INCREASE_PCT.

Args:
    customer_id: Google Ads customer ID.
    budget_id: Budget ID to update.
    amount: New daily budget amount in currency.
    name: New budget name.
    delivery_method: New delivery method -- 'STANDARD' or 'ACCELERATED'.
    confirm: Must be True to apply an amount or delivery change.

Inputs: budget_id (required), customer_id (required), name, amount, +2 more.

update_campaignA
Idempotent

Update an existing campaign's properties.

Only provided fields will be updated.

Safety: enabling or removing the campaign, or changing bidding targets or
dates, returns a preview first; call again with confirm=True to apply.
Renaming and pausing are applied immediately.

Args:
    customer_id: Google Ads customer ID.
    campaign_id: Campaign ID to update.
    name: New campaign name.
    status: New status -- 'ENABLED', 'PAUSED'.
    target_cpa: New target CPA (for maximize_conversions with target).
    target_roas: New target ROAS (for maximize_conversion_value with target).
    start_date: New start date (YYYY-MM-DD).
    end_date: New end date (YYYY-MM-DD).
    confirm: Must be True to apply a gated change.

Inputs: campaign_id (required), customer_id (required), name, status, +5 more.

update_keyword_bidA
Idempotent

Update the CPC bid for a keyword.

Safety: returns a preview first; call again with confirm=True. Refused if
cpc_bid is above GOOGLE_ADS_MAX_CPC_BID.

Args:
    customer_id: Google Ads customer ID.
    ad_group_id: Ad group ID containing the keyword.
    criterion_id: Keyword criterion ID to update.
    cpc_bid: New max CPC bid in currency (e.g., 2.50 for $2.50).
    confirm: Must be True to apply the new bid.

Inputs: cpc_bid (required), ad_group_id (required), customer_id (required), criterion_id (required), +1 more.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelogโ€ฆ

    TDQS

    B3.3/5.0

    Scored across 47 tools

    Disambiguation3/5

    Most tools target distinct resources and actions, but several boundaries blur: get_keyword_performance overlaps heavily with get_keyword_performance_report, and status changes can be done via set_*_status, update_*, or remove_campaign. execute_gaql intentionally overlaps every read tool as a fallback, which is reasonable but adds selection ambiguity.

    Naming Consistency5/5

    Tool names consistently use snake_case verb_noun conventions such as list_budgets, create_campaign, update_ad_group, and set_ad_status. Minor singular/plural and _report suffix differences do not break the overall predictable pattern.

    Tool Count2/5

    At 47 tools, the surface is well above the typical 3-15 sweet spot and includes overlapping helpers and duplicate reporting paths. Google Ads is a broad domain, but this set would benefit from consolidation and fewer near-duplicate status/performance tools.

    Completeness3/5

    Core campaign, ad group, ad, keyword, budget, PMax, and reporting workflows are covered, and execute_gaql helps fill read gaps. However, notable gaps remain, especially no asset upload/management tool despite display and PMax ad creation requiring pre-uploaded asset resource names, plus limited targeting, conversion, and ad-content update support.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      A
      quality
      F
      maintenance
      Enables managing Google Ads campaigns through an AI assistant with read-only reporting, recommendations, and gated write operations for bids, budgets, and statuses, all backed by preview and audit logging.
      31
      1
      MIT
    • F
      license
      Not graded
      quality
      B
      maintenance
      Enables authorized users to manage Google Ads accounts through natural language, with guardrails like role tiers, account allowlists, spend limits, and two-step confirmations to prevent accidental changes.
      -
    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables managing and analyzing ad accounts in plain language from AI assistants, including cross-account performance reports, keyword research, GAQL queries, and safe previewed changes.
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables AI apps to plan, build, audit, and report on Google Ads, GA4, Search Console, and Tag Manager accounts through natural language. Accounts are read-only by default, and every change is validated in a preview, applied only after confirmation, logged, and reversible.
      4
      MIT