Four write tools and an approval nobody enforces

Google’s official bridge between AI assistants and Google Ads learned to write on November 2, and Google did not mention it. Version 0.0.6 of the open source Google Ads MCP server added four tools that change an account: two for assets, two for labels. They are switched on by default. The developer integration guide, last updated October 30, still says the server is “strictly read-only.”

If your team or your agency approved this server for client accounts because Google called it read-only, that approval is now out of date. The new tools are narrow, and the safety step is real but thinner than it looks: the server can prove that what gets written matches what was proposed, but it cannot prove a person said yes. That second part is on you.

This is a primary source review. I read the v0.0.6 release, the pull request that added the write tools, the README, the bundled configuration file and the Python source for the confirmation flow, the label tools and the asset tool, all at the v0.0.6 tag. I did not connect it to a Google Ads account. For a live account test I lean on Thomas Wismer, a Swiss consultant who ran the tools in a client account on November 9, as reported by PPC Land, which also read the code and reached the same conclusion I did.

What it is

MCP, the Model Context Protocol, is the open standard that lets AI assistants such as Claude, ChatGPT, Codex and Gemini discover and call outside tools. Google released its own Google Ads MCP server in October 2025 as a reporting bridge: ask your assistant how campaigns did this week, and the server runs the query against the Google Ads API and hands the data back. Until this month it had three tools, all reads: one to run Google Ads Query Language searches, one to list the accounts you can reach, and one to describe the fields on a resource like a campaign.

It is free, open source under the Apache 2.0 license, and you run it yourself, either locally next to your assistant or on Google Cloud Run so a team can share it. Access to the API now follows your Google Cloud project’s access level; the guide says developer tokens were sunset on September 9.

What changed in 0.0.6

Four write tools, according to the README and the source:

  • create_asset makes text, image, YouTube video, sitelink, callout and structured snippet assets, plus other asset types through an extra parameters field.
  • upload_video_asset uploads a local video file to YouTube through the Ads API, in local mode only.
  • manage_labels creates, renames and removes account labels.
  • manage_label_associations attaches labels to, or removes them from, accounts, campaigns, ad groups and keywords.

The pull request description is blunt: “Mutate tools are also enabled by default.” The bundled configuration file now reads labels: true and assets: true next to the three read namespaces. Anyone who installs the server the way Google’s guide shows, with pipx run --spec git+https://github.com/googleads/google-ads-mcp.git, gets whatever is on the main branch that day. That command does not pin a version, so the write tools arrived for those users without them changing anything.

There was never a separate permission to grant. The server uses the single Google Ads API OAuth scope, which already allows writes at the API level. What kept it read-only was its own tool list.

Aerial photograph of a wooden fence across a frosted field with plain tags on each post, one tag fallen to the grass and a yellow tag hanging in its place.

What works

The confirmation flow is better built than most agent write paths this site has reviewed in marketing tools. Every write runs twice. The first call defaults to a dry run: the server validates the change, for assets and labels by sending it to the Google Ads API with the validate only flag, and returns a list of plain language change items plus a checksum. Nothing is written. The second call has to repeat the exact same parameters and customer ID along with that checksum, and only then does the change commit. Change one character between the two calls and it is rejected.

That kills a real class of mistakes. An assistant cannot propose a harmless label and then quietly commit a different one, or validate against one account and write to another. Wismer’s test matches the design. Per PPC Land, he dry ran a label and a callout, committed the label, read it back with a query, removed it with a second cycle and confirmed it showed as removed. The callout never got committed. “Created a test label, read it back, removed it again. Works,” he wrote.

The tools are also honestly labelled for the clients that read hints: both label tools are marked as potentially destructive, which some assistants use to decide how loudly to ask before calling them.

Practically, there are two jobs this helps with right now. One is building out an asset library in bulk, such as Black Friday sitelinks, callouts and structured snippets across many accounts, drafted by an assistant and reviewed in a list before anything is created. The other is label hygiene: tagging campaigns for reporting at scale instead of clicking through the interface.

What breaks

The approval is an instruction, not a lock. The tool description tells the assistant to “present the change_items to the user and wait for explicit user approval” before confirming. That is text the model is asked to obey. I read the checksum function in propose_and_confirm.py: it is a plain SHA-256 hash of the customer ID and the operation, with no secret key and no expiry, and the server keeps no record of proposals between calls. It recomputes the hash on the confirming call and compares. So the checksum proves the parameters did not change. It does not prove a dry run was shown to anyone, or that anyone approved it. An assistant running unattended, or one told to “just fix the labels,” can propose and confirm back to back. Wismer said it plainly: “Whether a human approved it in between, the server cannot check.”

Labels are a control surface. Many teams use labels to decide what Google Ads scripts, automated rules and reports act on. If a script pauses or rebids everything carrying a certain label, an agent that can attach or remove that label can change spend without touching a budget field. The tool cannot change bids. Your own automation might, based on what the tool changes.

Assets go nowhere. The asset tool calls the asset service only. It creates assets in the account library and cannot attach them to a campaign or ad group. Wismer’s test sitelink landed in the library unattached. That limits the damage from a bad asset, and it also means you still need a person or another tool to make any asset live.

The docs are wrong. Google’s guide says the server “cannot modify bids, pause campaigns, or create new assets.” The first two are still true. The third is not. Security reviews, client approvals and vendor questionnaires that quoted “read-only” now describe something that no longer exists.

Shared deployments raise the stakes. The guide shows Cloud Run deployments with unauthenticated access at the infrastructure layer, relying on OAuth inside the app, and warns that leaving out the OAuth client settings exposes the container’s own credentials to anyone who calls it. That warning was written for a reporting server. On 0.0.6 the same mistake exposes label and asset writes as well, minus video uploads and local image paths, which only work in local mode.

Aerial photograph of a stone barn with its doors open on a frosted morning, wooden crates stacked outside and a yellow wheelbarrow nearby.

Who it is for

PPC leads and agency ops people already wiring Claude, Codex or Antigravity into Google Ads for reporting, who want an official, auditable way to bulk create assets and tidy labels, and who are willing to add their own approval step. It is not a campaign management agent. It cannot create or edit campaigns, ad groups or ads, change budgets, bids or bidding strategies, pause or enable anything, or add keywords and negatives. If you wanted an assistant to run your account, this is not that. Third party servers go further, but as Wismer points out, they hold a token with access to every account under your manager account.

Pricing and limits

The server is free. You pay for your own hosting if you put it on Cloud Run, and your API usage follows your Cloud project’s access level. Video uploads and local image file paths work only when the server runs on the same machine as your assistant. Images are capped at 20 MB per the source as reported by PPC Land. The configuration file decides which tools exist; if you point the server at a configuration file by environment variable and that file is missing or invalid, the server refuses to start, which is the behaviour you want for a locked down setup.

What to do this week

Find every install. Ask your team and your agencies who runs the Google Ads MCP server, where, and which version. Anything launched with the unpinned git command from Google’s guide is on 0.0.6 or later.

Decide read or write on purpose. For reporting only, pin the version and ship a configuration file with labels: false and assets: false, loaded through the GOOGLE_ADS_MCP_TOOLS_CONFIG environment variable so a missing file stops the server instead of falling back to the bundled default with writes on.

Put the human back in code. If you keep writes, add an approval hook in the assistant that blocks any call with validate_only set to false until a named person confirms it. Wismer runs one in Claude Code. Do not rely on the tool description.

Use account permissions as the real lock. Authenticate the server as a Google user whose Google Ads access level is read only for any account where you want no writes at all. The API respects that role whatever the tool list says.

Audit label driven automation. List every script, rule and report that selects by label. Through Cyber Monday, either keep agents off those labels or move the automation to a different selector.

Fix the paperwork. Update client approvals and security notes that described the server as read-only, and check any Cloud Run deployment has both OAuth client settings in place.

Four write tools, all on the edges of the account, with a well built check that stops the wrong change and no check at all that a person looked. Used with a pinned version, a real approval hook and read only roles where they belong, it is a sensible way to let assistants do grunt work in Google Ads. Installed the way the guide still describes, it is a write tool your security review never saw.