MCP server for reading and writing the Google Ads API
Server has 16 tools with complete input schemas and descriptions. Naming follows verb_noun convention (list_, get_, create_, update_, add_, run_, apply_). Descriptions are present but brief (avg ~60 chars), lacking context on WHEN to use tools or dependencies. Parameters have types and descriptions, but many lack constraints (enums, ranges). Output schemas are not documented. Write tools implement a dry-run/confirm pattern via 'commit' and 'confirmation_token' params, which is good for safety, but error handling and recovery guidance are not visible in the code. No tool annotations (readOnlyHint/destructiveHint) detected. Composition is sound, tools are single-responsibility and chainable via resource names.
Add positive keywords to an ad group (match_type BROAD/PHRASE/EXACT).
Add campaign-level negative keywords.
Raw mutate escape hatch: a list of MutateOperation JSON objects.
Create an ad group in a campaign.
Create a campaign attached to an existing budget.
Create a campaign budget. amount_micros is per-day in micros.
Descriptions lack context on WHEN to use tools and dependencies. E.g., 'List campaigns for an account' does not explain when to call this vs run_gaql, or that customer_id is required first. Descriptions average ~60 chars; production baseline is 194 chars.
Output schemas are not documented. Tools return lists or dicts, but LLMs cannot infer field names, types, or which fields are needed for downstream tool calls (e.g., does get_campaigns return campaign_id or campaign_resource_name?).
Enum constraints missing for string parameters. 'status' param in update_campaign_status accepts 'ENABLED|PAUSED|REMOVED' but is not declared as an enum, LLMs may hallucinate invalid values. Same for 'level' in get_performance, 'match_type' in add_keywords, 'advertising_channel_type' in create_campaign.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 60 | 2026-07-28+ | v2 |
Create a paused responsive search ad (3-15 headlines, 2-4 descriptions).
List ad groups for an account.
List campaigns for an account.
List keywords for an account.
Performance metrics (impressions/clicks/cost/conversions) by level.
List all ad accounts under the manager (MCC) account.
Run an arbitrary Google Ads Query Language (GAQL) read query.
Set an ad group's status: ENABLED, PAUSED, or REMOVED.
Change a campaign budget's daily amount (micros).
Set a campaign's status: ENABLED, PAUSED, or REMOVED.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint) detected. Read tools (list_accounts, get_campaigns) should be marked readOnly=true; write tools (create_*, update_*, add_*) should be marked destructive=true. This helps LLMs reason about safety and retry logic.
Error handling and recovery guidance not visible in source. No evidence of actionable error messages (e.g., 'Invalid status: got X, must be one of Y'). Agents cannot self-correct on invalid input without explicit error guidance.