Google Ads - AdLoop
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Capabilities
Features and capabilities supported by this server
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
| logging | {} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
| extensions | {
"io.modelcontextprotocol/ui": {}
} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| health_checkA | Test AdLoop connectivity — checks OAuth token, GA4 API, and Google Ads API. Run this first if other tools are failing. Returns status for each service and actionable guidance if something is broken. |
| get_account_summariesA | List all GA4 accounts and properties accessible by the authenticated user. Use this as the first step to discover which GA4 properties are available. Returns account names, property names, and property IDs. |
| run_ga4_reportA | Run a custom GA4 report with specified dimensions, metrics, and date range. Common dimensions: date, pagePath, sessionSource, sessionMedium, country, deviceCategory, eventName Common metrics: sessions, totalUsers, newUsers, screenPageViews, conversions, eventCount, bounceRate Date formats: "today", "yesterday", "7daysAgo", "28daysAgo", "90daysAgo", or "YYYY-MM-DD". If property_id is empty, uses the default from config. |
| run_realtime_reportA | Run a GA4 realtime report showing current active users and events. Useful for checking if tracking is firing correctly after code changes. Common dimensions: unifiedScreenName, eventName, country, deviceCategory Common metrics: activeUsers, eventCount |
| get_tracking_eventsA | List all GA4 events and their volume for the given date range. Returns every distinct event name with its total event count. Use this to understand what tracking is configured and active. |
| list_accountsA | List accessible Google Ads accounts. Returns account names, IDs, and status. The default cap of 200 covers the vast majority of agency MCCs in one call. If the user explicitly asked to see ALL of their accounts and the response comes back with 'truncated: true', call this tool again with a much higher limit (e.g. list_accounts(limit=1000)) — do not stop at the truncated list. For workflows that target a specific account you don't need to enumerate at all: pass customer_id directly to get_campaign_performance, run_gaql, etc. |
| get_campaign_performanceA | Get campaign-level performance metrics for a date range. Returns: campaign name, status, type, impressions, clicks, cost, conversions, CPA, ROAS, CTR for each campaign. Date format: "YYYY-MM-DD". Empty = last 30 days. |
| get_ad_performanceB | Get ad-level performance data including headlines, descriptions, and metrics. Returns: ad type, headlines, descriptions, final URL, impressions, clicks, CTR, conversions, cost for each ad. |
| get_keyword_performanceB | Get keyword metrics including quality scores and competitive data. Returns: keyword text, match type, quality score, impressions, clicks, CTR, CPC, conversions for each keyword. |
| get_search_termsA | Get search terms report — what users actually typed before clicking your ads. Critical for finding negative keyword opportunities and understanding user intent. Returns: search term, campaign, ad group, impressions, clicks, conversions. |
| get_negative_keywordsA | List existing negative keywords for a campaign or all campaigns. Use this before adding negative keywords to check for duplicates. If campaign_id is empty, returns negatives across all campaigns. |
| get_negative_keyword_listsA | List all shared negative keyword lists (SharedSets) in the account. Returns each list's ID, name, status, and keyword count. Always call this before propose_negative_keyword_list to avoid creating duplicates — a suitable list may already exist and just need attaching to a campaign. |
| get_negative_keyword_list_keywordsA | List the keywords inside a shared negative keyword list. shared_set_id: numeric ID from get_negative_keyword_lists (shared_set.id). |
| get_negative_keyword_list_campaignsA | List which campaigns a shared negative keyword list is attached to. shared_set_id: numeric ID from get_negative_keyword_lists. Omit to see all list-to-campaign attachments across the account. |
| get_recommendationsA | Retrieve Google's auto-generated recommendations with estimated impact. Returns each recommendation's type, associated campaign/ad group, current (base) and projected (potential) metrics, and the estimated improvement. recommendation_types: optional filter — e.g. ["KEYWORD", "TARGET_CPA_OPT_IN", "MAXIMIZE_CONVERSIONS_OPT_IN", "RESPONSIVE_SEARCH_AD"]. Empty = all types. campaign_id: optional — scope to a single campaign. Includes insights that flag budget-increase recommendations (often self-serving) and highlight high-impact suggestions worth investigating. |
| get_pmax_performanceA | Get Performance Max campaign and asset group performance. Returns two result sets:
Includes insights flagging weak ad strength, zero-conversion asset groups, and network type distribution. Date format: "YYYY-MM-DD". Empty = last 30 days. |
| get_asset_performanceA | Get per-asset details for Performance Max campaigns. Returns each asset's field_type (HEADLINE, DESCRIPTION, MARKETING_IMAGE, YOUTUBE_VIDEO, etc.), primary_status (ELIGIBLE, NOT_ELIGIBLE, PAUSED, PENDING), and content (text or image URL). Note: per-asset performance labels (BEST/GOOD/LOW) are not available for PMax assets in Google Ads API v23. Use get_detailed_asset_performance to see which asset combinations Google selects most — the closest proxy for individual asset quality. campaign_id: optional filter to a single PMax campaign. Includes by_status and by_field_type summaries. |
| get_detailed_asset_performanceA | Get top-performing asset combinations for Performance Max campaigns. Shows which headline + description + image combinations Google selects most often. Each combination lists the assets used and their field types. This data helps identify which creative elements work well together. campaign_id: optional filter to a single PMax campaign. |
| get_audience_performanceA | Get audience segment performance metrics. Returns performance by audience type — remarketing lists (USER_LIST), in-market segments (USER_INTEREST), affinity, demographics (AGE_RANGE, GENDER), etc. Shows display_name, impressions, clicks, cost, conversions, CTR, and CPC for each audience. Works for campaigns with explicit audience targeting (Search, Display). PMax audience targeting is automatic and may not appear in this report. campaign_id: optional filter to a single campaign. Date format: "YYYY-MM-DD". Empty = last 30 days. |
| analyze_campaign_conversionsA | Campaign clicks → GA4 conversions mapping — the real cost-per-conversion. Combines Google Ads campaign metrics with GA4 session/conversion data to reveal click-to-session ratios (GDPR indicator), compare Ads-reported vs GA4-reported conversions, and compute cost-per-GA4-conversion. Also returns non-paid channel conversion rates for comparison context. Date format: "YYYY-MM-DD". Empty = last 30 days. |
| landing_page_analysisB | Analyze which landing pages convert and which don't. Combines ad final URLs with GA4 page-level data to show paid traffic sessions, conversion rates, bounce rates, and engagement per landing page. Identifies pages that get ad clicks but zero conversions and orphaned URLs. Date format: "YYYY-MM-DD". Empty = last 30 days. |
| attribution_checkA | Compare Ads-reported conversions vs GA4 — find tracking discrepancies. Checks whether conversions reported by Google Ads match what GA4 records, diagnoses GDPR consent gaps, attribution model differences, and missing conversion event configuration. conversion_events: optional list of GA4 event names to specifically check (e.g. ["sign_up", "purchase"]). If omitted, compares aggregate totals only. Date format: "YYYY-MM-DD". Empty = last 30 days. |
| run_gaqlA | Execute an arbitrary GAQL (Google Ads Query Language) query. Use this for advanced queries not covered by the other tools. See the GAQL reference in the AdLoop cursor rules for syntax help. format: "table" (default, readable), "json" (structured), "csv" (exportable) |
| draft_campaignA | Draft a full campaign structure — returns a PREVIEW, does NOT create anything. Creates: CampaignBudget + Campaign (PAUSED) + AdGroup + optional Keywords
bidding_strategy: MAXIMIZE_CONVERSIONS | TARGET_CPA | TARGET_ROAS | MAXIMIZE_CONVERSION_VALUE | TARGET_SPEND | MANUAL_CPC target_cpa: required if bidding_strategy is TARGET_CPA (in account currency) target_roas: required if bidding_strategy is TARGET_ROAS keywords: list of {"text": "keyword", "match_type": "EXACT|PHRASE|BROAD"} search_partners_enabled: include ads on Search partners display_network_enabled: enable Search campaign display expansion display_expansion_enabled: alias for display_network_enabled max_cpc: manual CPC bid for the initial ad group when bidding_strategy is MANUAL_CPC, or the Maximize Clicks CPC cap when bidding_strategy is TARGET_SPEND geo_target_ids: REQUIRED list of geo target constant IDs Common: "2276" Germany, "2040" Austria, "2756" Switzerland, "2840" USA, "2826" UK, "2250" France. Full list: Google Ads API geo target constants. language_ids: REQUIRED list of language constant IDs Common: "1001" German, "1000" English, "1002" French, "1004" Spanish, "1014" Portuguese. Full list: Google Ads API language constants. Call confirm_and_apply with the returned plan_id to execute. |
| draft_ad_groupA | Draft a new ad group within an existing campaign — returns a PREVIEW, does NOT create. Creates an ad group (ENABLED, type SEARCH_STANDARD) in the specified campaign. Optionally includes keywords in the same atomic operation. campaign_id: The campaign to add the ad group to (get from get_campaign_performance). ad_group_name: Name for the new ad group. keywords: Optional list of {"text": "keyword", "match_type": "EXACT|PHRASE|BROAD"}. cpc_bid_micros: Optional ad group CPC bid in micros (only for MANUAL_CPC campaigns). Call confirm_and_apply with the returned plan_id to execute. |
| update_campaignA | Draft an update to an existing campaign — returns a PREVIEW, does NOT apply. Only include the parameters you want to change. Omit the rest. campaign_id: the numeric ID of the campaign to update (required) bidding_strategy: MAXIMIZE_CONVERSIONS | TARGET_CPA | TARGET_ROAS | MAXIMIZE_CONVERSION_VALUE | TARGET_SPEND | MANUAL_CPC target_cpa: required if bidding_strategy is TARGET_CPA (in account currency) target_roas: required if bidding_strategy is TARGET_ROAS daily_budget: new daily budget in account currency geo_target_ids: REPLACES all geo targets. Common IDs: "2276" Germany, "2040" Austria, "2756" Switzerland, "2840" USA, "2826" UK language_ids: REPLACES all language targets. Common IDs: "1001" German, "1000" English, "1002" French, "1004" Spanish search_partners_enabled: include ads on Search partners display_network_enabled: enable Search campaign display expansion display_expansion_enabled: alias for display_network_enabled max_cpc: Maximize Clicks CPC cap when bidding_strategy is TARGET_SPEND, or when the existing campaign already uses TARGET_SPEND Call confirm_and_apply with the returned plan_id to execute. |
| draft_responsive_search_adA | Draft a Responsive Search Ad — returns a PREVIEW, does NOT create the ad. Provide 3-15 headlines (max 30 chars each) and 2-4 descriptions (max 90 chars each). The preview shows exactly what will be created. Call confirm_and_apply to execute. Each headline/description entry may be either:
Valid pin values: headlines: HEADLINE_1, HEADLINE_2, HEADLINE_3 descriptions: DESCRIPTION_1, DESCRIPTION_2 Google caps: at most 2 headlines per pin slot, at most 1 description per pin slot. Mixed plain-string and dict entries are allowed within a single call (e.g. brand pinned to HEADLINE_1, the rest unpinned). |
| draft_keywordsA | Draft keyword additions — returns a PREVIEW, does NOT add keywords. keywords: list of {"text": "keyword phrase", "match_type": "EXACT|PHRASE|BROAD"} Call confirm_and_apply with the returned plan_id to execute. |
| add_negative_keywordsA | Draft negative keyword additions — returns a PREVIEW. Negative keywords prevent your ads from showing for irrelevant searches. match_type: "EXACT", "PHRASE", or "BROAD" Call confirm_and_apply with the returned plan_id to execute. |
| propose_negative_keyword_listA | Draft a shared negative keyword list and attach it to a campaign — returns a PREVIEW. Creates a reusable negative keyword list that can later be applied to multiple campaigns, unlike add_negative_keywords which adds directly to one campaign. match_type: "EXACT", "PHRASE", or "BROAD" Call confirm_and_apply with the returned plan_id to execute. |
| add_to_negative_keyword_listA | Append keywords to an EXISTING shared negative keyword list — returns a PREVIEW. Use this when a suitable list already exists and only needs more keywords (instead of propose_negative_keyword_list, which creates a new list). Always call get_negative_keyword_lists first to find the right shared_set_id and get_negative_keyword_list_keywords to avoid duplicating existing terms. shared_set_id: numeric ID from get_negative_keyword_lists (shared_set.id). keywords: list of keyword strings to append (duplicates in the input list are collapsed). match_type: "EXACT", "PHRASE", or "BROAD" Call confirm_and_apply with the returned plan_id to execute. |
| attach_shared_set_to_campaignsA | Attach an existing shared set to one or more campaigns — returns a PREVIEW. Creates CampaignSharedSet linkages so the campaigns inherit the shared set's criteria (e.g. negative keywords). Most commonly used to attach a shared negative keyword list to newly-built campaigns. Use shared_set_id: numeric ID from get_negative_keyword_lists. campaign_ids: list of numeric campaign IDs to attach the set to. Call confirm_and_apply with the returned plan_id to execute. |
| detach_shared_set_from_campaignsA | Detach a shared set from one or more campaigns — returns a PREVIEW. Removes CampaignSharedSet linkages so the campaigns no longer inherit the shared set's criteria. The shared set itself is unchanged; only the per-campaign attachment is removed. Use shared_set_id: numeric ID from get_negative_keyword_lists. campaign_ids: list of numeric campaign IDs to detach the set from. Call confirm_and_apply with the returned plan_id to execute. |
| update_ad_groupC | Draft an ad group update for name and/or manual CPC bid. |
| draft_calloutsC | Draft campaign callout assets — returns a PREVIEW. |
| draft_structured_snippetsB | Draft campaign structured snippet assets — returns a PREVIEW. |
| draft_image_assetsC | Draft campaign image assets from local PNG, JPEG, or GIF files. |
| pause_entityA | Draft pausing a campaign, ad group, ad, or keyword — returns a PREVIEW. entity_type: "campaign", "ad_group", "ad", or "keyword" entity_id format by type:
Call confirm_and_apply with the returned plan_id to execute. |
| enable_entityA | Draft enabling a paused campaign, ad group, ad, or keyword — returns a PREVIEW. entity_type: "campaign", "ad_group", "ad", or "keyword" entity_id format by type:
Call confirm_and_apply with the returned plan_id to execute. |
| remove_entityA | Draft REMOVING an entity — returns a PREVIEW. This is IRREVERSIBLE. entity_type: "campaign", "ad_group", "ad", "keyword", "negative_keyword",
"shared_criterion", "campaign_asset", "asset", or "customer_asset"
entity_id: The resource ID.
For keywords: "adGroupId WARNING: Removed entities cannot be re-enabled. Use pause_entity instead if you just want to temporarily disable something. Call confirm_and_apply with the returned plan_id to execute. |
| draft_sitelinksA | Draft sitelink extensions for a campaign — returns a PREVIEW. Sitelinks appear as additional links below your ad, increasing click area and directing users to specific pages. campaign_id: the campaign to attach sitelinks to sitelinks: list of dicts, each with: - link_text (str, required, max 25 chars) — the clickable text shown - final_url (str, required) — destination URL for this sitelink - description1 (str, optional, max 35 chars) — first description line - description2 (str, optional, max 35 chars) — second description line Google recommends at least 4 sitelinks per campaign. Fewer than 2 may not show. Call confirm_and_apply with the returned plan_id to execute. |
| confirm_and_applyA | Execute a previously previewed change. IMPORTANT: Defaults to dry_run=True. You MUST explicitly pass dry_run=false to make real changes to the Google Ads account. Config override: if 'safety.require_dry_run: true' is set in the user's config file (default ~/.adloop/config.yaml), dry_run=false is IGNORED and this tool will keep returning DRY_RUN_SUCCESS. When that happens the response includes 'dry_run_forced_by', 'config_path', and 'remediation' fields — surface those to the user verbatim and STOP retrying. Calling this tool again with dry_run=false will not change anything until the user edits the config file, sets 'require_dry_run: false', and restarts the AdLoop MCP server. The plan_id comes from a prior draft_* or pause/enable tool call. |
| validate_trackingA | Compare tracking events found in the codebase against actual GA4 data. First, search the user's codebase for gtag('event', ...) or dataLayer.push calls and extract event names. Then pass those names here to check which ones actually fire in GA4. Returns: matched events, events missing from GA4, unexpected GA4 events, and auto-collected events (page_view, session_start, etc.). |
| generate_tracking_codeA | Generate a GA4 event tracking JavaScript snippet. Produces ready-to-paste gtag code for the specified event. Includes recommended parameters for well-known GA4 events (sign_up, purchase, etc.). Optionally checks GA4 to warn if the event already fires. trigger: "form_submit", "button_click", or "page_load" — wraps the gtag call in an appropriate event listener. Empty = bare gtag call. |
| estimate_budgetA | Forecast clicks, impressions, and cost for a set of keywords. Uses Google Ads Keyword Planner to estimate campaign performance without creating anything. Essential for budget planning before launching campaigns. keywords: list of {"text": "keyword", "match_type": "EXACT|PHRASE|BROAD", "max_cpc": 1.50} max_cpc is optional (defaults to 1.00 in account currency) geo_target_id: geo target constant (2276=Germany, 2840=USA, 2826=UK, 2250=France) language_id: language constant (1000=English, 1001=German, 1002=French, 1003=Spanish) daily_budget: if provided, insights will show what % of traffic the budget captures forecast_days: forecast horizon in days (default 30) |
| discover_keywordsA | Discover new keyword ideas using Google Ads Keyword Planner. Mirrors the "Discover new keywords" UI in Keyword Planner:
Returns keyword ideas sorted by avg monthly search volume, with competition level (LOW/MEDIUM/HIGH) and top-of-page bid range. geo_target_id: geo target constant (2276=Germany, 2840=USA, 2826=UK) language_id: language constant (1000=English, 1001=German, 1002=French) page_size: max keyword ideas to return (default 50, max 1000) |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
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/kLOsk/adloop'
If you have feedback or need assistance with the MCP directory API, please join our Discord server