Add write capabilities: campaigns, ad groups, ads, keywords, assets, and PMax support#36
Add write capabilities: campaigns, ad groups, ads, keywords, assets, and PMax support#36SaiSatya16 wants to merge 26 commits intogoogleads:mainfrom
Conversation
Queries without WHERE/ORDER BY/LIMIT clauses would produce invalid GAQL like "FROM resourcePARAMETERS..." instead of "FROM resource PARAMETERS..."
- Add get_googleads_client() and get_googleads_type() helpers - Add create_field_mask() for update operations using protobuf_helpers - Update scope comment to reflect read-write capability
- create_campaign: Create Search/Display/Shopping campaigns with budgets and bidding - create_performance_max_campaign: Create PMax campaigns with brand assets via batch mutate - update_campaign: Update campaign name, status, budget, and dates - set_campaign_status: Quick enable/pause/remove toggle Includes EU political advertising compliance (required since API v19.2) and supports all major bidding strategies (Manual CPC, Maximize Conversions, Maximize Conversion Value, Target CPA, Target ROAS, Target Spend).
- create_ad_group: Create ad groups with CPC bids and type settings - update_ad_group: Update ad group name, status, and bids
- create_responsive_search_ad: Create RSAs with multiple headlines and descriptions - add_keywords: Add keywords with match types (exact, phrase, broad) and optional bids - update_ad_status: Enable, pause, or remove ads - update_keyword: Update keyword status or bid
- create_sitelink_asset: Create sitelink extensions - create_callout_asset: Create callout extensions - create_structured_snippet_asset: Create structured snippet extensions - create_call_asset: Create call extensions - create_image_asset: Upload images from URL or local file path - create_promotion_asset: Create promotion extensions with discounts - create_price_asset: Create price listing extensions - create_lead_form_asset: Create lead generation form extensions - create_text_asset: Create text assets for PMax headlines/descriptions - create_youtube_video_asset: Create YouTube video assets for PMax
- link_asset_to_campaign: Attach assets to campaigns - link_asset_to_ad_group: Attach assets to ad groups - link_assets_to_customer: Attach assets at account level - remove_campaign_asset: Remove asset links from campaigns
- create_asset_group: Create asset groups with all assets in single batch mutate - add_assets_to_asset_group: Add more assets to existing asset groups - remove_asset_from_asset_group: Remove assets from asset groups Handles PMax requirement of creating asset group + asset links atomically.
Import campaigns, ad_groups, ads_keywords, assets, asset_links, and asset_groups modules to register their tools with the MCP server.
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
Regenerated golden_tools_list.json to include all new write tools so the smoke test passes.
Enables per-query login_customer_id parameter across all 28 tools, allowing users to access client accounts through a Manager Account without changing the MCP server config. Falls back to the GOOGLE_ADS_LOGIN_CUSTOMER_ID env var when not specified.
- Promotion asset: add required final_url, fix percent_off micros conversion, skip NONE enum values for occasion and discount_modifier - Lead form asset: add required call_to_action_description and final_urls fields - Remove asset from asset group: use field type string name in resource path instead of numeric enum value All 29 tools tested and verified against live Google Ads API.
The default client was eagerly created at import time, causing crashes when credentials are not available (e.g., in CI). Now uses lazy initialization on first use.
Full JSON schema comparison breaks across pydantic/Python versions due to different nullable type representations. Compare tool names and required parameters instead for stable cross-version testing.
|
Hi, thanks for looking into this and for all the work that you have been putting in this PR! We plan to release write capabilities in steps, so there's a chance that this PR will not be merged as we may prefer doing gradual releases for write features. I'll leave it open for now in case we change our plans. |
- Add remove_ad and remove_keyword tools with elicitation confirmation - Add elicitation to remove_campaign_asset and remove_asset_from_asset_group - Use ctx: Context type annotation for proper SDK injection - Falls back gracefully when client doesn't support elicitation - Tested end-to-end on Claude Code CLI v2.1.81 - Update golden tools list with all 32 tools
|
Thanks for the feedback @Raibaz! Makes total sense. I needed write tools to manage my google ads, I will be enhancing it further, if you guys change your plans I am happy to split these into a separate small PR if helpful. And if you want to cherry-pick specific write tool categories for gradual release, everything is modular — each tool file is independent. |
- Add get_resource_metadata tool using GoogleAdsFieldService for on-demand field discovery - Replace gaql_resources.json (8276 lines) with gaql_resources.txt (178 lines) - Search tool description reduced from 300K+ chars to ~2K chars - Update search description to reference get_resource_metadata for field lookup - Fixes context window overflow issue (github.com/googleads/issues/15) - Update update_references.py to generate flat text format - Update search tests for new description format
|
Closing in favor of a rebased PR on top of the latest main (post PR #37 merge). |
Summary
This PR adds 33 new tools to the Google Ads MCP server, transforming it from read-only to a full campaign management platform. All tools follow the existing code patterns, include proper docstrings, and have been tested against live Google Ads accounts.
Highlights
login_customer_idparameter on all tools — switch between client accounts without restartingNew tools by category
Campaign Management (4 tools)
Ad Group Management (2 tools)
Ads & Keywords (7 tools)
Targeting (2 tools)
Asset Creation (10 tools)
Asset Linking (4 tools)
Asset Groups / Performance Max (4 tools)
MCP Elicitation for Destructive Operations
All 4 destructive tools implement MCP Elicitation to prompt users for confirmation before proceeding:
```python
@mcp.tool()
async def remove_keyword(
customer_id: str,
ad_group_id: str,
criterion_id: str,
ctx: Context = None,
) -> Dict[str, str]:
result = await ctx.elicit(
message="DESTRUCTIVE ACTION: Permanently remove keyword?",
schema=Confirmation,
)
if result.action != "accept" or not result.data.confirm:
return {"message": "Keyword removal cancelled by user."}
```
Technical details
Test plan