Skip to main content
Glama
sujayrittikar

adsmith

A Google Ads MCP server that does more than read. It finds your wasted spend, your budget-capped winners, and your weak ad copy — then proposes the fix as a reviewable diff that you approve before a single cent moves.

Google's official Google Ads MCP server is read-only: three tools, no mutations. adsmith is the other half — the part that changes things, wrapped in the safety machinery that makes letting an LLM near an ad budget a reasonable idea.


Try it in 30 seconds — no Google account needed

uvx adsmith --demo

That's it. No OAuth, no developer token, no waiting on Google's approval queue. --demo boots a synthetic ad account with realistically messy data, and every tool works against it, including proposing, applying, and rolling back changes.

Wire it into Claude Code:

claude mcp add adsmith -- uvx adsmith --demo

Then ask: "where am I wasting money?"

> where am I wasting money?

  Pulling the search-terms report for Northwind Outdoor Gear...

  $6,274.92 of your $14,525 spend over the last 30 days went to search terms
  that produced zero conversions — about 43%. The pattern is clear:

  | search term                    | 30-day cost | campaign               |
  |--------------------------------|-------------|------------------------|
  | free hiking boots              |     $261.98 | Search - Hiking Boots  |
  | hiking boots repair near me    |     $238.70 | Search - Hiking Boots  |
  | northwind outdoor gear careers |     $231.27 | Brand - Northwind      |
  | how to clean hiking boots      |     $215.41 | Search - Hiking Boots  |
  | used camping gear cheap        |     $191.82 | Search - Generic Outdoor |

  Three intent groups worth blocking: job seekers, repair/rental, and
  free-seekers. Want me to propose negatives?

> yes

  Change-set cs_1a5956d1 (pending) on customer 1234567890
  Rationale: Non-commercial intent

    1. Negative keyword on Search - Generic Outdoor: + keyword=jobs
    2. Negative keyword on Search - Generic Outdoor: + keyword=rental
    3. Negative keyword on Search - Generic Outdoor: + keyword=diy
    4. Negative keyword on Search - Generic Outdoor: + keyword=wikipedia
    5. Negative keyword on Search - Generic Outdoor: + keyword=donation

  Estimated daily spend decrease: 19.92
  Estimated 30-day impact: 597.60

  Expires: 2026-08-07T18:06:21+00:00
  To apply: apply_changeset(changeset_id='cs_1a5956d1', confirm=True)

  Nothing has been applied. Note I left "careers" alone — that spend is on your
  brand campaign, which your guardrails protect.

Nothing was applied. That's the point.


Related MCP server: google-ads-mcp

Safety, up front

The honest first reaction to "AI edits my ad account" is no. So here is exactly what stops it going wrong.

Every mutation takes the same path. There is no other route to the API:

propose_*  →  guardrails  →  validate_only dry-run  →  apply_changeset(confirm=True)
                   ↓                    ↓
              BLOCK is final     Google validates without committing

Guardrails live in a file on disk, outside the model's reach. No tool can relax one. A BLOCK is terminal — the assistant can't argue past it, because the check is Python reading YAML, not a suggestion in a prompt.

budgets:
  max_increase_pct_per_day: 20        # no 10x raises from a stray decimal
  max_decrease_pct_per_day: 30
  account_daily_spend_ceiling: null   # set this before automating anything

bids:
  max_target_cpa_change_pct: 15       # big swings reset Smart Bidding's learning

pausing:
  never_pause_if_conversions_last_30d: 5   # conversions lag; "dead" often isn't
  max_keywords_paused_per_changeset: 50
  allow_pausing_campaigns: false

protected:
  campaign_ids: []
  campaign_name_patterns: ["*Brand*"] # brand campaigns are cheap and high-ROAS;
                                      # "optimizing" them is nearly always a loss

Ask for something out of bounds and you get this, not a workaround:

Guardrails:
  - [BLOCK] budgets.max_increase_pct_per_day (change 1): Raising the budget for
    Search - Hiking Boots from 80.00 to 800.00 is +900.0%, above the 20% daily cap.

BLOCKED by guardrails — this change-set cannot be applied. The [BLOCK] entries
above are final.
These limits live in ~/.config/adsmith/guardrails.yaml. I cannot override them;
editing that file is the only way to change them.

The rest of the safety model:

  • Approval is explicit. apply_changeset without confirm=True returns the diff and changes nothing.

  • Dry run first. Every apply is validated through the API's validate_only mode before it commits.

  • Undo. Change-sets carry pre-built inverse operations. Where something genuinely can't be reversed (creating an ad), it says so plainly instead of implying a clean undo.

  • Proposals go stale. A change-set built on last week's numbers expires rather than applying against an account that has moved.

  • Guardrails re-run at apply time, not just at propose time — so tightening the policy invalidates a proposal that was already sitting in the queue.

  • Everything is logged. audit_history answers "what changed last Tuesday?" with every proposal, verdict, dry-run, application, and rollback.

Full detail in SECURITY.md.


Playbooks

Five slash commands, each a written analysis procedure rather than a black box. They're plain prose you can read and edit — including the statistical guardrails that stop an eager assistant acting on noise.

Command

What it does

/wasted-spend

Mines search terms, groups them by intent (job seekers, DIY, free-seekers, repair), proposes negatives with a projected saving

/budget-check

Finds campaigns losing impression share to budget while hitting their CPA target, proposes a zero-sum reallocation

/bid-tuning

Compares actual CPA/ROAS to targets, proposes bounded steps — and refuses to act on fewer than 30 conversions

/ad-audit

Finds poor-strength RSAs, too-few headlines, over-pinned assets; proposes replacements that vary the angle, not the wording

/weekly-report

Digest with anomaly detection — and it checks whether a conversion cliff is a tracking break before calling it a performance drop


Tools

Tool

Returns

list_accounts

Every reachable account with currency and timezone

account_overview

Spend, conversions, CPA, ROAS vs. the preceding period

campaign_performance

Per-campaign metrics + impression share + budget

ad_group_performance

Per-ad-group metrics

keyword_performance

Per-keyword metrics with quality score

search_terms

What people typed, with wasted spend totalled

ad_performance

Ads plus a precomputed weak_ads diagnosis

budget_pacing

MTD spend, month-end projection, budget-capped campaigns

run_gaql

Read-only escape hatch — SELECT only

Reports pre-aggregate totals and cap rows by default. When a report truncates it says so, and the totals still cover every row — a capped report never understates account spend.

Tool

Notes

propose_negative_keywords

Defaults to PHRASE; BROAD negatives block converting traffic too often

propose_budget_change

Takes a whole reallocation map as one reviewable change-set

propose_bid_adjustment

tCPA/tROAS only; refuses to switch bidding strategy

propose_pause

Keywords, ads, campaigns

propose_rsa

Validates Google's 30/90-character limits before proposing

preview_changeset

Diff + validate_only dry run

apply_changeset

Requires confirm=True

rollback_changeset

Replays stored inverses

list_changesets

Recent proposals and their status

audit_history

The full record

show_guardrails

Active policy and where it's loaded from


Running it unattended

adsmith scan does the analysis headlessly — point cron at it and the work happens while you sleep.

adsmith scan --demo              # digest of everything worth your attention
adsmith scan --propose           # ...and queue change-sets for the clear-cut fixes
9 finding(s), roughly 9,157.94 per 30 days at stake.

1. [WARNING] Search - Generic Outdoor: 2,384.42 on non-converting search terms
   85 search term(s) spent money over 30 days with no conversions.
   Queued: cs_ace79e8b (pending your approval)

3. [WARNING] Search - Camping Gear: CPA is +105% against target
   Actual CPA 61.41 vs target 30.00 over 61 conversions.

5. [WARNING] Search - Hiking Boots is capped and beating its target
   Losing 38% of impressions to budget on 80.00/day, at a CPA of 38.00
   against a 45.00 target.

It never applies anything--propose queues change-sets in pending, and guardrails apply in full with nobody watching. The scan is deterministic Python, not an LLM: it costs nothing per run, gives identical output for identical input, and can't hallucinate a campaign ID. The judgement calls stay in the playbooks where you're present to read them.

Exit codes are cron-shaped (0 clean, 1 error, 2 findings), so adsmith scan || notify-me just works. Full setup, including systemd timers, in docs/SCHEDULING.md.

Read-only mode

adsmith --read-only

Unregisters every mutation tool, so the server physically cannot write — removal, not refusal. A good way to spend a first week on a real account.

Connecting a real account

--demo needs nothing. A real account needs three things from Google, and the developer token is the slow one — Google's review queue runs days to weeks, and a fresh token only works against test accounts until Basic access is approved.

Start the token application on day one, then keep using --demo while you wait. Full walkthrough in docs/SETUP.md.

pip install 'adsmith[live]'
adsmith auth                    # one-time OAuth; writes ~/.config/adsmith/credentials.json (0600)
adsmith init-config             # writes ~/.config/adsmith/guardrails.yaml — edit it
claude mcp add adsmith -- adsmith

Set account_daily_spend_ceiling in your guardrails before you do anything else.


How this differs from Google's official server

Both are open source and both are Python. They solve different halves.

googleads/google-ads-mcp

adsmith

Reads

Raw GAQL passthrough

9 curated reports + a GAQL escape hatch

Writes

5 proposal tools behind change-set review

Guardrails

Policy file the model can't override

Undo

Inverse operations + audit log

Playbooks

5 slash commands

Unattended scanning

adsmith scan (cron-shaped exit codes)

Read-only mode

Always read-only

--read-only opt-in

Try without a dev token

uvx adsmith --demo

Telemetry

Usage headers on API calls

None

Maintained by

Google

This repo

Use theirs if you want a thin, official, read-only wrapper. Use adsmith if you want the thing to actually improve the account.


Contributing

You don't need a Google Ads account to contribute — the whole test suite runs against the demo backend. See CONTRIBUTING.md.

The one rule: nothing reaches the API except through a change-set. A tool that calls mutate directly won't be merged, however convenient.

Status

Alpha, and honest about it. 102 tests, CI on 3.12/3.13.

The safety layer is thoroughly covered. The live Google API path is tested against real protobuf types — message construction, enums, field masks, error translation — with the network stubbed, but it has never run against Google's actual servers. That's the part most likely to surprise you.

If you connect a real account: start with --read-only for a week, then tight guardrails and one small change. docs/SETUP.md §7 has the round trip worth doing first.

Licence

MIT.

A
license - permissive license
-
quality - not tested
A
maintenance

Maintenance

Maintainers
Response time
Release cycle
1Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    A
    quality
    F
    maintenance
    A read-write MCP server for managing Google Ads campaigns, ad groups, keywords, and ads via natural language.
    12
    2
    The Unlicense
  • A
    license
    -
    quality
    A
    maintenance
    MCP server that provides tools and resources for interacting with Google Ads API, enabling search, metadata retrieval, and account management through natural language.
    843
    Apache 2.0
  • A
    license
    A
    quality
    A
    maintenance
    An MCP server that gives your AI assistant read + write access to Google Ads and GA4 — with safety guardrails that prevent accidental spend.
    67
    232
    MIT
  • A
    license
    -
    quality
    C
    maintenance
    A Model Context Protocol server providing full read and write control over Google Ads, enabling AI assistants to build campaigns, fix targeting, rewrite ads, and manage bidding strategies without opening a browser.
    1
    MIT

View all related MCP servers

Related MCP Connectors

  • MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.

  • Remote MCP for AI Studio Android release gate MCP, structured receipts, audit logs, and reviewer-rea

  • Hosted Google Calendar MCP server for AI agents. No self-hosting or Google Cloud setup.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sujayrittikar/adsmith'

If you have feedback or need assistance with the MCP directory API, please join our Discord server