Google Marketing MCP
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| ADS_READ_ONLY | No | If true, blocks all mutations in the Google Ads domain. | false |
| GA4_READ_ONLY | No | If true, blocks all mutations in the GA4 domain. | false |
| GSC_READ_ONLY | No | If true, blocks all mutations in the Search Console domain. | false |
| GTM_READ_ONLY | No | If true, blocks all mutations in the Tag Manager domain. | false |
| GTM_ALLOW_PUBLISH | No | If true, allows publishing GTM container versions (extra safety gate). | false |
| GOOGLE_OAUTH_CLIENT_ID | No | OAuth client ID from Google Cloud Console for the unified token covering all domains. | |
| GOOGLE_ADS_REFRESH_TOKEN | No | Refresh token obtained via ads/auth.py for domain-specific Google Ads OAuth. | |
| GOOGLE_ADS_DEVELOPER_TOKEN | No | Google Ads developer token from Google Ads UI > API Center (required for Google Ads tools). | |
| GOOGLE_OAUTH_CLIENT_SECRET | No | OAuth client secret from Google Cloud Console for the unified token. | |
| GOOGLE_OAUTH_REFRESH_TOKEN | No | Refresh token obtained via auth_unified, providing access to Ads, Tag Manager, Search Console, and GA4. | |
| GOOGLE_ADS_LOGIN_CUSTOMER_ID | No | MCC customer ID to use when reaching client accounts through a manager account. | |
| GOOGLE_APPLICATION_CREDENTIALS | No | Path to the JSON key file for a service account used by GTM, Search Console, and GA4 (alternative to unified OAuth). |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| ads_list_accountsA | List Google Ads accounts (customer ids + names) available to use. When GOOGLE_ADS_LOGIN_CUSTOMER_ID is set to a manager (MCC) account, this enumerates the whole tree under that manager -- which is what you want for an agency setup. Otherwise it falls back to the directly accessible customers. Start here to discover the 10-digit customer_id for other tools. |
| ads_get_account_detailsA | Get details for a single account: name, currency, time zone, status, auto-tagging, conversion tracking, and whether it is a manager account. Args: customer_id: 10-digit account id (dashes ok). Defaults to env default. |
| ads_run_gaqlA | Run an arbitrary GAQL (Google Ads Query Language) query and return rows. This is the most flexible read tool. Use it for any custom report. Example query: SELECT campaign.id, campaign.name, metrics.clicks, metrics.cost_micros FROM campaign WHERE segments.date DURING LAST_7_DAYS ORDER BY metrics.clicks DESC Args: customer_id: 10-digit account id (dashes ok). query: full GAQL query string. limit: max rows to return (client-side cap; default 200). |
| ads_campaign_performanceA | Campaign performance report: impressions, clicks, CTR, cost, conversions, CPA, ROAS, conversion value. Sorted by cost descending. Args: customer_id: 10-digit account id. date_range: a GAQL date constant (e.g. LAST_7_DAYS, LAST_30_DAYS, THIS_MONTH). limit: max campaigns. only_active: restrict to ENABLED campaigns. |
| ads_keyword_performanceA | Keyword-level performance: text, match type, quality score, clicks, cost, conversions, CPA. Useful to find wasteful or high-performing keywords. Args: customer_id: 10-digit account id. date_range: GAQL date constant. campaign_id: optional filter to one campaign. limit: max keywords. |
| ads_monitor_accountA | Health/status monitor. Surfaces issues that need attention:
Args: customer_id: 10-digit account id. |
| ads_keyword_ideasA | Keyword research: generate keyword ideas with avg monthly searches, competition level, and top-of-page bid range (low/high). Seed from keywords and/or a landing page URL. This is the Keyword Planner research tool. Args: customer_id: 10-digit account id (any account with Planner access works). seed_keywords: list of seed terms, e.g. ["running shoes","trail shoes"]. page_url: optional landing page URL to seed ideas from. location_ids: Google geo target ids (e.g. [2840] = United States, [2826] = United Kingdom, [2356] = India). Omit for no geo constraint. language_id: language constant id (1000 = English, 1019 = Spanish, 1010 = French, 1001 = German). limit: max ideas to return. include_adult: include adult keywords (default False). |
| ads_historical_search_volumeA | Get historical monthly search volume + competition for a specific list of keywords (no idea expansion). Use to size demand for exact terms you already have. Args: customer_id: 10-digit account id. keywords: exact keyword list to look up. location_ids: geo target ids (e.g. [2840] = US). language_id: language constant id (1000 = English). |
| ads_create_campaignA | Create a new campaign with its own daily budget. Created PAUSED by default so it never spends until you explicitly enable it. Args: customer_id: 10-digit account id. name: campaign name (must be unique). daily_budget: daily budget in account currency (e.g. 25.00). channel_type: SEARCH | DISPLAY | SHOPPING | VIDEO | PERFORMANCE_MAX. NOTE: Google blocks VIDEO campaign creation via the API (MUTATE_NOT_ALLOWED, trigger=VIDEO) — the campaign shell must be made in the Google Ads UI. The video tools (create_video_ad_group / create_video_ad) still work to populate an existing video campaign. channel_sub_type: optional VIDEO sub type. Leave None for a plain video views / TrueView (skippable in-stream, CPV) campaign. Set VIDEO_ACTION for conversion video, VIDEO_NON_SKIPPABLE for CPM reach, VIDEO_SEQUENCE, or VIDEO_REACH_TARGET_FREQUENCY. bidding_strategy: MAXIMIZE_CONVERSIONS | MAXIMIZE_CONVERSION_VALUE | TARGET_SPEND | MANUAL_CPC | TARGET_CPM | TARGET_CPV. Skippable in-stream CPV = TARGET_CPV (per-view bid set on the ad group via create_video_ad_group; manual CPV is retired by Google). target_cpa: optional target CPA (currency) for MAXIMIZE_CONVERSIONS. target_roas: optional target ROAS (e.g. 4.0 = 400%) for value strategies. status: ENABLED | PAUSED (default PAUSED). start_paused: force PAUSED regardless of status (safety, default True). confirm: must be true to actually apply (else dry-run validate only). |
| ads_set_campaign_statusA | Enable, pause, or remove a campaign. Core status-monitoring action. Args: customer_id: 10-digit account id. campaign_id: campaign id. status: ENABLED | PAUSED | REMOVED. confirm: must be true to apply (else dry-run). |
| ads_update_campaign_budgetA | Change a campaign's daily budget (in account currency). Looks up the campaign's budget resource and updates the amount. Money-affecting change. Args: customer_id: 10-digit account id. campaign_id: campaign id. new_daily_budget: new daily budget (e.g. 40.00). confirm: must be true to apply (else dry-run). |
| ads_set_campaign_bidding_strategyA | Change an existing campaign's standard (non-portfolio) bidding strategy. Sets the new strategy oneof on the campaign and updates only that field. Switching strategy resets the previous one. Bid-affecting change. Args: customer_id: 10-digit account id. campaign_id: campaign id. bidding_strategy: MAXIMIZE_CONVERSIONS | MAXIMIZE_CONVERSION_VALUE | TARGET_SPEND | MANUAL_CPC. target_cpa: optional target CPA (currency) for MAXIMIZE_CONVERSIONS. target_roas: optional target ROAS (e.g. 4.0 = 400%) for value strategy. cpc_ceiling: max CPC ceiling (currency) for TARGET_SPEND/Maximize Clicks. Required for TARGET_SPEND (Google rejects a zero/unset ceiling). confirm: must be true to apply (else dry-run validate only). |
| ads_create_video_ad_groupA | Create a video ad group inside a VIDEO campaign. Use this (not create_ad_group) for video campaigns. For skippable in-stream TrueView with CPV bidding, keep the default ad_group_type and pass cpv_bid (the max cost-per-view, e.g. 1.00). The parent campaign must be channel_type VIDEO with MANUAL_CPV bidding. Args: customer_id: 10-digit account id. campaign_id: parent VIDEO campaign id. name: ad group name. cpv_bid: max cost-per-view in account currency (skippable in-stream / CPV). ad_group_type: VIDEO_TRUE_VIEW_IN_STREAM (default, skippable in-stream) | VIDEO_BUMPER | VIDEO_NON_SKIPPABLE_IN_STREAM | VIDEO_TRUE_VIEW_IN_DISPLAY | VIDEO_RESPONSIVE | VIDEO_EFFICIENT_REACH. status: ENABLED | PAUSED. confirm: must be true to apply (else dry-run). |
| ads_create_ad_groupA | Create an ad group inside a campaign. Args: customer_id: 10-digit account id. campaign_id: parent campaign id. name: ad group name. default_cpc_bid: optional default max CPC (currency) for manual bidding. status: ENABLED | PAUSED. confirm: must be true to apply (else dry-run). |
| ads_set_ad_group_statusB | Enable, pause, or remove an ad group. Args: customer_id: 10-digit account id. ad_group_id: ad group id. status: ENABLED | PAUSED | REMOVED. confirm: must be true to apply (else dry-run). |
| ads_set_ad_group_bidA | Set an ad group's default max CPC bid (manual bidding only). Money change. Args: customer_id: 10-digit account id. ad_group_id: ad group id. cpc_bid: new max CPC in account currency (e.g. 1.50). confirm: must be true to apply (else dry-run). |
| ads_create_video_adA | Create a video ad in a video ad group, linking an existing YouTube video asset. The YouTube video must already exist as an asset in the account (type YOUTUBE_VIDEO). Find its id via a GAQL asset query. The video_format must match the ad group type: IN_STREAM = skippable TrueView (VIDEO_TRUE_VIEW_IN_STREAM), BUMPER = 6s bumper, NON_SKIPPABLE = non-skippable in-stream. Created PAUSED. Args: customer_id: 10-digit account id. ad_group_id: target video ad group id. video_asset_id: numeric id of an existing YOUTUBE_VIDEO asset. final_url: landing page URL (https://...). video_format: IN_STREAM (default) | BUMPER | NON_SKIPPABLE | OUT_STREAM. name: optional ad name. action_headline: optional CTA headline overlay (in_stream only). action_button_label: optional CTA button label (in_stream only). status: ENABLED | PAUSED (default PAUSED). confirm: must be true to apply (else dry-run). |
| ads_create_responsive_search_adA | Create a Responsive Search Ad (RSA) in an ad group. Google policy/limits:
Args: customer_id: 10-digit account id. ad_group_id: target ad group id. final_url: landing page URL (https://...). headlines: 3-15 headline strings (<=30 chars). descriptions: 2-4 description strings (<=90 chars). path1: optional display URL path segment (<=15 chars). path2: optional second display URL path segment (<=15 chars). status: ENABLED | PAUSED (default PAUSED). confirm: must be true to apply (else dry-run). |
| ads_set_ad_statusA | Enable, pause, or remove a specific ad. Args: customer_id: 10-digit account id. ad_group_id: ad group id the ad belongs to. ad_id: ad id. status: ENABLED | PAUSED | REMOVED. confirm: must be true to apply (else dry-run). |
| ads_add_keywordsA | Add positive keywords to an ad group. Args: customer_id: 10-digit account id. ad_group_id: target ad group id. keywords: keyword text list. match_type: EXACT | PHRASE | BROAD (default PHRASE). cpc_bid: optional per-keyword max CPC (currency). confirm: must be true to apply (else dry-run). |
| ads_add_negative_keywordsA | Add negative keywords to an ad group (block wasteful queries). Args: customer_id: 10-digit account id. ad_group_id: target ad group id. keywords: negative keyword text list. match_type: EXACT | PHRASE | BROAD. confirm: must be true to apply (else dry-run). |
| ads_list_recommendationsA | List Google's optimization Recommendations for the account (the same suggestions shown in the Ads UI 'Recommendations' tab): add keywords, fix budgets, improve bids, ad strength, etc. Each has a resource_name + type you can pass to apply_recommendation. Args: customer_id: 10-digit account id. limit: max recommendations. |
| ads_apply_recommendationA | Apply a specific Google Ads Recommendation by its resource_name (from list_recommendations). This can change bids, budgets, keywords, or ads. Args: customer_id: 10-digit account id. resource_name: recommendation resource name to apply. confirm: must be true to apply (else dry-run; recommendations support validate_only). |
| ads_search_terms_reportA | Search-terms report: the actual queries that triggered ads, with cost and conversions. Use to mine new keywords (high converters) and negatives (spend, zero conversions). Args: customer_id: 10-digit account id. date_range: GAQL date constant (e.g. LAST_30_DAYS). campaign_id: optional campaign filter. limit: max rows. |
| gtm_list_accountsA | List every Tag Manager account this credential can reach. Call this first. If it returns nothing, the service account has not been added under GTM > Admin > Account User Management on any account. |
| gtm_list_containersA | List containers in an account. Note the two different ids: container_id is numeric and is what every other tool wants; public_id is the GTM-XXXXXXX string you paste into a site. |
| gtm_get_containerA | Full detail for one container, including its usage context (web, server, ios, android, amp) and the domains it is declared on. |
| gtm_container_snippetC | The install snippet for a web container: the script and the |
| gtm_list_user_permissionsA | Who has access to this GTM account, and at what level. Useful for confirming the service account itself is wired correctly, and for auditing who can publish. |
| gtm_list_workspacesB | List workspaces in a container. A workspace is an isolated set of pending changes. The Default Workspace is usually id 1. Prefer creating your own workspace for a batch of edits so the change set stays reviewable and easy to abandon. |
| gtm_create_workspaceA | Create a workspace to hold a batch of changes. Do this before any set of edits you might want to abandon. Deleting a workspace discards everything in it, which is far cleaner than unpicking edits made directly in the Default Workspace. GTM allows a limited number of concurrent workspaces per container (3 on the free tier), so delete them once merged. |
| gtm_delete_workspaceA | Delete a workspace and discard every uncommitted change inside it. This cannot be undone. Run workspace_status first to see what is about to be thrown away. |
| gtm_workspace_statusA | Every uncommitted change in a workspace, and any conflict with the live container. This is the diff to review before creating a version. A non-empty merge_conflicts list means the live container moved underneath you; call sync_workspace to resolve. |
| gtm_sync_workspaceA | Pull the latest live container state into a workspace. Run this when workspace_status reports merge conflicts. Changes that cannot be merged automatically are returned so you can resolve them by hand. |
| gtm_list_entitiesA | List entities of any type in a workspace. Args: entity_type: one of tags, triggers, variables, folders, templates, clients, transformations, zones, built_in_variables, gtag_config. name_contains: case-insensitive substring filter on the entity name. full: return the complete API object instead of a compact summary. Use this when you are about to copy an entity, since update_entity needs the full body. |
| gtm_get_entityA | Fetch one entity in full, including its parameter tree. Read a working entity of the same type before creating a new one -- tag and trigger parameter shapes are strict and mirroring a known-good example is far more reliable than guessing. |
| gtm_create_entityA | Create an entity of any type. Args: entity_type: tags, triggers, variables, folders, templates, clients, transformations, zones, gtag_config. name: display name in the GTM UI. type: the GTM type string, e.g. 'gaawe' for a GA4 event tag, 'googtag' for a Google tag, 'awct' for an Ads conversion, 'linkClick' for a trigger, 'jsm' for a custom JavaScript variable. Not needed for folders. parameters: plain dict, converted to the API's typed shape. Reference other variables with double braces, e.g. {"pageUrl": "{{Page URL}}"}. firing_trigger_ids: trigger ids that fire a tag. blocking_trigger_ids: trigger ids that block a tag. extra: any additional top-level fields to merge into the request body, for fields this signature does not name (monitoringMetadata, consentSettings, scheduleStartMs, and so on). confirm: set true to actually create. |
| gtm_update_entityA | Update an entity by merging The API replaces the whole object on update, so this reads the entity first
and merges, rather than making you resend every field. Pass Example updates: {"name": "New name", "paused": true} |
| gtm_delete_entityA | Delete an entity from a workspace. Deleting a trigger or variable that a tag still references leaves that tag broken, and the API will not warn you. Run find_references first. |
| gtm_enable_built_in_variablesA | Turn on GTM built-in variables. Built-in variables are enabled by type, not created. Common types: pageUrl, pageHostname, pagePath, referrer, event, clickElement, clickClasses, clickId, clickTarget, clickUrl, clickText, formElement, formClasses, formId, formTarget, formUrl, formText, scrollDepthThreshold, videoStatus, containerId, environmentName. Click and form triggers silently fail to capture anything useful when the matching built-in variables are off, so this is usually step one. |
| gtm_find_referencesA | Find everything that references a variable or trigger, by name or id. Run this before deleting or renaming. The API has no referential integrity: deleting a trigger a tag still fires on, or renaming a variable another entity interpolates as {{Name}}, breaks silently at runtime. |
| gtm_create_ga4_event_tagA | Create a GA4 event tag (type 'gaawe'). Args: measurement_id: the G-XXXXXXX id, or a variable reference such as {{GA4 Measurement ID}} if you keep it in a constant. event_name: the GA4 event, e.g. generate_lead, purchase, phone_call_click. firing_trigger_ids: trigger ids that fire this tag. Get them from list_entities with entity_type='triggers'. event_parameters: extra event parameters as a plain dict, e.g. {"value": "{{DL - value}}", "currency": "INR"}. |
| gtm_create_ads_conversion_tagC | Create a Google Ads conversion tracking tag (type 'awct'). Args: conversion_id: the AW-XXXXXXXXX id, digits only or with the AW- prefix. conversion_label: the label from the Google Ads conversion action. conversion_value: a fixed number, or a variable reference like {{DL - value}}. Leave unset for a valueless conversion. currency_code: ISO code, or a variable reference. |
| gtm_create_triggerB | Create a trigger. Args: trigger_type: pageview, domReady, windowLoaded, click, linkClick, formSubmission, customEvent, historyChange, scrollDepth, elementVisibility, timer, youTubeVideo, jsError. conditions: list of {variable, operator, value}. Operator is one of equals, contains, startsWith, endsWith, matchRegex, greater, less. Variable is a GTM variable reference, e.g. '{{Page URL}}'. Example: [{"variable": "{{Page URL}}", "operator": "contains", "value": "/thank-you"}] event_name: required for customEvent triggers -- the dataLayer event name. A click or form trigger only captures useful conditions when the matching built-in variables are enabled; call enable_built_in_variables first. |
| gtm_create_datalayer_variableB | Create a Data Layer Variable (type 'v'). Args: datalayer_name: the dataLayer key to read, e.g. 'ecommerce.value'. default_value: returned when the key is absent. version: dataLayer version, 2 unless you have a specific reason. |
| gtm_create_constant_variableB | Create a Constant variable (type 'c'). Worth doing for any id used in more than one tag -- a GA4 measurement id or an Ads conversion id. Changing it then means editing one variable rather than hunting every tag that hardcoded it. |
| gtm_list_versionsA | List container version headers, newest first. Use this to find a version to roll back to. The live version is reported by get_live_version. |
| gtm_get_live_versionB | The version currently serving live traffic. Compare this against your workspace before publishing, and note the version_id so you have a rollback target. |
| gtm_get_versionB | Full detail of one container version, including every tag it contains. |
| gtm_create_versionA | Snapshot a workspace into a container version. This does not publish. It freezes the current workspace so it can be reviewed, published, or rolled back to later. Write real notes -- they are the only record of why a change was made. |
| gtm_publish_versionA | Publish a container version to live traffic. This takes effect immediately for every visitor. There is no staging step and no undo beyond publishing an earlier version, so note the current live version id first via get_live_version. Requires GTM_ALLOW_PUBLISH=true in addition to confirm=true, and Publish permission on the container. |
| gtm_audit_containerB | Full container health check in one call. Reports: tags that can never fire, paused tags, triggers and variables nothing uses, references to variables that do not exist, and inconsistent GA4 or Ads ids. Findings are ordered most severe first. |
| gtm_tag_coverageA | What this container actually measures: every tag with the trigger names that fire it, resolved from ids to readable names. This is the map to read before adding anything, so you do not duplicate a conversion that already fires. |
| gsc_list_sitesA | List every Search Console property this credential can read, with the permission level held on each. Call this first. The returned site_url strings are the exact values every other tool expects -- domain properties look like 'sc-domain:example.com', URL-prefix properties keep their scheme and trailing slash. permission_level meanings: siteOwner / siteFullUser -- full access, URL inspection works. siteRestrictedUser -- performance data only, URL inspection blocked. siteUnverifiedUser -- verification incomplete; most calls will fail. |
| gsc_search_analyticsA | Run any Search Console performance query. The most flexible read tool -- use it for anything the shortcut tools do not cover. Args:
site_url: property, exactly as list_sites reports it.
dimensions: any mix of query, page, country, device, date,
searchAppearance. Empty list returns a single totals row.
start_date / end_date: YYYY-MM-DD. Omit both to use the last |
| gsc_top_queriesA | Top search queries by clicks. Args: site_url: property. start_date / end_date / days: date window. limit: how many queries. page_filter: optional substring; restricts to URLs containing it, so you can ask which queries drive a particular section of the site. |
| gsc_top_pagesC | Top landing pages by clicks, with impressions, CTR and average position. |
| gsc_queries_for_pageA | Every query a specific URL ranks for. Use this before rewriting a page -- it shows what the page actually earns impressions on, which is often not what it was written to target. Args: page_url: exact URL, or a substring to match loosely. |
| gsc_compare_periodsA | Compare a window against the equal-length window immediately before it, and return the biggest gainers and losers. This is the tool for "what changed". The API cannot diff periods itself, so this runs both windows and joins them. Args: dimension: query, page, country, or device. days: length of each window (default 28, so 28 vs the prior 28). limit: how many gainers and how many losers to return. |
| gsc_ctr_opportunitiesB | Queries that already rank well but earn far fewer clicks than their position implies. These are title and meta-description problems, not ranking problems, which makes them the cheapest wins available. Args: min_impressions: ignore low-volume noise (default 100). max_position: only consider queries ranking this well or better. limit: how many opportunities to return. Returns rows sorted by estimated clicks left on the table. |
| gsc_striking_distanceA | Queries ranking just off page one, where a small gain converts to real traffic. Position 8-20 by default. Each row carries the page currently ranking, so the work has an obvious target. Sorted by impressions, since that is the traffic on offer. |
| gsc_cannibalizationC | Queries where several of your own URLs compete for the same term. Google usually picks one and splits authority across the rest. Consolidating, or differentiating the pages by intent, normally lifts the winner. Args: min_pages: how many competing URLs before it counts (default 2). min_impressions: total impressions across the competing pages. |
| gsc_content_decayB | Pages that lost the most traffic against the previous equal-length period. Catches decaying content early, while it still has enough authority that a refresh works. Only pages that had real traffic before are considered, so a page going from 1 click to 0 does not crowd out a page that went from 200 to 90. Args: min_prev_clicks: ignore pages below this in the earlier window. |
| gsc_inspect_urlA | Inspect one URL: is it indexed, which canonical Google chose, when it was last crawled, whether robots.txt allows it, mobile usability, and any rich results detected. Requires Full or Owner permission on the property -- Restricted users get a 403 here even though performance data works for them. Args: page_url: the exact URL to inspect. Must sit inside site_url. site_url: the property that owns the URL. language_code: BCP-47 code for the returned messages. Quota note: the API allows roughly 2000 inspections per property per day and 600 per minute, so avoid looping it over a whole sitemap. |
| gsc_inspect_urlsA | Inspect several URLs and return a compact per-URL verdict table. Use this to check a batch after a deploy or a migration. Keep the list under about 20 -- each URL is a separate API call and the per-minute quota is real. A failure on one URL does not stop the rest; it is reported inline. |
| gsc_list_sitemapsA | List every sitemap submitted for a property, with error and warning counts and how many URLs each one carries. A sitemap that has never been downloaded, or that shows errors, is the first thing to check when new pages are not getting indexed. |
| gsc_get_sitemapA | Detail for one sitemap, including per-content-type submitted and indexed counts. Args: feedpath: full URL of the sitemap, e.g. https://example.com/sitemap.xml |
| gsc_submit_sitemapB | Submit a sitemap to Search Console. This is a write. It is a dry run unless confirm=true. Args: feedpath: full URL of the sitemap, e.g. https://example.com/sitemap.xml confirm: set true to actually submit. |
| gsc_delete_sitemapA | Remove a sitemap from Search Console. This only stops Google tracking that sitemap; it does not deindex the URLs inside it. It is a dry run unless confirm=true. |
| ga4_list_accountsA | List every GA4 account this credential can reach. Call this first. If it returns nothing, the service account has not been added under Admin > Account Access Management on any account. |
| ga4_list_propertiesA | List GA4 properties, optionally filtered to one account. Args: account_id: numeric account id from ga4_list_accounts. Omit to list every property the credential can reach across all accounts. |
| ga4_get_propertyB | Full detail for one GA4 property. |
| ga4_create_propertyA | Create a new GA4 property under an account. Args: account_id: numeric account id from ga4_list_accounts. display_name: property name shown in the GA4 UI. time_zone: IANA time zone, e.g. Asia/Calcutta. currency_code: ISO currency code, e.g. INR, USD. industry_category: optional, e.g. REAL_ESTATE, EDUCATION, RETAIL. confirm: must be true to actually create. |
| ga4_update_propertyB | Update a GA4 property's display name, time zone, currency, or industry. Only the fields you pass are changed. |
| ga4_list_data_streamsA | List data streams on a property, with the measurement id (G-XXXXXXX) used to wire up GTM tags or a site's gtag.js. |
| ga4_create_data_streamA | Create a data stream. For WEB_DATA_STREAM this mints the measurement id (G-XXXXXXX) a GTM Google tag or site gtag.js points at. Args: display_name: stream name shown in the GA4 UI. default_uri: the site's root URL, required for WEB_DATA_STREAM. stream_type: WEB_DATA_STREAM | ANDROID_APP_DATA_STREAM | IOS_APP_DATA_STREAM. confirm: must be true to actually create. |
| ga4_update_data_streamB | Update a data stream's display name or (web streams only) default URI. |
| ga4_delete_data_streamA | Delete a data stream. Always needs confirm=true -- deleting the wrong stream orphans every GTM tag or gtag.js call still pointed at its measurement id, and it stops silently rather than erroring. |
| ga4_list_conversion_eventsA | List conversion events (Key events) on a property, with whether each is custom or a default GA4 event, and whether it counts (deleted events can appear briefly with countingMethod unset during propagation). |
| ga4_create_conversion_eventA | Mark an event as a conversion (Key event) so it feeds Ads bidding and the Conversions column, once GA4↔Ads is linked (see ga4_create_google_ads_link). Args: event_name: the exact dataLayer/gtag event name, e.g. generate_lead, purchase, phone_call_click. The event must already be firing at least once, or GA4 rejects it. confirm: must be true to actually create. |
| ga4_delete_conversion_eventA | Un-mark an event as a conversion. Always needs confirm=true. Args: event_id: numeric id from ga4_list_conversion_events (not the event name -- the id is the last path segment of conversionEvents/). |
| ga4_list_custom_dimensionsB | List custom dimensions on a property. |
| ga4_create_custom_dimensionA | Register a custom dimension so an event parameter becomes reportable. Check first whether GA4's predefined dimensions already cover it (Link URL / Link text / Link classes / Link ID, Page path, etc.) -- a custom copy of an already-predefined parameter just duplicates it. Args: parameter_name: the event/user parameter key, e.g. 'value', 'listing_id'. scope: EVENT | USER | ITEM. confirm: must be true to actually create. |
| ga4_archive_custom_dimensionA | Archive a custom dimension. GA4 has no delete for these -- archive is permanent and the parameter name cannot be reused. Always needs confirm=true. |
| ga4_list_custom_metricsB | List custom metrics on a property. |
| ga4_create_custom_metricB | Register a custom metric (a numeric event parameter, e.g. a lead value). |
| ga4_list_audiencesB | List audiences on a property, including the ones GA4 auto-creates when a Google Ads link is made ('All Users', 'Purchasers'). |
| ga4_create_audienceA | Create a simple event-based audience (e.g. 'viewed a property page, no generate_lead'). For anything beyond a single event condition, build it in the GA4 UI -- the filterClauses shape for sequences and multi-step funnels is deep enough that hand-building the request body here would be more error-prone than the UI's audience builder. Args: membership_duration_days: how long a user stays in the audience once they qualify, 1-540. RLSA on Search needs 1,000+ members before it can serve. event_name_filter: if set, membership = fired this event at least once. Leave unset and build the audience by hand in the UI for anything more complex. confirm: must be true to actually create. |
| ga4_list_google_ads_linksA | List Google Ads accounts linked to a GA4 property. |
| ga4_create_google_ads_linkA | Link a Google Ads account to a GA4 property. Creates the auto-audiences ('All Users', 'Purchasers') and lets GA4 conversion events (Key events) import into Ads as conversions once each is also marked biddable in Ads. Args: customer_id: 10-digit Ads customer id, dashes ok. confirm: must be true to actually create. |
| ga4_delete_google_ads_linkA | Remove a GA4<->Ads link, e.g. one pointed at a deactivated Ads account. Args: link_id: from ga4_list_google_ads_links (not the customer_id). confirm: must be true to actually delete. If this 403s, the credential has Viewer, not Editor, on the property -- fix under Admin > Property Access Management, or delete it by hand in the GA4 UI as a fallback. |
| ga4_run_reportA | Run a GA4 report: any dimension x metric combination over a date range. Args: dimensions: e.g. ["sessionSourceMedium", "date"], ["eventName"], ["landingPagePlusQueryString"], ["city"], ["deviceCategory"]. metrics: e.g. ["sessions", "activeUsers", "engagementRate", "averageSessionDuration", "eventCount", "conversions", "totalRevenue"]. start_date / end_date: 'YYYY-MM-DD', or relative like 'today', 'yesterday', 'NdaysAgo'. dimension_filter_field / dimension_filter_value: optional single exact-match filter, e.g. field='eventName', value='generate_lead'. order_by_metric: metric name to sort by. Defaults to the first metric. desc: sort descending (default) or ascending. |
| ga4_run_realtime_reportC | Realtime report: activity in roughly the last 30 minutes. Args: dimensions: e.g. ["unifiedScreenName"], ["deviceCategory"], ["country"]. metrics: e.g. ["activeUsers"], ["screenPageViews"], ["eventCount"]. |
| ga4_top_conversion_pathsB | Convenience report: sessions by source/medium alongside conversions and conversion rate, sorted by conversions descending. Answers 'which channels actually produce leads', the question this project's client reports keep needing (see kolkataproperties-ads-report §4.1). |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 94 tools
Tools are grouped by clear product prefixes (ads_, gtm_, gsc_, ga4_) with a consistent resource+action structure, making selection unambiguous. Even where convenience wrappers overlap generic tools (e.g., gtm_create_entity vs specialized GTM creators), the descriptions explicitly delineate when to use which.
The dominant <prefix>_<verb>_<noun> pattern is very consistent, with clear get/list/create/update/delete/run verbs. Minor deviations exist: several read-only/report tools use noun-only names (e.g., ads_campaign_performance, gtm_workspace_status, gsc_top_queries), and GA4 reports use run_ while Ads/GSC search analytics do not.
94 tools is far beyond the 25+ threshold, even for a server spanning four Google products. Many convenience wrappers (specialized GTM tag creators, GSC insight shortcuts) duplicate generic tools like gtm_create_entity or gsc_search_analytics, and the sheer surface area creates a heavy context burden for agents.
The set covers the full end-to-end marketing lifecycle: GA4 property/data stream setup, GTM container and tag publishing, Google Ads campaign/ad group/ad creation, Search Console insights, and cross-product linking. Minor gaps exist (no keyword removal/update in Ads, no GA4 data stream getter or audience update/delete, no GSC property creation), but generic query tools partially compensate.