Bug 1 — Array parameter received as string
Calling update_campaign with geo_target_ids always fails with:
1 validation error for call[update_campaign]
geo_target_ids
Input should be a valid list [type=list_type, input_value='["2840"]', input_type=str]
The MCP bridge serialises the list to a string before the tool receives it, regardless of whether values are strings or integers. The tool never receives a Python list, making geo_target_ids completely unusable.
Bug 2 — No support for location exclusions
The Google Ads API distinguishes campaign_criterion.negative: false (inclusions) from campaign_criterion.negative: true (exclusions). update_campaign has no geo_exclusion_ids parameter. Even if Bug 1 were fixed, calling the tool on a campaign with existing exclusions would silently wipe them — a potentially expensive mistake.
Suggested fixes
- Deserialise list parameters with
json.loads() when the schema expects a list but receives a string.
- Add a
geo_exclusion_ids parameter (or rename to geo_inclusion_ids / geo_exclusion_ids pair).
- When
geo_target_ids is called on a campaign with existing exclusions, either preserve them or warn explicitly.
Reproduction
Any call to update_campaign with geo_target_ids set to a list triggers Bug 1. Bug 2 is visible by querying campaign_criterion with the negative field — real campaigns commonly have dozens of exclusions alongside a single inclusion.
Bug 1 — Array parameter received as string
Calling
update_campaignwithgeo_target_idsalways fails with:The MCP bridge serialises the list to a string before the tool receives it, regardless of whether values are strings or integers. The tool never receives a Python list, making
geo_target_idscompletely unusable.Bug 2 — No support for location exclusions
The Google Ads API distinguishes
campaign_criterion.negative: false(inclusions) fromcampaign_criterion.negative: true(exclusions).update_campaignhas nogeo_exclusion_idsparameter. Even if Bug 1 were fixed, calling the tool on a campaign with existing exclusions would silently wipe them — a potentially expensive mistake.Suggested fixes
json.loads()when the schema expects a list but receives a string.geo_exclusion_idsparameter (or rename togeo_inclusion_ids/geo_exclusion_idspair).geo_target_idsis called on a campaign with existing exclusions, either preserve them or warn explicitly.Reproduction
Any call to
update_campaignwithgeo_target_idsset to a list triggers Bug 1. Bug 2 is visible by queryingcampaign_criterionwith thenegativefield — real campaigns commonly have dozens of exclusions alongside a single inclusion.