Skip to main content
Glama

Search creatives

search_creatives
Read-only

Browse and filter Meta creative families (source=meta only; TikTok callers must use search_ads with source=tiktok and dedupe=true) and return metadata only. Filters include country/countries, exclude_countries, categories, ai_subcategory, media_type/media_types, domain_zone, advertiser_id/advertiser_ids, webmaster_id, fanpages, hub_domains/channel, active_ads_today_from, last_seen_from/to, period_from/to, max_countries, min_geo_share, folder_id and saved=all. last_seen_from/to is creative activity eligibility; period_from/to (date_from/to aliases) is the independent in-period window for ads_in_period — the window itself does NOT filter rows (total and rows stay the same); add ads_in_period_from=N to keep only creatives with at least N ads in it (not yet with country/countries). The applied window is echoed in meta.period_window. Sort by relevance, total_ads, ads_in_period/reuploads, active_ads, last_seen or fb_created. With an advertiser/webmaster slice, pagination.sort_semantics=slice_ordered_by_webmaster|slice_ordered_by_advertiser and slice.ads_in_slice is the ordering key. total_ads remains the lifetime whole-family count; ads_in_period is the count for the selected period on the backend-reported date axis. Always read pagination.period_axis: first_seen means first discovery by Spytrend; facebook_start_date means launch on Facebook after the verified launch-generation cutover. query/search_in searches the texts of the creative family's ads; all query words must match the family. Cursor-paginated. Download with get_media and save with add_to_favorites. QUOTA: 1 MCP credit per DELIVERED result (default page 20 = 20 MCP credits; short pages auto-refund). Results carry metadata only; get_ad/get_media charge 50 MCP credits per multilang-upload ad opening, 1 per ordinary ad, and get_media charges 10 per creative-catalogue item. Each new opening call is billed separately. Meta search_ads rows include is_multilang and opening_price (Spytrend MCP credits per ad per call); unavailable/null means the price could not be verified, not zero. is_multilang=true marks a multi-language upload («залив языками»): a masked carousel where some slides are decoys for ad review; where the real (black) slide is found it is the one shown first and used for grouping. multilang_black_missing=true means the real slide is not found yet: the media shown is a decoy and must not be treated as the creative. Opening quotes are not a debit or a price lock. Request small limits and narrow filters. PERIOD PARITY CONTRACT: the /creo web filters ai_subcategory, hub_domains[] and active_ads_today_from are available here too. last_seen_from/to filters the creative's LAST recorded activity and does not change count semantics. period_from/period_to is the independent inclusive window used for ads_in_period; date_from/date_to are compatibility aliases of it and, unlike search_ads.date_from, do not filter rows — ads_in_period_from does. A closed explicit period enables ads_in_period automatically. sort_by=ads_in_period or reuploads ranks by that measured in-period count, while total_ads remains lifetime family reuse. The legacy period_metric=ad_debuts plus closed last_seen bounds remains accepted temporarily. Empty pages do not fabricate a count. Invalid/open/reversed periods are rejected before quota or upstream work, and a backend response missing ads_in_period is rejected rather than presented as zero. AXIS CONTRACT: read pagination.period_axis on every period response. "first_seen" means the ad was first discovered by Spytrend; "facebook_start_date" means the ad was launched on Facebook, and is emitted only after the verified launch-generation cutover. Never assume an axis from the request or description. PRICING: price × number of filters set (min 1), on paid plans ×1 after 500 MCP credits/month; one-time consent via accept_pricing_terms; before calling, get the maximum debit from estimate_cost (free) and tell the user.

Input Schema

NameRequiredDescriptionDefault
limitNomax metadata rows (default 20, max 200; each delivered row costs 1 MCP credit) — fetch media with get_media (entity_type=creo, 10 MCP credits per creative).
queryNofree-text keyword search over the creative FAMILY: every word must appear in the texts of the creative's ads (all of them, not one representative ad). Combine with any other filter; use search_in to narrow the area.
savedNosaved scope selector. Use saved=all to restrict results to creatives saved in ANY favourites folder.
cursorNopagination cursor
sourceNocreative catalogue source: meta (default). TikTok is not supported by this tool; use search_ads with source=tiktok and dedupe=true for TikTok ad representatives. Unsupported sources are rejected before charging.
channelNomessaging channel the creative sends traffic to: whatsapp or telegram. Filters to creatives landing on that channel's chat domains. Use for 'bundles going to WhatsApp/Telegram'.
countryNoISO-2 country code to filter creatives shown in that geo (e.g. US, BR). Country may be combined with categories, ai_subcategory, media_type/media_types, max_countries, advertiser_id/advertiser_ids, webmaster_id, fanpages, hub_domains, domain_zone, active_ads_today_from, last_seen dates, min_geo_share and supported sorting filters. Do not combine a country scope with hub_category or channel.
date_toNoALIAS of period_to (YYYY-MM-DD). It sets the window of the ads_in_period metric and does NOT filter rows — unlike search_ads.date_to. To keep only creatives with ads in the window add ads_in_period_from=1. The applied window is echoed in meta.period_window; read pagination.period_axis for its date axis.
sort_byNoorder by: relevance (needs country), total_ads (lifetime), ads_in_period/reuploads (count in a closed period; read pagination.period_axis for its date axis), active_ads, last_seen or fb_created
fanpagesNothe /creo fanpages filter: keep only creatives that ran on ANY of these fanpage ids (advertiser external_ids — the Facebook page ids; OR-semantic). Entries may also be pasted facebook.com page links in any form (vanity, profile id, Ads Library) — each is resolved to its canonical page id. Get page ids from get_creative's fanpages, an ad's page_id (search_ads), or get_advertiser's external_id. Max 50.
countriesNoISO country codes to INCLUDE. The visible /creo geo picker is a multi-select — pass several markets in one call instead of one call per country.
date_fromNoALIAS of period_from (YYYY-MM-DD). It sets the window of the ads_in_period metric and does NOT filter rows — unlike search_ads.date_from, the result set and total stay the same. To keep only creatives with ads in the window add ads_in_period_from=1. The applied window is echoed in meta.period_window; read pagination.period_axis for its date axis.
folder_idNorestrict results to creatives saved in this favourites folder UUID. Mirrors the /creo folder view.
period_toNoin-period window end (YYYY-MM-DD), independent from creative last activity; requires period_from; read pagination.period_axis to learn which date axis was used
search_inNowhere to search when query is set: all (default - ad headline/link text/CTA, fan page names, landing domains AND ad body text), title (headline/link description/CTA), text (ad body text), advertiser (fan page names). Ignored without query.
categoriesNoAI category slugs to filter by (e.g. gambling_and_betting, impersonation_funnels, crypto_and_trading). Multiple = OR.
media_typeNomedia type filter: image or video
sort_orderNosort direction: asc or desc
domain_zoneNolanding-domain zones/TLDs without the dot (e.g. com, shop, online). Mirrors the /creo domain-zone filter.
hub_domainsNoexact destination hostnames to include (the web Hub filter). Use domains as a compatibility alias if needed; values are normalized hostnames, maximum 50.
media_typesNomedia types to include (image, video) — the visible /creo media multi-select. Prefer this over the singular media_type.
period_fromNoin-period window start (YYYY-MM-DD), independent from creative last activity; requires period_to; read pagination.period_axis to learn which date axis was used
hub_categoryNofilter to creatives whose destination is in this TOP-LEVEL hub category. Valid slugs: social, app_stores, shortlinks, amazon, ecommerce, popular, platforms (NOT 'social_media' — the slug is 'social'). For a specific messaging channel use channel - hub_category does NOT accept whatsapp/telegram sub-slugs.
last_seen_toNodate range end (YYYY-MM-DD): only creatives whose LAST recorded activity is on or before this date. Combine with last_seen_from for a closed activity window.
webmaster_idNoonly creatives used by this webmaster id (from search_webmasters)
advertiser_idNoonly creatives run by this INTERNAL advertiser UUID (search_advertisers field advertiser_id, an ad's advertiser_id in search_ads, or get_trends dimension=advertisers). A Facebook page id or page link sent here is applied as the fanpages filter when fanpages is empty (reported in params.normalized); any other value is rejected.
max_countriesNoonly creatives shown in at most this many countries
min_geo_shareNoD1 geo-relevance FILTER (0-1): keep only creatives where 'country' is at least this share of the creative's ads — i.e. that geo is the creative's dominant / #1 country (e.g. 0.5 = the country is >=50% of its ads). Requires country. Combine with sort_by=relevance to rank by ad-volume IN that country.
period_metricNoderived in-period metric: ad_debuts counts ads in the inclusive period_from/period_to window on the backend-reported date axis; pagination.period_axis explains the result (first_seen = first discovery by Spytrend, facebook_start_date = Facebook launch after the verified cutover)
advertiser_idsNomulti-select advertiser filter: creatives run by ANY of these advertiser UUIDs (OR). Each returned card then carries slice.ads_in_slice / slice.active_in_slice = the EXACT summed ad counts of exactly these advertisers inside the creative's family (additive — an ad belongs to one advertiser). Supersedes advertiser_id when both are sent.
ai_subcategoryNoAI subcategory slugs to filter by. Multiple = OR; combine with categories when needed.
last_seen_fromNodate range start (YYYY-MM-DD): only creatives whose LAST recorded activity/fixation is on or after this date. This activity filter is independent from period_from/period_to; it is not an interval-overlap or first-seen filter.
exclude_countriesNoISO country codes to EXCLUDE: a creative targeting ANY of them is hidden. Mirrors the /creo geo EXCLUDE column.
ads_in_period_fromNorow FILTER on the period window: keep only creatives with at least this many ads counted in ads_in_period for the closed period_from/period_to (or date_from/date_to) window, e.g. 1 = creatives with at least one ad in the window. Requires the closed window. Not available together with country/countries yet (the per-country period series is not maintained, so it would return a false empty page); such calls are refused, not answered with 0.
active_ads_today_fromNominimum number of ads active today for the creative family; 0 or omitted disables this filter

Output Schema

NameRequiredDescriptionDefault
dataNo
metaNo
errorNoPresent only when isError is true: machine-readable failure. The human explanation stays in content.
paramsNoRequest parameter echo: applied = parameters that shaped this result; normalized = parameters rewritten before applying (alias, type coercion, resolved id); ignored = parameters that were accepted but NOT applied, with the reason.
paginationNo
addon_hintsNoAdd-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed10 schema fields changed
    • changedInput schema / properties / limit / description
      Previous value: -"max metadata rows (default 20, max 200; each delivered row costs 1 token) — fetch media with get_media (entity_type=creo, 10 tokens per creative)."New value: +"max metadata rows (default 20, max 200; each delivered row costs 1 MCP credit) — fetch media with get_media (entity_type=creo, 10 MCP credits per creative)."
    • removedInput schema / properties / sa_country
      Removed value: -{
      -  "description": "ISO-2 codes of the countries the ads are shown in (OR), e.g. US, GB, DE — NOT the visitor country of the site. Implies search_arbitrage.",
      -  "items": {
      -    "type": "string"
      -  },
      -  "type": [
      -    "null",
      -    "array"
      -  ]
      -}
    • removedInput schema / properties / sa_lang
      Removed value: -{
      -  "description": "ISO 639-1 language codes of the search phrases (OR), e.g. en, de, es. Implies search_arbitrage.",
      -  "items": {
      -    "type": "string"
      -  },
      -  "type": [
      -    "null",
      -    "array"
      -  ]
      -}
    • removedInput schema / properties / sa_network
      Removed value: -{
      -  "description": "search-arbitrage network slugs (OR): the search-ads network the site monetises through, e.g. tonic, visymo, medianet, cortex, predicto, codefuel, brandclick, system1. Live list with counts: search_arbitrage_facets. Implies search_arbitrage.",
      -  "items": {
      -    "type": "string"
      -  },
      -  "type": [
      -    "null",
      -    "array"
      -  ]
      -}
    • removedInput schema / properties / sa_phrase
      Removed value: -{
      -  "description": "exact search phrases (OR), lower-case, as returned by search_arbitrage_phrases; a phrase containing a comma cannot be used here. Implies search_arbitrage.",
      -  "items": {
      -    "type": "string"
      -  },
      -  "type": [
      -    "null",
      -    "array"
      -  ]
      -}
    • removedInput schema / properties / sa_pub
      Removed value: -{
      -  "description": "Google publisher account ids (OR), e.g. pub-1902826156353358: the AdSense/AFS account the site earns under — one account usually means one operator. A bare number or ca-pub-… is accepted. Implies search_arbitrage.",
      -  "items": {
      -    "type": "string"
      -  },
      -  "type": [
      -    "null",
      -    "array"
      -  ]
      -}
    • removedInput schema / properties / sa_source
      Removed value: -{
      -  "description": "how the site earns from search (OR): rsoc (Google related-search ads through a partner), afs (Google AdSense for Search), yahoo_feed, bing_feed or other. Implies search_arbitrage.",
      -  "items": {
      -    "enum": [
      -      "rsoc",
      -      "afs",
      -      "yahoo_feed",
      -      "bing_feed",
      -      "other"
      -    ],
      -    "type": "string"
      -  },
      -  "type": [
      -    "null",
      -    "array"
      -  ]
      -}
    • removedInput schema / properties / sa_topic
      Removed value: -{
      -  "description": "topic slugs of the search phrases the sites push (OR); live list with counts: search_arbitrage_facets. Implies search_arbitrage.",
      -  "items": {
      -    "type": "string"
      -  },
      -  "type": [
      -    "null",
      -    "array"
      -  ]
      -}
    • removedInput schema / properties / search_arbitrage
      Removed value: -{
      -  "description": "SEARCH ARBITRAGE filter (confirmed search-arbitrage sites only): true = keep only creatives of search-arbitrage ads — ads whose landing page earns from search-ads clicks (Google RSOC/AFS through networks such as Tonic or Visymo, Yahoo/Bing feeds) instead of selling a product. Every sa_* filter implies it. Omit or false = no search-arbitrage filter. Valid sa_* values and counts: search_arbitrage_facets; the phrases behind them: search_arbitrage_phrases.",
      -  "type": "boolean"
      -}
    • addedOutput schema / properties / addon_hints
      Added value: +{
      +  "description": "Add-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about.",
      +  "items": {
      +    "properties": {
      +      "available_data_types": {
      +        "description": "kinds of data the module confirmedly has for the object",
      +        "items": {
      +          "type": "string"
      +        },
      +        "type": "array"
      +      },
      +      "info_url": {
      +        "description": "the object (or its limited breakdown) inside the module on spytrend.com",
      +        "type": "string"
      +      },
      +      "module": {
      +        "description": "nutra | crypto | web2app | search_arb | startups",
      +        "type": "string"
      +      },
      +      "object_id": {
      +        "description": "the ad id, or the site domain for site rows",
      +        "type": "string"
      +      },
      +      "preland_downloadable": {
      +        "description": "Nutra / Crypto: the saved pre-lander can be downloaded in the module",
      +        "type": "boolean"
      +      },
      +      "subscription_status": {
      +        "description": "active | not_connected",
      +        "type": "string"
      +      }
      +    },
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
  2. Changed4 schema fields changed
    • removedInput schema / properties / sa_evidence_min
      Removed value: -{
      -  "description": "minimum evidence share of the site, 0 to 1 (e.g. 0.8): the fraction of the site's checked pages that showed the network's markers; higher means a more certain verdict. Implies search_arbitrage.",
      -  "maximum": 1,
      -  "minimum": 0,
      -  "type": "number"
      -}
    • removedInput schema / properties / sa_link
      Removed value: -{
      -  "description": "how the ad reaches the site: tracker (a network tracking/redirect link that carries the phrase) or direct (the ad points straight at the monetised site). Omit for both. Implies search_arbitrage.",
      -  "enum": [
      -    "tracker",
      -    "direct"
      -  ],
      -  "type": "string"
      -}
    • removedInput schema / properties / sa_verdict
      Removed value: -{
      -  "description": "detection confidence (OR): confirmed (network markers found on the site) or probable. Omit for both. Implies search_arbitrage.",
      -  "items": {
      -    "enum": [
      -      "confirmed",
      -      "probable"
      -    ],
      -    "type": "string"
      -  },
      -  "type": [
      -    "null",
      -    "array"
      -  ]
      -}
    • changedInput schema / properties / search_arbitrage / description
      Previous value: -"SEARCH ARBITRAGE filter: true = keep only creatives of search-arbitrage ads — ads whose landing page earns from search-ads clicks (Google RSOC/AFS through networks such as Tonic or Visymo, Yahoo/Bing feeds) instead of selling a product. Every sa_* filter implies it. Omit or false = no search-arbitrage filter. Valid sa_* values and counts: search_arbitrage_facets; the phrases behind them: search_arbitrage_phrases."New value: +"SEARCH ARBITRAGE filter (confirmed search-arbitrage sites only): true = keep only creatives of search-arbitrage ads — ads whose landing page earns from search-ads clicks (Google RSOC/AFS through networks such as Tonic or Visymo, Yahoo/Bing feeds) instead of selling a product. Every sa_* filter implies it. Omit or false = no search-arbitrage filter. Valid sa_* values and counts: search_arbitrage_facets; the phrases behind them: search_arbitrage_phrases."
  3. Changed11 schema fields changed
    • addedInput schema / properties / sa_country
      Added value: +{
      +  "description": "ISO-2 codes of the countries the ads are shown in (OR), e.g. US, GB, DE — NOT the visitor country of the site. Implies search_arbitrage.",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": [
      +    "null",
      +    "array"
      +  ]
      +}
    • addedInput schema / properties / sa_evidence_min
      Added value: +{
      +  "description": "minimum evidence share of the site, 0 to 1 (e.g. 0.8): the fraction of the site's checked pages that showed the network's markers; higher means a more certain verdict. Implies search_arbitrage.",
      +  "maximum": 1,
      +  "minimum": 0,
      +  "type": "number"
      +}
    • addedInput schema / properties / sa_lang
      Added value: +{
      +  "description": "ISO 639-1 language codes of the search phrases (OR), e.g. en, de, es. Implies search_arbitrage.",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": [
      +    "null",
      +    "array"
      +  ]
      +}
    • addedInput schema / properties / sa_link
      Added value: +{
      +  "description": "how the ad reaches the site: tracker (a network tracking/redirect link that carries the phrase) or direct (the ad points straight at the monetised site). Omit for both. Implies search_arbitrage.",
      +  "enum": [
      +    "tracker",
      +    "direct"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / sa_network
      Added value: +{
      +  "description": "search-arbitrage network slugs (OR): the search-ads network the site monetises through, e.g. tonic, visymo, medianet, cortex, predicto, codefuel, brandclick, system1. Live list with counts: search_arbitrage_facets. Implies search_arbitrage.",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": [
      +    "null",
      +    "array"
      +  ]
      +}
    • addedInput schema / properties / sa_phrase
      Added value: +{
      +  "description": "exact search phrases (OR), lower-case, as returned by search_arbitrage_phrases; a phrase containing a comma cannot be used here. Implies search_arbitrage.",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": [
      +    "null",
      +    "array"
      +  ]
      +}
    • addedInput schema / properties / sa_pub
      Added value: +{
      +  "description": "Google publisher account ids (OR), e.g. pub-1902826156353358: the AdSense/AFS account the site earns under — one account usually means one operator. A bare number or ca-pub-… is accepted. Implies search_arbitrage.",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": [
      +    "null",
      +    "array"
      +  ]
      +}
    • addedInput schema / properties / sa_source
      Added value: +{
      +  "description": "how the site earns from search (OR): rsoc (Google related-search ads through a partner), afs (Google AdSense for Search), yahoo_feed, bing_feed or other. Implies search_arbitrage.",
      +  "items": {
      +    "enum": [
      +      "rsoc",
      +      "afs",
      +      "yahoo_feed",
      +      "bing_feed",
      +      "other"
      +    ],
      +    "type": "string"
      +  },
      +  "type": [
      +    "null",
      +    "array"
      +  ]
      +}
    • addedInput schema / properties / sa_topic
      Added value: +{
      +  "description": "topic slugs of the search phrases the sites push (OR); live list with counts: search_arbitrage_facets. Implies search_arbitrage.",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": [
      +    "null",
      +    "array"
      +  ]
      +}
    • addedInput schema / properties / sa_verdict
      Added value: +{
      +  "description": "detection confidence (OR): confirmed (network markers found on the site) or probable. Omit for both. Implies search_arbitrage.",
      +  "items": {
      +    "enum": [
      +      "confirmed",
      +      "probable"
      +    ],
      +    "type": "string"
      +  },
      +  "type": [
      +    "null",
      +    "array"
      +  ]
      +}
    • addedInput schema / properties / search_arbitrage
      Added value: +{
      +  "description": "SEARCH ARBITRAGE filter: true = keep only creatives of search-arbitrage ads — ads whose landing page earns from search-ads clicks (Google RSOC/AFS through networks such as Tonic or Visymo, Yahoo/Bing feeds) instead of selling a product. Every sa_* filter implies it. Omit or false = no search-arbitrage filter. Valid sa_* values and counts: search_arbitrage_facets; the phrases behind them: search_arbitrage_phrases.",
      +  "type": "boolean"
      +}
  4. Changed7 schema fields changed
    • addedInput schema / properties / ads_in_period_from
      Added value: +{
      +  "description": "row FILTER on the period window: keep only creatives with at least this many ads counted in ads_in_period for the closed period_from/period_to (or date_from/date_to) window, e.g. 1 = creatives with at least one ad in the window. Requires the closed window. Not available together with country/countries yet (the per-country period series is not maintained, so it would return a false empty page); such calls are refused, not answered with 0.",
      +  "type": "integer"
      +}
    • changedInput schema / properties / advertiser_id / description
      Previous value: -"only creatives run by this advertiser id (from an ad's advertiser_id in search_ads, or get_trends dimension=advertisers)"New value: +"only creatives run by this INTERNAL advertiser UUID (search_advertisers field advertiser_id, an ad's advertiser_id in search_ads, or get_trends dimension=advertisers). A Facebook page id or page link sent here is applied as the fanpages filter when fanpages is empty (reported in params.normalized); any other value is rejected."
    • changedInput schema / properties / date_from / description
      Previous value: -"compatibility alias of period_from for the in-period window; read pagination.period_axis to learn which date axis was used"New value: +"ALIAS of period_from (YYYY-MM-DD). It sets the window of the ads_in_period metric and does NOT filter rows — unlike search_ads.date_from, the result set and total stay the same. To keep only creatives with ads in the window add ads_in_period_from=1. The applied window is echoed in meta.period_window; read pagination.period_axis for its date axis."
    • changedInput schema / properties / date_to / description
      Previous value: -"compatibility alias of period_to for the in-period window; read pagination.period_axis to learn which date axis was used"New value: +"ALIAS of period_to (YYYY-MM-DD). It sets the window of the ads_in_period metric and does NOT filter rows — unlike search_ads.date_to. To keep only creatives with ads in the window add ads_in_period_from=1. The applied window is echoed in meta.period_window; read pagination.period_axis for its date axis."
    • addedOutput schema / properties / error
      Added value: +{
      +  "description": "Present only when isError is true: machine-readable failure. The human explanation stays in content.",
      +  "properties": {
      +    "code": {
      +      "description": "fine-grained, stable failure code (e.g. invalid_arguments, backend_busy)",
      +      "type": "string"
      +    },
      +    "kind": {
      +      "description": "failure class: invalid_argument, not_found, permission_denied, unauthenticated, quota_exceeded, rate_limited, temporarily_unavailable, unavailable_until_ready, unsupported, internal",
      +      "type": "string"
      +    },
      +    "message": {
      +      "description": "the same human text as content[0]",
      +      "type": "string"
      +    },
      +    "outcome": {
      +      "description": "activity-feed outcome class",
      +      "type": "string"
      +    },
      +    "param": {
      +      "description": "the request parameter the failure is about, when known",
      +      "type": "string"
      +    },
      +    "retry_after_seconds": {
      +      "description": "wait this long before retrying",
      +      "type": "integer"
      +    },
      +    "retryable": {
      +      "description": "true when repeating the SAME call can succeed (after retry_after_seconds when present)",
      +      "type": "boolean"
      +    }
      +  },
      +  "type": "object"
      +}
    • addedOutput schema / properties / params
      Added value: +{
      +  "description": "Request parameter echo: applied = parameters that shaped this result; normalized = parameters rewritten before applying (alias, type coercion, resolved id); ignored = parameters that were accepted but NOT applied, with the reason.",
      +  "properties": {
      +    "applied": {
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    },
      +    "ignored": {
      +      "items": {
      +        "properties": {
      +          "param": {
      +            "type": "string"
      +          },
      +          "reason": {
      +            "type": "string"
      +          },
      +          "to": {
      +            "description": "the parameter it was applied as, when renamed",
      +            "type": "string"
      +          },
      +          "value": {
      +            "description": "the value actually applied, when rewritten",
      +            "type": "string"
      +          }
      +        },
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    "normalized": {
      +      "items": {
      +        "properties": {
      +          "param": {
      +            "type": "string"
      +          },
      +          "reason": {
      +            "type": "string"
      +          },
      +          "to": {
      +            "description": "the parameter it was applied as, when renamed",
      +            "type": "string"
      +          },
      +          "value": {
      +            "description": "the value actually applied, when rewritten",
      +            "type": "string"
      +          }
      +        },
      +        "type": "object"
      +      },
      +      "type": "array"
      +    }
      +  },
      +  "type": "object"
      +}
    • removedOutput schema / required
      Removed value: -[
      -  "data",
      -  "pagination"
      -]
  5. Changed1 schema field changed
    • changedInput schema / properties / period_metric / description
      Previous value: -"derived in-period metric: ad_debuts counts ads in the inclusive period_from/period_to window on the backend-reported date axis; pagination.period_axis explains the result (first_seen = first discovery by SpyTrend, facebook_start_date = Facebook launch after the verified cutover)"New value: +"derived in-period metric: ad_debuts counts ads in the inclusive period_from/period_to window on the backend-reported date axis; pagination.period_axis explains the result (first_seen = first discovery by Spytrend, facebook_start_date = Facebook launch after the verified cutover)"
  6. Changed2 schema fields changed
    • changedInput schema / properties / last_seen_from / description
      Previous value: -"date range start (YYYY-MM-DD): only creatives whose LAST recorded activity/fixation is on or after this date. This is the ONLY date filter; it is not an interval-overlap or first-seen filter."New value: +"date range start (YYYY-MM-DD): only creatives whose LAST recorded activity/fixation is on or after this date. This activity filter is independent from period_from/period_to; it is not an interval-overlap or first-seen filter."
    • addedInput schema / properties / source
      Added value: +{
      +  "description": "creative catalogue source: meta (default). TikTok is not supported by this tool; use search_ads with source=tiktok and dedupe=true for TikTok ad representatives. Unsupported sources are rejected before charging.",
      +  "enum": [
      +    "meta",
      +    "tiktok"
      +  ],
      +  "type": "string"
      +}
  7. First observed

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only assert readOnly/openWorld/non-destructive; the description adds substantial unseen behaviour: per-delivered-result credit billing with auto-refund on short pages, separate 50/10/1 credit opening charges, validation that rejects invalid/open/reversed periods before quota work, refusal instead of returning a false zero when ads_in_period is missing, the period_axis contract, and the multilang/decoy-slide caveat. This is exactly the context annotations cannot carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose is front-loaded, but the body is roughly 700 words of run-on prose that restates the same period-window rule at least four times (opening paragraph, PERIOD PARITY CONTRACT, AXIS CONTRACT, and again in each of date_from/date_to/period_from/period_to parameter descriptions). Critical operational facts such as "Request small limits and narrow filters" and the pricing-consent requirement are buried mid-paragraph rather than surfaced.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 35-parameter search tool with an output schema, the description covers what matters: billing model, consent prerequisite, filter interaction rules, sort semantics, date-axis ambiguity, and failure modes. An agent could invoke this correctly from the description plus schema, which is the standard that matters here.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is already 100%, yet the description adds semantics the schema cannot express: date_from/date_to are aliases of period_from/period_to and do NOT filter rows (contrasted with search_ads.date_from), sort_by=ads_in_period ranks by measured in-period count while total_ads stays lifetime, and slice.ads_in_slice is the ordering key for advertiser/webmaster slices. It also explains meta.period_window and pagination.sort_semantics echoes.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource+scope: "Browse and filter Meta creative families (source=meta only...)" and immediately delimits it against the sibling search_ads for TikTok. It also states the output shape ("return metadata only"), so an agent knows exactly what this tool is versus search_ads, search_hubs, or get_creative.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit routing rules and alternatives: TikTok must use search_ads with source=tiktok and dedupe=true; download via get_media, save via add_to_favorites; get a max debit from estimate_cost before calling and tell the user. It also names the exclusions that change behaviour (ads_in_period_from not yet combinable with country, hub_category not combinable with country/channel).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.