Google Ads MCP Server
Provides 47 tools for running a Google Ads account: reporting (campaign, ad group, keyword and search-term reports, account summaries, arbitrary read-only GAQL queries), campaign creation for Search, Display, Video, Demand Gen and Shopping (PAUSED by default), full Performance Max setup, ad creation, keyword add/remove/re-bid, budget management, and MCC hierarchy exploration. Spend-affecting actions return a cost preview requiring explicit confirmation, with optional hard caps on daily budget, budget increase percentage and CPC bids.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Google Ads MCP Server Which campaigns spent the most in the last 30 days, and what was their ROAS?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
๐ Contents
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 |
โจ 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 + |
๐ง | 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 |
๐ณ | Docker | Non-root image, credentials mounted at runtime, health check |
๐งฉ | Claude plugin |
|
๐ก๏ธ 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: successWhat 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 |
Removing campaigns, ad groups, ads, keywords or PMax assets | Preview first (marked not reversible), then |
Anything above a configured spend limit | Refused, even with |
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-mcpThen 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 |
| โ | From the API Center in your Google Ads manager account |
| โ | Path to the service-account JSON key |
| MCC only | Your manager (MCC) account ID |
| Default account when a tool call omits | |
| Workspace only | User to impersonate with domain-wide delegation |
Steps
In Google Cloud, create a service account, enable the Google Ads API, and download its JSON key.
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.Get a developer token from Tools โ API Center in your manager account.
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) | โ | โ | |
ChatGPT | โ | โ (HTTPS or Secure MCP Tunnel) | |
Gemini CLI | โ | โ | |
Cursor | โ | โ |
{
"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 |
|
| No budget, campaign or PMax campaign above 500/day |
|
| No single budget increase above +50% |
|
| No ad-group or keyword max-CPC bid above 20 |
Transport and remote protection
Variable | Default | Effect |
|
|
|
|
| Bind address for HTTP transports ( |
| โ | Required |
| โ | Your public domain(s), comma-separated, for |
|
| Requests per window per client IP |
|
| Rate-limit window |
|
| 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 ๐ข |
|
Campaigns | ๐ข |
Ad groups | ๐ข |
Budgets | ๐ข |
Ads | ๐ข |
Keywords | ๐ข |
Performance Max | ๐ข |
Reporting ๐ข |
|
Utilities ๐ข |
|
* 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/healthDocker
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 --buildThe 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,
.envor 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,
Hostallow-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 |
| Check the |
| Expected โ review the preview and call again with |
| A |
| Set a bearer token, or bind to |
| Send |
| Add your domain to |
| Wait |
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 |
๐บ๏ธ Roadmap
Planned work is tracked as GitHub issues in four milestones:
Milestone | Focus | Highlights |
Security and reliability | Validated GAQL inputs, | |
Better answers | Period comparisons, budget pacing, wasted-spend finder, Quality Score, change history, account health | |
More actions | Negative keywords, sitelinks and callouts, location targeting, bulk pause, conversions, image uploads, experiments | |
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 toolsadd_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_microsARead-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_gaqlARead-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_hierarchyBRead-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_infoBRead-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_summaryCRead-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_detailsBRead-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_groupCRead-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_performanceCRead-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_detailsBRead-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_performanceBRead-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_utilizationBRead-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_campaignCRead-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_performanceARead-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_metadataARead-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_performanceBRead-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_reportBRead-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_performanceARead-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_reportCRead-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_accountsBRead-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_groupsARead-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_adsARead-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_groupsCRead-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_budgetsCRead-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_campaignsARead-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_resourcesARead-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_keywordsARead-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_groupADestructiveIdempotent
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_campaignADestructiveIdempotent
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_keywordADestructiveIdempotent
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_statusADestructiveIdempotent
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_statusADestructiveIdempotent
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_statusADestructiveIdempotent
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_groupAIdempotent
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_budgetAIdempotent
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_campaignAIdempotent
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_bidAIdempotent
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
Scored across 47 tools
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.
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.
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.
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
Related MCP Connectors
Manage Google, Meta, TikTok, Snapchat and LinkedIn ads, plus GA4, Tag Manager and Search Console, by chat from Claude or ChatGPT. Spend increases need your confirmation first.
- AdCopilotDeprecatedcloud.adcopilot
Google Ads, GA4, Search Console and Tag Manager for AI assistants. Every change is proposed first.
Run Google Ads and Meta Ads from ChatGPT or Claude: audit wasted spend, create and manage campaigns.
Run Google Ads, Meta, TikTok, LinkedIn, GA4 & Search Console from chat. Changes wait for approval.
Related MCP Servers
- AlicenseAqualityFmaintenanceEnables 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.311MIT
- FlicenseNot gradedqualityBmaintenanceEnables 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.-
- AlicenseNot gradedqualityDmaintenanceEnables 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
- AlicenseNot gradedqualityBmaintenanceEnables 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.4MIT