Google Ads MCP: build the whole tree from your agent, atomically

Hermoso's MCP server creates a Google Ads campaign, ad group, responsive search or display ad and its keywords in a single atomic mutate — so a rejected ad means the budget was never created either. Performance Max builds the same way, asset group and all. Plus Keyword Planner research, conversion tracking, sitelinks, Merchant Center feed reads and writes, GAQL reporting, Google Analytics 4 for what the clicks actually did, and a confirm gate on anything that starts spend.

Google Ads is a tree, and trees are where scripted campaign creation usually goes wrong. You create a budget, then a campaign, then an ad group, then an ad — and if the ad is rejected at step four you are left holding three orphaned objects and a budget you did not want. Cleaning that up by hand is the reason most people give up on automating Google Ads.

Hermoso’s MCP server builds the whole tree in one atomic operation, using temporary resource ids so the children can reference parents that do not exist yet. Either the campaign, ad group, ad and keywords all come into existence, or none of them do. A rejected ad means the budget was never created either.

Install it once: in Claude Code, Cursor or Codex run claude mcp add --transport http hermoso https://app.hermoso.ai/mcp. In Claude.ai or Claude Desktop, paste https://app.hermoso.ai/mcp under Settings → Connectors and approve it with your Hermoso account. For a terminal agent, npm install -g hermoso then hermoso auth login. Full setup on the MCP & CLI page.

The Google Ads tools

Build. create_google_ads_campaign, create_google_ads_ad_group, create_google_ads_ad, add_google_ads_keywords, create_google_ads_performance_max_campaign, upload_google_ads_asset, add_google_ads_assets for sitelinks, callouts and structured snippets.

Configure. set_google_ads_budget, set_google_ads_bidding (six strategies), set_google_ads_targeting (geo and language), find_google_ads_locations, create_google_ads_conversion_action and list_google_ads_conversion_actions.

Research. google_ads_keyword_ideas puts Keyword Planner in the conversation — real monthly search volumes, competition and top-of-page bid ranges, seeded from a set of keywords, a landing page or a whole site.

Read and change. list_google_ads_campaigns, google_ads_report for arbitrary GAQL, google_ads_change_history for what moved in the account and when, delete_google_ads_object to remove one, and set_google_ads_status — the one confirm-gated switch that starts real spend.

create_google_ads_campaign also accepts a dry-run mode, so an agent can validate a whole tree against the live API without creating anything — a good default when it is proposing a plan for you to approve.

Performance Max, built the same way

create_google_ads_performance_max_campaign builds Google’s cross-surface campaign type — Search, YouTube, Display, Discover, Gmail and Maps from one campaign — and it builds it in a single atomic operation because Google requires exactly that: budget, campaign, location and language targeting, the asset group and every asset link go up together, so a rejected asset leaves no half-built campaign behind. It is created paused, and the whole tree is read back from Google before your agent tells you it exists.

Google’s asset minimums are checked here before anything is sent, so a missing square image is a clear message rather than an opaque API rejection: 3–15 headlines of 30 characters or less, 1–5 long headlines up to 90, 2–5 descriptions up to 90, one business name up to 25, and at least one logo, one marketing image and one square marketing image. Upload the images with upload_google_ads_asset first and pass the resource names. A YouTube video is optional — Google will generate one from the asset group if you leave it out.

Performance Max has no keywords and no manual bidding: it optimises toward conversions and nothing else. So the build refuses on an account with no enabled conversion action rather than create a campaign that cannot optimise, and it names both ways out — create one with create_google_ads_conversion_action, or run a strategy that does not need it. Brand guidelines are on by default for new PMax campaigns since Google Ads API v21, which changes where the business name and logo attach; Hermoso links them to the campaign for you.

Shopping-feed (retail) Performance Max works the same way: pass merchantCenterId and the campaign advertises your Merchant Center catalogue, with feedLabel to narrow it to one feed. It is built and read back exactly like the campaign above — the read-back reports the Merchant Center account and feed label Google actually stored, so you can see it really is a retail campaign rather than take our word for it. It advertises the whole feed under one root listing group; partitioning a feed by brand, category or custom label is not built, and it is refused by name rather than quietly ignored — you can never end up believing you narrowed a feed when you did not.

Merchant Center, so the agent knows what it is selling

“Why is this product not showing?” is a question Google Ads reporting structurally cannot answer, because a disapproved product has no impressions to report on. That answer lives in Merchant Center — and the same Google connection reaches it, with no second login.

Your agent can list the Merchant Center accounts your connected Google account can reach with list_merchant_accounts (an agency usually has several, so it asks which store rather than guessing), read the products in a feed with list_merchant_products — the actual catalogue a Shopping or retail Performance Max campaign serves — and read the account-level issues Google is raising against the account with list_merchant_issues. That is enough to write ad copy about products that really exist, at prices that are really live, and to explain a silent campaign.

It writes, too. create_merchant_data_source makes an API product feed, upsert_merchant_product puts a product in it, update_merchant_product changes the fields that move daily — price and availability — and delete_merchant_product and delete_merchant_data_source remove them behind a confirmation. list_merchant_data_sources shows which feeds can actually take a write.

Three things worth knowing up front. Google blocks every Merchant API call until Hermoso’s Cloud project is registered against your Merchant Center account, so register_merchant_developer performs that link once and says so by name — it is not a broken connection, and reconnecting will not fix it. Product writes only go into an API data source: a file feed, an autofeed and the feed Merchant Center’s own UI creates all list normally and all refuse writes, so Hermoso resolves a writable feed for you, creates one if there is none, and refuses by name if there are several rather than putting your product in a market your campaigns may not target. And upsert_merchant_product is a whole-row write while update_merchant_product is a patch — send every field you want kept to the first, only the fields you are changing to the second.

None of that means you have to move your catalogue. If the feed already lives in Shopify or your platform, keep it there and let the agent read it; the writes are for the cases where nothing owns the feed yet, or where one price or availability needs correcting now rather than at the next sync.

Google Analytics 4, so you can see what the clicks did

Google Ads reporting ends at the click. What happened next — the session, the signup, the order — lives in Google Analytics, and the same Google sign-in reaches it (it is its own connection, because it needs its own permission).

Your agent can resolve which GA4 property to read with list_analytics_properties — worth knowing, because every Analytics call takes a numeric property id and what you actually have is the G-XXXXXXXXX Measurement ID out of your tracking snippet. Then analytics_report returns sessions, users, conversions and revenue broken down by channel, source/medium, campaign, landing page, country, device or date, and analytics_realtime shows who is on the site right now. So “build the campaign” and “tell me what it earned” are the same conversation.

It writes, too, and this is the part that feeds straight back into Google Ads: create_analytics_key_event marks an event GA4 already collects as a key event, which is exactly what Google Ads imports as a conversion — and a conversion action is what every smart-bidding strategy on this page is undeliverable without. create_analytics_custom_dimension registers an event parameter so reports can break down by it, and list_analytics_definitions shows what the property already measures before you add either. Two things that stay true forever: this is GA4 only, since the API has no Universal Analytics surface at all, and a custom dimension can be archived but never deleted, with 50 event-scoped slots per property — so the agent checks the existing set first.

The live-spend gate is wider than one tool

Pausing a campaign is not the only way to avoid spending, and treating it that way is a real trap: creating an enabled ad group, ad or keyword under an already enabled parent serves on the very next auction. So the same confirmation that guards set_google_ads_status also guards create_google_ads_ad_group, create_google_ads_ad and add_google_ads_keywords whenever the parent is live — read off the row each of those already fetches, at no extra round trip. Negative keywords only ever restrict spend, so they are never gated.

GAQL reporting, with one caveat worth knowing

google_ads_report takes arbitrary GAQL, so your agent can ask for whatever slice it needs rather than being boxed into a fixed report shape. One thing to keep in mind if you are writing queries by hand or letting a model write them: GAQL is not SQL. It has no subqueries, and IN takes a literal list. A WHERE id IN (SELECT …) is invalid and will fail rather than quietly return the wrong rows. Pipe the result straight into a spreadsheet with create_sheet and append_to_sheet, or into a document with create_doc.

Read back, then report

After the mutate, the tree is read back from Google and the summary you get is built from that read-back — not from what was requested. It is a small discipline that catches the specific failure where an agent confidently narrates a campaign the platform actually coerced or rejected.

What it will not do without asking

An agent with a budget is only useful if the blast radius is bounded, so spend authority is fenced in the server rather than in a prompt. Meta campaigns, ad sets and ads are created PAUSED with no caller override. The status switches that can arm real ad spend — one on every ad platform, set_meta_campaign_status, set_google_ads_status, set_microsoft_ads_status, set_reddit_ads_status, set_linkedin_ads_status, set_pinterest_ads_status, set_x_ads_status and set_openai_ads_status among them — each refuse to run without an explicit confirmation flag, and that same gate covers creating an enabled Google Ads ad group, ad or keyword under an already-enabled parent, because that serves on the very next auction. Deletes are confirm-gated too. On the generation side, hermoso_capabilities publishes each model’s exact credit cost before anything runs, and every render reserves an estimate then settles the true cost, so a failed dispatch refunds instead of quietly billing you.

Connecting your Google Ads account

You connect Google Ads to Hermoso through Google’s own OAuth flow in Connectors settings; no password passes through the model. Google Ads connections are shared at the brand level, so a whole team on a brand works from one connection rather than each person re-authorizing.

The creative half

Campaign management is only useful if there is something to run. The same server researches what is already winning in your market across the Meta, Google and LinkedIn ad libraries, renders finished image and video creative grounded in your real product across 50+ models, and uploads the assets — so “what should we run” and “build it” are one conversation instead of two tools. See the marketing MCP overview, the full tool list, or the Meta Ads MCP if you run both.

Frequently asked

Is there an MCP server for Google Ads?

Yes. Hermoso’s MCP server builds and manages Google Ads from any MCP client: create_google_ads_campaign, create_google_ads_ad_group, create_google_ads_ad and add_google_ads_keywords to build a search or display tree; create_google_ads_performance_max_campaign for Performance Max; set_google_ads_budget, set_google_ads_bidding and set_google_ads_targeting to configure; google_ads_keyword_ideas for Keyword Planner research; list_google_ads_campaigns and google_ads_report for reporting; Merchant Center reads for the product feed behind a Shopping campaign; and a confirm-gated set_google_ads_status to activate.

Can an AI agent create a Google Ads campaign?

Yes, and the whole tree is created in a single atomic operation using temporary resource ids — campaign, ad group, responsive search or display ad and keywords together. If the ad is rejected, the budget was never created either, so you are not left cleaning up orphaned objects. A dry-run mode validates the tree against the live API without creating anything.

Can it create a Performance Max campaign?

Yes. create_google_ads_performance_max_campaign builds the budget, campaign, targeting, asset group and every asset link in one atomic operation — Google requires them together — and the campaign is created paused and read back before the agent reports on it. Google’s asset minimums are enforced before anything is sent: 3–15 headlines, 1–5 long headlines, 2–5 descriptions, a business name, and at least one logo, marketing image and square marketing image. PMax bids only on conversions, so it refuses to build on an account with no enabled conversion action rather than create a campaign that cannot optimise. Shopping-feed (retail) PMax works the same way: pass merchantCenterId and the campaign advertises your Merchant Center catalogue, with feedLabel to narrow it to one feed, and the read-back reports the Merchant Center account and feed label Google actually stored.

Does it work with Google Merchant Center?

Yes, reads and writes, over the same Google connection. The agent can list the Merchant Center accounts your account can reach, read the products in a feed — the catalogue a Shopping or retail Performance Max campaign actually serves — and read the account-level issues Google raises, which is the only place to find out why a product is not showing, since a disapproved product has no impressions for Google Ads reporting to show. Google requires a one-time registration of Hermoso’s Cloud project against your Merchant Center account before the API answers, and there is a tool that performs it. It writes as well: create_merchant_data_source, upsert_merchant_product, update_merchant_product for the price and availability changes that move daily, and confirm-gated delete_merchant_product and delete_merchant_data_source. Google only accepts product writes into an API data source, so Hermoso resolves a writable feed for you and refuses by name if the account has several.

Can it do keyword research?

Yes. google_ads_keyword_ideas calls Google’s Keyword Planner and returns real monthly search volumes, competition and top-of-page bid ranges, seeded from keywords, a landing page URL or a whole site. The agent can take those straight into add_google_ads_keywords, or write them to a Google Sheet.

Can it start spending my Google Ads budget?

Only with an explicit confirmation. set_google_ads_status is the switch that arms real money, and because creating an enabled child under an already-enabled parent serves on the very next auction, the same confirmation also guards create_google_ads_ad_group, create_google_ads_ad and add_google_ads_keywords when the parent is live. Negative keywords only restrict spend and are never gated.

Can it run reports?

Yes. google_ads_report takes arbitrary GAQL, so the agent can request whatever slice it needs. Note that GAQL is not SQL: it has no subqueries and IN takes a literal list, so a WHERE id IN (SELECT …) is invalid. Results can be written straight into a Google Sheet or Doc.

What bidding and targeting can it set?

Six bidding strategies, campaign schedule, and geographic and language targeting, with find_google_ads_locations to resolve location targets by name. Budgets are set through set_google_ads_budget, and keywords support negatives and per-keyword CPC.

Does the agent get my Google account password?

No. You connect Google Ads through Google’s own OAuth flow in Hermoso’s Connectors settings, and Hermoso holds the resulting token. The agent only calls Hermoso’s tools. Google Ads connections are shared at the brand level so a whole team works from one connection.

Can it make the ad creative as well?

Yes. The same server researches competitor ads, plans the concept, renders finished image and video creative across 50+ models with your real product composited in, and uploads assets with upload_google_ads_asset — so research, creative and campaign build happen in one conversation.

Connect Google Ads once, and your agent can research the market, write the ad, build the tree and report on it — with a hard gate before anything spends.

Start free   Read the MCP docs →