Skip to main content
Glama

Server Details

Meta and TikTok advertising analytics with ads, creatives, advertisers, rankings and six workflows.

Ownership verified
Status
Healthy
OAuth
Works in Glama
Last Tested
Transport
Streamable HTTP
URL
Repository
Spytrend/spytrend-mcp
GitHub Stars
0

Available Tools

21 tools
add_to_favoritesAdd to favouritesA
Idempotent
Inspect

Save a SELECTION of entities to one of the caller's favourites folders so they can review them later on spytrend.com. entity_type is creo (creatives), webmaster, ad, hub (a hub profile from search_hubs) or shop (a shop domain from search_shops); ids is the list of entity ids from search_ads / search_webmasters / search_creatives / search_hubs / search_shops. For entity_type=hub you MUST also pass hub (the hub slug the ids came from, e.g. 'ecommerce'). folder is OPTIONAL — PREFER a short descriptive name from the user's search (e.g. 'Gambling ads US · Jun 2026'), created automatically if absent; if omitted, a stable dated folder is used. Idempotent — items already in the folder are reported as already_saved, never duplicated or re-charged. BILLING: saving an ad costs 1 token and saving a creative costs 10 tokens (you are taking the creative — same cost as get_media); saving a webmaster, a hub profile or a shop is FREE. Already-saved items cost nothing.

ParametersJSON Schema
NameRequiredDescriptionDefault
hubNoREQUIRED only when entity_type=hub: the hub slug the ids came from (the same 'hub' you passed to search_hubs, e.g. 'ecommerce', 'facebook', 'amazon')
idsYesthe entity ids to save (from search_ads / search_webmasters / search_creatives / search_shops results; for entity_type=hub these are the hub profile ids/domains from search_hubs; for entity_type=shop these are the shop domains from search_shops)
folderNoOPTIONAL folder name; created if absent. PREFER a short descriptive name from the user's search context (e.g. 'Gambling ads US · Jun 2026'). If omitted, a stable dated folder ('AI saved ads · YYYY-MM-DD') is used
entity_typeYeswhat kind of entity to save: creo (creative), webmaster, ad, hub (a hub profile from search_hubs) or shop (a shop domain from search_shops)

Output Schema

ParametersJSON Schema
NameRequiredDescription
addedYes
failedNo
folderYes
entity_typeYes
already_savedYes

TDQS

A4.6/5.0
Behavior5/5

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

Going well beyond the idempotentHint/destructiveHint=false annotations, the description discloses concrete behavioral traits: idempotency semantics (already_saved reported, never duplicated or re-charged), per-type token costs (1 token per ad, 10 per creative, free for webmaster/hub/shop), automatic folder creation with a stable dated fallback, and the required hub parameter when entity_type=hub. This materially helps an agent predict side effects and cost before invoking.

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

Conciseness4/5

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

The purpose is front-loaded in the first sentence, and every sentence carries decision-relevant information: parameter mapping, conditional requirement, folder guidance, idempotency, and billing. It is a long single paragraph that could benefit from section breaks, but there is no waste.

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?

An output schema is present, so return values need no explanation, and the description covers purpose, all parameters, the conditional hub requirement, idempotency, and billing. Nothing an agent needs to call this tool correctly is missing.

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

Parameters4/5

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

The input schema already documents all 4 parameters with 100% coverage, so the baseline is 3. The description adds value by linking ids provenance to the exact sibling search tools, clarifying the hub/entity_type dependency with an example, and tying entity_type to billing behavior. It is somewhat redundant with the already-thorough schema, so not a 5.

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?

The description opens with a specific verb ('Save'), a clear resource ('a SELECTION of entities to one of the caller's favourites folders'), and the purpose ('so they can review them later on spytrend.com'). It also disambiguates all five entity_type values and ties each to its source search tool, making it clearly distinct from the read/search siblings like list_favorites and the search_* tools.

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

Usage Guidelines4/5

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

It states the intended use case — saving entities surfaced by the search_* tools for later review — and adds practical guidance such as preferring a folder name from the user's search context and the billing implications per entity type. It does not explicitly name alternatives or exclusions (e.g., 'use list_favorites to view saved items'), so it stops short of a 5.

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

find_similar_adsFind related adsA
Read-only
Inspect

Find ads related to one source ad by an explicit overlap basis: fanpage (same Facebook page_id) or domain (same exact landing_domain). This is entity overlap, NOT visual similarity of the material; use find_similar_creatives for that. The source ad is excluded from data, but pagination.total remains the upstream overlap-candidate count before that exclusion; source_excluded and total_semantics make this explicit instead of fabricating an adjusted exact total. Metadata only, cursor-paginated. QUOTA: 1 token per delivered row (default page 20).

ParametersJSON Schema
NameRequiredDescriptionDefault
ad_idYessource ad UUID from search_ads
basisYesoverlap basis: fanpage (same Facebook page_id) or domain (same exact landing_domain)
limitNomaximum metadata rows (default 20, maximum 200; 1 token per delivered row)
cursorNopagination cursor returned by the previous call

Output Schema

ParametersJSON Schema
NameRequiredDescription
dataYes
paginationYes
basis_valueYes
source_ad_idYes
source_excludedYes
total_semanticsYes
similarity_basisYes

TDQS

A4.7/5.0
Behavior5/5

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

Annotations already mark this as readOnly and non-destructive, and the description adds important behavioral context beyond those: the source ad is excluded from results, pagination.total reflects the upstream count before exclusion, metadata-only returns, and cursor pagination. No contradictions with annotations.

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

Conciseness5/5

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

The description is dense but every sentence earns its place: it defines the operation, disambiguates from a sibling, clarifies pagination semantics, and states quota. The key exclusion and alternative are front-loaded.

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?

With an output schema present, annotations covering safety, full parameter schema coverage, and the description covering pagination, exclusion behavior, quota, and alternative routing, the agent has everything needed to select and invoke this tool correctly.

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

Parameters3/5

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

Schema description coverage is 100%, so the parameters are already fully documented in the schema. The description reinforces the meaning of basis and the 1-token-per-row quota but does not add substantial semantics beyond what the schema already provides.

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?

The description states a specific verb ('Find ads related to'), resource ('one source ad'), and the overlap basis ('fanpage' or 'domain'). It explicitly distinguishes itself from find_similar_creatives, so an agent can differentiate between entity overlap and visual similarity without inspecting siblings.

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?

It gives explicit when-to-use guidance: entity overlap by fanpage or domain, and explicitly names the alternative ('use find_similar_creatives for that') for visual similarity. This makes the selection boundary unambiguous.

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

find_similar_creativesFind creatives that look the sameA
Read-only
Inspect

Find creatives that look the same as one creative, using the production similarity index. This is visual similarity, not exact creative membership. threshold_status distinguishes an explicitly requested threshold from the production default; result_status=bounded_native_cap means the upstream similarity endpoint exposes at most 20 candidates and has_more is conservative at that cap. Returns metadata without media URLs; use get_media for selected ids. QUOTA: 1 token per delivered row.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNomaximum metadata rows to return (default 20, maximum 20)
thresholdNooptional maximum visual difference between two creatives (0 uses the production default; maximum 128 — lower is stricter)
creative_idYessource creative UUID from search_creatives

Output Schema

ParametersJSON Schema
NameRequiredDescription
dataYes
has_moreYes
thresholdYes
result_statusYes
similarity_basisYes
threshold_statusYes
source_creative_idYes

TDQS

A4.5/5.0
Behavior5/5

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

Beyond the readOnly/openWorld annotations, it discloses the 20-candidate upstream cap, conservative has_more semantics, threshold_status vs result_status meaning, metadata-only output without media URLs, and per-row quota. This is substantial behavioral context that helps an agent predict side effects and limits. No contradiction with annotations.

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

Conciseness5/5

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

Four dense sentences that all earn their place: purpose, visual-similarity clarification, cap/has_more semantics, get_media routing, and quota. Front-loaded with the main verb and resource, with no filler.

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 read-only similarity search with 3 documented parameters and an output schema, the description covers the relevant edge cases (default vs explicit threshold, native cap, has_more behavior) and routing. Nothing an agent needs to call or interpret the result is missing.

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

Parameters3/5

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

Input schema documentation covers all three parameters (100% coverage), including threshold's lower-is-stricter semantics and default. The description adds no substantive parameter-level detail beyond framing threshold as part of the production similarity index, so the baseline score of 3 applies.

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?

States a specific action: finding creatives visually similar to a source creative via the production similarity index. Explicitly differentiates visual similarity from exact creative membership, and the resource term 'creatives' distinguishes it from sibling tools for ads and webmasters.

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

Usage Guidelines4/5

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

Provides clear context that this is for visual look-alikes and explicitly says it is not exact membership, giving a when-not. It also points to get_media for media URLs. However, it does not explicitly compare against find_similar_ads or find_similar_webmasters, leaving some routing to the tool name.

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

find_similar_webmastersFind similar webmastersA
Read-only
Inspect

Find other webmasters sharing normalized URL-parameter values with a source webmaster. First call get_webmaster_similarity_facets, then pass one returned param_key; optionally narrow to selected values. similarity_basis is url_parameter_overlap and rarity_count shows how many webmasters share the value. Results are deterministically ordered and bounded by the canonical source cap of 5000; result_status/result_cap/total_status state whether that bounded set is complete. QUOTA: 1 token per delivered row (default page 20).

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNomaximum rows to return (default 20, maximum 200; 1 token per delivered row)
offsetNozero-based deterministic result offset
valuesNooptional subset of normalized source values for this param_key
param_keyYesURL parameter key returned by get_webmaster_similarity_facets
webmaster_idYessource webmaster UUID from search_webmasters

Output Schema

ParametersJSON Schema
NameRequiredDescription
dataYes
limitYes
offsetYes
has_moreYes
param_keyYes
result_capYes
total_statusYes
result_statusYes
similarity_basisYes
source_webmaster_idYes

TDQS

A4.7/5.0
Behavior5/5

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

Beyond the readOnly/openWorld/destructive annotations, the description discloses determinism, the canonical 5000-result cap, result completeness fields (result_status/result_cap/total_status), and the token quota per delivered row. This gives an agent substantial behavioral expectations without contradiction.

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

Conciseness5/5

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

The description is dense but efficiently organized: purpose first, workflow second, behavioral semantics third, quota last. Every sentence adds information and there is no filler or repetition of schema text.

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?

The description covers the prerequisite call, parameter selection, result ordering, cap behavior, completeness signals, and quota. Since an output schema exists, return-value details are not necessary, and nothing essential is missing for an agent to invoke the tool correctly.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description adds meaningful context: param_key must come from get_webmaster_similarity_facets, values are an optional subset of normalized source values, and webmaster_id is the source webmaster. It also clarifies pagination/quota behavior tied to limit.

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?

The description states a specific verb and resource: 'Find other webmasters sharing normalized URL-parameter values with a source webmaster.' It also names the matching mechanism (url_parameter_overlap) and differentiates from the sibling find_similar_ads/find_similar_creatives tools by explicitly targeting webmasters.

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

Usage Guidelines4/5

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

The description gives an explicit workflow: first call get_webmaster_similarity_facets, then pass one returned param_key, and optionally narrow by values. This is clear contextual guidance for when and how to use the tool, though it does not state when-not-to-use alternatives or explicitly exclude sibling tools.

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

get_adGet ad by id (with media)A
Read-only
Inspect

Fetch a single ad by its id with FULL details including its creative media: the full ad TEXT in body (this is the only surface that serves it), body_chars (its length in UTF-8 characters), title, creative URL, geos, status, advertiser. body is absent when the ad genuinely has no text; body_chars is absent when the length could not be read — never read an absent field as zero. Media urls on media.spytrend.com are permanent; a media entry with expiring=true is the original signed Facebook CDN link of a not-yet-mirrored fresh ad — it dies within hours/days, NEVER put it into reports or exports (re-fetch the ad later for the permanent link). QUOTA: 1 token (this delivers the ad's creative media). With source=tiktok: 100 tokens (the TikTok row is the billable resource).

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesthe ad id to fetch (with source=tiktok: a TikTok ad id from search_ads source=tiktok results)
sourceNoad corpus: meta (default, 1 token — delivers the ad's media) or tiktok (⚠️ 100 tokens per TikTok ad row; Pro plan required)

Output Schema

ParametersJSON Schema
NameRequiredDescription
dataNo
sourceNo
tiktok_dataNo

TDQS

A4.7/5.0
Behavior5/5

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

The description goes far beyond the readOnly/openWorld/destructive annotations by disclosing absence semantics for body and body_chars, permanent vs. expiring media URLs, and the TikTok billable-resource behavior. It explicitly warns against treating absent fields as zero and against putting expiring media into reports or exports. This is rich behavioral disclosure that genuinely helps an agent avoid misuse.

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

Conciseness5/5

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

The description is dense but every sentence carries essential operational information: field availability, absent-field semantics, media URL permanence, expiring-link warnings, and quota distinctions. It front-loads the core purpose before diving into caveats, and no sentence is filler or redundant with the schema.

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?

Given that output schema exists and annotations cover the read-only safety profile, the description supplies the remaining context an agent needs: exact response semantics, data-quality caveats, quota behavior, and how to handle the TikTok source variant. Nothing essential is missing for correctly selecting and invoking this tool.

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

Parameters4/5

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

The input schema already covers both parameters with 100% coverage, so the baseline is 3. The description adds value by clarifying the quota implications of source=tiktok and by tying the tool's purpose to the media-delivery expectation. It does not add new meaning to the id parameter itself, but the source parameter is meaningfully enriched.

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?

The description opens with a precise verb and resource: 'Fetch a single ad by its id with FULL details including its creative media,' then enumerates the specific fields returned. It also differentiates this tool from sibling media/search tools by stating that this is 'the only surface' that serves the full ad text, making its role unmistakable.

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

Usage Guidelines4/5

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

The description gives clear context about when to use this tool: when fetching a single ad by id and when full creative media and text are needed. It also provides practical guidance around TikTok source selection and quota costs, and warns against using expiring media links in reports. It does not explicitly name sibling alternatives or state exclude conditions, so it falls just short of a 5.

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

get_ads_analyticsGet ads selection analyticsA
Read-only
Inspect

Get the bounded analytics overview for the current Meta /ads selection: total and display_total plus statuses, countries, AI categories, landing domains, advertisers and webmasters. This is a Pro-or-higher paid surface; every delivered breakdown row costs 1 token, pending/error responses refund the reservation. The default is 10 rows per section and the absolute maximum is 20; results are flattened in data with a dimension field and include section readiness/truncation metadata. Totals are nullable: null with pending/unavailable status is NOT zero; exact zero is numeric 0 with an exact status. Only the status section removes its own filter; every other section uses the full filtered universe. No pagination, sorting, source, scheduler, force-scrape, TikTok, raw SQL or storage coordinates are accepted. Auto-applied subscription categories are reported in auto_applied_verticals and scope_note. Re-issue the identical call after retry_after_seconds when pending; do not blindly retry paid calls.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryNofree-text filter, at most 100 UTF-8 bytes
savedNosaved scope: all
dedupeNocollapse duplicate creative rows
channelNomessaging shortcut: whatsapp or telegram
countryNolegacy single ISO-2 include country; prefer countries
date_toNoFacebook launch upper bound YYYY-MM-DD
page_idNoFacebook page id or bounded facebook.com page URL
pixel_idNobounded Facebook pixel identifier
countriesNounique uppercase ISO-2 include countries, maximum 200
date_fromNoFacebook launch lower bound YYYY-MM-DD
folder_idNonon-zero favorite folder UUID
languagesNotarget language slugs, maximum 50
platformsNoMeta publisher placements, maximum 6
search_inNoquery scope: all, title, advertiser or text
categoriesNoAI category slugs, maximum 50
cta_buttonsNoCTA labels, maximum 50
hub_domainsNonormalized destination hostnames, maximum 50
media_typesNomedia types: image or video
parsing_geoNoone uppercase ISO-2 parser GEO
resolved_ipNoresolved IPv4/IPv6 address
search_termNohistorical search term, at most 100 UTF-8 bytes
domain_zonesNolowercase landing TLD/zone labels, maximum 50
hub_categoryNoclosed top-level hub category
status_todayNocurrent status: active, inactive or vanished
webmaster_idNonon-zero webmaster UUID
advertiser_idNonon-zero advertiser UUID
country_matchNocountry semantics: any or only
first_seen_toNoSpyTrend discovery upper bound YYYY-MM-DD
max_countriesNomaximum additional/total GEOs, 0 disables, maximum 200
ai_subcategoryNotaxonomy-valid AI subcategory slugs
days_active_toNonon-negative active-days upper bound; null omits the filter, 0 is meaningful
favorites_onlyNorestrict to the token-derived user's favorite webmaster scope
impressions_toNonon-negative impressions bucket upper bound
landing_domainNonormalized landing hostname
max_page_likesNonon-negative page-like upper bound; null omits the filter, 0 is meaningful
media_count_toNonon-negative media-count upper bound
min_page_likesNonon-negative page-like lower bound
platforms_modeNoplacement semantics: any or all
first_seen_fromNoSpyTrend discovery lower bound YYYY-MM-DD
min_days_activeNonon-negative active-days lower bound
ai_enriched_onlyNoonly AI-enriched ads
creative_formatsNocreative formats: video, carousel, single or dynamic
impressions_fromNonon-negative impressions bucket lower bound
media_count_fromNonon-negative media-count lower bound
ai_confidence_minNominimum AI confidence: low, middle or high
contains_in_linksNotracking-link fragment, at most 255 UTF-8 bytes
fan_page_categoriesNovalidated fan-page category groups
landing_domain_exactNorestrict landing domain to exact hostname
max_items_per_sectionNorows per breakdown section, default 10, maximum 20

Output Schema

ParametersJSON Schema
NameRequiredDescription
winNo
dataYes
tierYes
totalYes
domainsYes
pendingYes
statusesYes
countriesYes
ai_labeledYes
from_cacheNo
scope_noteNo
webmastersYes
advertisersYes
computed_atNo
total_statusYes
ai_categoriesYes
display_totalYes
result_statusYes
sections_readyYes
sections_totalYes
display_total_basisNo
retry_after_secondsNo
display_total_statusYes
auto_applied_verticalsNo

TDQS

A4.5/5.0
Behavior5/5

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

Annotations only state readOnly/openWorld/non-destructive, leaving the description to carry behavioral detail, and it does so richly. It discloses token costs per delivered row, refund behavior on pending/error, row limits and defaults, flattened output shape with dimension field, section readiness/truncation metadata, nullable totals with non-zero semantics, status-section filter behavior, and retry guidance. This is far beyond what annotations provide and contains no contradiction.

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

Conciseness5/5

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

The description is long but information-dense; every sentence conveys a distinct operational constraint or behavioral caveat. It front-loads the core purpose before layering cost, limits, null semantics, and exclusions. This is appropriate given the tool's 49-parameter surface and the many edge cases an agent must respect.

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?

Given 49 parameters, 100% schema coverage, an existing output schema, and read-only annotations, the description covers the critical non-obvious context: pricing, retries, null semantics, section-scope behavior, unsupported features, and auto-applied vertical metadata. An agent has everything needed to decide whether and how to call this tool correctly.

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

Parameters3/5

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

Schema description coverage is 100%, so the baseline is 3 and the description is not required to restate all parameters. It does add useful context around output semantics and limits, such as default 10 rows and maximum 20, but this largely mirrors the max_items_per_section schema description. There is no meaningful per-parameter enrichment beyond what the schema already states.

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?

The description names a specific verb and resource: "Get the bounded analytics overview for the current Meta /ads selection." It enumerates exactly which breakdowns are included (statuses, countries, AI categories, landing domains, advertisers, webmasters) and the key totals, making the tool's scope unmistakable. This clearly differentiates it from search or single-entity sibling tools.

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

Usage Guidelines4/5

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

The description provides strong usage context: it targets the current Meta /ads selection, is a Pro-or-higher paid surface, and explicitly lists unsupported features such as pagination, sorting, source, scheduler, force-scrape, TikTok, raw SQL, and storage coordinates. It also instructs agents to re-issue identical calls after retry_after_seconds and not to blindly retry paid calls. It stops short of explicitly naming alternative tools and when to prefer them, so it does not fully earn a 5.

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

get_advertiserGet advertiser by idA
Read-only
Inspect

Fetch a single advertiser's FULL card by id — the same data as the spytrend.com/advertisers page: name, external_id (FB page id), avatar_url, page_url, total_ads and active_ads (EXACT precomputed counts — THIS is the cheap way to answer 'how many ads / how many are active does this advertiser run', NOT paginating search_ads, whose total is estimated for advertiser_id), launched_14d, top_countries (geo breakdown), platforms, top_landing (destination domains), page_like_count (followers), born (founded date), categories and recent creatives. The card also embeds top_creatives — the advertiser's MOST RE-UPLOADED creatives (a creative's total_ads = how many ads reuse the same material, ordered desc, media stripped/free); present these as the headline at the end and download with get_media (entity_type=creo). The id is an advertiser UUID (from an ad's advertiser_id / get_trends dimension=advertisers) OR a Facebook page id — a fanpage id from get_creative's fanpages, or an ad's page_id: a page id is resolved to its advertiser automatically, so a fanpage you found in a creative resolves straight to its card. A pasted facebook.com page link (any form — vanity name, profile 100…-id, profile.php, Ads Library) is likewise resolved to the page automatically. To list the advertiser's ads, call search_ads with advertiser_id. CATEGORY COUNTERS CONTRACT category_total_ads / subcategory_total_ads and every top_categories[].ads_count / top_subcategories[].ads_count count ONLY the advertiser's AI-LABELED ads - they are a share of the labeled subset, NOT of the page's ad universe. The labeling share is ai_coverage (labeled / total_ads). Read them as: 'N of total_ads ads are labeled (ai_coverage), and X% of THOSE are '. Never compare category_total_ads against total_ads/active_ads directly, and never report a category share as the advertiser's overall vertical mix when ai_coverage is low. QUOTA: 1 token (one entity card). TOP_CREATIVES CONTRACT each top_creatives entry's total_ads counts the creative's FULL family of matching material across the whole serving universe as the market-wide reuse of that creative; note the family may span MORE advertisers than this page — it is the creative's market-wide reuse, not this advertiser's share.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesthe resource id to fetch

Output Schema

ParametersJSON Schema
NameRequiredDescription
dataNo

TDQS

A4.9/5.0
Behavior5/5

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

Annotations already declare readOnlyHint, openWorldHint, and destructiveHint, and the description adds substantial behavioral detail beyond them: quota cost ('1 token'), exact vs. estimated count semantics, the AI-labeling caveat for category counters, and the top_creatives market-wide reuse contract. These are significant non-obvious behaviors that could change how an agent interprets results.

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

Conciseness4/5

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

The description is front-loaded with the core purpose and field list, then proceeds through essential contracts and caveats. It is quite long and dense, but nearly every sentence carries a necessary distinction or warning. Some redundancy and lack of paragraph breaks reduce readability, but there is minimal fluff.

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?

Given the tool's complexity, the presence of an output schema, and the low parameter count, the description is extremely complete. It covers id formats, quota, when to use alternatives, caveats about counts and categories, and the meaning of top_creatives totals. There is no obvious gap an agent would need to guess about.

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?

The input schema only says 'the resource id to fetch', which is generic and unhelpful. The description compensates fully by explaining the id can be an advertiser UUID, a Facebook page id, a fanpage id, or a pasted facebook.com page link, and that page ids are auto-resolved to advertisers. This transforms a vague parameter into a precisely understood input.

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?

The description opens with a specific verb and resource: 'Fetch a single advertiser's FULL card by id', and enumerates the exact fields included. It differentiates itself from search_ads by noting this is 'the cheap way to answer how many ads' and from get_media by directing creatives downloads there. This is a clear, distinguishing statement of purpose.

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?

The description explicitly tells when to use this tool versus alternatives: use it for exact counts instead of 'paginating search_ads', use search_ads to list an advertiser's ads, and use get_media for downloading creatives. It also explains what kinds of IDs can be passed and that Facebook page links resolve automatically, giving an agent actionable selection criteria.

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

get_creativeGet creative details and breakdown by idA
Read-only
Inspect

Fetch ONE creative's metadata plus its canonical bounded breakdown by id: activity period/quality, max_days_active with max_days_active_source/max_days_active_quality, delivery_languages with explicit legacy provenance, aggregate counts, advertisers, fanpages, landing domains, webmasters and geos. The ambiguous legacy languages alias is intentionally omitted. When a speech transcript has already been generated for a video, copy_languages is returned separately with copy_language_source=cached_asr_transcript and copy_language_scope=spoken_audio; it describes spoken audio only, not title/body or visual OCR. copy_language_status is available for measured confidence >=0.8, available_low_confidence below that, available_unscored when the provider supplied no probability, and unavailable when there is no valid cached result. This read never starts transcription. Breakdown lists are sorted by ad count desc and capped at 1000 rows; each dimension has its own *_status, _returned and (where a snapshot cardinality exists) _count/_truncated/_count_status. breakdown_status is available_bounded only when every dimension query completed, partial when at least one dimension is unavailable, and unavailable when the breakdown endpoint itself failed. The id is a creative UUID from search_creatives. Media URLs are intentionally excluded; download with get_media (entity_type=creo, same id). Fanpage ids feed the search_creatives fanpages filter and search_ads page_id. QUOTA: 1 token (one entity card).

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesthe resource id to fetch

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

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

Annotations already indicate readOnlyHint=true and destructiveHint=false, and the description substantially extends this with behavioral detail: canonical bounded breakdown, omission of the ambiguous legacy languages alias, copy_languages provenance and scope, breakdown status semantics, sorting/capping at 1000 rows, per-dimension status fields, and the explicit statement that this read never starts transcription. No contradiction with annotations exists.

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

Conciseness5/5

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

Although long, the description is front-loaded with the core purpose and every subsequent clause carries operational meaning: statuses, sorting, truncation, provenance, exclusions, and quota. There is no redundant filler or repetition of schema or annotation content.

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 single-parameter read tool with a full output schema, the description covers the essential context: how to obtain the id, what data is included and excluded, how to route to get_media, breakdown status conditions, quota cost, and behavioral guarantees like no transcription. Nothing critical is left unresolved.

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

Parameters4/5

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

The schema only says id is 'the resource id to fetch,' while the description adds crucial meaning: it is a creative UUID from search_creatives, the same id used for get_media with entity_type=creo, and it selects a single creative. This is meaningful value beyond the schema's generic description.

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?

The description opens with a specific verb and resource: 'Fetch ONE creative's metadata plus its canonical bounded breakdown by id.' It clearly distinguishes this from search_creatives by emphasizing a single id lookup rather than search, and it names the id provenance as a creative UUID from search_creatives.

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?

The description gives explicit routing guidance: it tells the agent to use get_media for media URLs with entity_type=creo and the same id, and states that fanpage ids feed the search_creatives fanpages filter and search_ads page_id. It also clarifies this tool never starts transcription, preventing misuse for transcript generation.

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

get_mediaGet creative media (download URLs)A
Read-only
Inspect

Fetch downloadable creative MEDIA (image/video URL + thumbnail) for 1-500 ad or creative UUIDs returned by search_ads / search_creatives. This is the paid delivery step. entity_type is 'ad' or 'creo'. Existing clients keep the {entity_type,items:[{id,media:[{media_type,url,thumbnail_url,fallback_urls}]}]} fields; additive counts, partial and failures explain malformed, quota-limited and unavailable items, plus interrupted items when at least one peer was delivered. Malformed/zero UUIDs never reach the API or consume quota; valid peers in a mixed batch are still processed. duplicate_count reports canonical duplicates, which are fetched and billed once. IMPORTANT: a blob coordinate can go stale after storage compaction, so if url returns an HTTP error (e.g. 416/404), retry fallback_urls in order before treating it as unavailable. Typical flow: search_ads (browse metadata, free) → pick ids → get_media. QUOTA: charges only for media actually delivered — 1 token per ad, 10 per creative (free starter: 500 tokens total; paid plans: 40,000/month). If your balance can't cover every id it delivers as many as fit. get_usage is free.

ParametersJSON Schema
NameRequiredDescriptionDefault
idsYes1 to 500 ad or creative UUIDs to resolve (from search_ads / search_creatives results); malformed ids are reported per item and never consume quota
entity_typeYeswhat kind of media to fetch: 'ad' (creative media of ads from search_ads) or 'creo' (media of creatives from search_creatives)

Output Schema

ParametersJSON Schema
NameRequiredDescription
itemsYes
partialYes
failuresNo
entity_typeYes
valid_countYes
attempted_countYes
delivered_countYes
duplicate_countYes
requested_countYes

TDQS

A4.7/5.0
Behavior5/5

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

The description adds substantial behavioral detail beyond the readOnly/destructive annotations: quota charges, retry of fallback_urls on stale blob coordinates, malformed UUIDs not consuming quota, duplicate_count billing behavior, and partial/interrupted item handling. This fully prepares the agent for real-world failures.

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

Conciseness5/5

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

The description is long but every sentence carries operational information. It uses clear labels like QUOTA and IMPORTANT, front-loads the core purpose, and organizes edge cases logically without repetition or filler.

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 tool with quota, paid delivery, fallback URLs, and partial-failure semantics, the description is remarkably complete. It covers success, malformed input, mixed batches, duplicates, quota exhaustion, stale URLs, and the recommended call flow, so an agent can invoke it correctly in nearly any scenario.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3. The description adds meaningful semantics beyond the schema, especially for ids: malformed UUIDs never reach the API or consume quota, valid peers in a mixed batch are still processed, and duplicates are fetched/billed once.

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?

The description states a specific verb and resource: 'Fetch downloadable creative MEDIA (image/video URL + thumbnail)' for 1-500 ad or creative UUIDs. It clearly distinguishes from siblings like get_ad or get_creative by emphasizing the media delivery use case and the search_ads/search_creatives source.

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

Usage Guidelines4/5

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

The typical flow 'search_ads → pick ids → get_media' and the explicit phrase 'This is the paid delivery step' give clear usage context. It does not explicitly name alternative tools to avoid, but the flow and media-specific wording effectively route an agent to the right tool.

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

get_shopGet shop by domainA
Read-only
Inspect

Fetch one domain surface's FULL profile. Primary visits is the monthly estimate for traffic_as_of; fetched_at is ingestion time. traffic_sources is typed, while a separate legacy snapshot is kept alongside, and its similarly named traffic fields are not interchangeable with primary visits. the estimate's page title is not a canonical company/brand name; a missing rank on a subdomain is not evidence that the parent domain has no rank. domain_created is the best available registrable-root registration date, not product launch; its per-row RDAP/WHOIS-vs-legacy-fallback provenance is not retained in ClickHouse. ads_monthly/ads_burn use first_parsed_date and mark the open month is_complete=false. fb_signal is correlation_only. The domain/subdomain may be a funnel, runtime, blog or redirect rather than a company/product; inspect registrable_domain and surface_type. Includes AI-ad-category breakdown, recent ads and products. To save it use add_to_favorites (entity_type=shop, ids=[domain]). QUOTA: 1 token (one entity card).

ParametersJSON Schema
NameRequiredDescriptionDefault
domainYesthe shop domain to fetch (e.g. 'example.com'), as returned by search_shops

Output Schema

ParametersJSON Schema
NameRequiredDescription
dataNo

TDQS

A4.2/5.0
Behavior5/5

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

Annotations already mark the tool read-only and non-destructive, but the description adds substantial field-level caveats: legacy traffic snapshot fields are not interchangeable, domain_created is registration date not launch date, ads_monthly marks open months incomplete, and fb_signal is correlation-only. It also discloses the QUOTA and warns that domains may be funnels/runtime pages rather than companies.

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

Conciseness4/5

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

The first sentence is front-loaded with the action and resource, and every subsequent caveat earns its place. However, the description is one sprawling paragraph with lowercase continuations and run-on transitions, so it could be better structured without losing information.

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 single-object fetch tool, this is remarkably complete: the output schema covers structure, and the description provides non-obvious field semantics, provenance limitations, quota information, and a save-to-favorites workflow. Nothing essential for calling the tool correctly is missing.

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

Parameters4/5

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

The input schema already covers the domain parameter with 100% description coverage and a concrete example, so the baseline is met. The description adds extra meaning by warning that the domain/subdomain may be a funnel, runtime, blog, or redirect rather than a company/product, which is not present in the schema.

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?

Main clause 'Fetch one domain surface's FULL profile' pairs a specific verb with a clear resource and scope. It is easily distinguishable from the sibling get_* tools because 'shop'/'domain surface' is explicit in the title and description.

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

Usage Guidelines2/5

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

No explicit when-to-use or when-not-to-use guidance relative to siblings. It never mentions search_shops as the discovery step or get_advertiser/get_webmaster as alternatives; the only workflow hint is 'To save it use add_to_favorites', which is a next action, not a selection criterion.

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

get_usageGet usage / quotaA
Read-onlyIdempotent
Inspect

Return the caller's current MCP quota: plan, tokens used, remaining and limit (free starter = 500 tokens total forever; paid plans = 40,000/month ≈ 2,000 default-page searches; Enterprise = personal limit via support). Token costs: 1 per delivered result (an ad/webmaster/advertiser row, a trends row, an entity card), ad media = 1, creative media = 10, TikTok row = 100. You pay only for results actually delivered (short pages auto-refund). This call is FREE — it consumes no quota.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
noteNo
planYes
usedYes
limitYes
windowYes
reset_atNo
remainingYes
unlimitedNo
server_versionNo

TDQS

A4.7/5.0
Behavior5/5

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

Beyond the annotations, the description discloses the key behavioral fact that the call consumes no quota, and it explains the broader cost model including auto-refund behavior for short pages. It also clarifies plan-specific limits, adding meaningful context not present in the annotations.

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

Conciseness5/5

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

The description is information-dense but well organized, front-loading the core purpose before plan details and cost rules. Every sentence adds value: the plan breakdown, token costs, and the free-call note are all relevant to using the tool correctly.

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?

With no parameters and an output schema present, the description fully covers the situational and behavioral context an agent needs: what the quota is, how plans differ, how token costs are computed, refund behavior, and that the call itself is free.

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

Parameters4/5

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

The tool has zero parameters and the schema is an empty object, so there is nothing for the description to document. The baseline of 4 applies because no parameter explanation is needed and the description doesn't mislead about parameters.

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?

The description opens with a specific verb and resource: "Return the caller's current MCP quota." It enumerates the included fields (plan, tokens used, remaining, limit), making the tool's function unambiguous and distinct from sibling data-fetching tools.

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

Usage Guidelines4/5

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

The description provides clear context: it explains plan variants, token costs, and that "This call is FREE." It doesn't explicitly name alternatives or exclusion criteria, but the tool is unique among siblings and its purpose is so evident that no alternative-routing is needed.

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

get_webmasterGet webmaster by idA
Read-only
Inspect

Fetch a single webmaster (affiliate NETWORK) by UUID: aggregate stats PLUS top_creatives — the creatives this webmaster re-uploads the MOST, ordered by the webmaster's OWN in-slice ad count (slice.ads_in_slice desc — the deliberate slice order, matching what the profile page shows), media stripped/free. Each entry's total_ads is the creative's market-wide family size, folded best-effort from family redirects and floored at ads_in_slice — total_ads == ads_in_slice therefore often means 'family cards not yet built', not 'this webmaster owns the whole market'; it is context, not the sort key. analytics_pending=true means the canonical PostgreSQL identity exists but its ClickHouse aggregate is not published yet, so zero counters are not analytical zeroes. fanpages_status explicitly reports advertiser-aligned lifecycle enrichment as available, partial, unavailable or not_applicable; an omitted fanpages array is therefore never evidence that a page is alive. The id MUST be the canonical UUID returned by search_webmasters; domain names and display names are rejected instead of silently widening to the whole database. Present top_creatives as the headline final step; for the rest of the network use search_creatives?webmaster_id / search_ads?webmaster_id, and download media with get_media (entity_type=creo). identifier_inventory_semantics explains why historical page/domain/pixel inventory counts are not comparable to total_ads. attribution_link_stats.merge_edges answers WHY these identifiers sit in one network: each entry is a {page_id, page_name, domain, ads} pair — that fanpage ran exactly that many ads on that landing domain, and such a pair is what merges two networks into one (an ad whose domain belongs to network A and whose fanpage belongs to network B fuses them permanently). Weigh the edges before claiming a single operator: a 1-3 ad edge next to 100+ ad edges is a thin bridge, typically a catalog/feed ad, and is weak evidence of shared ownership; identifiers with no edge at all are inherited from earlier merges and prove nothing today. QUOTA: 1 token (one entity card). TIKTOK: with source=tiktok this fetches the TikTok cluster card instead (business-id rollup, same UUID space as search_webmasters source=tiktok results) — ⚠️ costs 100 tokens and requires a Pro-or-higher plan; the Meta-only embeds (top_creatives, attribution link-stats) are omitted on the TikTok card.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesthe webmaster UUID (from search_webmasters — same id space for both corpora)
sourceNowebmaster corpus: meta (default, FREE) or tiktok (⚠️ 100 tokens for the TikTok cluster card; Pro plan required)

Output Schema

ParametersJSON Schema
NameRequiredDescription
dataNo

TDQS

A5/5.0
Behavior5/5

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

The description adds substantial behavioral context beyond the readOnly/openWorld/destructive hints: 1-token quota, 100-token TikTok cost, analytics_pending semantics, total_ads folding and flooring, fanpages_status lifecycle meaning, and merge-edge interpretation. These are exactly the non-obvious behaviors an agent needs to avoid misreading results.

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

Conciseness5/5

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

The description is long, but it is information-dense and front-loaded: the core fetch behavior appears first, followed by warnings, field semantics, alternatives, and quota/TikTok caveats. Every sentence carries meaningful guidance; none is filler or repetition.

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?

The description is complete given the call's complexity and the presence of an output schema. It covers input constraints, token costs, plan requirements, open-world caveats, sensitive field interpretations, source-specific behavior, and sibling endpoints for extending the query. Nothing an agent needs to call it correctly is missing.

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?

Although schema coverage is already 100%, the description enriches both parameters: id must be the canonical UUID from search_webmasters and domain/display names are rejected, while source=tiktok is explained as the business-id cluster card with Meta-only embeds omitted. This goes well beyond the schema's enum and type descriptions.

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?

The description opens with a specific verb and resource: 'Fetch a single webmaster (affiliate NETWORK) by UUID.' It clearly defines the return focus — aggregate stats plus top_creatives — and explicitly distinguishes the canonical-UUID requirement from silent widening, which separates it from search-style siblings.

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?

The description gives explicit routing guidance: for the rest of the network use search_creatives?webmaster_id / search_ads?webmaster_id, and download media with get_media. It also defines when the TikTok variant applies and that it requires Pro or higher, leaving no ambiguity about when this tool should be selected.

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

get_webmaster_similarity_facetsGet webmaster similarity facetsA
Read-onlyIdempotent
Inspect

List the URL-parameter keys and normalized values that can be used to find related webmasters. Similarity here means shared affiliate/tracking parameter values, not name or domain similarity. Returns only facets that have at least one other webmaster match. FREE.

ParametersJSON Schema
NameRequiredDescriptionDefault
webmaster_idYessource webmaster UUID from search_webmasters

Output Schema

ParametersJSON Schema
NameRequiredDescription
dataYes
webmaster_idYes
similarity_basisYes

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already declare readOnly, idempotent, openWorld, and non-destructive behavior, so the description adds value by disclosing extra behaviors: only facets with at least one other webmaster match are returned, and the tool is FREE. It also clarifies the semantic scope of similarity, which is not present in annotations. No contradiction exists.

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

Conciseness5/5

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

The description is compact and front-loaded, with the key verb and resource in the first sentence. Each subsequent sentence earns its place: the similarity definition, the match-filtering behavior, and the cost note. No filler or repetition.

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?

With one fully documented parameter, strong annotations, and an output schema present, the description covers the important non-schema context: what facets are, how similarity is defined, and that only matched facets are returned. An agent has enough information to select and invoke this tool correctly without confusion.

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

Parameters3/5

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

Schema coverage is 100%, so the single parameter webmaster_id is already fully documented as 'source webmaster UUID from search_webmasters'. The description itself does not add significant parameter-level detail beyond the tool's overall purpose. This matches the baseline for high schema coverage.

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?

The description uses a specific verb ('List') and a clear resource ('URL-parameter keys and normalized values' / facets). It also actively disambiguates the meaning of similarity by stating it is about shared affiliate/tracking parameter values, not name or domain similarity. This clearly separates it from siblings like find_similar_webmasters and get_webmaster.

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

Usage Guidelines4/5

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

The description clearly frames when to use the tool: to discover URL-parameter facets that can be used for finding related webmasters. It gives helpful context about what similarity means and that only facets with at least one other match are returned. It does not explicitly name alternatives or say when not to use it, but the use case is clear enough for an agent.

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

list_favoritesList favouritesA
Read-onlyIdempotent
Inspect

List the caller's favourites folders (name, entity_type, item_count). Pass entity_type (creo/webmaster/ad/hub/shop) to filter; omit it to list folders across all types. Pass folder (a folder name) to instead return the ITEMS inside that folder: entity ids for creo/webmaster/ad (usable with get_creative / get_webmaster / get_ad), resolved hub profiles (hub + id + label) for hub folders, and domains for shop folders. Use this to confirm what add_to_favorites saved and to read a folder back. FREE — does not consume quota.

ParametersJSON Schema
NameRequiredDescriptionDefault
folderNoOPTIONAL folder name; when set, returns the ITEMS inside that folder (ids for creo/webmaster/ad — usable with get_creative/get_webmaster; resolved hub profiles for hub folders; domains for shop folders) instead of the folder list. If a name matches folders of several types, pass entity_type to disambiguate
entity_typeNooptional filter: creo, webmaster, ad, hub or shop; omit to list folders of all types

Output Schema

ParametersJSON Schema
NameRequiredDescription
foldersNo
folder_contentsNo

TDQS

A4.7/5.0
Behavior5/5

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

Annotations already declare readOnly, idempotent, and non-destructive behavior, and the description adds useful behavioral context beyond them: the operation is caller-scoped, consumes no quota, and the return content differs by folder type. No contradiction exists between the description and annotations.

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

Conciseness5/5

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

The description is front-loaded with the primary purpose, then packs filtering, folder-item behavior, return shapes, a use-case, and quota information into a compact set of sentences. Every sentence earns its place and none are redundant with the schema.

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?

The description covers the tool's scope, all parameter behaviors, return-shape differences, the intended use case, and quota impact. With an output schema present and no required parameters, an agent has everything needed to select and invoke this tool correctly.

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

Parameters3/5

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

Schema description coverage is 100%, so the schema already documents both parameters in detail. The description adds some interpretive context such as using returned ids with get_creative/get_webmaster/get_ad, but it largely restates what the schema already provides, so a baseline score of 3 is appropriate.

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?

The description uses a specific verb ('List') with a clear resource ('the caller's favourites folders') and explicitly explains the two modes: listing folders or listing items inside a named folder. It also distinguishes itself from add_to_favorites, its write counterpart, making the tool's role unambiguous.

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?

The description gives explicit usage guidance: pass entity_type to filter, omit it to list across all types, and pass folder to read items. It also tells the agent when to use this tool — to confirm what add_to_favorites saved and to read a folder back — naming the sibling tool that performs the corresponding write.

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

search_adsSearch adsA
Read-only
Inspect

Search the spytrend.com ad database and return ad METADATA: title, body_chars (the LENGTH of the ad text in UTF-8 characters), landing domain, status, geos, activity, advertiser, ai_enrichment (ai_category/media_type), media_count and creative-format metadata. The ad TEXT ITSELF is deliberately NOT in list rows — an average body is ~1.1k characters and would bloat a 20-row page 20-80x; fetch the text for a specific ad with get_ad, and use body_chars plus min_body_chars/max_body_chars to find the ads worth opening. The visible /ads Format filter targets creative_formats (video/carousel/single/dynamic); publisher placements are filtered separately via platforms. The downloadable creative media is NOT included here — fetch it with get_media using the returned ids. Filters: keyword (query), country/countries (multi-geo), platforms, categories (ai_category slug), ai_subcategory, status_today (active/inactive/vanished), advertiser_id, webmaster_id, landing_domain, media_type; languages, formats (creative_formats: video/carousel/single/dynamic), cta_buttons, domain_zones, search_in (which field query matches: all/title/advertiser/text), platforms_mode (platforms any/all); point lookups pixel_id / page_id / resolved_ip and contains_in_links (tracking fragments like pixel_id=/sub1=/utm); ranges min_days_active/days_active_to, min_page_likes/max_page_likes, min_body_chars/max_body_chars (ad-text length in characters; both directions cover only ads with known non-empty text), date_from/date_to (Facebook launch date — THE axis for 'new ads in a window': new = launched on Facebook then; first_seen_from/to is the date we first indexed the ad, which also catches late-indexed OLD ads — never use it for market newness); max_countries (with selected countries: additional GEOs outside them; without selected GEO: total GEOs), dedupe (unique creatives only), and saved/folder scopes (saved=all, folder_id). Sort with sort_by + sort_order. Use sort_by=most_reused_creative to rank the selected results by how many ads share the same creative; rows include same_creative_ads_in_selection and other_ads_with_same_creative for the selected filters, plus same_creative_ads_lifetime and advertisers_using_same_creative for the lifetime catalog. creative_match_type=exact identifies the matching contract and creative_reuse_status=exact|unavailable qualifies the counts. For most_reused_creative the absolute number of distinct creative groups is intentionally unavailable/null; page with has_more and next_cursor instead of retrying for a total. To find ads on a domain use landing_domain — NOT query. Cursor pagination via next_cursor; pagination always includes total and total_status (exact/estimated/unavailable), plus counted_at/count_cached for exact analytical totals. Any closed launch OR discovery window of at most 31 calendar days completes a raw exact unique-ad count in-call. A discovery request with exactly one country plus optional AI category/subcategory filters can instead use the canonical daily cube for an exact count across up to 90 inclusive days, or from first_seen_from through today; no other filters may be present on that cube path. Other wider/open combinations use the normal estimated/unavailable contract, and malformed/reversed dates are rejected. An exact count that includes today is exact for ads ingested so far, while analysis.includes_open_utc_day and data_complete_through make the incomplete tail explicit. status_today always means CURRENT state: with a date window, active is the currently-active survivors of that selected cohort, not historical activity on each date. Except for the intentional most_reused_creative group-total omission described above, unavailable means the async count did not settle inside this call: the number is PENDING, not zero and not a measurement; re-issue the identical call in a few seconds to obtain it (analysis.count_note repeats this warning in-band). NEVER present an unavailable count as 0. With categories set, matches and totals cover AI-LABELED ads only — a labeled SUBSET of the market (analysis.category_semantics=ai_labeled_ads_only_not_comparable_to_extrapolated_trends); get_trends aggregates for the same category×geo are extrapolated market estimates and will always be larger — never cross-compare the two. For an advertiser's or webmaster's EXACT ad count (total AND active), do NOT paginate search_ads — call get_advertiser / get_webmaster. To download the creatives, pass the ids to get_media; to SAVE them, pass the ids to add_to_favorites. Respects the caller's plan/verticals. For aggregate rankings use get_trends. QUOTA: 1 token per DELIVERED result (default page 20 = 20 tokens; short pages auto-refund — you pay only for results you receive). Results carry metadata only (no downloadable media) — the creative MEDIA is billed separately via get_media (1 token per ad, 10 per creative). Request small limits and narrow filters instead of paginating wide. TIKTOK SOURCE: pass source="tiktok" to query the TIKTOK ad corpus instead of Meta. (The platforms filter does NOT do this — platforms are Meta publisher placements.) ⚠️ TIKTOK IS PAID PER ROW at a premium: every DELIVERED TikTok ad row costs 100 tokens and every TikTok webmaster row/card costs 100 tokens (Meta rows cost 1), deducted from the same token balance (free starter: 500 tokens total = 5 TikTok rows EVER; paid plans: 40,000/month = up to 400 TikTok rows). Request small limits and narrow filters; you are charged only for rows actually delivered (short pages auto-refund; if the balance covers only part of the request, that part is delivered — a 3-row request on a 150-token balance returns 1 row and charges 100). TikTok requires a Pro-or-higher plan: free/starter callers and unlinked agents get an actionable upgrade refusal, never data and never a charge. TikTok rows have their OWN shape, returned under tiktok_data (verified live 2026-07-30): id/external_id (TikTok ad id), advertiser{id,external_id,name} plus advertiser_id (TikTok BUSINESS id), start_date/end_date (the ad's delivery window) and first_seen_date/last_seen_date (SpyTrend indexing), days_active, is_active + status_today, ai_category/ai_subcategory, countries + targeting_geos + targeting_details (OS/age/gender/regions), audience_size, objective, sponsor (the 'paid for by' funder) and registry_location, landing_domain + link_url, body/title/call_to_action, creative_format, creative_id, creative_ad_count (how many ads reuse that creative), is_blurred/is_cloaked, and media[] with media_type + thumbnail_url on media-tt.spytrend.com. Media comes WITH the row — do NOT call get_media for TikTok ids (it serves Meta entities only). There are no TikTok engagement counters (plays/likes/comments/shares) on this surface. The TikTok feed serves the ARCHIVED TikTok corpus — exactly what the spytrend.com /ads TikTok tab shows — and pagination carries has_more/next_cursor plus total with total_status (exact unless ttads marks the count estimated). With source=tiktok the honored filters are: query (+search_in), country, categories, landing_domain, advertiser_id (TikTok business id), contains_in_links, media_type, cta_buttons, domain_zones, status_today (active/inactive only), min_days_active/days_active_to, max_countries (with country: additional GEOs outside it; without country: total GEOs), dedupe, date_from/date_to, sort_by=date|days_active, limit (default 10 for TikTok — rows are paid), cursor. Meta-only params (platforms/formats/languages, pixel_id/page_id/resolved_ip, webmaster_id, first_seen_from/to, page-likes ranges, hub_category/channel) are REJECTED with an explanation rather than silently ignored.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNomax rows to return (default 20; each delivered row costs 1 token). IGNORED on geo and geo_timeline — both return their complete set (geo: the whole per-country stock table, ~194 rows; geo_timeline: every populated date×country point) while charging only the page size you asked (a flat 20 by default). Those responses can be large: pass verbosity=compact to drop the heavy per-row nested structures.
queryNofree-text keyword to match in ad title, body or link
savedNosaved scope selector. Use saved=all to restrict results to ads saved in ANY favorites folder, matching the saved-ads view on /ads.
cursorNopagination cursor from a previous response's next_cursor
dedupeNowhen true, collapse duplicates so each unique creative appears once
sourceNoad corpus to search: meta (default — the Facebook/Meta library, 1 token per delivered row) or tiktok (the TikTok corpus — ⚠️ PAID: 100 tokens per DELIVERED TikTok ad row, embedded media links included; Pro plan required; default limit drops to 10). platforms=[tiktok] does NOT do this.
channelNomessaging channel the ad sends traffic to: whatsapp or telegram. Filters to ads landing on that channel's chat domains (whatsapp: api.whatsapp.com/wa.me/chat.whatsapp.com; telegram: t.me). Use for 'ads/bundles going to WhatsApp/Telegram'.
countryNosingle ISO country code filter (legacy form, e.g. US, BR, DE). Prefer countries[] for UI parity and multi-country requests.
date_toNoonly ads whose Facebook launch date is on or before this date (YYYY-MM-DD); combine with date_from in a closed window of at most 31 calendar days for an exact in-call total
formatsNocreative format filter from the visible /ads Format control: video, carousel, single or dynamic. Distinct from platforms, which filters publisher placements like facebook/instagram.
page_idNopoint lookup: only ads from this Facebook page id; also accepts a pasted facebook.com page link in any form (vanity, profile id, profile.php, Ads Library view_all_page_id) — resolved to the canonical page id automatically
sort_byNoorder results by: date (default, newest first), most_popular, folder_added or most_reused_creative. most_reused_creative ranks ads by how many ads share the same exact creative within the selected filters and dates; default/desc gives most reused first, asc gives least reused first. It requires a specific advertiser/page/pixel/webmaster/query/landing-domain/creative anchor or a launch/discovery window of at most 31 days. Rows include semantic same-creative reuse counts and creative_reuse_status. folder_added is only meaningful on folder-scoped or saved=all views; most_popular is the Trending preset ranking
pixel_idNopoint lookup: only ads carrying this Facebook pixel id
countriesNoISO country codes to filter by. Mirrors the /ads UI multi-country picker. With country_match=any (default) an ad matches when at least one selected geo is present; with country_match=only every known geo must belong to this set.
date_fromNoonly ads whose Facebook launch/delivery start date is on or after this date (YYYY-MM-DD). THE canonical date axis for 'new ads in a window' questions — new means LAUNCHED ON FACEBOOK in that window, not indexed by spytrend. Combine with date_to in a closed window of at most 31 calendar days for an exact in-call total
folder_idNorestrict results to ads saved in this favorites folder UUID. Mirrors the /ads favorites page scope.
languagesNoISO language codes the ad targets (e.g. en, pt, es). The /ads Language filter.
platformsNoplatform names to include (e.g. facebook, instagram)
search_inNowhich field the free-text query matches: all (default), title, advertiser or text. The /ads search-scope toggle.
categoriesNoAI category slugs to include. Use the underscore slug form, e.g. gambling_and_betting, ecommerce_and_retail, finance_and_banking, dating_and_relationships, healthcare_and_medical, impersonation_funnels, crypto_and_trading (NOT short words like 'gambling')
media_typeNofilter by creative media type: image or video
sort_orderNosort direction: asc or desc (default desc)
cta_buttonsNocall-to-action button labels (e.g. Shop Now, Learn More, Sign Up, Download). The /ads CTA filter.
hub_domainsNoexact hub/destination domains to filter landings by (e.g. linktr.ee, wa.me). The visible /ads Hub filter sends these; hub_category stays the coarse category form. When channel is also set, the explicit domains and channel domains are combined deterministically into one OR-list.
resolved_ipNopoint lookup: only ads whose landing domain resolves to this IP
domain_zonesNolanding-domain TLD/zone without the dot (e.g. com, shop, online, xyz). The /ads domain-zone filter.
hub_categoryNofilter to ads whose landing 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 the channel param instead - hub_category does NOT accept whatsapp/telegram sub-slugs.
status_todayNocurrent status: active, inactive or vanished
webmaster_idNoreturn only ads from this webmaster id (from search_webmasters)
advertiser_idNoreturn only ads from this advertiser id (from search_advertisers)
country_matchNohow the countries filter matches: any (default, overlap semantics) or only (strict subset semantics). The /ads UI sends any explicitly when countries are selected.
first_seen_toNoonly ads spytrend first INDEXED on or before this date (YYYY-MM-DD) — internal discovery date, not the Facebook launch date; for 'new ads' questions use date_from/date_to. See first_seen_from for exact-total windows
max_countriesNowith countries or country selected, allow at most this many additional GEOs outside that selected set; without a selected GEO, allow at most this many total GEOs
ai_subcategoryNoAI subcategory slugs to include under the chosen ai_category set. Mirrors the visible /ads subcategory drill-down.
days_active_toNoupper bound of the days-active range — only ads running at most this many days
landing_domainNolanding domain filter. By default it preserves the historical /ads behavior: match this hostname AND its subdomains. Set landing_domain_exact=true to restrict to the normalized hostname itself only.
max_body_charsNoonly ads whose AD TEXT is at most this many characters long (UTF-8 characters, not bytes). Ads with no text are NOT returned as length 0 — the length filters cover only ads with known non-empty text. Combine with min_body_chars for a closed length range, e.g. 100..500
max_page_likesNoonly ads from pages with at most this many likes
min_body_charsNoonly ads whose AD TEXT is at least this many characters long (UTF-8 characters, not bytes). Both length filters match only ads whose text length is KNOWN and non-zero: ads with no text at all are outside the length axis entirely and are returned by neither direction. Pairs with the body_chars field returned on every row; the ad text itself is served by get_ad, not by this list
min_page_likesNoonly ads from pages with at least this many likes
platforms_modeNohow the platforms filter combines: any (OR, default) or all (AND — the ad must run on EVERY selected platform). The /ads platform match-mode toggle.
first_seen_fromNoonly ads spytrend first INDEXED on or after this date (YYYY-MM-DD) — an internal discovery date, NOT the ad's Facebook launch date. Do NOT use it for 'new ads recently' questions: spytrend also indexes OLD ads late, so late-indexed old ads would pollute the answer — use date_from/date_to (Facebook launch) for market newness. Exact totals: any closed window up to 31 days; a single-country request with only AI-category filters can use the canonical daily cube for up to 90 days or from this date through today
min_days_activeNoonly ads running at least this many days (e.g. 30 → long-running 'winning' ads). Lower bound of the days-active range
contains_in_linksNomatch a fragment inside the ad's tracking links - e.g. a pixel id, sub id or UTM fragment like 'pixel_id=123', 'sub1=', 'utm_campaign=xyz'
landing_domain_exactNowhen true, restrict landing_domain to the normalized hostname itself and exclude subdomains. Mirrors the /ads UI exact-host toggle.

Output Schema

ParametersJSON Schema
NameRequiredDescription
dataYes
metaNo
sourceNo
analysisNo
paginationYes
tiktok_dataNo
auto_applied_verticalsNo

TDQS

A4.6/5.0
Behavior5/5

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

Annotations only indicate readOnly/openWorld/non-destructive, so the description carries the behavioral burden and fulfills it richly. It discloses the token-cost model (1 per Meta row, 100 per TikTok row), exact/estimated/unavailable count semantics, the 'unavailable is pending, not zero' rule, status_today's current-state interpretation, and the AI-labeled-subset caveat. No contradiction with annotations exists.

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 description is a single dense block with no section breaks, lists, or formatting, making it hard for an agent to scan quickly. It also repeats details already present in the input schema, such as formats, status_today values, and min/max body_chars semantics. While front-loaded with a clear purpose, its excessive length and lack of structure undermine its usability.

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 complex 45-parameter search tool, the description covers every operationally relevant area: filter semantics, pagination, exact-count windows, quota/token costs, status interpretations, TikTok-specific behavior, and unsupported-parameter rejections. Given that an output schema exists, not restating return shapes is acceptable; nothing critical for correct invocation is missing.

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

Parameters4/5

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

Schema coverage is 100% with detailed per-parameter descriptions, so the baseline is 3. The description adds cross-parameter value by grouping filters, explaining the date_from vs. first_seen_from distinction, max_countries behavior with and without a selected GEO, and which parameters are honored or rejected on the TikTok source. However, much of the parameter-level detail already appears in the schema, so the increment above baseline is moderate.

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?

The description opens with a specific verb and resource: 'Search the spytrend.com ad database' and explicitly enumerates the returned metadata fields (title, body_chars, landing domain, status, etc.). It also distinguishes itself from siblings by stating what it deliberately does not return (ad text, media) and pointing to get_ad and get_media for those needs.

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?

The description gives explicit routing rules: fetch ad text with get_ad, media with get_media, exact advertiser/webmaster counts with get_advertiser/get_webmaster, aggregate rankings with get_trends, and saving with add_to_favorites. It also warns not to use query for domain lookups and not to use first_seen_from/to for market newness, steering instead to landing_domain and date_from/date_to.

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

search_advertisersSearch advertisersA
Read-only
Inspect

Search advertisers by NAME, numeric Facebook page id, or a pasted facebook.com page link (typeahead; query ≥2 chars). A link in any form (vanity name, profile 100…-id, profile.php, Ads Library view_all_page_id) and either id namespace resolve to the canonical fanpage with the exact match first. Returns advertisers with external_id and ad_count. To fetch ONE advertiser's full card by id use get_advertiser; to see an advertiser's ads, call search_ads with advertiser_id. For advertiser RANKINGS, ordering and filters (category/country/followers/founded-date/life_status/hubs), use get_trends with dimension=advertisers. FREE PLAN COUNTS: when the plan's archive window narrows a request, pagination.total_status is "restricted" and meta.plan_window_cutoff names the boundary — the count then describes the window actually searched, NOT the one requested, so a zero means "nothing in the archive window" and never "nothing exists". QUOTA: 1 token per DELIVERED result from your plan balance (free starter: 500 tokens lifetime; paid plans: 40,000/month; short pages auto-refund — you pay only for results you receive). Default page is 20 results = 20 tokens; pass limit (1–200) to size it. get_usage is free. Autonomous agents must be linked to a spytrend account to access data — an unlinked agent gets an actionable connect-your-account refusal (create agent credentials at spytrend.com/settings?tab=ai, or a human claims it by client_id), NOT a server error. Calls are rate-limited per authenticated user (deployment defaults: 60/minute and 1000/hour); a rate-limit refusal is an MCP tool error with structured error.code=rate_limit_exceeded, scope, window and retry_after_seconds. CONCURRENCY: heavy analytical calls (get_trends, search_ads, search_creatives) are admitted ONE AT A TIME per account — fanning out 5-10 of them in parallel does not go faster, it returns admission refusals for all but one. Issue heavy calls sequentially; light lookups (get_ad, get_advertiser, get_usage) are not gated.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNomax results, 1-50 (default 20 — this typeahead is capped at 50 upstream; a larger value is clamped, not rejected). Each delivered result costs 1 token.
queryNoadvertiser name (at least 2 characters), a numeric Facebook page id (either the Ads Library page id or the direct-page profile 100…-id), OR a pasted facebook.com page link in any form (vanity, profile.php, Ads Library) — links and ids resolve to the canonical fanpage with the exact match first

Output Schema

ParametersJSON Schema
NameRequiredDescription
metaNo
itemsYes
totalNo

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already mark the call read-only and non-destructive, and the description goes much further: it discloses plan-window count restrictions, quota/token accounting, required account linking for autonomous agents, rate-limit refusal behavior, and one-at-a-time concurrency for heavy calls. These are exactly the behavioral traits an agent needs to avoid failed or expensive calls.

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

Conciseness4/5

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

Long but well labeled and front-loaded: core semantics and alternatives come first, then quotas, auth, rate limits, and concurrency. Some sections are dense enough to be hard to scan, but almost every sentence earns its place; only minor trimming would improve it.

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 tool with quota, authentication, rate-limit, and concurrency constraints, the description covers all operationally critical areas while the output schema covers return structure. The only completeness issue is the limit-range contradiction, but that is better attributed to parameter semantics.

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

Parameters3/5

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

Schema covers both parameters at 100%, so the baseline is 3. The description adds useful cost semantics (1 token per delivered result; default 20) and query-form resolution, but it says limit is 1–200 while the schema says 1–50 with clamping, a conflicting instruction that makes the added semantic value partially unreliable.

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?

The description opens with a specific action and resource: 'Search advertisers by NAME, numeric Facebook page id, or a pasted facebook.com page link', and specifies the typeahead behavior (query ≥2 chars) and primary returns (external_id, ad_count). It also clearly contrasts with search_ads and get_advertiser, so an agent can tell which tool is intended.

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?

It explicitly routes to alternatives: get_advertiser for one full card, search_ads for an advertiser's ads, and get_trends with dimension=advertisers for rankings, ordering, and filters. This is direct when-to-use vs when-not-to-use guidance with named sibling tools.

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

search_creativesSearch creativesA
Read-only
Inspect

Browse and filter unique creative families 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. 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. Creatives have no free-text search; use search_ads for discovery. Cursor-paginated. Download with get_media and save with add_to_favorites. QUOTA: 1 token per DELIVERED result (default page 20 = 20 tokens; short pages auto-refund — you pay only for results you receive). Results carry metadata only (no downloadable media) — the creative MEDIA is billed separately via get_media (1 token per ad, 10 per creative). Request small limits and narrow filters instead of paginating wide. 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. 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.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNomax metadata rows (default 20, max 200; each delivered row costs 1 token) — fetch media with get_media (entity_type=creo, 10 tokens 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
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_toNocompatibility alias of period_to for the in-period window; read pagination.period_axis to learn which date axis was used
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_fromNocompatibility alias of period_from for the in-period window; read pagination.period_axis to learn which date axis was used
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 advertiser id (from an ad's advertiser_id in search_ads, or get_trends dimension=advertisers)
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 is the ONLY date filter; 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.
active_ads_today_fromNominimum number of ads active today for the creative family; 0 or omitted disables this filter

Output Schema

ParametersJSON Schema
NameRequiredDescription
dataYes
metaNo
paginationYes

TDQS

A4.9/5.0
Behavior5/5

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

The description goes far beyond the readOnly/destructive annotations by disclosing quota semantics (1 token per delivered result, short-page auto-refund), metadata-only behavior, separate media billing, the period_axis contract, empty-page behavior, and rejection of invalid periods before upstream work. These are behavioral details not inferable from annotations alone.

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

Conciseness4/5

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

The description is long but densely packed with operationally important information, and it is front-loaded with purpose then quota then contracts. However, it repeats the period_axis contract and last_seen/period definitions in multiple places, so it is not maximally concise.

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 complex 33-parameter tool with no required parameters and an output schema present, the description covers pricing, pagination, period semantics, aliases, sort behavior, slice semantics, error handling, and sibling routing. Nothing essential for correct invocation appears missing.

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%, so the baseline is 3, but the description adds substantial meaning: last_seen vs period date semantics, date_from/date_to aliases, period_axis interpretation, slice.ads_in_slice ordering, min_geo_share's country requirement, and the closed-period auto-enablement of ads_in_period. This clearly exceeds the baseline.

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?

The description opens with a specific verb-resource pair: 'Browse and filter unique creative families and return metadata only.' It also explicitly distinguishes the tool from search_ads by stating that creatives have no free-text search and that search_ads is for discovery, which helps an agent tell siblings apart.

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?

The description gives explicit routing guidance: use search_ads for free-text discovery, get_media for downloading media, and add_to_favorites for saving. It also advises requesting small limits and narrow filters instead of wide pagination, making the intended usage pattern clear.

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

search_hubsSearch hubs (destinations)A
Read-only
Inspect

Explore HUBS — where ads send traffic, grouped by destination (Social Media: Facebook/Instagram/Telegram/WhatsApp; App Stores; Amazon; E-commerce; Popular; Platforms). Call WITHOUT hub to get the catalog (the list of hub slugs + labels) — that is FREE. Call WITH hub set to a slug to drill into that hub's destination profiles, filtered by query (free-text profile name/id search), ai_category, min_total/min_active/min_sticky ads, date_from/date_to, window (7d/30d/90d; NOTE: lifetime counters on the default snapshot path — window is a no-op there, prefer date_from/date_to or sort=active_desc for recency), country (ISO alpha-2 — keep only profiles with ads in that geo) and exclude_cloaking (drop multi-geo redirect/cloaking domains), ordered by sort (ad_count_desc default = LIFETIME volume, ad_count_asc, last_seen_desc, sticky_desc, sticky_asc, active_desc/active_asc = CURRENTLY-active 'hot now', or relevance = ad volume IN the selected country — needs country). For a per-geo ranking of real storefronts (e.g. top e-commerce in BR), combine country + sort=relevance + exclude_cloaking. The catalog call (no hub) is FREE; profile rows cost 1 token each. FREE PLAN COUNTS: when the plan's archive window narrows a request, pagination.total_status is "restricted" and meta.plan_window_cutoff names the boundary — the count then describes the window actually searched, NOT the one requested, so a zero means "nothing in the archive window" and never "nothing exists". QUOTA: 1 token per DELIVERED result from your plan balance (free starter: 500 tokens lifetime; paid plans: 40,000/month; short pages auto-refund — you pay only for results you receive). Default page is 20 results = 20 tokens; pass limit (1–200) to size it. get_usage is free. Autonomous agents must be linked to a spytrend account to access data — an unlinked agent gets an actionable connect-your-account refusal (create agent credentials at spytrend.com/settings?tab=ai, or a human claims it by client_id), NOT a server error. Calls are rate-limited per authenticated user (deployment defaults: 60/minute and 1000/hour); a rate-limit refusal is an MCP tool error with structured error.code=rate_limit_exceeded, scope, window and retry_after_seconds. CONCURRENCY: heavy analytical calls (get_trends, search_ads, search_creatives) are admitted ONE AT A TIME per account — fanning out 5-10 of them in parallel does not go faster, it returns admission refusals for all but one. Issue heavy calls sequentially; light lookups (get_ad, get_advertiser, get_usage) are not gated.

ParametersJSON Schema
NameRequiredDescriptionDefault
hubNohub slug to drill into. IT IS THE NESTED ONE: the catalog (returned when hub is omitted) is TWO levels — each row is a CATEGORY with its own slug (social_media, app_stores, …) and a hubs[] array whose entries carry the drill-in slugs (facebook, instagram, google_play, …). Pass hubs[].slug, NOT the category slug — a category slug is rejected. Leave empty to list the hub catalog (free).
sortNoprofiles only: ad_count_desc (default, LIFETIME volume), ad_count_asc, last_seen_desc, sticky_desc, sticky_asc, active_desc/active_asc (CURRENTLY-active ads — 'what's hot now', avoids the dead-domain top), or relevance (rank by ad volume in the selected country — REQUIRES country)
limitNoprofiles only: max results (default 20; each delivered profile costs 1 token). The catalog call (no hub) is free.
queryNoprofiles only: free-text search by profile id/name within the hub (the same box as the profile search on the /hubs page). Requires hub.
windowNoprofiles only: lookback window 7d, 30d (default) or 90d. NOTE: on the default snapshot read path counters are LIFETIME and window is a no-op — for recency use date_from/date_to (profile activity dates) or sort=active_desc instead
countryNoprofiles only: ISO-3166 alpha-2 country code (e.g. US, BR). Keeps only profiles with ads in that country and enables sort=relevance (rank by ad volume IN that country) — turns the global lifetime top into a real per-geo ranking.
date_toNoprofiles only: active on or before this date (YYYY-MM-DD)
date_fromNoprofiles only: active on or after this date (YYYY-MM-DD)
min_totalNoprofiles only: minimum total ads
min_activeNoprofiles only: minimum active ads
min_stickyNoprofiles only: minimum sticky (long-running) ads
ai_categoryNoprofiles only: AI category slug filter
exclude_cloakingNoprofiles only: drop multi-geo redirect / cloaking domains (a real storefront targets a few countries; a cloaking redirect runs in 90+). Use with country+relevance to surface genuine storefronts instead of infrastructure domains.

Output Schema

ParametersJSON Schema
NameRequiredDescription
dataYes
metaNo
paginationYes

TDQS

A4.5/5.0
Behavior5/5

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

Annotations only declare readOnlyHint/openWorldHint/destructiveHint; the description adds significant behavioral context: token costs, restricted archive counts, window no-op behavior, unlinked-agent refusal handling, rate-limit error codes, and concurrency admission limits. No contradiction with annotations.

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

Conciseness3/5

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

The description is front-loaded with the core purpose and call patterns, but it becomes a long rambling paragraph with repeated FREE/token reminders and extensive quota/rate-limit/concurrency details that could be summarized or bulleted. It is informative but not concise.

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?

Given the 13 parameters and already-rich schema, the description covers everything an agent needs: invocation modes, filter semantics, sort behavior, cost model, auth requirements, rate limits, error shapes, and concurrency guidance. The output schema being present means return-value details are not required here.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3. The description adds value beyond the schema by explaining the token cost per delivered profile, the 1–200 limit range, the semantic difference between lifetime and currently-active sorts, and how to combine country, relevance, and exclude_cloaking to get meaningful per-geo rankings.

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?

The description clearly states that search_hubs explores destination hubs where ads send traffic, and precisely distinguishes the two modes: without hub it returns the catalog, with hub it drills into destination profiles. This makes the tool's scope unambiguous relative to sibling search tools.

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

Usage Guidelines4/5

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

It explicitly explains when to call without hub vs with hub, and gives a concrete recipe for per-geo storefront rankings (country + relevance + exclude_cloaking). However, it does not explicitly contrast search_hubs with sibling search_* tools or state when not to use it.

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

search_shopsSearch domains and their trafficA
Read-only
Inspect

Search domain-level traffic surfaces with commerce and advertising intelligence. A row is a DOMAIN/SUBDOMAIN surface, not necessarily a company or product. visits is a MONTHLY estimate for traffic_as_of (not live traffic); fetched_at is ingestion time. Judge every estimate using traffic_quality, traffic_confidence, traffic_is_small, traffic_is_data_from_ga, traffic_data_status and history. traffic_paid_share is display + paid-search + paid-social share; trust it only when traffic_sources_available=true. visits_growth_pct is latest-vs-previous month PERCENT; min_growth and sort_by=growth only return growth_qualified rows (current cohort, contiguous 3-month window, previous month >=10k, non-small estimate, confidence >=0.60). category is an estimated SITE category and may be missing/wrong; ai_category is SpyTrend's AD category and is preferred for ad-market discovery. created_from/to filter domain_created: best available registration date of the REGISTRABLE ROOT, not product/subdomain launch or SpyTrend first-seen. The ClickHouse row does not retain whether that date came from the preferred registry lookup or the legacy fallback. traffic_start_max compares the current estimate with the MAXIMUM of both preceding complete months and excludes stale/low-quality windows; combine with traffic_end_min. ads_monthly counts ads first observed by SpyTrend (first_parsed_date), and each point has is_complete=false for the open current month. fb_signal is correlation_only, not causal attribution; honest statuses are correlated_growth, ad_growth_ahead, ad_growth_flat_traffic, ad_growth_declining_traffic, traffic_growth_without_fb_growth, stable_or_mixed and insufficient_signal. sort_by=relevance REQUIRES ai_category and is rejected otherwise. Sorts: visits/revenue/growth/ads/rank/backlinks/ai_traffic/products/fb_score/per_ad/relevance. a separate legacy snapshot is kept alongside; never substitute its similarly named traffic fields for the primary visits/traffic_as_of contract. Returns total, has_more and offset. Use get_shop for the full source payload. Saving shops is free. FREE PLAN COUNTS: when the plan's archive window narrows a request, pagination.total_status is "restricted" and meta.plan_window_cutoff names the boundary — the count then describes the window actually searched, NOT the one requested, so a zero means "nothing in the archive window" and never "nothing exists". QUOTA: 1 token per DELIVERED result from your plan balance (free starter: 500 tokens lifetime; paid plans: 40,000/month; short pages auto-refund — you pay only for results you receive). Default page is 20 results = 20 tokens; pass limit (1–200) to size it. get_usage is free. Autonomous agents must be linked to a spytrend account to access data — an unlinked agent gets an actionable connect-your-account refusal (create agent credentials at spytrend.com/settings?tab=ai, or a human claims it by client_id), NOT a server error. Calls are rate-limited per authenticated user (deployment defaults: 60/minute and 1000/hour); a rate-limit refusal is an MCP tool error with structured error.code=rate_limit_exceeded, scope, window and retry_after_seconds. CONCURRENCY: heavy analytical calls (get_trends, search_ads, search_creatives) are admitted ONE AT A TIME per account — fanning out 5-10 of them in parallel does not go faster, it returns admission refusals for all but one. Issue heavy calls sequentially; light lookups (get_ad, get_advertiser, get_usage) are not gated.

ParametersJSON Schema
NameRequiredDescriptionDefault
qNosubstring search on the normalized domain; URLs are normalized to their host
limitNomax results (default 20; each delivered result costs 1 token).
savedNosaved scope selector. Use saved=all to restrict results to shops saved in ANY favourites folder.
offsetNopagination offset (0-based)
pixelsNocomma-separated pixel identifiers to filter by
countryNoISO-2 country code — keep only shops with traffic in this country
has_adsNotrue = only shops with at least one ad in the database
min_adsNominimum number of ads
socialsNocomma-separated social-media handle filters
sort_byNoorder by: visits (default), revenue, growth, ads, rank, backlinks, ai_traffic, products, fb_score, per_ad or relevance; relevance REQUIRES ai_category and is rejected without it
categoryNoestimated site-category filter; may be missing or misclassified, so prefer ai_category for ad-market discovery
platformNocommerce platform the site runs on: Shopify, WooCommerce, WordPress, Wix, Squarespace, Magento, PrestaShop or BigCommerce
fb_statusNoobserved ads/traffic relationship: correlated_growth, ad_growth_ahead, ad_growth_flat_traffic, ad_growth_declining_traffic, traffic_growth_without_fb_growth, stable_or_mixed or insufficient_signal; correlation only
folder_idNorestrict results to shops saved in this favourites folder UUID. Mirrors the /shops folder view.
created_toNoregistrable-root registration date on/before YYYY-MM-DD; NOT product/subdomain launch; per-row RDAP/WHOIS-vs-legacy provenance is unavailable
max_bounceNomaximum bounce rate in PERCENT (0-100) — max_bounce=30 keeps only sticky sites, the reason this control exists. The server converts it to the fraction the column stores.
max_growthNoupper end of the traffic-growth range (percent). The /shops panel has BOTH ends; pair it with min_growth for a band such as 10..50.
max_per_adNomaximum visits-per-ad efficiency
max_visitsNomaximum monthly visits
min_bounceNominimum bounce rate in PERCENT (0-100), matching the visible /shops bounce slider — min_bounce=70 keeps only high-bounce sites. The server converts it to the fraction the column stores.
min_growthNominimum latest-vs-previous monthly visits growth PERCENT; only current-cohort growth_qualified rows pass (contiguous 3 months, previous >=10k, non-small, confidence >=0.60)
min_per_adNominimum visits-per-ad efficiency (traffic / active ads)
min_visitsNominimum monthly visits
sort_orderNosort direction: asc or desc (default desc)
ai_categoryNoAI category slug the shop's ads belong to (e.g. ecommerce_and_retail)
min_revenueNominimum estimated monthly revenue (USD)
shopify_appNoShopify app slug filter (shops using this app)
created_fromNoregistrable-root registration date on/after YYYY-MM-DD; NOT product/subdomain launch or SpyTrend first-seen; per-row RDAP/WHOIS-vs-legacy provenance is unavailable
has_productsNotrue = only shops with a product catalog in our database
min_productsNominimum number of catalogued products
shopify_planNoShopify plan name filter (e.g. Basic, Shopify, Advanced)
min_backlinksNominimum total backlinks
shopify_themeNoShopify theme slug filter
has_ai_trafficNotrue = only shops receiving AI-referred traffic (ai_traffic_share > 0)
has_trustpilotNotrue = only shops with Trustpilot reviews
country_excludeNoISO-2 country code to exclude from results
traffic_end_minNolatest monthly estimate at traffic_as_of is at least this value; combine with traffic_start_max
traffic_start_maxNomaximum allowed baseline traffic, where baseline=max(two complete months before traffic_as_of); stale, low-quality, incomplete and non-contiguous windows are excluded; combine with traffic_end_min
min_trustpilot_ratingNominimum Trustpilot rating (0-5)
exclude_infrastructureNodrop rows that are transit rather than an offer — link shorteners / link-in-bio, app stores and marketplaces, social networks and messengers, ad servers. Every row also carries surface_role (destination | redirect | store | social | adserver; absent for an ordinary merchant site) so you can filter yourself instead. NOTE: rows are dropped after the page is fetched, so an excluded page can return fewer than limit rows — page on has_more/offset, not on row count.

Output Schema

ParametersJSON Schema
NameRequiredDescription
dataYes
metaNo
totalYes
offsetYes
has_moreYes

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already cover the safety profile (readOnlyHint=true, openWorldHint=true, destructiveHint=false), so the bar is lower — yet the description goes far beyond: visits is a MONTHLY estimate, fetched_at is ingestion time, quality fields must gate judgment, paid_share trusts only when traffic_sources_available=true, growth rows require a qualifying cohort, category may be wrong, provenance of registration dates is not retained (ClickHouse row caveat), free-plan archive windows change what total reports, rate-limit refusal surfaces as structured error.code=rate_limit_exceeded, and concurrency gates heavy calls. Failure modes and data caveats are disclosed in unusual depth.

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

Conciseness4/5

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

The description is long, but every sentence carries a substantive caveat or behavior — no obvious padding. It front-loads the core row/visits contract before quota, rate-limit, and concurrency details. The length is justified by 40 params, a token-cost model, and complex data semantics; it loses a point only because a wall of unheadered prose is harder for an agent to scan selectively than structured sections.

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 tool with this complexity — 40 loosely-coupled filters, quota accounting, plan-window restrictions, rate limits, concurrency, and data-quality caveats — the description covers nearly everything an agent needs: return shape (total/has_more/offset), pagination restriction semantics, token cost per delivered row including auto-refund, the unlinked-agent refusal mode, and the exact rate-limit error contract. An output schema exists, so return-value details are appropriately left to it.

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

Parameters4/5

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

Schema coverage is 100%, giving a baseline of 3. The description adds interpretave semantics beyond the schema: it ties visits_growth_pct to the growth_qualified cohort conditions, ranks ai_category over category for ad-market discovery, and explains traffic_start_max's baseline of both preceding complete months with stale windows excluded. It doesn't fully compensate for the sheer number of params on its own, but genuinely elevates understanding of the key filter semantics.

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?

The description opens with a specific verb and resource — 'Search domain-level traffic surfaces with commerce and advertising intelligence' — and immediately defines the row unit (DOMAIN/SUBDOMAIN) to prevent over-interpretation. This distinguishes it from siblings like search_ads, search_creatives, and search_advertisers, whose resources are different entities, and it explicitly points to get_shop for the full source payload.

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

Usage Guidelines4/5

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

Explicit alternative guidance is present: 'Use get_shop for the full source payload.' The concurrency paragraph also implies search_shops is not a gated heavy call (unlike get_trends, search_ads, search_creatives), and the quota/plan section gives clear cost-based context for calling it. It stops short of an explicit when-not-to-use list against the other search_* siblings, so a 4 rather than a 5.

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

search_webmastersSearch webmastersA
Read-only
Inspect

Search webmasters (affiliates) — a webmaster is a whole ad NETWORK (landing domains, pixels, pages and geos grouped as one). Copy workflow: search by domain, take the canonical UUID, then search_creatives/search_ads with webmaster_id. Finish with the most reused material: get_webmaster.top_creatives or search_creatives sort_by=total_ads; total_ads is how many ads reuse the same material over its lifetime, not a weekly debut count. Returns total/active counts, top countries and geo counts. Find by name or pixel_id/domain/page_id/resolved_ip. Filter by category, AI category/subcategory, countries, languages, platforms, format, current status, dates and count ranges. For a geo ranking combine countries + min_geo_share + sort_by=relevance. Save returned UUIDs with add_to_favorites. Exact pixel_id/domain/page_id/resolved_ip lookups use the webmaster's CURRENT canonical identifier membership; historical identifiers removed from a webmaster do not count as matches. Exact page_id results report fanpages_status as available, partial, unavailable or not_applicable. When available, the selected page is included in fanpages[] with life_status from the same page-lifetime source as /advertisers (alive/deleted/banned, or unknown when lifetime coverage has no row); when unavailable, an omitted fanpages[] is not evidence that the page is alive. FREE PLAN COUNTS: when the plan's archive window narrows a request, pagination.total_status is "restricted" and meta.plan_window_cutoff names the boundary — the count then describes the window actually searched, NOT the one requested, so a zero means "nothing in the archive window" and never "nothing exists". QUOTA: 1 token per DELIVERED result from your plan balance (free starter: 500 tokens lifetime; paid plans: 40,000/month; short pages auto-refund — you pay only for results you receive). Default page is 20 results = 20 tokens; pass limit (1–200) to size it. get_usage is free. Autonomous agents must be linked to a spytrend account to access data — an unlinked agent gets an actionable connect-your-account refusal (create agent credentials at spytrend.com/settings?tab=ai, or a human claims it by client_id), NOT a server error. Calls are rate-limited per authenticated user (deployment defaults: 60/minute and 1000/hour); a rate-limit refusal is an MCP tool error with structured error.code=rate_limit_exceeded, scope, window and retry_after_seconds. CONCURRENCY: heavy analytical calls (get_trends, search_ads, search_creatives) are admitted ONE AT A TIME per account — fanning out 5-10 of them in parallel does not go faster, it returns admission refusals for all but one. Issue heavy calls sequentially; light lookups (get_ad, get_advertiser, get_usage) are not gated. TIKTOK SOURCE: pass source="tiktok" to query the TIKTOK ad corpus instead of Meta. (The platforms filter does NOT do this — platforms are Meta publisher placements.) ⚠️ TIKTOK IS PAID PER ROW at a premium: every DELIVERED TikTok ad row costs 100 tokens and every TikTok webmaster row/card costs 100 tokens (Meta rows cost 1), deducted from the same token balance (free starter: 500 tokens total = 5 TikTok rows EVER; paid plans: 40,000/month = up to 400 TikTok rows). Request small limits and narrow filters; you are charged only for rows actually delivered (short pages auto-refund; if the balance covers only part of the request, that part is delivered — a 3-row request on a 150-token balance returns 1 row and charges 100). TikTok requires a Pro-or-higher plan: free/starter callers and unlinked agents get an actionable upgrade refusal, never data and never a charge. TikTok rows have their OWN shape, returned under tiktok_data (verified live 2026-07-30): id/external_id (TikTok ad id), advertiser{id,external_id,name} plus advertiser_id (TikTok BUSINESS id), start_date/end_date (the ad's delivery window) and first_seen_date/last_seen_date (SpyTrend indexing), days_active, is_active + status_today, ai_category/ai_subcategory, countries + targeting_geos + targeting_details (OS/age/gender/regions), audience_size, objective, sponsor (the 'paid for by' funder) and registry_location, landing_domain + link_url, body/title/call_to_action, creative_format, creative_id, creative_ad_count (how many ads reuse that creative), is_blurred/is_cloaked, and media[] with media_type + thumbnail_url on media-tt.spytrend.com. Media comes WITH the row — do NOT call get_media for TikTok ids (it serves Meta entities only). There are no TikTok engagement counters (plays/likes/comments/shares) on this surface. The TikTok feed serves the ARCHIVED TikTok corpus — exactly what the spytrend.com /ads TikTok tab shows — and pagination carries has_more/next_cursor plus total with total_status (exact unless ttads marks the count estimated). With source=tiktok rows are TikTok webmaster CLUSTERS (business-id rollup — the same entity the spytrend.com /webmaster TikTok tab shows; a different id space from ttads domain clusters). Honored filters: query (name/domain/cabinet legal names), domain, countries (+min_geo_share), ai_category (dominant category), min_total_ads, min_active_ads, date_from/date_to, sort_by=total_ads|active_ads|created_at|relevance, limit (default 10, server caps at 100 for TikTok). TikTok-only filter has_funder=true keeps only clusters with an EXTERNAL 'paid for by' sponsor. Meta-only lookups (pixel_id/page_id/resolved_ip, languages/platforms/creative_format, status_today, ai_subcategory, min_geo_share without countries) are REJECTED, not ignored. TikTok has no status-checker: active means 'shown within the last 30 days'.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNomax results (default 20; each delivered result costs 1 token).
queryNofree-text webmaster (affiliate) name to search for
savedNosaved scope selector. Use saved=all to restrict results to webmasters saved in ANY favourites folder.
domainNopoint lookup: webmasters on this landing domain
offsetNopagination offset — skip the first N rows. The /webmasters ranking pages by offset (not a cursor), so this is how a caller reaches page two and beyond. Max 5000.
sourceNowebmaster corpus: meta (default — Facebook/Meta networks, 1 token per delivered row) or tiktok (TikTok business-id clusters — ⚠️ PAID: 100 tokens per DELIVERED row; Pro plan required; default limit drops to 10, server caps TikTok at 100)
date_toNoonly webmasters active on or before this date (YYYY-MM-DD)
page_idNoexact current-ownership lookup by Facebook page id (a pasted facebook.com page link in any form is also accepted and resolved to the canonical page id); fanpages_status reports lifecycle coverage and available results include alive/deleted/banned/unknown lifecycle
sort_byNoorder by: total_ads (default), active_ads or relevance (relevance ranks by ad-VOLUME in the selected countries — geo-relevance; needs countries)
categoryNovertical filter: gambling or other
pixel_idNopoint lookup: webmasters using this Facebook pixel id
countriesNoISO country codes the webmaster's ads ran in
date_fromNoonly webmasters active on or after this date (YYYY-MM-DD)
folder_idNorestrict results to webmasters saved in this favourites folder UUID. Mirrors the /webmasters folder view.
languagesNolanguage codes filter
platformsNoplatform names filter (e.g. facebook, instagram)
has_funderNoTikTok only (source=tiktok): keep only clusters with an EXTERNAL 'paid for by' sponsor (the funded-by filter). Rejected for the Meta corpus.
sort_orderNosort direction: asc or desc (default desc)
ai_categoryNoAI category slug filter (e.g. gambling_and_betting)
resolved_ipNopoint lookup: webmasters whose domain resolves to this IP
status_todayNocurrent status: active, inactive or vanished
min_geo_shareNoGEO-RELEVANCE gate (0-1, the relevant-only toggle): keep only webmasters where the 'countries' you pass are at least this fraction of their ads — i.e. that geo is their DOMINANT geo (e.g. 0.5 = country >=50% of their ads). Without it, countries is a mere 'present-in' match and a webmaster with 0.5% of ads in BR ranks as a 'BR webmaster'. Requires countries. Each returned row's geo field carries the per-country ad-count breakdown so you can read the real exposure.
min_total_adsNoonly webmasters with at least this many total ads
ai_subcategoryNoAI subcategory slug filter
min_active_adsNoonly webmasters with at least this many ACTIVE ads
creative_formatNosingle creative format filter (legacy form). Prefer creative_formats[] — the visible /webmasters control is a multi-select.
creative_formatsNocreative formats to include (video, carousel, single, dynamic). Mirrors the visible /webmasters format multi-select.
exclude_countriesNoISO country codes to EXCLUDE — drops webmasters whose ads run in ANY of them. Mirrors the /webmasters geo EXCLUDE column; combine with countries to keep one market while removing noise markets.

Output Schema

ParametersJSON Schema
NameRequiredDescription
dataYes
metaNo
sourceNo
paginationYes
tiktok_dataNo

TDQS

A4.9/5.0
Behavior5/5

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

Annotations already mark the tool read-only and non-destructive, and the description goes far beyond that: it discloses token quotas and per-row costs, free-plan archive-window restrictions, per-user rate limits, one-at-a-time concurrency gating for heavy calls, current-membership matching semantics for exact lookups, and TikTok-specific row/charge behavior. No contradiction with the annotations exists.

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

Conciseness4/5

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

The description is well-organized with clear section markers (FREE PLAN COUNTS, QUOTA, CONCURRENCY, TIKTOK) and front-loads the core search workflow before edge cases. It is very long, though, and parts of the TikTok row-shape enumeration overlap what the output schema should already provide, so not every sentence earns its place.

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 28-parameter tool with quota, rate-limit, concurrency, and dual-corpus behavior, the description is exceptionally complete: it covers cost per delivered row, archive-window count semantics, error shapes, upgrade refusals, TikTok-only filters, and how to paginate. An agent has everything needed to invoke this tool correctly without guessing.

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 100%, so the schema already documents every parameter, but the description adds meaning the schema cannot convey: min_geo_share is explained as a geo-relevance dominance gate, sort_by=relevance is tied to country ad-volume, source is priced and plan-gated, and boolean/count filters get interpretation warnings. This materially helps an agent choose correct parameter values.

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?

The description opens with a specific verb and resource: 'Search webmasters (affiliates)', then defines a webmaster as an ad NETWORK. It also embeds the tool in an explicit downstream workflow ('search by domain, take the canonical UUID, then search_creatives/search_ads with webmaster_id'), which clearly distinguishes this search tool from sibling search/retrieval tools.

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?

The description gives concrete when-to-use guidance: search first, capture the canonical UUID, then pass webmaster_id to search_creatives/search_ads or get_webmaster.top_creatives. It also states when alternatives apply, distinguishes Meta vs TikTok corpus selection via source, and warns which filters are rejected for TikTok — explicit usage routing.

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

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 1 tool update
    • Changedsearch_ads2 fields changed
      • changedInput schema / properties / max_body_chars / description
        Previous value: -"only ads whose AD TEXT is at most this many characters long (UTF-8 characters, not bytes). Combine with min_body_chars for a closed length range, e.g. 100..500"New value: +"only ads whose AD TEXT is at most this many characters long (UTF-8 characters, not bytes). Ads with no text are NOT returned as length 0 — the length filters cover only ads with known non-empty text. Combine with min_body_chars for a closed length range, e.g. 100..500"
      • changedInput schema / properties / min_body_chars / description
        Previous value: -"only ads whose AD TEXT is at least this many characters long (UTF-8 characters, not bytes). Pairs with the body_chars field returned on every row; the ad text itself is served by get_ad, not by this list"New value: +"only ads whose AD TEXT is at least this many characters long (UTF-8 characters, not bytes). Both length filters match only ads whose text length is KNOWN and non-zero: ads with no text at all are outside the length axis entirely and are returned by neither direction. Pairs with the body_chars field returned on every row; the ad text itself is served by get_ad, not by this list"
  2. 21 tool updates
    • First observedadd_to_favorites
    • First observedfind_similar_ads
    • First observedfind_similar_creatives
    • First observedfind_similar_webmasters
    • First observedget_ad
    • First observedget_ads_analytics
    • First observedget_advertiser
    • First observedget_creative
    • First observedget_media
    • First observedget_shop
    • First observedget_trends
    • First observedget_usage
    • First observedget_webmaster
    • First observedget_webmaster_similarity_facets
    • First observedlist_favorites
    • First observedsearch_ads
    • First observedsearch_advertisers
    • First observedsearch_creatives
    • First observedsearch_hubs
    • First observedsearch_shops
    • First observedsearch_webmasters

Frequently Asked Questions

Discussions

No comments yet. Be the first to start the discussion!

Related MCP Connectors

Related MCP Servers

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

TDQS

A4.5/5.0
Disambiguation5/5

Each tool pairs a distinct action verb with a distinct entity type: search_* queries databases, get_* fetches single-entity cards, find_similar_* performs similarity lookups, and add_to_favorites/list_favorites handle saved items. The three find_similar tools explicitly cross-reference their differences (visual vs entity overlap vs URL-parameter), and get_adversus search_advertisers are clearly single-card vs typeahead.

Naming Consistency5/5

All 21 tools follow a consistent verb_noun snake_case pattern: six search_* tools, ten get_* tools, three find_similar_* tools, plus add_to_favorites and list_favorites. No camelCase, no mixed verb styles, and the similarity trio shares an identical prefix, making the set highly predictable.

Tool Count4/5

At 21 tools this is above the typical 3-15 sweet spot, but the server spans six entity domains (ads, creatives, advertisers, webmasters, hubs, shops) plus cross-cutting media delivery, favorites, trends, analytics, similarity and usage. Nearly every tool maps to a distinct workflow step, so the set feels dense rather than bloted.

Completeness4/5

The core lifecycle is fully covered: search every entity type, fetch detail cards, download media, save to favorites, list favorites back, plus trends, analytics, similarity and TikTok surfaces. The main gaps are a remove_from_favorites operation and a standalone hub detail card, neither of which blocks the primary ad-intelligence workflows.