Skip to main content
Glama

Server Details

Analytics, advertising: Facebook/Meta, TikTok, competitor ads. Free plan; Spytrend OAuth in browser

Ownership verified
Status
Healthy
Uptime
76.0% over 55 days
OAuth
Works in Glama
Last Tested
Transport
Streamable HTTP · MCP 2025-11-25
URL
Repository
Spytrend/spytrend-mcp
GitHub Stars
29
Server Listing
Spytrend MCP Server

TDQS

A4.1/5.0

Scored across 29 tools

Disambiguation4/5

The search_* / get_* / find_similar_* split maps cleanly onto list, entity-card and relatedness operations, and the descriptions explicitly fence off confusable pairs (search_ads vs search_creatives, find_similar_ads by overlap vs find_similar_creatives by visual similarity, get_trends vs get_ads_analytics). The main residual overlap is between search_ads and search_creatives plus the several vertical search tools (search_content, search_influencers, search_affiliate_offers, search_shops), which require careful reading rather than being instantly distinct. Overall an agent can almost always pick correctly, but it is not frictionless.

Naming Consistency5/5

Every tool is snake_case verb_noun (search_ads, get_shop, find_similar_creatives, add_to_favorites, estimate_cost, accept_pricing_terms), with no camelCase or bare-noun outliers. The prefixes also encode operation class consistently, so the name alone predicts the call shape.

Tool Count2/5

29 tools exceeds the comfortable band and splits into ten search surfaces (ads, creatives, advertisers, webmasters, shops, products, influencers, content, hubs, affiliate offers) plus ten get_* cards, several of which serve optional paid verticals that most callers never touch. The scope is genuinely broad rather than padded, but the surface is heavy enough to make selection and prompt overhead costly.

Completeness3/5

Core read paths (search -> get -> get_media, favorites, cost/quota, trends) are well covered, but estimate_cost repeatedly documents a Startups family (search_startups, get_startup, enrich_startups, get_startup_ads) that is absent from the tool set, leaving dangling references an agent will chase. Favorites are add-only: there is list_favorites and add_to_favorites but no remove/delete, so a saved-selection workflow has a dead end.

Available Tools

29 tools
accept_pricing_termsAccept the MCP pricing termsA
Idempotent
Inspect

Records the account's one-time consent to the current Spytrend MCP pricing (search price × number of filters, ×1 after 500 MCP credits a month). Paid tools refuse with pricing_consent_required until it is given. Call WITHOUT confirm to get the terms text and status; show the terms to the user and call with confirm=true and terms_version ONLY after the user explicitly agrees — never accept on the user's behalf. FREE — does not consume quota.

NameRequiredDescriptionDefault
confirmNotrue ONLY after the user explicitly agreed to the terms shown to them; omitted/false returns the terms and the consent status without recording anything
terms_versionNorequired with confirm=true: the terms version the user agreed to (from the terms text or get_usage.pricing.terms_version)

Output Schema

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

TDQS

A4.9/5.0
Behavior5/5

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

Annotations cover safety (idempotent, non-destructive, closed-world), and the description adds real context beyond them: the consent gate that blocks paid tools, the free/no-quota cost profile, and the no-argument mode that returns terms without recording anything. This is the kind of state-transition detail annotations cannot express.

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?

Front-loads the effect and the safety-critical instruction in four tight sentences; the parenthetical pricing formula is the only dense piece and it is relevant to informed consent. Nothing is redundant.

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?

Output schema exists, so return-value explanation is unnecessary; the description nonetheless covers both invocation modes, the prerequisite it unlocks, and the cost profile. An agent has everything needed to sequence the call 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 baseline would be 3, but the description reinforces the semantic distinction between the two modes (without confirm = read terms; with confirm = record) and ties terms_version to its source. It adds workflow meaning rather than restating types.

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 verb+resource ('Records the account's one-time consent to ... pricing') and frames the consent-gating role that no sibling tool shares. An agent can identify this as the prerequisite step for paid tools without opening any schema.

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?

Explicit two-step workflow: call without confirm to retrieve terms and status, then call with confirm=true and terms_version only after explicit user agreement. It also names the behavioral consequence (paid tools refuse with pricing_consent_required) and an explicit prohibition ('never accept on the user's behalf').

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

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 (including multilang) costs 1 MCP credit and saving a creative costs 10 MCP credits; saving does not include another ad media opening; saving a webmaster, a hub profile or a shop is FREE. Already-saved items cost nothing. PRICING: on paid plans ×1 after 500 MCP credits/month; one-time consent via accept_pricing_terms; before calling, get the maximum debit from estimate_cost (free) and tell the user.

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

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

TDQS

A4.6/5.0
Behavior5/5

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

Goes well beyond the annotations: explicit per-entity-type credit costs (1 for ad, 10 for creative, free for webmaster/hub/shop), the fact that already-saved items are never duplicated or re-charged, and the one-time consent/pricing multiplier rule. Annotations only assert idempotency generically; the description explains the observable behavior (already_saved reporting) and the cost consequences.

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?

Front-loads what is saved and where, then dependencies, then billing — a sensible order. It is dense but every clause carries operational information; the main inefficiency is duplicated entity-type enumerations that also appear in 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?

An output schema exists so return values need no explanation, and the description covers everything else an agent needs: valid entity types, id source, the conditional hub parameter, folder defaults, idempotency, and the full billing/consent workflow.

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 cross-parameter logic (hub is REQUIRED only when entity_type=hub) and actionable guidance on folder naming ('PREFER a short descriptive name from the user's search', dated fallback). Some sentences restate schema text verbatim, which caps it below 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?

Opens with a specific verb and resource ('Save a SELECTION of entities to one of the caller's favourites folders'), states the downstream purpose (review later on spytrend.com), and enumerates the entity types. It is clearly distinguishable from the read-side sibling list_favorites.

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?

Gives concrete prerequisites: ids must come from the search_* tools, hub slug is mandatory for entity_type=hub, and estimate_cost must be called before invoking with pricing terms accepted. It doesn't name an explicit alternative or when-not-to-use, but the conditions for correct use are clear.

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

estimate_costEstimate the cost of a callA
Read-onlyIdempotent
Inspect

FREE pre-call estimate. Pass the paid tool you are about to call and exactly its arguments; returns max_tokens — the most that call can debit at the account's current balance under the current pricing (filters × monthly step), with the factors used. Call it BEFORE every paid call and tell the user the number. For searches it is an upper bound: only delivered rows are charged, undelivered ones are refunded. For the Startups tools (search_startups, get_startup, enrich_startups, get_startup_ads and the rest) it returns max_objects (Startups objects: 1 per row, 5 per company card) and the subscription's objects_remaining this month instead of MCP credits. Does not run the tool and does not consume quota.

NameRequiredDescriptionDefault
toolYesthe paid tool you are about to call, e.g. search_ads
argumentsNoexactly the arguments you will pass to that tool

Output Schema

NameRequiredDescription
freeNo
noteNo
toolNo
unitNo
usedNo
errorNoPresent only when isError is true: machine-readable failure. The human explanation stays in content.
paramsNoRequest parameter echo: applied = parameters that shaped this result; normalized = parameters rewritten before applying (alias, type coercion, resolved id); ignored = parameters that were accepted but NOT applied, with the reason.
filtersNo
max_unitsNo
remainingNo
max_tokensNo
multiplierNo
unit_priceNo
addon_hintsNoAdd-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about.
max_objectsNo
upper_boundNo
filter_factorNo
consent_statusNo
threshold_factorNo
objects_remainingNo

TDQS

A4.8/5.0
Behavior5/5

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

Beyond readOnlyHint/destructiveHint=false, it discloses that the tool does not execute the target and consumes no quota, that the estimate is a maximum bounded by current balance, that the pricing is 'filters × monthly step', and that undelivered search rows are refunded. These are the exact behavioral facts needed to trust and quote the number.

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?

Front-loaded with FREE and the return value; every sentence carries content (refunds, pricing formula, Startups exception, non-execution). Slightly dense, with one heavily parenthesized sentence, but 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?

Covers the tricky parts an agent would otherwise get wrong: what the number means (a max/upper bound, not a charge), the refund rule for undelivered rows, and the alternate accounting model for Startups tools. Output schema exists, so return-shape detail is appropriately left out.

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% and already documents both parameters with an example, so the description only needs to reinforce. It does add useful framing — the arguments must be *exactly* those of the upcoming call, and it enumerates which tool families expect max_objects rather than max_tokens — which goes slightly beyond the schema text.

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 verb and resource ('pre-call estimate' of a tool call's cost) and immediately names the return value (max_tokens) plus its Startups variant (max_objects). An agent can distinguish it from get_usage or any paid search sibling without opening a schema.

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?

'Call it BEFORE every paid call and tell the user the number' gives an explicit trigger and a required follow-up action. It also scopes the behavior per tool family (searches = upper bound, Startups tools = objects model), so the agent knows what changes when the target tool differs.

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 MCP credit per delivered row (default page 20). PRICING: on paid plans ×1 after 500 MCP credits/month; one-time consent via accept_pricing_terms; before calling, get the maximum debit from estimate_cost (free) and tell the user.

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 MCP credit per delivered row)
cursorNopagination cursor returned by the previous call

Output Schema

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

TDQS

A4.6/5.0
Behavior5/5

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

Annotations only cover the safety profile (readOnly/openWorld/non-destructive); the description adds quota cost per delivered row, tiered pricing, consent requirement, and a non-obvious pagination caveat. The total-semantics disclosure (total is the upstream candidate count, source ad excluded, source_excluded/total_semantics fields expose that) is exactly the kind of behavior annotations cannot convey.

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?

Front-loaded with purpose and the sibling distinction, then behavioral caveats, then commercial terms — a sensible order. Slightly dense and the fanpage/domain basis is restated a second time, but nearly every clause carries decision-relevant 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?

Output schema exists so return values need not be explained, and the description still covers the one return-value subtlety that would mislead (the unadjusted total). For a paginated, quota-metered read tool with four simple params, nothing an agent needs before calling 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?

Schema coverage is 100% and already documents ad_id, basis, limit and cursor including the enum meanings, so the description's restatement of the fanpage/domain basis adds little. It does not explain the interaction between limit and credit cost beyond what the schema row says. Baseline 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?

States a specific verb ('find ads related to one source ad') plus the exact overlap bases (fanpage page_id, exact landing_domain), and explicitly separates itself from find_similar_creatives ('entity overlap, NOT visual similarity'). An agent can route between the two siblings without opening either schema.

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

Usage Guidelines5/5

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

Gives an explicit alternative ('use find_similar_creatives for that'), a pre-call prerequisite chain (estimate_cost for the max debit, accept_pricing_terms for consent, inform the user), and when-not-to-use via the visual-similarity exclusion. This is the full when/when-not/alternatives package.

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 MCP credit per delivered row. PRICING: on paid plans ×1 after 500 MCP credits/month; one-time consent via accept_pricing_terms; before calling, get the maximum debit from estimate_cost (free) and tell the user.

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

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

TDQS

A4.6/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 upstream 20-candidate cap and that has_more is conservative at that cap, explains threshold_status and result_status semantics, warns that no media URLs are returned, and lays out quota (1 credit/row) and pricing (×1 after 500 credits/month). This is unusually rich behavioral context for an agent to reason about cost and result completeness.

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?

Front-loaded with the core purpose and the key disambiguation (visual vs membership) before the operational notes. Dense but every sentence carries information; the status-code explanations add length though a slightly tighter phrasing could carry the same signal.

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 exists, so return values needn't be re-explained; instead the description covers the operational gaps an agent would otherwise stumble on — the 20-row native cap, conservative has_more, absence of media URLs, and the quota/pricing/consent path. Complete for a 3-param, capped similarity search.

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 creative_id, limit, and threshold are already documented including defaults and max values. The description adds marginal framing (threshold_status distinguishes explicit vs default) but no new parameter syntax or format beyond the schema. Baseline 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?

States a specific verb and resource ('Find creatives that look the same as one creative') and explicitly scopes it as visual similarity rather than exact creative membership. It also names sibling tools (search_creatives for the source id, get_media for media) so the agent can place it in the tool graph immediately.

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?

Explicitly distinguishes the use case from exact-membership lookups, directs the agent to get_media for selected ids, and prescribes the pricing workflow ('get the maximum debit from estimate_cost (free) and tell the user' plus one-time accept_pricing_terms consent). When/when-not guidance and alternatives are both present.

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 MCP credit per delivered row (default page 20). PRICING: on paid plans ×1 after 500 MCP credits/month; one-time consent via accept_pricing_terms; before calling, get the maximum debit from estimate_cost (free) and tell the user.

NameRequiredDescriptionDefault
limitNomaximum rows to return (default 20, maximum 200; 1 MCP credit 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

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

TDQS

A4.6/5.0
Behavior5/5

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

Beyond the readOnly/openWorld/non-destructive annotations, it discloses deterministic ordering, a 5000-row canonical cap, how result_status/result_cap/total_status signal completeness of the bounded set, and the credit/quota model (1 credit per delivered row, ×1 after 500/month). These are exactly the operational facts an agent needs before calling a metered tool.

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 core behavior and the prerequisite tool lead, followed by result-shape, then QUOTA/PRICING blocks. It is dense and mostly earns its space, though the pricing paragraph is long relative to the reminder value it adds.

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?

Covers workflow prerequisite, result-set bounding semantics, ordering determinism, cost model, and consent requirement; an output schema exists, so return values need no further explanation. Nothing an agent needs to invoke this correctly 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?

Schema description coverage is 100%, so the schema already documents limit, offset, values, param_key, and webmaster_id. The description only reinforces provenance ('pass one returned param_key', 'optionally narrow to selected values'), so it meets but does not exceed the baseline when the schema does the heavy lifting.

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 verb and resource ('Find other webmasters sharing normalized URL-parameter values with a source webmaster') and scopes it to the URL-parameter-overlap basis, which cleanly separates it from sibling similarity tools like find_similar_ads and find_similar_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?

Explicitly gives the required workflow ('First call get_webmaster_similarity_facets, then pass one returned param_key'), the optional narrowing step, and the pre-call pricing sequence (estimate_cost for max debit, accept_pricing_terms consent, tell the user). Alternatives and prerequisites are all named.

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, 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 may be issued to your account for a limited time — download them promptly rather than storing them, and call get_ad again when a link stops working; a media entry with expiring=true is the original signed Facebook CDN link of a not-yet-mirrored fresh ad — it may die even sooner (re-fetch the ad later for our mirrored link). QUOTA: 50 MCP credits for a multilang-upload ad opening; 1 MCP credit for an ordinary ad. The price includes the available media returned with this card. Each new opening call is charged separately; no subscription to an individual ad is created. A blurred card or a response without usable media is not charged. With source=tiktok: 10 MCP credits per delivered TikTok row. MULTILANG CONTENT: get_ad and get_media(ad) use the same full detail carousel. primary_creative identifies its selected first creative; primary_creative_selection.status describes selected, fallback or unavailable. carousel_position is the original 1-based carousel position, not the returned array index. Missing/unconfirmed selected primary media is not charged or disclosed; both tools report primary_creative_unavailable. Per-slide title/body/link_url describe that slide; when the API omits a slide override, the ad-level value is supplied as its fallback, consistently in both tools. original_landing_domain describes the original ad, while creative_destination_url/domain describe the primary creative's destination. cloaking_detected is a detected domain/copy mismatch, not a verified redirect or a guarantee that a creative is black. Actual per-call debit is reported in _meta.billing.tokens_charged, in Spytrend quota MCP credits (not model tokens); admin may be exempt. PRICING: on paid plans ×1 after 500 MCP credits/month; one-time consent via accept_pricing_terms; before calling, get the maximum debit from estimate_cost (free) and tell the user.

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

Output Schema

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

TDQS

A4.3/5.0
Behavior5/5

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

Annotations already mark this as read-only, open-world, and non-destructive, but the description adds substantial behavioral detail beyond them: quota and billing mechanics, absence semantics for body and body_chars, expiring media links, TikTok pricing, multilang carousel behavior, primary creative status, and cloaking caveats. It does not contradict 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.

Conciseness3/5

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

The description is front-loaded with the core purpose, but it is very dense and lengthy, with repeated billing and pricing explanations across multiple sections. The information is relevant, yet some sentences could be tightened or consolidated without losing necessary meaning.

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, output schema, annotations, and billing behavior, the description is complete enough to guide correct invocation. It covers media lifetime, quota, billing reconciliation via _meta.billing, multilang content semantics, and primary creative handling, so an agent has the operational context it needs.

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?

The schema has 100% description coverage for both parameters, including the source enum and its TikTok credit implications, so the schema already does most of the work. The description reinforces source=tiktok pricing and id provenance, but adds limited parameter-specific meaning beyond 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?

The opening sentence states a specific verb and resource: fetch a single ad by id with full details and creative media. It also names the relevant sibling relationship by noting that get_ad and get_media(ad) share the same full detail carousel, which helps an agent distinguish the 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 gives clear operational context: call estimate_cost before invoking, accept pricing terms once, re-fetch when media links expire, and note TikTok-specific credit costs. It does not explicitly say when to prefer get_ad over get_media or search_ads in all cases, but it provides enough routing context for correct use.

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 MCP credit, 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. PRICING: price × number of filters set (min 1), on paid plans ×1 after 500 MCP credits/month; one-time consent via accept_pricing_terms; before calling, get the maximum debit from estimate_cost (free) and tell the user.

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 MCP credit-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

NameRequiredDescription
winNo
dataNo
tierNo
errorNoPresent only when isError is true: machine-readable failure. The human explanation stays in content.
totalNo
paramsNoRequest parameter echo: applied = parameters that shaped this result; normalized = parameters rewritten before applying (alias, type coercion, resolved id); ignored = parameters that were accepted but NOT applied, with the reason.
domainsNo
pendingNo
statusesNo
countriesNo
ai_labeledNo
from_cacheNo
scope_noteNo
webmastersNo
addon_hintsNoAdd-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about.
advertisersNo
computed_atNo
total_statusNo
ai_categoriesNo
display_totalNo
result_statusNo
sections_readyNo
sections_totalNo
display_total_basisNo
retry_after_secondsNo
display_total_statusNo
auto_applied_verticalsNo

TDQS

A4.3/5.0
Behavior5/5

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

Goes well beyond the readOnlyHint/destructiveHint annotations by disclosing the credit cost per breakdown row, reservation-and-refund behavior, the row cap, flattened-with-dimension result shape, nullable totals semantics (null pending vs numeric 0), the status-section filter exception, and the retry protocol. This is unusually full behavioral disclosure for a paid read surface.

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?

Front-loads the core purpose, then cost, then retry/pricing, so an agent can decide early. It is dense and abbreviation-heavy (Pro-or-higher, PRICING block), and the 20-row cap is stated twice, but nearly every sentence carries operative 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?

Output schema exists, yet the description still supplies what matters for correct invocation: pricing model, credit reservation, nullability rules, truncation metadata, and the retry path. Nothing an agent needs to call this correctly and warn the user about cost appears 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 already 100%, so the baseline is 3; the description earns above that by clarifying max_items_per_section bounds and default, and by stating which parameters are deliberately rejected. It still leaves the 49 filter params to the schema rather than explaining filter interactions or date semantics.

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

Purpose4/5

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

Names a specific verb and resource (analytics overview for the current Meta /ads selection) and enumerates exactly which breakdown dimensions come back. It implicitly separates itself from search_* siblings by scoping to an already-made selection, but never names those alternatives explicitly.

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?

Gives concrete operational guidance: check estimate_cost first, obtain consent via accept_pricing_terms, re-issue the identical call after retry_after_seconds on pending, and don't blindly retry paid calls. It also lists what is not accepted (pagination, sorting, TikTok, raw SQL, etc.), but never explicitly contrasts when to choose this over search_ads or get_trends.

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 MCP credit (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. PRICING: on paid plans ×1 after 500 MCP credits/month; one-time consent via accept_pricing_terms; before calling, get the maximum debit from estimate_cost (free) and tell the user.

NameRequiredDescriptionDefault
idYesthe resource id to fetch

Output Schema

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

TDQS

A4.9/5.0
Behavior5/5

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

Annotations already cover the read-only/non-destructive profile, and the description adds substantially more: exact quota cost (1 MCP credit), paid-plan multiplier and 500-credit threshold, one-time consent via accept_pricing_terms, ID auto-resolution behavior, and detailed contracts about what category_total_ads and top_creatives[].total_ads actually count. This is well beyond what annotations or schema disclose.

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?

Front-loaded with purpose and the field list, then ID resolution, then the category-counter contract, quota, top_creatives contract, and pricing. Each block earns its place, though the ALL-CAPS emphasis and repeated contract caveats make it denser than strictly necessary.

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?

Despite an output schema existing, the description explains the return payload's semantics (what total_ads/active_ads mean, what top_creatives' total_ads counts, how ai_coverage interacts with category counters) — precisely the interpretive context an agent needs to avoid misreporting. Nothing material 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?

The schema only says 'the resource id to fetch' despite 100% coverage, but the description compensates heavily: the id may be an advertiser UUID (from an ad's advertiser_id or get_trends dimension=advertisers), a Facebook page id (from get_creative's fanpages or an ad's page_id), or a pasted facebook.com URL in any form — all auto-resolved. That is far more actionable than the schema text.

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 verb and resource ('Fetch a single advertiser's FULL card by id') and enumerates the exact fields returned (name, external_id, total_ads, active_ads, top_countries, etc.), making it unmistakable against siblings like search_advertisers or get_ad. It also explicitly contrasts its exact precomputed counts with search_ads' estimated totals.

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

Usage Guidelines5/5

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

Gives explicit routing: 'To list the advertiser's ads, call search_ads with advertiser_id', and warns not to paginate search_ads just to count ads. It also prescribes a pre-call workflow ('get the maximum debit from estimate_cost (free) and tell the user'), naming the sibling tool to use.

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 MCP credit (one entity card). PRICING: on paid plans ×1 after 500 MCP credits/month; one-time consent via accept_pricing_terms; before calling, get the maximum debit from estimate_cost (free) and tell the user.

NameRequiredDescriptionDefault
idYesthe resource id to fetch

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

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

The annotations already establish readOnlyHint=true and destructiveHint=false, but the description adds substantial behavior beyond them: it says transcription is never started, describes bounded breakdown truncation and status aggregation, explains copy_language provenance/confidence states, and gives quota/pricing behavior. These details materially help an agent interpret and safely invoke the tool.

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 remains organized around behavior, id/media guidance, and pricing. It is dense and includes some return-status detail that could be tightened, especially given the output schema, but most of the content is relevant to correct invocation.

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 existing output schema, and annotations, the description is highly complete. It covers what is returned, truncation/status behavior, language-transcript caveats, id provenance, media alternatives, and pricing prerequisites.

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% and the schema already defines the single required id parameter generically. The description adds useful meaning by specifying that the id is a creative UUID from search_creatives, improving parameter semantics beyond 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?

The description uses a specific verb/resource pair, 'Fetch ONE creative's metadata plus its canonical bounded breakdown by id,' and enumerates the included breakdown dimensions. It clearly distinguishes this tool from media retrieval by saying media URLs are excluded and should be downloaded with get_media.

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 explains that the id is a creative UUID from search_creatives, names get_media as the alternative for media downloads, and gives pre-call pricing guidance via estimate_cost. It does not explicitly compare when to choose this over other creative/ad detail siblings, but the usage context is clear enough.

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

get_influencerGet influencer cardA
Read-only
Inspect

Fetch one creator card from the influencer directory by platform (youtube or instagram) and slug (as returned by search_influencers). Same fields as a search row plus checked_at (YouTube: when the channel was last re-read), channel_created_at, long_video_count, shorts_count, last_short_at (YouTube) and following, markets (Instagram). CONTACTS, BIOS, VIDEOS AND POSTS ARE NEVER RETURNED — has_email is only a yes/no. Free accounts can open a limited number of cards per day. QUOTA: 1 MCP credit (one entity card). PRICING: on paid plans ×1 after 500 MCP credits/month; one-time consent via accept_pricing_terms; before calling, get the maximum debit from estimate_cost (free) and tell the user.

NameRequiredDescriptionDefault
slugYesthe creator slug as returned by search_influencers
platformYesyoutube or instagram

Output Schema

NameRequiredDescription
urlNo
nameNo
slugNo
errorNoPresent only when isError is true: machine-readable failure. The human explanation stays in content.
nicheNo
paramsNoRequest parameter echo: applied = parameters that shaped this result; normalized = parameters rewritten before applying (alias, type coercion, resolved id); ignored = parameters that were accepted but NOT applied, with the reason.
countryNo
marketsNo
categoryNo
platformNo
usernameNo
avg_viewsNo
followersNo
followingNo
has_emailNo
lang_hintNo
checked_atNo
addon_hintsNoAdd-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about.
count_viewsNo
is_verifiedNo
media_countNo
last_post_atNo
shorts_countNo
stats_hiddenNo
last_short_atNo
last_video_atNo
long_video_countNo
channel_created_atNo

TDQS

A4.6/5.0
Behavior5/5

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

Beyond the readOnly/openWorld annotations, the description discloses negative behavior ('CONTACTS, BIOS, VIDEOS AND POSTS ARE NEVER RETURNED — has_email is only a yes/no'), per-platform field availability, daily free-tier limits, credit cost, and pricing escalation. These are behavioral facts nothing in the annotations or schema conveys.

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 core capability and field list are front-loaded, and the all-caps warnings about withheld data earn their emphasis. The QUOTA/PRICING block is verbose and partly instructional policy rather than tool semantics, but it remains dense and purposeful rather than 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 two-param, read-only lookup with an output schema, the description covers cost, consent, rate limits, and the field-difference between platforms. The only mild redundancy is restating return fields that the output schema already defines, which does more good than harm for a paid tool.

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% and both parameters are enum/typed with their own descriptions, so the schema does the heavy lifting. The description reinforces that slug comes from search_influencers and that platform drives which return fields appear (YouTube-only vs Instagram-only), which is useful but marginal at the parameter level.

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 creator card from the influencer directory') and states the exact addressing scheme (platform + slug). It explicitly contrasts with search_influencers by saying the card has 'the same fields as a search row plus' extras, so an agent can distinguish it from the sibling search tool without opening either schema.

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 specifies the prerequisite ('slug as returned by search_influencers'), the access constraints ('Free accounts can open a limited number of cards per day'), and a concrete pre-call sequence: get max debit from estimate_cost (free), tell the user, then one-time consent via accept_pricing_terms. That is explicit when-to-use and how-to-prepare guidance referencing the correct siblings.

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 media URL can become unavailable, 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, 1 MCP credit per row) → pick ids → get_media. QUOTA: 50 MCP credits per delivered multilang-upload ad, 1 per ordinary ad, 10 per creative-catalogue item (free starter: 500 MCP credits total; paid plans: 40,000/month). The ad price is per returned ad, not per media file. Actual ad membership determines the price even without a preceding filtered search. Every new call is billed; get_ad already includes media, so do not call get_media again for files you already received. Invalid, missing or undelivered items are not charged. Mixed batches examine a quota-bounded prefix and return affordable items with explicit failures for the rest; an unexamined tail may contain affordable ordinary ads, which can be requested separately. get_usage is free. MULTILANG CONTENT: get_ad and get_media(ad) use the same full detail carousel. primary_creative identifies its selected first creative; primary_creative_selection.status describes selected, fallback or unavailable. carousel_position is the original 1-based carousel position, not the returned array index. Missing/unconfirmed selected primary media is not charged or disclosed; both tools report primary_creative_unavailable. Per-slide title/body/link_url describe that slide; when the API omits a slide override, the ad-level value is supplied as its fallback, consistently in both tools. original_landing_domain describes the original ad, while creative_destination_url/domain describe the primary creative's destination. cloaking_detected is a detected domain/copy mismatch, not a verified redirect or a guarantee that a creative is black. Actual per-call debit is reported in _meta.billing.tokens_charged, in Spytrend quota MCP credits (not model tokens); admin may be exempt. PRICING: on paid plans ×1 after 500 MCP credits/month; one-time consent via accept_pricing_terms; before calling, get the maximum debit from estimate_cost (free) and tell the user.

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

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

TDQS

A4.6/5.0
Behavior5/5

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

Annotations only declare readOnly/openWorld/destructive=false; the description adds the non-obvious economics and failure semantics: per-delivered-item quota costs (50/1/10 credits), duplicate ids fetched and billed once, malformed ids never consuming quota, partial batch behavior, and a quota-bounded prefix with an unexamined tail. It also gives an operational rule to retry fallback_urls on 416/404 before treating a URL as unavailable.

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?

Purpose is front-loaded, but the body is a ~350-word run-on wall covering quota tables, multilang carousel semantics, cloaking detection, and _meta.billing details for a two-parameter tool. Several passages (carousel_position, cloaking_detected, original_landing_domain) are far from the tool's stated job and bury the actionable parts.

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?

Despite an output schema, the description states the return shape, additive counts, partial/failure reporting and duplicate_count, so an agent can interpret results without guessing. Pricing, retry and batch-partiality behavior cover everything needed to call it 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 baseline is 3; the description still adds value by tying 'ad' to search_ads results and 'creo' to search_creatives, and by explaining that malformed/zero UUIDs are reported per item without billing and that duplicates are canonicalized. It stops short of describing id format beyond 'UUID', which the schema already covers.

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 opening sentence gives a specific verb, resource, output shape (image/video URL + thumbnail) and the exact id domain (1-500 UUIDs from search_ads / search_creatives). It also explicitly differentiates from sibling get_ad by stating get_ad already includes media.

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 states the typical flow (search_ads → pick ids → get_media), an explicit when-not-to-use rule ('do not call get_media again for files you already received'), and prerequisites ('before calling, get the maximum debit from estimate_cost (free) and tell the user', one-time consent via accept_pricing_terms). Alternatives and exclusions are both present.

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, with its embedded products paged by products_offset/products_limit (20 by default, at most 50). products_page reports embedded_total, has_more and next_offset; follow it to retrieve every embedded product without losing its fields. products_total counts the product pages of the whole catalog, not embedded_total; use search_products to browse the rest of the catalog. 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. Its active_ads/total_ads count the Meta ads of the WHOLE domain; the product / best-seller list carries no per-product ad counts — call search_products with domain= for per-product numbers. To save it use add_to_favorites (entity_type=shop, ids=[domain]). COUNTS: every count is ONE network over ONE window — never add counts together, never derive a new count, and never present a sum across networks or windows as the domain's total. active_ads / total_ads = Meta (Facebook/Instagram) ads of the whole domain: active now / all time. ads_last_month / ads_prev_month = Meta ads first seen in our data in the last / the previous complete calendar month. ads_active_7d / ads_active_14d / ads_active_28d = Meta ads that were active 7 / 14 / 28 days ago; launches_7d / launches_28d = Meta ad launches counted for the shop over the last 7 / 28 days. google_ads / google_ads_active = Google ads: all published / active now. tt_ads / tt_ads_30d = TikTok ads: all time / active in the last 30 days. The Google and TikTok fields are omitted when no ads of that network were found for the domain. ads_geo[] is per targeted country: ads = Meta ads targeting that country, share = that count over an internal row count of the domain (not total_ads); one ad targets several countries, so ads_geo rows overlap and shares do not add up to 1 — never divide ads by share, never add ads_geo rows, ads_monthly or ads_burn months into a total: the all-time Meta total is total_ads. To describe ads across networks, name each network with its own number and window. Product counts are different fields — product_count is the shop's catalog: the number of UNIQUE products, where several product pages (URLs/handles) of one product, such as a -1 copy or a funnel duplicate, count once (merged by brand and title); only when our product data is smaller than the site crawler's counter is product_count that crawler counter. products_unique = unique products in our data, products_total = product pages (URLs) of the shop in our data, duplicates of one product included, catalog_size_true = catalog size from the sitemap (0 = unknown): call product_count the catalog and quote any other field by its meaning; products is a SAMPLE of the catalog's pages (best-sellers first) — its length is not a product count. A number with no field here is not available: say it is not available instead of computing it. QUOTA: 1 MCP credit (one entity card). PRICING: on paid plans ×1 after 500 MCP credits/month; one-time consent via accept_pricing_terms; before calling, get the maximum debit from estimate_cost (free) and tell the user.

NameRequiredDescriptionDefault
domainYesthe shop domain to fetch (e.g. 'example.com'), as returned by search_shops
products_limitNonumber of embedded products per page (default 20, maximum 50); all other shop profile fields remain present on each page
products_offsetNozero-based offset into the embedded products list; use products_page.next_offset to retrieve the next page

Output Schema

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

TDQS

A4.7/5.0
Behavior5/5

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

Beyond the readOnly/openWorld annotations, the description discloses extensive behavior: paging via products_page, what embedded_total vs products_total mean, count non-additivity rules, provenance caveats for domain_created and traffic fields, sample-vs-catalog distinctions, and quota/pricing considerations. These are substantive operational details an agent would otherwise miss.

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 definition is front-loaded with a clear purpose sentence and uses some headings for COUNTS, QUOTA, and PRICING, so it is not unstructured. However, it is extremely long and dense, with many run-on caveats and repeated non-additivity warnings that could be tightened or moved into field documentation.

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 rich annotations, the description is more than complete. It covers purpose, paging, field semantics, count pitfalls, provenance limits, alternatives, quota, and pricing so an agent has enough context to call it 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 description coverage is 100%, so the baseline is 3, but the description adds useful paging semantics beyond the schema: products are paged by products_offset/products_limit, products_page exposes next_offset, and all other profile fields remain present on each page. It does not add much about the domain parameter beyond what the schema already says.

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 first sentence states a specific verb and resource: 'Fetch one domain surface's full profile' with embedded products. It scopes the tool to a single domain surface and later distinguishes it from catalog-wide browsing via search_products.

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 routes agents to alternatives: use search_products to browse the rest of the catalog, call search_products with domain=<domain> for per-product ad numbers, and use add_to_favorites to save the shop. It also gives a prerequisite workflow for estimate_cost and accept_pricing_terms before calling.

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, MCP credits used, remaining and limit (free starter = 500 MCP credits total forever; paid plans = 40,000/month ≈ 2,000 default-page searches; Enterprise = personal limit via support). MCP credit costs: 1 per delivered result (an ad/webmaster/advertiser row, a trends row, an entity card), ordinary ad media = 1, multilang-upload ad opening = 50, creative media = 10, TikTok row = 10. Each opening call is billed separately. You pay only for results actually delivered (short pages auto-refund). This call is FREE — it consumes no quota.

NameRequiredDescriptionDefault

No parameters

Output Schema

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

TDQS

A4.4/5.0
Behavior5/5

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

Goes well beyond the readOnly/idempotent annotations by disclosing that the call is free and consumes no quota, that billing is per delivered result, that short pages auto-refund, and per-item credit costs. This is exactly the kind of behavioral context annotations cannot convey.

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?

Front-loads what the tool returns, then explains credits. The credit-cost enumeration is dense but relevant to interpreting the returned numbers; slightly verbose for a quota lookup but each sentence carries 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?

An output schema exists so return values needn't be described, yet the description still tells the agent how to interpret plan tiers and credit numbers. Nothing needed to call or interpret this zero-param tool 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 tool takes zero parameters, so parameter semantics baseline is 4. Nothing to explain, and the description does not waste space on nonexistent inputs.

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 verb+resource ('Return the caller's current MCP quota') and enumerates exactly what is returned: plan, credits used, remaining, limit. An agent can distinguish this from estimate_cost or any search tool without opening the schema.

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

Usage Guidelines3/5

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

The context of checking quota before spending credits is implied by the pricing detail, but there is no explicit 'use this before/after X' or reference to the sibling estimate_cost tool. Usage is inferable but not stated.

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

get_web2app_marketWeb2App market summaryA
Read-only
Inspect

PAID ADD-ON «Web2App» (MCP comes with the annual plan). Summary of the web2app (quiz-to-paywall) advertising market from the Spytrend ad base: ads by brand, category, domain, page, country, language or month, with month range and filters. Without the add-on the call is refused; a monthly «site» subscriber is told that MCP access is part of the annual plan. QUOTA: 1 MCP credit per call; summaries are not limited by the section row allowance. The funnels themselves (quiz screens, paywall, prices) are NOT returned through MCP: every row carries funnels_url — the funnels of that brand / category / domain / page / language in the Spytrend library, which the account owner opens on the site to view and download them. PRICING: on paid plans ×1 after 500 MCP credits/month; one-time consent via accept_pricing_terms; before calling, get the maximum debit from estimate_cost (free) and tell the user.

NameRequiredDescriptionDefault
qNofree-text filter over brands and domains
toNolast month YYYY-MM
geoNoISO-2 countries (OR)
fromNofirst month YYYY-MM
brandNobrands (OR)
groupNobreakdown: brand (default), category, domain, page, geo, lang or month
limitNorows, 1-100 (default 25)
categoryNoweb2app categories (OR)

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.1/5.0
Behavior5/5

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

Beyond the readOnly/openWorld annotations it discloses quota cost (1 MCP credit per call), that summaries escape the section row allowance, the pricing multiplier after 500 credits/month, the consent requirement, and crucially that funnel contents are NOT returned but every row carries funnels_url. This is exactly the extra context annotations cannot carry.

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

Conciseness4/5

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

Dense and front-loaded: access gating first, then quota, then the funnels_url limitation, then pricing. The ALL-CAPS section labels make it scannable, but the description is long and a few clauses (e.g. the subscriber explanation) could be tightened.

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 exists so return values need no explanation, yet the description still flags the one return-value nuance an agent must relay (funnels_url instead of funnel data). Combined with quota, consent and pricing prerequisites, an agent has everything needed to call it correctly and set user expectations.

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. The description restates the breakdown dimensions available (brand, category, domain, page, country, language, month) matching the group parameter and mentions 'with month range and filters', but adds no format or interplay details beyond the schema.

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

Purpose4/5

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

States concretely that it returns a summary of the web2app (quiz-to-paywall) ad market from the Spytrend ad base, with the dimensions available (brand, category, domain, page, country, language, month). It is distinguishable from generic ad-search siblings by the explicit quiz-to-paywall framing, though it never names a sibling it competes with.

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?

Gives explicit preconditions and a workflow: the call is refused without the annual-plan add-on, a monthly 'site' subscriber is told MCP requires the annual plan, and the agent must call estimate_cost first and obtain accept_pricing_terms consent. It lacks explicit 'use X instead when Y' routing against siblings, so it falls 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_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 MCP credit (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 10 MCP credits and requires a Pro-or-higher plan; the Meta-only embeds (top_creatives, attribution link-stats) are omitted on the TikTok card. PRICING: on paid plans ×1 after 500 MCP credits/month; one-time consent via accept_pricing_terms; before calling, get the maximum debit from estimate_cost (free) and tell the user.

NameRequiredDescriptionDefault
idYesthe webmaster UUID (from search_webmasters — same id space for both corpora)
sourceNowebmaster corpus: meta (default, FREE) or tiktok (⚠️ 10 MCP credits for the TikTok cluster card; Pro plan required)
date_toNowindow end YYYY-MM-DD
countriesNoISO-2 codes, comma separated: recompute the card for these geos, as the site does
date_fromNowindow start YYYY-MM-DD; with a window the card returns windowed counters, exactly like the site

Output Schema

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

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, non-destructive, and open-world, but the description adds substantial behavioral context: analytics_pending semantics, fanpages_status caveats, total_ads interpretation, quota/pricing, consent, and TikTok plan/cost differences. There is 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.

Conciseness4/5

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

The answer is front-loaded with the core purpose and headline output, and most sentences carry necessary caveats for a complex analytics card. It is dense and long, but the length is largely justified by the tool's many behavioral edge cases.

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 rich annotations, full schema coverage, and output schema, the description is complete enough for correct invocation. It covers identity constraints, alternate corpora, pricing, quota, and interpretation guidance for the returned analytics.

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%, but the description still adds decision-relevant meaning: id must be the canonical UUID from search_webmasters and domain/display names are rejected; source switches corpus and cost; date window and countries change the returned card behavior.

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 a single webmaster by UUID, returning aggregate stats plus top_creatives. It clearly distinguishes the entity-card fetch from sibling search tools and explains the headline output.

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 the agent: use search_webmasters to obtain the canonical UUID, use search_creatives?webmaster_id or search_ads?webmaster_id for the rest of the network, and get_media for downloads. It also gives the TikTok alternative and its different cost/plan requirements.

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.

NameRequiredDescriptionDefault
webmaster_idYessource webmaster UUID from search_webmasters

Output Schema

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

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, openWorldHint and destructiveHint=false, so safety is covered. The description adds real behavioral context beyond that: it explains what 'similarity' means semantically and that only facets with at least one other match are returned (an implicit filter on results). The 'FREE' note is useful cost information not present in 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 short sentences, each carrying distinct information: purpose, a disambiguation of 'similarity', a result-filter guarantee, and cost. The key semantic disambiguation is front-loaded rather than buried, and there is no filler.

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

Completeness4/5

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

An output schema exists so return shape need not be described, the single parameter is fully documented in schema, and annotations cover the safety profile. What remains is a light gap: the relationship to find_similar_webmasters (the natural follow-up call) is never made explicit.

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% and the single parameter is documented as 'source webmaster UUID from search_webmasters', which already gives origin and type. The description adds no syntax, format, or sourcing detail beyond the schema. Baseline 3 applies when the schema does the work.

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

Purpose4/5

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

Uses a specific verb and resource: 'List the URL-parameter keys and normalized values' that identify related webmasters. It also pre-empts a likely misreading by defining similarity as shared affiliate/tracking parameter values rather than name or domain matching. It never names the sibling find_similar_webmasters, so the boundary between 'discover facets' and 'fetch matches' is left implicit.

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

Usage Guidelines3/5

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

'can be used to find related webmasters' implies this is a discovery step preceding find_similar_webmasters, but the relationship is never stated explicitly and no alternative is named. There are no exclusions or prerequisites beyond the required webmaster_id. Usage must be inferred rather than read.

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.

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

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

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and openWorldHint, so safety is covered; the description adds non-trivial context: the quota cost, and the fact that output shape changes depending on whether folder is passed. It does not describe pagination or limits, keeping it at 4.

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?

Dense but front-loaded: the dual-mode behavior and the filter come first, then the return contents, then the use case and cost. The middle sentence is long, but every clause carries actionable 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?

Despite an output schema existing, the description still spells out what each folder type returns, which is the exact decision-critical detail an agent needs. Nothing needed 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.

Parameters4/5

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

Schema coverage is 100% so baseline would be 3; the description adds value by mapping each entity_type to the sibling tool that consumes the returned ids (get_creative/get_webmaster/get_ad) and by explaining the disambiguation need when a folder name spans types.

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 verb+resource (list the caller's favourites folders) and immediately clarifies the dual behavior: folder list vs. items inside a named folder. An agent can distinguish this from siblings like add_to_favorites or get_creative without opening the schema.

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

Usage Guidelines5/5

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

Gives explicit when-to-use ('confirm what add_to_favorites saved', 'read a folder back'), explains the omit-vs-pass condition for entity_type, and the folder-vs-list switch. The 'FREE — does not consume quota' note routes the agent here over quota-consuming siblings when it only needs a read-back.

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. Meta pages contain at most 20 complete rows; follow next_cursor to retrieve more, even if a legacy caller requests limit=200. 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. MULTILANG UPLOAD: formats=[carousel_multilang] selects the same detected carousel pattern as the website; carousel_multilang_categorized selects its AI-categorized subset. This is independent of the languages filter. Formats combine with OR, so do not combine the base and categorized variants when requesting only categorized results. Search remains 1 MCP credit per row; opening a matching ad with get_ad or get_media costs 50 MCP credits. EU transparency: ads delivered in the EU carry a disclosure with eu_total_reach (accounts reached inside the EU over the ad's lifetime — reach, not impressions or spend), the countries it was delivered in, audience gender/age and the payer. Filter on it with eu_only, eu_countries (+ eu_countries_match), eu_reach_min/max, eu_gender, eu_age_min/max and eu_payer; every result row then carries an eu_transparency block, and get_ad adds the country × age × gender breakdown. Meta source only. QUOTA: 1 MCP credit per DELIVERED result (default page 20 = 20 MCP credits; short pages auto-refund). Results carry metadata only; get_ad/get_media charge 50 MCP credits per multilang-upload ad opening, 1 per ordinary ad, and get_media charges 10 per creative-catalogue item. Each new opening call is billed separately. Meta search_ads rows include is_multilang and opening_price (Spytrend MCP credits per ad per call); unavailable/null means the price could not be verified, not zero. is_multilang=true marks a multi-language upload («залив языками»): a masked carousel where some slides are decoys for ad review; where the real (black) slide is found it is the one shown first and used for grouping. multilang_black_missing=true means the real slide is not found yet: the media shown is a decoy and must not be treated as the creative. Opening quotes are not a debit or a price lock. Request small limits and narrow filters. 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 10 MCP credits and every TikTok webmaster row/card costs 10 MCP credits (Meta rows cost 1), deducted from the same MCP credit balance (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 15-MCP credit balance returns 1 row and charges 10). 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, estimated or unavailable; unavailable is not zero). With source=tiktok: Supported TikTok filters: query/search_in, country/countries, country_match, categories, ai_subcategory, languages, formats (single|carousel|video), landing_domain, advertiser_id (TikTok business id), webmaster_id, contains_in_links, media_type, cta_buttons, domain_zones, status_today (active|inactive), min_days_active/days_active_to, max_countries, dedupe, date_from/date_to (delivery-window overlap), sort_by=date|days_active, sort_order, limit, cursor. Countries overrides country. Categories and ai_subcategory combine with OR on TikTok. title and text both search the ad text; advertiser searches the advertiser name. date_from/date_to selects ads whose delivery window overlaps the requested inclusive period, not ads launched in that period. Active means shown within the last 3 calendar days. Unsupported filters (including hub_domains, folder_id, saved and landing_domain_exact) are REJECTED before charging; no filter is silently ignored. Default TikTok limit is 10; each delivered row costs 10 MCP credits. PRICING: price × number of filters set (min 1), on paid plans ×1 after 500 MCP credits/month; one-time consent via accept_pricing_terms; before calling, get the maximum debit from estimate_cost (free) and tell the user.

NameRequiredDescriptionDefault
limitNomax ad rows per page: Meta returns at most 20 (larger legacy requests are normalized to 20); follow pagination.next_cursor for the rest, with all row fields intact. TikTok defaults to 10 at 10 MCP credits per delivered row. Meta costs 1 MCP credit per delivered row.
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 MCP credit per delivered row) or tiktok (the TikTok corpus — ⚠️ PAID: 10 MCP credits 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_toNoMeta: only 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. TikTok: delivery-window overlap; the first delivery date must be on or before date_to
eu_onlyNowhen true, return only ads that carry an EU transparency disclosure (reach inside the EU, audience, payer). Any other eu_* filter implies it.
formatsNocreative formats: video, carousel, single, dynamic, carousel_multilang, carousel_multilang_categorized. Multilang upload detection is independent of languages; the categorized variant additionally requires an AI category. Values combine with OR. Search costs 1 MCP credit per row; opening a multilang ad costs 50 MCP credits.
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_byNoTikTok: date or days_active only. Meta: order 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
eu_payerNoexact payer name from the EU disclosure, case-insensitive (the legal entity that paid for the ad)
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_fromNoMeta: only 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. TikTok: delivery-window overlap; the last delivery date must be on or after date_from, not necessarily the launch date
eu_genderNoaudience gender from the EU disclosure: women or men (ads aimed at all genders match neither)
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')
eu_age_maxNoupper bound of the audience age window, 13-65
eu_age_minNolower bound of the audience age window, 13-65; matches ads whose disclosed age range overlaps the window
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.
eu_countriesNoISO-2 EU/EEA countries where the ad was actually delivered according to its EU disclosure (e.g. DE, FR). This is delivered reach, not the targeting filter in countries.
eu_reach_maxNomaximum EU reach (accounts reached inside the EU)
eu_reach_minNominimum EU reach: accounts reached inside the EU over the ad's lifetime
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 INTERNAL advertiser UUID — search_advertisers field advertiser_id, an ad row's advertiser_id, or get_trends dimension=advertisers. A Facebook page id or facebook.com page link sent here is applied as page_id (reported in params.normalized); any other value is rejected. For a page id prefer page_id (search_advertisers field external_id).
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.
exclude_domainsNoHide ads whose landing domain is one of these or its subdomain, e.g. appsflyer.com, play.google.com
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'
eu_countries_matchNohow eu_countries matches: any (default, delivered in at least one) or all (delivered in every listed country)
landing_domain_exactNowhen true, restrict landing_domain to the normalized hostname itself and exclude subdomains. Mirrors the /ads UI exact-host toggle.

Output Schema

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

TDQS

A4.7/5.0
Behavior5/5

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

Annotations only declare readOnly/openWorld; the description carries far more: per-row credit costs (1 Meta, 10 TikTok, 50 to open a multilang ad), plan gating (Pro-or-higher for TikTok), refunds on short pages, partial delivery when balance is short, a 20-row Meta page cap despite limit=200, and a subtle correctness rule that an 'unavailable' count is PENDING not zero. It also discloses intentional omissions (most_reused_creative group totals) and semantic traps (status_today is current state, not historical).

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 purpose and the highest-value caveats are front-loaded, but the description is a single multi-thousand-word paragraph with no headings or line breaks, making the TikTok block and EU block hard to locate mid-read. Credit pricing is restated at least three times (per-row cost, opening cost, TikTok 10x premium, plus the PRICING clause) and 'Request small limits and narrow filters' appears twice. Informative, but clearly not trimmed.

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 exists, so return shapes need not be spelled out, yet the description still explains the pagination contract (has_more/next_cursor, total/total_status with exact/estimated/unavailable and counted_at), the exact-count preconditions (≤31-day closed window, or the single-country cube up to 90 days), TikTok's distinct tiktok_data shape, and EU transparency blocks. For a 55-parameter open-world search tool with real billing consequences, this is as complete as it needs to be.

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 schema sets the baseline at 3, but the description adds real semantics beyond it: date_from is the Facebook LAUNCH axis vs first_seen = indexing date, formats combine with OR (so don't mix base and categorized variants), categories totals cover an AI-labeled subset only and are not comparable to get_trends extrapolations, body_chars length filters exclude textless ads, and max_countries changes meaning depending on whether a country set is selected. Not every one of the 55 params gets this treatment, 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 opening sentence names a specific verb+resource (search the spytrend.com ad database) and immediately scopes the return value as METADATA with an enumerated field list (title, body_chars, landing domain, status, geos...). It explicitly differentiates from siblings: body text is fetched with get_ad, creatives with get_media, aggregates with get_trends, advertiser totals with get_advertiser. An agent can pick this tool over its 30 siblings without opening any schema.

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?

Explicit routing rules throughout: use landing_domain NOT query to find ads on a domain; use date_from/date_to not first_seen_from/to for market newness (with the reason: late-indexed old ads); do NOT paginate search_ads for an advertiser's exact count, call get_advertiser/get_webmaster; use get_trends for aggregate rankings; do NOT call get_media for TikTok ids. It also states when-not conditions (unsupported TikTok filters are rejected, not silently ignored) and the cube-path preconditions.

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 (the Facebook page id), advertiser_id (the INTERNAL advertiser UUID; advertiser_ids lists every internal record when a page has several) 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 page_id=<external_id> (covers every internal record of the page) or advertiser_id=<advertiser_id>. For advertiser RANKINGS, ordering and filters (category/country/followers/founded-date/life_status/hubs), use get_trends with dimension=advertisers. With search_arbitrage=true or any sa_* filter it lists the advertisers whose ads are search arbitrage (ads leading to pages that earn from search-ads clicks), most ads first. 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 MCP credit per DELIVERED result from your plan balance (free starter: 500 MCP credits lifetime; paid plans: 40,000/month; short pages auto-refund — you pay only for results you receive). Default page is 20 results = 20 MCP credits; 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. PRICING: price × number of filters set (min 1), on paid plans ×1 after 500 MCP credits/month; one-time consent via accept_pricing_terms; before calling, get the maximum debit from estimate_cost (free) and tell the user.

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 MCP credit.
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. With search_arbitrage / sa_* the query is optional and matches a name substring or one exact numeric page id; pasted links are NOT resolved there.

Output Schema

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

TDQS

A4.7/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 credit cost model (1 MCP credit per delivered result, 20 by default, refunds on short pages), plan balance limits, auth-linking requirement with the failure mode (actionable refusal, not a server error), per-user rate limits with structured error.code=rate_limit_exceeded, and one-at-a-time admission for heavy calls. It even explains the restricted-archive-window behavior so a zero count isn't misread as 'no such advertiser'.

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?

Purpose and routing are front-loaded, which is good, but the paragraph is very long for a two-parameter tool and carries a large block of cross-cutting operational policy (quota, auth, rate limits, concurrency, pricing) that reads like boilerplate repeated across the server. Every sentence is informative, yet the density makes the tool-specific signal harder to extract.

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 exists, so return shapes needn't be explained, yet the description still names the key fields (external_id, advertiser_id, advertiser_ids, ad_count) that drive the follow-up calls it recommends. Combined with cost, auth, and failure-mode disclosure, nothing an agent needs to invoke this 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?

Schema coverage is 100%, so the baseline is 3; the description still adds real meaning — that links in any form resolve to the canonical fanpage with the exact match first, that either id namespace works, and that under search_arbitrage/sa_* the query becomes optional and pasted links are not resolved. One defect: the description says 'pass `limit` (1–200)' while the schema caps it at 1–50, a range inconsistency an agent could trip over.

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 opening sentence names the verb and resource and enumerates the three accepted query forms (name, numeric page id, pasted facebook.com link). It explicitly separates this tool from get_advertiser (single card by id) and search_ads (an advertiser's ads), so an agent can route without opening schemas.

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?

Alternatives are named with the exact condition that selects each: get_advertiser for one advertiser's full card, search_ads with page_id/advertiser_id for ads, get_trends with dimension=advertisers for rankings and filters. It also flags the arbitrage-only mode (search_arbitrage=true or sa_* filters) as a distinct usage context.

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

search_affiliate_offersSearch nutra & crypto affiliate offersA
Read-only
Inspect

PAID ADD-ONS «Nutra» and «Crypto», sold separately (MCP comes with the annual plan of each vertical). Find Meta ads whose landing pages are nutra or crypto affiliate offers, filtered by vertical (lp_category), niche (lp_subcategory) and offer (lp_product). Each row: ad_id, advertiser, landing_domain, vertical, niche, offer. Without the add-on the call is refused; a monthly «site» subscriber is told that MCP access is part of the annual plan. QUOTA: 1 MCP credit per delivered row; section rows have their own allowance — up to 500 rows per UTC day and 5 000 per UTC month per account, shared by every tool (search_ads, get_ad, get_media and the rest count the Nutra / Crypto / Web2App rows they return too), which MCP credit packs do not raise; market summaries (get_web2app_market) are outside it. PRICING: on paid plans ×1 after 500 MCP credits/month; one-time consent via accept_pricing_terms; before calling, get the maximum debit from estimate_cost (free) and tell the user.

NameRequiredDescriptionDefault
qNofree-text search in the ad
limitNorows to return, 1-50 (default 20)
lp_productNooffer (product) name as shown by this tool (OR)
lp_categoryNovertical: nutra_affiliate or crypto_affiliate (OR); omitted = the verticals your annual plans open
lp_subcategoryNoniche as vertical/niche, e.g. nutra_affiliate/weight_loss (OR)

Output Schema

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

TDQS

A4/5.0
Behavior5/5

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

The description adds substantial behavioral context beyond annotations: paid add-on dependency, refusal behavior, shared daily/monthly quotas, quota exclusions for get_web2app_market, pricing multiplier, consent requirement, and estimate_cost prerequisite. These details materially affect whether and how an agent should call the tool.

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 dense but mostly front-loaded, with labeled sections for paid add-ons, quota, and pricing. Some access and pricing details are repeated across sentences, making it longer than ideal, but the information is largely relevant to correct invocation.

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 commercial access model, quota sharing, pricing terms, and the presence of an output schema, the description covers the operational constraints an agent needs before calling. It lists the returned row fields and points to estimate_cost and accept_pricing_terms, leaving little critical context 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?

Schema description coverage is 100%, so the schema already documents all five parameters. The description maps lp_category to vertical, lp_subcategory to niche, and lp_product to offer, but it does not mention q or limit beyond the schema, so it adds only modest meaning over structured data.

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

Purpose4/5

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

The description states a specific verb+resource: 'Find Meta ads whose landing pages are nutra or crypto affiliate offers,' and names the exact filtering dimensions. This is clear enough to distinguish it from general searches in practice, but it does not explicitly contrast itself with sibling tools such as search_ads.

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

Usage Guidelines3/5

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

It gives important access context—paid add-on required, refusal without it, and monthly site subscriber messaging—plus prerequisite steps like estimate_cost and accept_pricing_terms. However, it does not explicitly say when to choose this over search_ads or other search tools, so usage guidance is implied rather than fully specified.

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

search_contentSearch content ideas (Content AI)A
Read-only
Inspect

Content AI (lite) search: find short-video content ideas by meaning — Instagram Reels, TikTok and YouTube Shorts ranked for a free-text query (a topic, a niche, a hook, an idea, up to 500 characters; any language). One row = one video. Rows carry id, platform, views, likes, comments, shares (null when the platform hides it), viral_score, published_at, language and duration_sec. AUTHORS, CAPTIONS, TITLES AND LINKS ARE NOT RETURNED — Content AI masks them by design; never invent them, and send the user to Content AI on spytrend.com for the full cards. Filters: platforms (instagram, tiktok, youtube — a list; empty = all), published_within_days (7, 30 or 90 — only videos published in that window), sort (best_match default, fire, views, likes, comments, newest). The tool returns the FIRST page only (limit at most 10): there is no paging, repeat the search with a sharper query instead. total is the number of matches found so far for the query (not an exact market size) and can be absent; low_relevance=true means nothing matched well — say so instead of presenting weak rows as ideas. filters_applied=false means this deployment ignored sort, platforms and published_within_days for this call — do not claim the result was filtered by them. Each search also counts against the account's daily Content AI search limit; a repeated identical query is served from cache. Gate errors are reported as tool errors: subscription_required (Content AI needs a subscription or token balance on the account), not available, or busy (retry after the indicated delay). QUOTA: 1 MCP credit per delivered row; short pages are refunded. PRICING: price × number of filters set (min 1), on paid plans ×1 after 500 MCP credits/month; one-time consent via accept_pricing_terms; before calling, get the maximum debit from estimate_cost (free) and tell the user.

NameRequiredDescriptionDefault
sortNoorder: best_match (default), fire, views, likes, comments or newest
limitNomax rows (default 10, at most 10; each delivered row costs 1 MCP credit). There is no paging.
queryYeswhat to look for: a topic, niche, idea or hook in free text, 1-500 characters, any language
platformsNolimit to platforms: instagram, tiktok, youtube (a list; empty = all)
published_within_daysNoonly videos published in the last 7, 30 or 90 days

Output Schema

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

TDQS

A4.8/5.0
Behavior5/5

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

Discloses far more than the readOnly/openWorld annotations: masked authors, captions, titles and links; first-page-only with limit ≤ 10; imprecise 'total'; low_relevance and filters_applied flags; per-account daily search limits; cache behavior for repeated queries; and specific gate errors (subscription_required, busy with retry). Nothing contradicts readOnlyHint=true.

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?

Purpose is front-loaded in the first clause and nearly every sentence carries actionable information (masking, cost, flags, errors). It is a dense single-paragraph block, though, and some schema-redundant field enumeration could be trimmed for readability.

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 paid, quota-metered, read-only search tool the description covers the full call lifecycle: required precondition (estimate_cost), consent, cost model, result-shape caveats, failure modes and what not to claim. Return fields are enumerated even though an output schema exists, which is redundant but not harmful.

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 parameter documentation is already strong; the description still adds meaning by stating that empty platforms means all, that published_within_days only accepts 7/30/90 windows, that limit is capped at 10 with no paging, and that each delivered row costs a credit. Most of this is reinforcement of the schema rather than new semantics, keeping it just short of 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?

States a specific verb and resource — semantically search short-video content ideas across Instagram Reels, TikTok and YouTube Shorts — and scopes it as 'Content AI (lite)'. Clearly distinct from sibling tools like search_ads, search_creatives or search_influencers, which cover other entity types.

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

Usage Guidelines5/5

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

Gives explicit when-to-use context (free-text topic/niche/hook lookup), names the alternative behavior for going deeper ('repeat the search with a sharper query instead' since there is no paging), and routes the agent to siblings estimate_cost and accept_pricing_terms before calling. It also says what to do when low_relevance=true and filters_applied=false.

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

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

Output Schema

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

TDQS

A4.7/5.0
Behavior5/5

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

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

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

Conciseness2/5

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

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

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

Completeness5/5

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

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

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

Parameters5/5

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

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

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

Purpose5/5

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

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

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

Usage Guidelines5/5

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

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

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

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 MCP credit 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 MCP credit per DELIVERED result from your plan balance (free starter: 500 MCP credits lifetime; paid plans: 40,000/month; short pages auto-refund — you pay only for results you receive). Default page is 20 results = 20 MCP credits; 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. PRICING: price × number of filters set (min 1), on paid plans ×1 after 500 MCP credits/month; one-time consent via accept_pricing_terms; before calling, get the maximum debit from estimate_cost (free) and tell the user.

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 MCP credit). 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

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

TDQS

A4.2/5.0
Behavior5/5

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

Adds rich context beyond the annotations: the catalog call is free, profile rows cost 1 MCP credit each, plan-window restrictions surface as total_status=restricted, and rate-limit/concurrency behavior is described. These details do not contradict readOnlyHint=true or destructiveHint=false.

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 purpose and catalog-vs-drill-in distinction are front-loaded, but the description expands into long platform-wide sections on quota, rate limits, concurrency, and pricing that are generic and likely repeated across tools. It is organized but not tight.

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 13 parameters, an output schema, and read-only annotations, the description covers the remaining critical context: costs, plan-window restrictions, account linking, rate limits, and concurrency. An agent has enough to call the tool correctly without needing return-value details.

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 schema already documents most parameters and the baseline is 3. The description still adds value with the limit range (1–200) and the combined country+relevance+exclude_cloaking recipe, which the schema does not spell out.

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

Purpose4/5

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

Starts with a specific verb and resource: “Explore HUBS — where ads send traffic, grouped by destination,” and clearly separates the free catalog mode from the drill-in mode. It never names a sibling tool such as search_shops or search_ads, so it is clear but stops short of explicit sibling differentiation.

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?

Explicitly says “Call WITHOUT hub … FREE” and “Call WITH hub set to a slug …” and gives a concrete recipe combining country + sort=relevance + exclude_cloaking for per-geo rankings. It does not tell the agent when to choose a different sibling tool instead.

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

search_influencersSearch influencersA
Read-only
Inspect

Search the INFLUENCER directory (the website's /influence page): YouTube channels and Instagram accounts with audience size and activity. One row = one creator. platform is required: youtube or instagram. Filters: q (name / topic words), country (ISO-2 code such as US, or the English country name as the directory writes it, comma separated), category and niche (YouTube only; the directory's own labels, exact match, comma separated — YouTube category examples: Gaming, Music, Education, Comedy, Sports, 'Beauty & Makeup', 'Tech, AI & Software', 'Finance & Cryptocurrency', 'Food, Drink & Cooking', Fitness, 'Travel & Events'; when unsure of a label search by q instead), followers_min / followers_max (subscribers / followers), last_video_days (creators active in the last N days: last video on YouTube, last post on Instagram), has_email (true = creators with an email in the directory), sort (YouTube: followers default, views, videos, last_video; Instagram: followers only). Instagram rows carry the account handle in username and have no niche, avg_views or lang_hint. Rows: slug, name, platform, followers, avg_views (YouTube: average views per video), count_views (YouTube: total views), media_count (videos / posts), country, niche, category, lang_hint (YouTube writing-script hint such as 'latin' — NOT a language), last_video_at / last_post_at, has_email, url (YouTube creator page on spytrend.com). CONTACTS ARE NEVER RETURNED: no emails, phones, websites, social links or bios — has_email is only a yes/no. total_estimate is an ESTIMATE scaled to the directory size, never an exact count. Pagination: limit is at most 10; offset must be a multiple of limit. Callers without an Influence subscription get subscription_locked=true: only the first row carries statistics, the others are name/country/niche teasers (stats_hidden=true, not charged) and there is no second page. QUOTA: 1 MCP credit per row that carries statistics; teaser rows and short pages are refunded. PRICING: price × number of filters set (min 1), on paid plans ×1 after 500 MCP credits/month; one-time consent via accept_pricing_terms; before calling, get the maximum debit from estimate_cost (free) and tell the user.

NameRequiredDescriptionDefault
qNoname or topic words to search for (creator name, channel topic)
sortNoorder: followers (default), views, videos or last_video; Instagram supports followers only
limitNomax rows (default 10, at most 10; each row with statistics costs 1 MCP credit)
nicheNoYouTube only: the directory's own niche label (exact match, comma separated), e.g. 'Mobile Games'. Unsure of the label — use q
offsetNopagination offset, a multiple of limit (0, 10, 20…)
countryNoISO-2 code (US, BR, DE…) or the English country name as the directory writes it ('United States'); comma separated for several. Matches the creator's country, not the audience's
categoryNothe directory's own category label (exact match, comma separated), e.g. Gaming or 'Beauty & Makeup'. Unsure of the label — use q
platformYesdirectory to search: youtube or instagram
has_emailNotrue = only creators with an email in the directory (the email itself is never returned)
followers_maxNomaximum subscribers (YouTube) / followers (Instagram)
followers_minNominimum subscribers (YouTube) / followers (Instagram)
last_video_daysNoonly creators active in the last N days (last video on YouTube, last post on Instagram)

Output Schema

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

TDQS

A4.7/5.0
Behavior5/5

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

Annotations only declare readOnly/openWorld; the description adds substantial non-obvious behavior: contacts are never returned, total_estimate is an estimate, subscription_locked produces teaser rows with stats_hidden and no second page, quota is 1 credit per row with refunds, and pricing scales with the number of filters set. This is exactly the context the annotations cannot supply.

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?

Front-loads resource and required parameter, then filters, then rows, then commercial terms — a sensible order. It is dense and long, with some schema-restating detail (row field list) that could be trimmed, but nearly every sentence carries operational value.

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 12-parameter, paid, quota-metered search tool this covers everything an agent needs: pagination constraint (limit ≤ 10, offset multiple of limit), locked-subscription degradation, cost preview workflow, and output limitations. The output schema exists, yet the description still flags the fields callers must not expect (emails, bios).

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?

Even at 100% schema coverage the description adds real meaning: country matches the creator's country not the audience's, category/niche are exact-match directory labels with enumerated YouTube examples, sort is followers-only on Instagram, and Instagram rows lack niche/avg_views/lang_hint. It also clarifies lang_hint is a writing-script hint, not a language.

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

Purpose5/5

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

Opens with a specific verb+resource and scope: 'Search the INFLUENCER directory (the website's /influence page)', and defines the unit ('One row = one creator') plus the two supported platforms. This clearly separates it from get_influencer (single-creator lookup) among the siblings.

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?

Gives concrete routing advice inside the tool: use q instead of category/niche 'when unsure of a label', platform is required, and specifies prerequisite workflow steps (estimate_cost for max debit, accept_pricing_terms consent). It does not explicitly contrast with sibling search tools or get_influencer, so it stops short of full when-not guidance.

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

search_productsSearch advertised productsA
Read-only
Inspect

Search e-commerce PRODUCTS that ads lead to — the data behind the website's /shops/products page. One row = ONE product page (domain/products/handle) of ONE shop, with that product's OWN ad counters: ads = ads leading to this product among the ads Spytrend first saw in the last 180 days; ads_active = how many of them were ACTIVE on active_as_of — the day of the daily data snapshot the counters are taken on, returned with the result (say 'active on 04.10', never 'active now'); creatives, reuploads and geos; days_in_ads = days from the product's first launch to today (if something is active) or to its last launch; fb_launch_date / last_launch_date = first and last Facebook launch of the product's ads (YYYY-MM-DD); win_badge = testing (active, under 14 days in ads) | heating (active, 14-29 days) | proven (active, 30+ days and 10+ ads) | ran30 (30+ days, not proven); no badge = not active and under 30 days. price/currency come from the shop catalog (0 = no catalog). shop = the store (domain, platform, top_country, monthly visits estimate, categories). product_url is the product page on spytrend.com (link it); ads_url lists the product's ads. COUNTS ARE PER PRODUCT: never use a shop's active_ads/total_ads from search_shops/get_shop as a product's numbers — they count the WHOLE domain. Filters: q = substring of the product handle, i.e. the URL slug (lower-case words joined by dashes: 'weighted blanket' matches weighted-blanket-queen) — NOT the product title: a product sold as 'CloudAlign Pillow' may live at cloud-alignment-pillow, so when a named product is missing from the rows, retry with a shorter fragment or the compound word split by a dash ('cloudalign' -> 'cloud-align'), or domain= when the shop is known; country = ISO-2 codes (comma separated) of the SHOP's main visitor country, not of the ads — never present it as the country the ads run in; ai_category = Spytrend AD category slugs (comma separated); site_category = estimated site category slug; platform = commerce platform of the shop (comma separated, e.g. Shopify); domain = exact shop domains (comma separated) — use it for 'products of this shop'; active_only=true = only products with an ad active on active_as_of; win_badge = comma separated badges; date_from/date_to (YYYY-MM-DD) = window of Facebook launches ('launched/advertised during a period'): a product matches when one of its ads launched inside the window, and ads_in_period is the number of such launches — this includes old products that relaunched an ad in the window. first_seen_days (1-365) = only products whose FIRST Facebook launch (fb_launch_date) happened in the last N days: for 'first seen / new products / started advertising in the last N days and still active' pass first_seen_days=N + active_only=true — the tool sets the same boundary as the website's 'last N days' preset (today minus N days; the exact date comes back as first_seen_from), so NEVER compute the date yourself, the same wording must give the same window for every country (do not rely on date_from alone); first_seen_from (YYYY-MM-DD) = the same filter for an explicit calendar date the user named ('first seen since 20 September'), not for relative periods; if both are given first_seen_days wins; total then counts only such products (if the result has filter_note, the tool filtered the API pages itself and total is just the number of returned rows). win_badge=testing is the site's badge for 'active, under 14 days in ads'. min_price/max_price filter the catalog price; min_ads/max_ads filter the product's own ads count. sort_by: ads (default), ads_active, ads_in_period (needs a date window), price, visits (shop traffic), score (Winning Products: days x creatives x geos x reuploads). Returns total (the number of matching products — quote it as the number found; the rows are only the first limit of them), has_more, offset and data_through (last day the data is computed for; a date window is cut at it) and active_as_of (date of the daily snapshot the ads_active counters belong to). If a requested window starts after data_through there is no data for it yet: say the data is available through data_through, never print a period whose start is after its end. Rows with access=teaser have their ad counters blanked by the plan. 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 MCP credit per DELIVERED result from your plan balance (free starter: 500 MCP credits lifetime; paid plans: 40,000/month; short pages auto-refund — you pay only for results you receive). Default page is 20 results = 20 MCP credits; 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. PRICING: price × number of filters set (min 1), on paid plans ×1 after 500 MCP credits/month; one-time consent via accept_pricing_terms; before calling, get the maximum debit from estimate_cost (free) and tell the user.

NameRequiredDescriptionDefault
qNosubstring of the product handle (URL slug): words in lower case joined by dashes, e.g. 'weighted blanket' matches weighted-blanket-queen. Not a shop name and not a free-text search of ad copy.
limitNomax results per call (default 20, at most 100 — the products API serves 100 rows per page; a larger value is reduced to 100 and noted in params.normalized, page further with offset; each delivered result costs 1 MCP credit).
domainNoexact shop domains, comma separated — products of these shops only (e.g. 'mellowsleep.com')
offsetNopagination offset (0-based)
countryNoISO-2 codes, comma separated: keep products of shops whose MAIN visitor country is one of them (not the countries the ads ran in)
date_toNowindow of Facebook launches, end YYYY-MM-DD
max_adsNomaximum number of ads of the product itself (180 days)
min_adsNominimum number of ads of the product itself (180 days)
sort_byNoorder by: ads (default, descending), ads_active, ads_in_period (needs date_from/date_to), price, visits (shop traffic) or score (Winning Products)
platformNocommerce platform of the shop, comma separated: Shopify, WooCommerce, WordPress, Wix, Squarespace, Magento, PrestaShop or BigCommerce
date_fromNowindow of Facebook launches, start YYYY-MM-DD: products with an ad launched inside the window (old products that relaunched included); rows then carry ads_in_period. For 'first seen in the last N days' use first_seen_days instead
max_priceNomaximum catalog price (shop currency)
min_priceNominimum catalog price (shop currency); products without a catalog price drop out
win_badgeNocomma separated Winning Products badges: testing (active, under 14 days in ads), heating (active, 14-29 days), proven (active, 30+ days and 10+ ads), ran30 (30+ days, not proven)
active_onlyNotrue = only products with at least one ad active on active_as_of (the daily data snapshot day returned with the result)
ai_categoryNoSpytrend AD category slugs, comma separated (e.g. ecommerce_and_retail,beauty_and_cosmetics)
site_categoryNoestimated site category slug of the shop (comma separated); may be missing or wrong, ai_category is better for ad-market discovery
first_seen_daysNo1-365: only products whose FIRST Facebook launch (fb_launch_date) was within the last N days — use it for 'new / first seen / started advertising in the last N days'. The tool sets first_seen_from = today minus N days (the website's 'last N days' preset boundary) and returns it as first_seen_from; do not compute the date yourself. Wins over first_seen_from.
first_seen_fromNoYYYY-MM-DD: only products whose FIRST Facebook launch (fb_launch_date) is on or after this date — ONLY for an explicit calendar date the user named; for relative periods ('last N days') use first_seen_days, never compute the date yourself. Ignored when first_seen_days is given. total counts only such products.

Output Schema

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

TDQS

A4.8/5.0
Behavior5/5

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

Beyond the annotations, it discloses quota costs, credit charging, rate limits, concurrency admission behavior, pricing mechanics, teaser blanking, free-plan archive restrictions, and the active_as_of snapshot semantics. These are material behavioral traits that an agent would otherwise not know from schema or 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 content is relevant and front-loaded, but the description is a very long, dense paragraph that is difficult to scan and repeats some schema details. Global pricing, quota, and concurrency notes are useful but make the definition heavy for a single tool.

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 19 optional parameters, rich annotations, and an output schema, the description covers the operational context an agent needs: filtering semantics, pagination, totals, snapshot dates, quota costs, and edge cases. No critical calling information appears to be 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 adds substantial semantic guidance beyond the schema: q is a handle substring and not a title search, country is the shop's main visitor country and not the ad country, first_seen_days takes precedence over first_seen_from, and date_from/date_to describe launch-window matches including relaunches. It also clarifies total vs returned rows and special restricted-count behavior.

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: searching e-commerce products that ads lead to. It defines the row granularity as one product page per shop and contrasts product counts with shop-level counts from search_shops/get_shop, so an agent can distinguish it from 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 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 for many ambiguous cases: q vs domain, first_seen_days vs first_seen_from, date windows vs first-seen filters, and active_only combined with first_seen_days. It also warns against using shop-level active_ads/total_ads as product counts and explains how to handle named products missing from handle search.

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

search_shopsSearch online stores and their trafficA
Read-only
Inspect

Search ONLINE STORES — the same catalogue as the website's /shops page (not every domain: general sites such as google.com or youtube.com are not in it). Each row carries traffic, commerce and advertising intelligence for one store domain. Shops advertising now in a country ("shops with fresh/active ads in Mexico"): country= + has_ads=true (only shops with ACTIVE ads now; add min_ads=N for a floor) + sort_by=ads — do NOT use search_ads for this; there is no separate freshness-window filter. 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; sort_by=ads orders by the number of ACTIVE ads now (active_ads), not by total_ads — never describe it as 'sorted by total number of ads'; sort_by=revenue and min_revenue use website_value — the estimated VALUE of the site in USD, NOT revenue, and outliers with tiny traffic are possible. country/country_exclude match the shop's MAIN visitor country (top_country). An empty page carries a note explaining why. product_count is the number of products shown on the website shop card (the larger of the crawler counter and the real catalog size products_total). 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; total is the exact number of matching stores and has_more is true whenever total > offset+rows. FREE SAMPLE: without a Shops subscription the catalogue returns a short preview (a few rows) whatever the limit and deeper offsets come back empty — the result then carries a note "Free sample: N of TOTAL…" and params.normalized limit (requested→delivered); say it is a sample of TOTAL stores, never that only N exist. 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 MCP credit per DELIVERED result from your plan balance (free starter: 500 MCP credits lifetime; paid plans: 40,000/month; short pages auto-refund — you pay only for results you receive). Default page is 20 results = 20 MCP credits; 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. PRICING: price × number of filters set (min 1), on paid plans ×1 after 500 MCP credits/month; one-time consent via accept_pricing_terms; before calling, get the maximum debit from estimate_cost (free) and tell the user.

NameRequiredDescriptionDefault
qNosubstring search on the normalized domain; URLs are normalized to their host
limitNomax results (default 20, at most 200; each delivered result costs 1 MCP credit). Without a Shops subscription the catalogue answers a free sample of a few rows whatever the limit: params.normalized then reports limit as requested→delivered, note says the page is a free sample and has_more stays true while total exceeds offset+rows.
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 (any case; unknown codes are rejected) — keep only shops whose MAIN visitor country (top_country) is this country, NOT every shop with some traffic there. For small sites top_country can come from the site's country ranking instead of visitor shares, so a small shop whose visitors mostly come from another country may be listed under the wrong one
has_adsNotrue = only shops with ACTIVE ads now (the site's 'Has active ads' chip)
min_adsNominimum number of ads
socialsNocomma-separated social-media handle filters
sort_byNoorder by: visits (default), revenue (= website_value, the estimated site VALUE in USD, not revenue), growth, ads (= number of ACTIVE ads now, active_ads — not total_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 site value estimate in USD (website_value — the estimated VALUE of the site, not monthly revenue; the row field is website_value)
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 (any case) — drop shops whose MAIN visitor country (top_country) is this country
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

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

TDQS

A4.2/5.0
Behavior3/5

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

Annotations already declare readOnly/openWorld/no-destruction, and the description adds substantial non-obvious behavior: per-result credit cost, free-sample preview caps, restricted pagination windows (total_status=restricted, plan_window_cutoff), and an empty page carrying an explanatory note. However it also spends a large share of its length on account-level concerns (quota balances, consent, concurrency admission, rate-limit error codes) that apply to many tools rather than this one, so the tool-specific behavioral signal is diluted.

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?

Roughly 700 dense words with the actual filtering guidance interleaved among pricing, quota, rate-limit and concurrency paragraphs that repeat verbatim-style boilerplate rather than telling the caller anything about search_shops. Several clauses restate the schema (fb_signal status list, sort_by enumeration, created_from/to semantics) instead of adding to it, so the high-value routing sentences are buried.

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 40-parameter open-world search with an output schema, the description still covers the things structured fields cannot: the free-sample distortion, the archive-window zero-means-nothing-in-window caveat, cost per delivered row, and the has_more/offset pagination contract. Nothing an agent needs to call or interpret results 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%, so baseline is 3; the description earns above that by adding cross-parameter meaning the schema states only in isolation: sort_by=ads is active_ads not total_ads, country matches top_country (main visitor country) rather than any traffic, min_growth filters to growth_qualified rows, and traffic_start_max is meant to be paired with traffic_end_min.

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

Purpose5/5

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

Opens with a specific verb+resource and an explicit boundary: the /shops catalogue, not every domain (google.com, youtube.com excluded). It also names siblings it is not — 'do NOT use search_ads for this' and 'Use get_shop for the full source payload' — so an agent can route without opening another schema.

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

Usage Guidelines5/5

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

Gives an explicit recipe for a real task ('shops with fresh/active ads in Mexico': country + has_ads=true + sort_by=ads) and names the wrong tool to use. Also states a hard precondition (sort_by=relevance requires ai_category and is rejected otherwise) and where to go for detail (get_shop).

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 MCP credit per DELIVERED result from your plan balance (free starter: 500 MCP credits lifetime; paid plans: 40,000/month; short pages auto-refund — you pay only for results you receive). Default page is 20 results = 20 MCP credits; 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 10 MCP credits and every TikTok webmaster row/card costs 10 MCP credits (Meta rows cost 1), deducted from the same MCP credit balance (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 15-MCP credit balance returns 1 row and charges 10). 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, estimated or unavailable; unavailable is not zero). With source=tiktok rows are TikTok webmaster clusters. Supported TikTok webmaster filters: query, domain, countries (+min_geo_share), exclude_countries, ai_category (dominant), min_total_ads, min_active_ads, date_from/date_to, has_funder, sort_by=total_ads|active_ads|created_at|relevance, sort_order, offset (0-5000), limit (server caps TikTok at 100). Date filters select clusters whose activity window overlaps the requested period. Active means shown within the last 3 calendar days. Meta-only lookups, languages/platforms/creative_format(s), status_today, ai_subcategory, folder_id and saved are REJECTED before charging. Default TikTok limit is 10; each delivered row costs 10 MCP credits. PRICING: price × number of filters set (min 1), on paid plans ×1 after 500 MCP credits/month; one-time consent via accept_pricing_terms; before calling, get the maximum debit from estimate_cost (free) and tell the user.

NameRequiredDescriptionDefault
limitNomax results (default 20; each delivered result costs 1 MCP credit).
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 MCP credit per delivered row) or tiktok (TikTok business-id clusters — ⚠️ PAID: 10 MCP credits 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

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

TDQS

A4.5/5.0
Behavior5/5

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

Annotations already declare readOnlyHint=true and destructiveHint=false, but the description adds substantial behavioral context beyond them: 1 MCP credit per delivered row, 10 credits per delivered TikTok row, plan-based quota, rate-limit refusal semantics, concurrency gating, and the fact that unlinked agents receive an actionable connect-account refusal rather than a server error. It also discloses subtle correctness semantics — exact identifier lookups use current membership only, and plan-window narrowing makes a zero mean 'nothing in the archive window', not 'nothing 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 opening paragraph is well front-loaded, but the description then balloons into a multi-section manual covering pricing, rate limits, concurrency policies for unrelated tools (get_trends, search_ads, search_creatives), and a long field-by-field description of TikTok AD row shape that does not apply to this tool's webmaster-cluster output. Sentences such as the media-tt thumbnail and 'no TikTok engagement counters' notes do not earn their place here and actively blur what this endpoint returns.

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

Completeness4/5

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

With an output schema present and 100% schema coverage, the description is more than complete on inputs, billing and access requirements. The gap is coherence rather than missing information: the long tiktok_data field enumeration describes ad rows, then the text later corrects itself with 'With source=tiktok rows are TikTok webmaster clusters', leaving the agent briefly unsure which return shape applies.

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 description coverage is 100%, so the baseline is 3. The description adds cross-parameter semantics the schema does not: sort_by=relevance requires countries, min_geo_share gates geo dominance vs mere presence, and Meta-only filters (languages/platforms/status_today/folder_id/saved) are rejected under source=tiktok before charging. It does not, however, explain every non-obvious parameter (e.g. saved=all vs folder_id) beyond what the schema already says.

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 first sentence gives a specific verb and resource and then defines the entity ('a webmaster is a whole ad NETWORK'), which is essential context an agent cannot get from the name alone. It also names the sibling tools that handle follow-on work (search_creatives, search_ads, get_webmaster.top_creatives, add_to_favorites), so the agent can place this tool in the workflow.

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 states an explicit copy workflow (search by domain, take the canonical UUID, then query search_creatives/search_ads with webmaster_id) and gives selection rules between modes, e.g. 'pass source="tiktok" to query the TIKTOK ad corpus' and 'For a geo ranking combine countries + min_geo_share + sort_by=relevance'. It also warns which filters are rejected in TikTok mode, which is unusable guidance without this text.

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.

  1. 30 tool updates
    • Changedaccept_pricing_terms1 field changed
      • addedOutput schema / properties / addon_hints
        Added value: +{
        +  "description": "Add-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about.",
        +  "items": {
        +    "properties": {
        +      "available_data_types": {
        +        "description": "kinds of data the module confirmedly has for the object",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "info_url": {
        +        "description": "the object (or its limited breakdown) inside the module on spytrend.com",
        +        "type": "string"
        +      },
        +      "module": {
        +        "description": "nutra | crypto | web2app | search_arb | startups",
        +        "type": "string"
        +      },
        +      "object_id": {
        +        "description": "the ad id, or the site domain for site rows",
        +        "type": "string"
        +      },
        +      "preland_downloadable": {
        +        "description": "Nutra / Crypto: the saved pre-lander can be downloaded in the module",
        +        "type": "boolean"
        +      },
        +      "subscription_status": {
        +        "description": "active | not_connected",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Changedadd_to_favorites1 field changed
      • addedOutput schema / properties / addon_hints
        Added value: +{
        +  "description": "Add-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about.",
        +  "items": {
        +    "properties": {
        +      "available_data_types": {
        +        "description": "kinds of data the module confirmedly has for the object",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "info_url": {
        +        "description": "the object (or its limited breakdown) inside the module on spytrend.com",
        +        "type": "string"
        +      },
        +      "module": {
        +        "description": "nutra | crypto | web2app | search_arb | startups",
        +        "type": "string"
        +      },
        +      "object_id": {
        +        "description": "the ad id, or the site domain for site rows",
        +        "type": "string"
        +      },
        +      "preland_downloadable": {
        +        "description": "Nutra / Crypto: the saved pre-lander can be downloaded in the module",
        +        "type": "boolean"
        +      },
        +      "subscription_status": {
        +        "description": "active | not_connected",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Changedestimate_cost1 field changed
      • addedOutput schema / properties / addon_hints
        Added value: +{
        +  "description": "Add-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about.",
        +  "items": {
        +    "properties": {
        +      "available_data_types": {
        +        "description": "kinds of data the module confirmedly has for the object",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "info_url": {
        +        "description": "the object (or its limited breakdown) inside the module on spytrend.com",
        +        "type": "string"
        +      },
        +      "module": {
        +        "description": "nutra | crypto | web2app | search_arb | startups",
        +        "type": "string"
        +      },
        +      "object_id": {
        +        "description": "the ad id, or the site domain for site rows",
        +        "type": "string"
        +      },
        +      "preland_downloadable": {
        +        "description": "Nutra / Crypto: the saved pre-lander can be downloaded in the module",
        +        "type": "boolean"
        +      },
        +      "subscription_status": {
        +        "description": "active | not_connected",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Changedfind_similar_ads7 fields changed
      • changedInput schema / properties / limit / description
        Previous value: -"maximum metadata rows (default 20, maximum 200; 1 token per delivered row)"New value: +"maximum metadata rows (default 20, maximum 200; 1 MCP credit per delivered row)"
      • addedOutput schema / properties / addon_hints
        Added value: +{
        +  "description": "Add-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about.",
        +  "items": {
        +    "properties": {
        +      "available_data_types": {
        +        "description": "kinds of data the module confirmedly has for the object",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "info_url": {
        +        "description": "the object (or its limited breakdown) inside the module on spytrend.com",
        +        "type": "string"
        +      },
        +      "module": {
        +        "description": "nutra | crypto | web2app | search_arb | startups",
        +        "type": "string"
        +      },
        +      "object_id": {
        +        "description": "the ad id, or the site domain for site rows",
        +        "type": "string"
        +      },
        +      "preland_downloadable": {
        +        "description": "Nutra / Crypto: the saved pre-lander can be downloaded in the module",
        +        "type": "boolean"
        +      },
        +      "subscription_status": {
        +        "description": "active | not_connected",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / data / items / properties / also_in
        Added value: +{
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedOutput schema / properties / data / items / properties / multilang_black_unresolved
        Added value: +{
        +  "type": [
        +    "null",
        +    "boolean"
        +  ]
        +}
      • addedOutput schema / properties / data / items / properties / opening_price / properties / MCP credits
        Added value: +{
        +  "type": [
        +    "null",
        +    "integer"
        +  ]
        +}
      • removedOutput schema / properties / data / items / properties / opening_price / properties / tokens
        Removed value: -{
        -  "type": [
        -    "null",
        -    "integer"
        -  ]
        -}
      • changedOutput schema / properties / data / items / properties / opening_price / required
        Previous value: -[
        -  "status",
        -  "tokens",
        -  "unit",
        -  "billing_basis"
        -]New value: +[
        +  "status",
        +  "MCP credits",
        +  "unit",
        +  "billing_basis"
        +]
    • Changedfind_similar_creatives1 field changed
      • addedOutput schema / properties / addon_hints
        Added value: +{
        +  "description": "Add-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about.",
        +  "items": {
        +    "properties": {
        +      "available_data_types": {
        +        "description": "kinds of data the module confirmedly has for the object",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "info_url": {
        +        "description": "the object (or its limited breakdown) inside the module on spytrend.com",
        +        "type": "string"
        +      },
        +      "module": {
        +        "description": "nutra | crypto | web2app | search_arb | startups",
        +        "type": "string"
        +      },
        +      "object_id": {
        +        "description": "the ad id, or the site domain for site rows",
        +        "type": "string"
        +      },
        +      "preland_downloadable": {
        +        "description": "Nutra / Crypto: the saved pre-lander can be downloaded in the module",
        +        "type": "boolean"
        +      },
        +      "subscription_status": {
        +        "description": "active | not_connected",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Changedfind_similar_webmasters2 fields changed
      • changedInput schema / properties / limit / description
        Previous value: -"maximum rows to return (default 20, maximum 200; 1 token per delivered row)"New value: +"maximum rows to return (default 20, maximum 200; 1 MCP credit per delivered row)"
      • addedOutput schema / properties / addon_hints
        Added value: +{
        +  "description": "Add-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about.",
        +  "items": {
        +    "properties": {
        +      "available_data_types": {
        +        "description": "kinds of data the module confirmedly has for the object",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "info_url": {
        +        "description": "the object (or its limited breakdown) inside the module on spytrend.com",
        +        "type": "string"
        +      },
        +      "module": {
        +        "description": "nutra | crypto | web2app | search_arb | startups",
        +        "type": "string"
        +      },
        +      "object_id": {
        +        "description": "the ad id, or the site domain for site rows",
        +        "type": "string"
        +      },
        +      "preland_downloadable": {
        +        "description": "Nutra / Crypto: the saved pre-lander can be downloaded in the module",
        +        "type": "boolean"
        +      },
        +      "subscription_status": {
        +        "description": "active | not_connected",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Changedget_ad7 fields changed
      • changedInput schema / properties / source / description
        Previous value: -"ad corpus: meta (default, 1 token — delivers the ad's media) or tiktok (⚠️ 100 tokens per TikTok ad row; Pro plan required)"New value: +"ad corpus: meta (default, 1 MCP credit — delivers the ad's media) or tiktok (⚠️ 10 MCP credits per TikTok ad row; Pro plan required)"
      • addedOutput schema / properties / addon_hints
        Added value: +{
        +  "description": "Add-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about.",
        +  "items": {
        +    "properties": {
        +      "available_data_types": {
        +        "description": "kinds of data the module confirmedly has for the object",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "info_url": {
        +        "description": "the object (or its limited breakdown) inside the module on spytrend.com",
        +        "type": "string"
        +      },
        +      "module": {
        +        "description": "nutra | crypto | web2app | search_arb | startups",
        +        "type": "string"
        +      },
        +      "object_id": {
        +        "description": "the ad id, or the site domain for site rows",
        +        "type": "string"
        +      },
        +      "preland_downloadable": {
        +        "description": "Nutra / Crypto: the saved pre-lander can be downloaded in the module",
        +        "type": "boolean"
        +      },
        +      "subscription_status": {
        +        "description": "active | not_connected",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / data / properties / also_in
        Added value: +{
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedOutput schema / properties / data / properties / multilang_black_unresolved
        Added value: +{
        +  "type": [
        +    "null",
        +    "boolean"
        +  ]
        +}
      • addedOutput schema / properties / data / properties / opening_price / properties / MCP credits
        Added value: +{
        +  "type": [
        +    "null",
        +    "integer"
        +  ]
        +}
      • removedOutput schema / properties / data / properties / opening_price / properties / tokens
        Removed value: -{
        -  "type": [
        -    "null",
        -    "integer"
        -  ]
        -}
      • changedOutput schema / properties / data / properties / opening_price / required
        Previous value: -[
        -  "status",
        -  "tokens",
        -  "unit",
        -  "billing_basis"
        -]New value: +[
        +  "status",
        +  "MCP credits",
        +  "unit",
        +  "billing_basis"
        +]
    • Changedget_ads_analytics2 fields changed
      • changedInput schema / properties / favorites_only / description
        Previous value: -"restrict to the token-derived user's favorite webmaster scope"New value: +"restrict to the MCP credit-derived user's favorite webmaster scope"
      • addedOutput schema / properties / addon_hints
        Added value: +{
        +  "description": "Add-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about.",
        +  "items": {
        +    "properties": {
        +      "available_data_types": {
        +        "description": "kinds of data the module confirmedly has for the object",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "info_url": {
        +        "description": "the object (or its limited breakdown) inside the module on spytrend.com",
        +        "type": "string"
        +      },
        +      "module": {
        +        "description": "nutra | crypto | web2app | search_arb | startups",
        +        "type": "string"
        +      },
        +      "object_id": {
        +        "description": "the ad id, or the site domain for site rows",
        +        "type": "string"
        +      },
        +      "preland_downloadable": {
        +        "description": "Nutra / Crypto: the saved pre-lander can be downloaded in the module",
        +        "type": "boolean"
        +      },
        +      "subscription_status": {
        +        "description": "active | not_connected",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Changedget_advertiser1 field changed
      • addedOutput schema / properties / addon_hints
        Added value: +{
        +  "description": "Add-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about.",
        +  "items": {
        +    "properties": {
        +      "available_data_types": {
        +        "description": "kinds of data the module confirmedly has for the object",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "info_url": {
        +        "description": "the object (or its limited breakdown) inside the module on spytrend.com",
        +        "type": "string"
        +      },
        +      "module": {
        +        "description": "nutra | crypto | web2app | search_arb | startups",
        +        "type": "string"
        +      },
        +      "object_id": {
        +        "description": "the ad id, or the site domain for site rows",
        +        "type": "string"
        +      },
        +      "preland_downloadable": {
        +        "description": "Nutra / Crypto: the saved pre-lander can be downloaded in the module",
        +        "type": "boolean"
        +      },
        +      "subscription_status": {
        +        "description": "active | not_connected",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Changedget_influencer1 field changed
      • addedOutput schema / properties / addon_hints
        Added value: +{
        +  "description": "Add-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about.",
        +  "items": {
        +    "properties": {
        +      "available_data_types": {
        +        "description": "kinds of data the module confirmedly has for the object",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "info_url": {
        +        "description": "the object (or its limited breakdown) inside the module on spytrend.com",
        +        "type": "string"
        +      },
        +      "module": {
        +        "description": "nutra | crypto | web2app | search_arb | startups",
        +        "type": "string"
        +      },
        +      "object_id": {
        +        "description": "the ad id, or the site domain for site rows",
        +        "type": "string"
        +      },
        +      "preland_downloadable": {
        +        "description": "Nutra / Crypto: the saved pre-lander can be downloaded in the module",
        +        "type": "boolean"
        +      },
        +      "subscription_status": {
        +        "description": "active | not_connected",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Changedget_media4 fields changed
      • addedOutput schema / properties / addon_hints
        Added value: +{
        +  "description": "Add-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about.",
        +  "items": {
        +    "properties": {
        +      "available_data_types": {
        +        "description": "kinds of data the module confirmedly has for the object",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "info_url": {
        +        "description": "the object (or its limited breakdown) inside the module on spytrend.com",
        +        "type": "string"
        +      },
        +      "module": {
        +        "description": "nutra | crypto | web2app | search_arb | startups",
        +        "type": "string"
        +      },
        +      "object_id": {
        +        "description": "the ad id, or the site domain for site rows",
        +        "type": "string"
        +      },
        +      "preland_downloadable": {
        +        "description": "Nutra / Crypto: the saved pre-lander can be downloaded in the module",
        +        "type": "boolean"
        +      },
        +      "subscription_status": {
        +        "description": "active | not_connected",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / items / items / properties / opening_price / properties / MCP credits
        Added value: +{
        +  "type": [
        +    "null",
        +    "integer"
        +  ]
        +}
      • removedOutput schema / properties / items / items / properties / opening_price / properties / tokens
        Removed value: -{
        -  "type": [
        -    "null",
        -    "integer"
        -  ]
        -}
      • changedOutput schema / properties / items / items / properties / opening_price / required
        Previous value: -[
        -  "status",
        -  "tokens",
        -  "unit",
        -  "billing_basis"
        -]New value: +[
        +  "status",
        +  "MCP credits",
        +  "unit",
        +  "billing_basis"
        +]
    • Changedget_shop1 field changed
      • addedOutput schema / properties / addon_hints
        Added value: +{
        +  "description": "Add-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about.",
        +  "items": {
        +    "properties": {
        +      "available_data_types": {
        +        "description": "kinds of data the module confirmedly has for the object",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "info_url": {
        +        "description": "the object (or its limited breakdown) inside the module on spytrend.com",
        +        "type": "string"
        +      },
        +      "module": {
        +        "description": "nutra | crypto | web2app | search_arb | startups",
        +        "type": "string"
        +      },
        +      "object_id": {
        +        "description": "the ad id, or the site domain for site rows",
        +        "type": "string"
        +      },
        +      "preland_downloadable": {
        +        "description": "Nutra / Crypto: the saved pre-lander can be downloaded in the module",
        +        "type": "boolean"
        +      },
        +      "subscription_status": {
        +        "description": "active | not_connected",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Changedget_trends10 fields changed
      • changedInput schema / properties / limit / description
        Previous value: -"max rows to return (default 20; each delivered row costs 1 token). Ignored for geo_timeline: that dimension has no pagination and returns every populated date×country point in the accepted window while charging only the requested page size."New value: +"max rows to return (default 20; each delivered row costs 1 MCP credit). Ignored for geo_timeline: that dimension has no pagination and returns every populated date×country point in the accepted window while charging only the requested page size."
      • removedInput schema / properties / sa_country
        Removed value: -{
        -  "description": "ISO-2 codes of the countries the ads are shown in (OR), e.g. US, GB, DE — NOT the visitor country of the site. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_lang
        Removed value: -{
        -  "description": "ISO 639-1 language codes of the search phrases (OR), e.g. en, de, es. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_network
        Removed value: -{
        -  "description": "search-arbitrage network slugs (OR): the search-ads network the site monetises through, e.g. tonic, visymo, medianet, cortex, predicto, codefuel, brandclick, system1. Live list with counts: search_arbitrage_facets. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_phrase
        Removed value: -{
        -  "description": "exact search phrases (OR), lower-case, as returned by search_arbitrage_phrases; a phrase containing a comma cannot be used here. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_pub
        Removed value: -{
        -  "description": "Google publisher account ids (OR), e.g. pub-1902826156353358: the AdSense/AFS account the site earns under — one account usually means one operator. A bare number or ca-pub-… is accepted. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_source
        Removed value: -{
        -  "description": "how the site earns from search (OR): rsoc (Google related-search ads through a partner), afs (Google AdSense for Search), yahoo_feed, bing_feed or other. Implies search_arbitrage.",
        -  "items": {
        -    "enum": [
        -      "rsoc",
        -      "afs",
        -      "yahoo_feed",
        -      "bing_feed",
        -      "other"
        -    ],
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_topic
        Removed value: -{
        -  "description": "topic slugs of the search phrases the sites push (OR); live list with counts: search_arbitrage_facets. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / search_arbitrage
        Removed value: -{
        -  "description": "SEARCH ARBITRAGE filter (confirmed search-arbitrage sites only), every dimension except apps: true = build the ranking only from search-arbitrage ads — ads whose landing page earns from search-ads clicks (Google RSOC/AFS through networks such as Tonic or Visymo, Yahoo/Bing feeds) instead of selling a product. Every sa_* filter implies it. Omit or false = no search-arbitrage filter. Valid sa_* values and counts: search_arbitrage_facets; the phrases behind them: search_arbitrage_phrases.",
        -  "type": "boolean"
        -}
      • addedOutput schema / properties / addon_hints
        Added value: +{
        +  "description": "Add-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about.",
        +  "items": {
        +    "properties": {
        +      "available_data_types": {
        +        "description": "kinds of data the module confirmedly has for the object",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "info_url": {
        +        "description": "the object (or its limited breakdown) inside the module on spytrend.com",
        +        "type": "string"
        +      },
        +      "module": {
        +        "description": "nutra | crypto | web2app | search_arb | startups",
        +        "type": "string"
        +      },
        +      "object_id": {
        +        "description": "the ad id, or the site domain for site rows",
        +        "type": "string"
        +      },
        +      "preland_downloadable": {
        +        "description": "Nutra / Crypto: the saved pre-lander can be downloaded in the module",
        +        "type": "boolean"
        +      },
        +      "subscription_status": {
        +        "description": "active | not_connected",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Changedget_usage1 field changed
      • addedOutput schema / properties / addon_hints
        Added value: +{
        +  "description": "Add-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about.",
        +  "items": {
        +    "properties": {
        +      "available_data_types": {
        +        "description": "kinds of data the module confirmedly has for the object",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "info_url": {
        +        "description": "the object (or its limited breakdown) inside the module on spytrend.com",
        +        "type": "string"
        +      },
        +      "module": {
        +        "description": "nutra | crypto | web2app | search_arb | startups",
        +        "type": "string"
        +      },
        +      "object_id": {
        +        "description": "the ad id, or the site domain for site rows",
        +        "type": "string"
        +      },
        +      "preland_downloadable": {
        +        "description": "Nutra / Crypto: the saved pre-lander can be downloaded in the module",
        +        "type": "boolean"
        +      },
        +      "subscription_status": {
        +        "description": "active | not_connected",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Addedget_web2app_market
    • Changedget_webmaster2 fields changed
      • changedInput schema / properties / source / description
        Previous value: -"webmaster corpus: meta (default, FREE) or tiktok (⚠️ 100 tokens for the TikTok cluster card; Pro plan required)"New value: +"webmaster corpus: meta (default, FREE) or tiktok (⚠️ 10 MCP credits for the TikTok cluster card; Pro plan required)"
      • addedOutput schema / properties / addon_hints
        Added value: +{
        +  "description": "Add-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about.",
        +  "items": {
        +    "properties": {
        +      "available_data_types": {
        +        "description": "kinds of data the module confirmedly has for the object",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "info_url": {
        +        "description": "the object (or its limited breakdown) inside the module on spytrend.com",
        +        "type": "string"
        +      },
        +      "module": {
        +        "description": "nutra | crypto | web2app | search_arb | startups",
        +        "type": "string"
        +      },
        +      "object_id": {
        +        "description": "the ad id, or the site domain for site rows",
        +        "type": "string"
        +      },
        +      "preland_downloadable": {
        +        "description": "Nutra / Crypto: the saved pre-lander can be downloaded in the module",
        +        "type": "boolean"
        +      },
        +      "subscription_status": {
        +        "description": "active | not_connected",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Changedget_webmaster_similarity_facets1 field changed
      • addedOutput schema / properties / addon_hints
        Added value: +{
        +  "description": "Add-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about.",
        +  "items": {
        +    "properties": {
        +      "available_data_types": {
        +        "description": "kinds of data the module confirmedly has for the object",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "info_url": {
        +        "description": "the object (or its limited breakdown) inside the module on spytrend.com",
        +        "type": "string"
        +      },
        +      "module": {
        +        "description": "nutra | crypto | web2app | search_arb | startups",
        +        "type": "string"
        +      },
        +      "object_id": {
        +        "description": "the ad id, or the site domain for site rows",
        +        "type": "string"
        +      },
        +      "preland_downloadable": {
        +        "description": "Nutra / Crypto: the saved pre-lander can be downloaded in the module",
        +        "type": "boolean"
        +      },
        +      "subscription_status": {
        +        "description": "active | not_connected",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Changedlist_favorites1 field changed
      • addedOutput schema / properties / addon_hints
        Added value: +{
        +  "description": "Add-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about.",
        +  "items": {
        +    "properties": {
        +      "available_data_types": {
        +        "description": "kinds of data the module confirmedly has for the object",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "info_url": {
        +        "description": "the object (or its limited breakdown) inside the module on spytrend.com",
        +        "type": "string"
        +      },
        +      "module": {
        +        "description": "nutra | crypto | web2app | search_arb | startups",
        +        "type": "string"
        +      },
        +      "object_id": {
        +        "description": "the ad id, or the site domain for site rows",
        +        "type": "string"
        +      },
        +      "preland_downloadable": {
        +        "description": "Nutra / Crypto: the saved pre-lander can be downloaded in the module",
        +        "type": "boolean"
        +      },
        +      "subscription_status": {
        +        "description": "active | not_connected",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Changedsearch_ads17 fields changed
      • changedInput schema / properties / formats / description
        Previous value: -"creative formats: video, carousel, single, dynamic, carousel_multilang, carousel_multilang_categorized. Multilang upload detection is independent of languages; the categorized variant additionally requires an AI category. Values combine with OR. Search costs 1 token per row; opening a multilang ad costs 50 tokens."New value: +"creative formats: video, carousel, single, dynamic, carousel_multilang, carousel_multilang_categorized. Multilang upload detection is independent of languages; the categorized variant additionally requires an AI category. Values combine with OR. Search costs 1 MCP credit per row; opening a multilang ad costs 50 MCP credits."
      • changedInput schema / properties / limit / description
        Previous value: -"max ad rows per page: Meta returns at most 20 (larger legacy requests are normalized to 20); follow pagination.next_cursor for the rest, with all row fields intact. TikTok defaults to 10 at 100 tokens per delivered row. Meta costs 1 token per delivered row."New value: +"max ad rows per page: Meta returns at most 20 (larger legacy requests are normalized to 20); follow pagination.next_cursor for the rest, with all row fields intact. TikTok defaults to 10 at 10 MCP credits per delivered row. Meta costs 1 MCP credit per delivered row."
      • removedInput schema / properties / sa_country
        Removed value: -{
        -  "description": "ISO-2 codes of the countries the ads are shown in (OR), e.g. US, GB, DE — NOT the visitor country of the site. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_lang
        Removed value: -{
        -  "description": "ISO 639-1 language codes of the search phrases (OR), e.g. en, de, es. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_network
        Removed value: -{
        -  "description": "search-arbitrage network slugs (OR): the search-ads network the site monetises through, e.g. tonic, visymo, medianet, cortex, predicto, codefuel, brandclick, system1. Live list with counts: search_arbitrage_facets. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_phrase
        Removed value: -{
        -  "description": "exact search phrases (OR), lower-case, as returned by search_arbitrage_phrases; a phrase containing a comma cannot be used here. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_pub
        Removed value: -{
        -  "description": "Google publisher account ids (OR), e.g. pub-1902826156353358: the AdSense/AFS account the site earns under — one account usually means one operator. A bare number or ca-pub-… is accepted. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_source
        Removed value: -{
        -  "description": "how the site earns from search (OR): rsoc (Google related-search ads through a partner), afs (Google AdSense for Search), yahoo_feed, bing_feed or other. Implies search_arbitrage.",
        -  "items": {
        -    "enum": [
        -      "rsoc",
        -      "afs",
        -      "yahoo_feed",
        -      "bing_feed",
        -      "other"
        -    ],
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_topic
        Removed value: -{
        -  "description": "topic slugs of the search phrases the sites push (OR); live list with counts: search_arbitrage_facets. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / search_arbitrage
        Removed value: -{
        -  "description": "SEARCH ARBITRAGE filter (confirmed search-arbitrage sites only): true = keep only search-arbitrage ads — ads whose landing page earns from search-ads clicks (Google RSOC/AFS through networks such as Tonic or Visymo, Yahoo/Bing feeds) instead of selling a product. Every sa_* filter implies it. Omit or false = no search-arbitrage filter. Meta source only. Valid sa_* values and counts: search_arbitrage_facets; the phrases behind them: search_arbitrage_phrases.",
        -  "type": "boolean"
        -}
      • changedInput schema / properties / source / description
        Previous value: -"ad 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."New value: +"ad corpus to search: meta (default — the Facebook/Meta library, 1 MCP credit per delivered row) or tiktok (the TikTok corpus — ⚠️ PAID: 10 MCP credits per DELIVERED TikTok ad row, embedded media links included; Pro plan required; default limit drops to 10). platforms=[tiktok] does NOT do this."
      • addedOutput schema / properties / addon_hints
        Added value: +{
        +  "description": "Add-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about.",
        +  "items": {
        +    "properties": {
        +      "available_data_types": {
        +        "description": "kinds of data the module confirmedly has for the object",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "info_url": {
        +        "description": "the object (or its limited breakdown) inside the module on spytrend.com",
        +        "type": "string"
        +      },
        +      "module": {
        +        "description": "nutra | crypto | web2app | search_arb | startups",
        +        "type": "string"
        +      },
        +      "object_id": {
        +        "description": "the ad id, or the site domain for site rows",
        +        "type": "string"
        +      },
        +      "preland_downloadable": {
        +        "description": "Nutra / Crypto: the saved pre-lander can be downloaded in the module",
        +        "type": "boolean"
        +      },
        +      "subscription_status": {
        +        "description": "active | not_connected",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / data / items / properties / also_in
        Added value: +{
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedOutput schema / properties / data / items / properties / multilang_black_unresolved
        Added value: +{
        +  "type": [
        +    "null",
        +    "boolean"
        +  ]
        +}
      • addedOutput schema / properties / data / items / properties / opening_price / properties / MCP credits
        Added value: +{
        +  "type": [
        +    "null",
        +    "integer"
        +  ]
        +}
      • removedOutput schema / properties / data / items / properties / opening_price / properties / tokens
        Removed value: -{
        -  "type": [
        -    "null",
        -    "integer"
        -  ]
        -}
      • changedOutput schema / properties / data / items / properties / opening_price / required
        Previous value: -[
        -  "status",
        -  "tokens",
        -  "unit",
        -  "billing_basis"
        -]New value: +[
        +  "status",
        +  "MCP credits",
        +  "unit",
        +  "billing_basis"
        +]
    • Changedsearch_advertisers10 fields changed
      • changedInput schema / properties / limit / description
        Previous value: -"max 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."New value: +"max results, 1-50 (default 20 — this typeahead is capped at 50 upstream; a larger value is clamped, not rejected). Each delivered result costs 1 MCP credit."
      • removedInput schema / properties / sa_country
        Removed value: -{
        -  "description": "ISO-2 codes of the countries the ads are shown in (OR), e.g. US, GB, DE — NOT the visitor country of the site. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_lang
        Removed value: -{
        -  "description": "ISO 639-1 language codes of the search phrases (OR), e.g. en, de, es. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_network
        Removed value: -{
        -  "description": "search-arbitrage network slugs (OR): the search-ads network the site monetises through, e.g. tonic, visymo, medianet, cortex, predicto, codefuel, brandclick, system1. Live list with counts: search_arbitrage_facets. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_phrase
        Removed value: -{
        -  "description": "exact search phrases (OR), lower-case, as returned by search_arbitrage_phrases; a phrase containing a comma cannot be used here. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_pub
        Removed value: -{
        -  "description": "Google publisher account ids (OR), e.g. pub-1902826156353358: the AdSense/AFS account the site earns under — one account usually means one operator. A bare number or ca-pub-… is accepted. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_source
        Removed value: -{
        -  "description": "how the site earns from search (OR): rsoc (Google related-search ads through a partner), afs (Google AdSense for Search), yahoo_feed, bing_feed or other. Implies search_arbitrage.",
        -  "items": {
        -    "enum": [
        -      "rsoc",
        -      "afs",
        -      "yahoo_feed",
        -      "bing_feed",
        -      "other"
        -    ],
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_topic
        Removed value: -{
        -  "description": "topic slugs of the search phrases the sites push (OR); live list with counts: search_arbitrage_facets. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / search_arbitrage
        Removed value: -{
        -  "description": "SEARCH ARBITRAGE filter (confirmed search-arbitrage sites only): true = list only advertisers whose ads lead to search-arbitrage pages — pages that earn from search-ads clicks (Google RSOC/AFS through networks such as Tonic or Visymo, Yahoo/Bing feeds) instead of selling a product — ordered by total ads. Every sa_* filter implies it. Omit or false = the plain name/page-id typeahead. Valid sa_* values and counts: search_arbitrage_facets; the phrases behind them: search_arbitrage_phrases.",
        -  "type": "boolean"
        -}
      • addedOutput schema / properties / addon_hints
        Added value: +{
        +  "description": "Add-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about.",
        +  "items": {
        +    "properties": {
        +      "available_data_types": {
        +        "description": "kinds of data the module confirmedly has for the object",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "info_url": {
        +        "description": "the object (or its limited breakdown) inside the module on spytrend.com",
        +        "type": "string"
        +      },
        +      "module": {
        +        "description": "nutra | crypto | web2app | search_arb | startups",
        +        "type": "string"
        +      },
        +      "object_id": {
        +        "description": "the ad id, or the site domain for site rows",
        +        "type": "string"
        +      },
        +      "preland_downloadable": {
        +        "description": "Nutra / Crypto: the saved pre-lander can be downloaded in the module",
        +        "type": "boolean"
        +      },
        +      "subscription_status": {
        +        "description": "active | not_connected",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Addedsearch_affiliate_offers
    • Removedsearch_arbitrage_facets
    • Removedsearch_arbitrage_phrases
    • Changedsearch_content2 fields changed
      • changedInput schema / properties / limit / description
        Previous value: -"max rows (default 10, at most 10; each delivered row costs 1 token). There is no paging."New value: +"max rows (default 10, at most 10; each delivered row costs 1 MCP credit). There is no paging."
      • addedOutput schema / properties / addon_hints
        Added value: +{
        +  "description": "Add-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about.",
        +  "items": {
        +    "properties": {
        +      "available_data_types": {
        +        "description": "kinds of data the module confirmedly has for the object",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "info_url": {
        +        "description": "the object (or its limited breakdown) inside the module on spytrend.com",
        +        "type": "string"
        +      },
        +      "module": {
        +        "description": "nutra | crypto | web2app | search_arb | startups",
        +        "type": "string"
        +      },
        +      "object_id": {
        +        "description": "the ad id, or the site domain for site rows",
        +        "type": "string"
        +      },
        +      "preland_downloadable": {
        +        "description": "Nutra / Crypto: the saved pre-lander can be downloaded in the module",
        +        "type": "boolean"
        +      },
        +      "subscription_status": {
        +        "description": "active | not_connected",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Changedsearch_creatives10 fields changed
      • changedInput schema / properties / limit / description
        Previous value: -"max metadata rows (default 20, max 200; each delivered row costs 1 token) — fetch media with get_media (entity_type=creo, 10 tokens per creative)."New value: +"max metadata rows (default 20, max 200; each delivered row costs 1 MCP credit) — fetch media with get_media (entity_type=creo, 10 MCP credits per creative)."
      • removedInput schema / properties / sa_country
        Removed value: -{
        -  "description": "ISO-2 codes of the countries the ads are shown in (OR), e.g. US, GB, DE — NOT the visitor country of the site. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_lang
        Removed value: -{
        -  "description": "ISO 639-1 language codes of the search phrases (OR), e.g. en, de, es. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_network
        Removed value: -{
        -  "description": "search-arbitrage network slugs (OR): the search-ads network the site monetises through, e.g. tonic, visymo, medianet, cortex, predicto, codefuel, brandclick, system1. Live list with counts: search_arbitrage_facets. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_phrase
        Removed value: -{
        -  "description": "exact search phrases (OR), lower-case, as returned by search_arbitrage_phrases; a phrase containing a comma cannot be used here. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_pub
        Removed value: -{
        -  "description": "Google publisher account ids (OR), e.g. pub-1902826156353358: the AdSense/AFS account the site earns under — one account usually means one operator. A bare number or ca-pub-… is accepted. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_source
        Removed value: -{
        -  "description": "how the site earns from search (OR): rsoc (Google related-search ads through a partner), afs (Google AdSense for Search), yahoo_feed, bing_feed or other. Implies search_arbitrage.",
        -  "items": {
        -    "enum": [
        -      "rsoc",
        -      "afs",
        -      "yahoo_feed",
        -      "bing_feed",
        -      "other"
        -    ],
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_topic
        Removed value: -{
        -  "description": "topic slugs of the search phrases the sites push (OR); live list with counts: search_arbitrage_facets. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / search_arbitrage
        Removed value: -{
        -  "description": "SEARCH ARBITRAGE filter (confirmed search-arbitrage sites only): true = keep only creatives of search-arbitrage ads — ads whose landing page earns from search-ads clicks (Google RSOC/AFS through networks such as Tonic or Visymo, Yahoo/Bing feeds) instead of selling a product. Every sa_* filter implies it. Omit or false = no search-arbitrage filter. Valid sa_* values and counts: search_arbitrage_facets; the phrases behind them: search_arbitrage_phrases.",
        -  "type": "boolean"
        -}
      • addedOutput schema / properties / addon_hints
        Added value: +{
        +  "description": "Add-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about.",
        +  "items": {
        +    "properties": {
        +      "available_data_types": {
        +        "description": "kinds of data the module confirmedly has for the object",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "info_url": {
        +        "description": "the object (or its limited breakdown) inside the module on spytrend.com",
        +        "type": "string"
        +      },
        +      "module": {
        +        "description": "nutra | crypto | web2app | search_arb | startups",
        +        "type": "string"
        +      },
        +      "object_id": {
        +        "description": "the ad id, or the site domain for site rows",
        +        "type": "string"
        +      },
        +      "preland_downloadable": {
        +        "description": "Nutra / Crypto: the saved pre-lander can be downloaded in the module",
        +        "type": "boolean"
        +      },
        +      "subscription_status": {
        +        "description": "active | not_connected",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Changedsearch_hubs2 fields changed
      • changedInput schema / properties / limit / description
        Previous value: -"profiles only: max results (default 20; each delivered profile costs 1 token). The catalog call (no hub) is free."New value: +"profiles only: max results (default 20; each delivered profile costs 1 MCP credit). The catalog call (no hub) is free."
      • addedOutput schema / properties / addon_hints
        Added value: +{
        +  "description": "Add-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about.",
        +  "items": {
        +    "properties": {
        +      "available_data_types": {
        +        "description": "kinds of data the module confirmedly has for the object",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "info_url": {
        +        "description": "the object (or its limited breakdown) inside the module on spytrend.com",
        +        "type": "string"
        +      },
        +      "module": {
        +        "description": "nutra | crypto | web2app | search_arb | startups",
        +        "type": "string"
        +      },
        +      "object_id": {
        +        "description": "the ad id, or the site domain for site rows",
        +        "type": "string"
        +      },
        +      "preland_downloadable": {
        +        "description": "Nutra / Crypto: the saved pre-lander can be downloaded in the module",
        +        "type": "boolean"
        +      },
        +      "subscription_status": {
        +        "description": "active | not_connected",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Changedsearch_influencers2 fields changed
      • changedInput schema / properties / limit / description
        Previous value: -"max rows (default 10, at most 10; each row with statistics costs 1 token)"New value: +"max rows (default 10, at most 10; each row with statistics costs 1 MCP credit)"
      • addedOutput schema / properties / addon_hints
        Added value: +{
        +  "description": "Add-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about.",
        +  "items": {
        +    "properties": {
        +      "available_data_types": {
        +        "description": "kinds of data the module confirmedly has for the object",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "info_url": {
        +        "description": "the object (or its limited breakdown) inside the module on spytrend.com",
        +        "type": "string"
        +      },
        +      "module": {
        +        "description": "nutra | crypto | web2app | search_arb | startups",
        +        "type": "string"
        +      },
        +      "object_id": {
        +        "description": "the ad id, or the site domain for site rows",
        +        "type": "string"
        +      },
        +      "preland_downloadable": {
        +        "description": "Nutra / Crypto: the saved pre-lander can be downloaded in the module",
        +        "type": "boolean"
        +      },
        +      "subscription_status": {
        +        "description": "active | not_connected",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Changedsearch_products2 fields changed
      • changedInput schema / properties / limit / description
        Previous value: -"max results per call (default 20, at most 100 — the products API serves 100 rows per page; a larger value is reduced to 100 and noted in params.normalized, page further with offset; each delivered result costs 1 token)."New value: +"max results per call (default 20, at most 100 — the products API serves 100 rows per page; a larger value is reduced to 100 and noted in params.normalized, page further with offset; each delivered result costs 1 MCP credit)."
      • addedOutput schema / properties / addon_hints
        Added value: +{
        +  "description": "Add-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about.",
        +  "items": {
        +    "properties": {
        +      "available_data_types": {
        +        "description": "kinds of data the module confirmedly has for the object",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "info_url": {
        +        "description": "the object (or its limited breakdown) inside the module on spytrend.com",
        +        "type": "string"
        +      },
        +      "module": {
        +        "description": "nutra | crypto | web2app | search_arb | startups",
        +        "type": "string"
        +      },
        +      "object_id": {
        +        "description": "the ad id, or the site domain for site rows",
        +        "type": "string"
        +      },
        +      "preland_downloadable": {
        +        "description": "Nutra / Crypto: the saved pre-lander can be downloaded in the module",
        +        "type": "boolean"
        +      },
        +      "subscription_status": {
        +        "description": "active | not_connected",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
    • Changedsearch_shops11 fields changed
      • changedInput schema / properties / limit / description
        Previous value: -"max results (default 20, at most 200; each delivered result costs 1 token). Without a Shops subscription the catalogue answers a free sample of a few rows whatever the limit: params.normalized then reports limit as requested→delivered, note says the page is a free sample and has_more stays true while total exceeds offset+rows."New value: +"max results (default 20, at most 200; each delivered result costs 1 MCP credit). Without a Shops subscription the catalogue answers a free sample of a few rows whatever the limit: params.normalized then reports limit as requested→delivered, note says the page is a free sample and has_more stays true while total exceeds offset+rows."
      • removedInput schema / properties / sa_country
        Removed value: -{
        -  "description": "ISO-2 codes of the countries the ads are shown in (OR), e.g. US, GB, DE — NOT the visitor country of the site. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_lang
        Removed value: -{
        -  "description": "ISO 639-1 language codes of the search phrases (OR), e.g. en, de, es. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_network
        Removed value: -{
        -  "description": "search-arbitrage network slugs (OR): the search-ads network the site monetises through, e.g. tonic, visymo, medianet, cortex, predicto, codefuel, brandclick, system1. Live list with counts: search_arbitrage_facets. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_phrase
        Removed value: -{
        -  "description": "exact search phrases (OR), lower-case, as returned by search_arbitrage_phrases; a phrase containing a comma cannot be used here. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_pub
        Removed value: -{
        -  "description": "Google publisher account ids (OR), e.g. pub-1902826156353358: the AdSense/AFS account the site earns under — one account usually means one operator. A bare number or ca-pub-… is accepted. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_source
        Removed value: -{
        -  "description": "how the site earns from search (OR): rsoc (Google related-search ads through a partner), afs (Google AdSense for Search), yahoo_feed, bing_feed or other. Implies search_arbitrage.",
        -  "items": {
        -    "enum": [
        -      "rsoc",
        -      "afs",
        -      "yahoo_feed",
        -      "bing_feed",
        -      "other"
        -    ],
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_topic
        Removed value: -{
        -  "description": "topic slugs of the search phrases the sites push (OR); live list with counts: search_arbitrage_facets. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / search_arbitrage
        Removed value: -{
        -  "description": "SEARCH ARBITRAGE filter (confirmed search-arbitrage sites only): true = keep only search-arbitrage sites — domains that earn from search-ads clicks (Google RSOC/AFS through networks such as Tonic or Visymo, Yahoo/Bing feeds) instead of selling a product. Every sa_* filter implies it. Omit or false = no search-arbitrage filter. Valid sa_* values and counts: search_arbitrage_facets; the phrases behind them: search_arbitrage_phrases.",
        -  "type": "boolean"
        -}
      • addedOutput schema / properties / addon_hints
        Added value: +{
        +  "description": "Add-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about.",
        +  "items": {
        +    "properties": {
        +      "available_data_types": {
        +        "description": "kinds of data the module confirmedly has for the object",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "info_url": {
        +        "description": "the object (or its limited breakdown) inside the module on spytrend.com",
        +        "type": "string"
        +      },
        +      "module": {
        +        "description": "nutra | crypto | web2app | search_arb | startups",
        +        "type": "string"
        +      },
        +      "object_id": {
        +        "description": "the ad id, or the site domain for site rows",
        +        "type": "string"
        +      },
        +      "preland_downloadable": {
        +        "description": "Nutra / Crypto: the saved pre-lander can be downloaded in the module",
        +        "type": "boolean"
        +      },
        +      "subscription_status": {
        +        "description": "active | not_connected",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / data / items / properties / also_in
        Added value: +{
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
    • Changedsearch_webmasters11 fields changed
      • changedInput schema / properties / limit / description
        Previous value: -"max results (default 20; each delivered result costs 1 token)."New value: +"max results (default 20; each delivered result costs 1 MCP credit)."
      • removedInput schema / properties / sa_country
        Removed value: -{
        -  "description": "ISO-2 codes of the countries the ads are shown in (OR), e.g. US, GB, DE — NOT the visitor country of the site. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_lang
        Removed value: -{
        -  "description": "ISO 639-1 language codes of the search phrases (OR), e.g. en, de, es. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_network
        Removed value: -{
        -  "description": "search-arbitrage network slugs (OR): the search-ads network the site monetises through, e.g. tonic, visymo, medianet, cortex, predicto, codefuel, brandclick, system1. Live list with counts: search_arbitrage_facets. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_phrase
        Removed value: -{
        -  "description": "exact search phrases (OR), lower-case, as returned by search_arbitrage_phrases; a phrase containing a comma cannot be used here. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_pub
        Removed value: -{
        -  "description": "Google publisher account ids (OR), e.g. pub-1902826156353358: the AdSense/AFS account the site earns under — one account usually means one operator. A bare number or ca-pub-… is accepted. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_source
        Removed value: -{
        -  "description": "how the site earns from search (OR): rsoc (Google related-search ads through a partner), afs (Google AdSense for Search), yahoo_feed, bing_feed or other. Implies search_arbitrage.",
        -  "items": {
        -    "enum": [
        -      "rsoc",
        -      "afs",
        -      "yahoo_feed",
        -      "bing_feed",
        -      "other"
        -    ],
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / sa_topic
        Removed value: -{
        -  "description": "topic slugs of the search phrases the sites push (OR); live list with counts: search_arbitrage_facets. Implies search_arbitrage.",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedInput schema / properties / search_arbitrage
        Removed value: -{
        -  "description": "SEARCH ARBITRAGE filter (confirmed search-arbitrage sites only): true = keep only webmasters (affiliate networks) whose ads lead to search-arbitrage pages — pages that earn from search-ads clicks (Google RSOC/AFS through networks such as Tonic or Visymo, Yahoo/Bing feeds) instead of selling a product. Every sa_* filter implies it. Omit or false = no search-arbitrage filter. Valid sa_* values and counts: search_arbitrage_facets; the phrases behind them: search_arbitrage_phrases.",
        -  "type": "boolean"
        -}
      • changedInput schema / properties / source / description
        Previous value: -"webmaster 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)"New value: +"webmaster corpus: meta (default — Facebook/Meta networks, 1 MCP credit per delivered row) or tiktok (TikTok business-id clusters — ⚠️ PAID: 10 MCP credits per DELIVERED row; Pro plan required; default limit drops to 10, server caps TikTok at 100)"
      • addedOutput schema / properties / addon_hints
        Added value: +{
        +  "description": "Add-on modules that have additional data for objects of this result (no prices, no paid values). subscription_status=active: the account has the module — use its normal path. Do not push a purchase the user did not ask about.",
        +  "items": {
        +    "properties": {
        +      "available_data_types": {
        +        "description": "kinds of data the module confirmedly has for the object",
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "info_url": {
        +        "description": "the object (or its limited breakdown) inside the module on spytrend.com",
        +        "type": "string"
        +      },
        +      "module": {
        +        "description": "nutra | crypto | web2app | search_arb | startups",
        +        "type": "string"
        +      },
        +      "object_id": {
        +        "description": "the ad id, or the site domain for site rows",
        +        "type": "string"
        +      },
        +      "preland_downloadable": {
        +        "description": "Nutra / Crypto: the saved pre-lander can be downloaded in the module",
        +        "type": "boolean"
        +      },
        +      "subscription_status": {
        +        "description": "active | not_connected",
        +        "type": "string"
        +      }
        +    },
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
  2. 8 tool updates
    • Changedget_trends4 fields changed
      • removedInput schema / properties / sa_evidence_min
        Removed value: -{
        -  "description": "minimum evidence share of the site, 0 to 1 (e.g. 0.8): the fraction of the site's checked pages that showed the network's markers; higher means a more certain verdict. Implies search_arbitrage.",
        -  "maximum": 1,
        -  "minimum": 0,
        -  "type": "number"
        -}
      • removedInput schema / properties / sa_link
        Removed value: -{
        -  "description": "how the ad reaches the site: tracker (a network tracking/redirect link that carries the phrase) or direct (the ad points straight at the monetised site). Omit for both. Implies search_arbitrage.",
        -  "enum": [
        -    "tracker",
        -    "direct"
        -  ],
        -  "type": "string"
        -}
      • removedInput schema / properties / sa_verdict
        Removed value: -{
        -  "description": "detection confidence (OR): confirmed (network markers found on the site) or probable. Omit for both. Implies search_arbitrage.",
        -  "items": {
        -    "enum": [
        -      "confirmed",
        -      "probable"
        -    ],
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • changedInput schema / properties / search_arbitrage / description
        Previous value: -"SEARCH ARBITRAGE filter, every dimension except apps: true = build the ranking only from search-arbitrage ads — ads whose landing page earns from search-ads clicks (Google RSOC/AFS through networks such as Tonic or Visymo, Yahoo/Bing feeds) instead of selling a product. Every sa_* filter implies it. Omit or false = no search-arbitrage filter. Valid sa_* values and counts: search_arbitrage_facets; the phrases behind them: search_arbitrage_phrases."New value: +"SEARCH ARBITRAGE filter (confirmed search-arbitrage sites only), every dimension except apps: true = build the ranking only from search-arbitrage ads — ads whose landing page earns from search-ads clicks (Google RSOC/AFS through networks such as Tonic or Visymo, Yahoo/Bing feeds) instead of selling a product. Every sa_* filter implies it. Omit or false = no search-arbitrage filter. Valid sa_* values and counts: search_arbitrage_facets; the phrases behind them: search_arbitrage_phrases."
    • Changedsearch_ads4 fields changed
      • removedInput schema / properties / sa_evidence_min
        Removed value: -{
        -  "description": "minimum evidence share of the site, 0 to 1 (e.g. 0.8): the fraction of the site's checked pages that showed the network's markers; higher means a more certain verdict. Implies search_arbitrage.",
        -  "maximum": 1,
        -  "minimum": 0,
        -  "type": "number"
        -}
      • removedInput schema / properties / sa_link
        Removed value: -{
        -  "description": "how the ad reaches the site: tracker (a network tracking/redirect link that carries the phrase) or direct (the ad points straight at the monetised site). Omit for both. Implies search_arbitrage.",
        -  "enum": [
        -    "tracker",
        -    "direct"
        -  ],
        -  "type": "string"
        -}
      • removedInput schema / properties / sa_verdict
        Removed value: -{
        -  "description": "detection confidence (OR): confirmed (network markers found on the site) or probable. Omit for both. Implies search_arbitrage.",
        -  "items": {
        -    "enum": [
        -      "confirmed",
        -      "probable"
        -    ],
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • changedInput schema / properties / search_arbitrage / description
        Previous value: -"SEARCH ARBITRAGE filter: true = keep only search-arbitrage ads — ads whose landing page earns from search-ads clicks (Google RSOC/AFS through networks such as Tonic or Visymo, Yahoo/Bing feeds) instead of selling a product. Every sa_* filter implies it. Omit or false = no search-arbitrage filter. Meta source only. Valid sa_* values and counts: search_arbitrage_facets; the phrases behind them: search_arbitrage_phrases."New value: +"SEARCH ARBITRAGE filter (confirmed search-arbitrage sites only): true = keep only search-arbitrage ads — ads whose landing page earns from search-ads clicks (Google RSOC/AFS through networks such as Tonic or Visymo, Yahoo/Bing feeds) instead of selling a product. Every sa_* filter implies it. Omit or false = no search-arbitrage filter. Meta source only. Valid sa_* values and counts: search_arbitrage_facets; the phrases behind them: search_arbitrage_phrases."
    • Changedsearch_advertisers4 fields changed
      • removedInput schema / properties / sa_evidence_min
        Removed value: -{
        -  "description": "minimum evidence share of the site, 0 to 1 (e.g. 0.8): the fraction of the site's checked pages that showed the network's markers; higher means a more certain verdict. Implies search_arbitrage.",
        -  "maximum": 1,
        -  "minimum": 0,
        -  "type": "number"
        -}
      • removedInput schema / properties / sa_link
        Removed value: -{
        -  "description": "how the ad reaches the site: tracker (a network tracking/redirect link that carries the phrase) or direct (the ad points straight at the monetised site). Omit for both. Implies search_arbitrage.",
        -  "enum": [
        -    "tracker",
        -    "direct"
        -  ],
        -  "type": "string"
        -}
      • removedInput schema / properties / sa_verdict
        Removed value: -{
        -  "description": "detection confidence (OR): confirmed (network markers found on the site) or probable. Omit for both. Implies search_arbitrage.",
        -  "items": {
        -    "enum": [
        -      "confirmed",
        -      "probable"
        -    ],
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • changedInput schema / properties / search_arbitrage / description
        Previous value: -"SEARCH ARBITRAGE filter: true = list only advertisers whose ads lead to search-arbitrage pages — pages that earn from search-ads clicks (Google RSOC/AFS through networks such as Tonic or Visymo, Yahoo/Bing feeds) instead of selling a product — ordered by total ads. Every sa_* filter implies it. Omit or false = the plain name/page-id typeahead. Valid sa_* values and counts: search_arbitrage_facets; the phrases behind them: search_arbitrage_phrases."New value: +"SEARCH ARBITRAGE filter (confirmed search-arbitrage sites only): true = list only advertisers whose ads lead to search-arbitrage pages — pages that earn from search-ads clicks (Google RSOC/AFS through networks such as Tonic or Visymo, Yahoo/Bing feeds) instead of selling a product — ordered by total ads. Every sa_* filter implies it. Omit or false = the plain name/page-id typeahead. Valid sa_* values and counts: search_arbitrage_facets; the phrases behind them: search_arbitrage_phrases."
    • Changedsearch_arbitrage_facets5 fields changed
      • removedInput schema / properties / sa_evidence_min
        Removed value: -{
        -  "description": "count only sites with at least this evidence share, 0 to 1 (e.g. 0.8)",
        -  "maximum": 1,
        -  "minimum": 0,
        -  "type": "number"
        -}
      • removedInput schema / properties / sa_link
        Removed value: -{
        -  "description": "tracker (network tracking/redirect link) or direct (ad points straight at the monetised site); omit for both",
        -  "enum": [
        -    "tracker",
        -    "direct"
        -  ],
        -  "type": "string"
        -}
      • removedInput schema / properties / sa_verdict
        Removed value: -{
        -  "description": "count only this detection confidence (OR): confirmed or probable; omit for both",
        -  "items": {
        -    "enum": [
        -      "confirmed",
        -      "probable"
        -    ],
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedOutput schema / properties / link
        Removed value: -{
        -  "items": {
        -    "additionalProperties": false,
        -    "properties": {
        -      "ads": {
        -        "type": "integer"
        -      },
        -      "domains": {
        -        "type": "integer"
        -      },
        -      "label": {
        -        "type": "string"
        -      },
        -      "network_label": {
        -        "type": "string"
        -      },
        -      "value": {
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "value",
        -      "ads",
        -      "domains"
        -    ],
        -    "type": "object"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • removedOutput schema / properties / verdict
        Removed value: -{
        -  "items": {
        -    "additionalProperties": false,
        -    "properties": {
        -      "ads": {
        -        "type": "integer"
        -      },
        -      "domains": {
        -        "type": "integer"
        -      },
        -      "label": {
        -        "type": "string"
        -      },
        -      "network_label": {
        -        "type": "string"
        -      },
        -      "value": {
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "value",
        -      "ads",
        -      "domains"
        -    ],
        -    "type": "object"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
    • Changedsearch_arbitrage_phrases3 fields changed
      • removedInput schema / properties / sa_evidence_min
        Removed value: -{
        -  "description": "minimum evidence share of the site, 0 to 1 (e.g. 0.8)",
        -  "maximum": 1,
        -  "minimum": 0,
        -  "type": "number"
        -}
      • removedInput schema / properties / sa_link
        Removed value: -{
        -  "description": "tracker (network tracking/redirect link) or direct (ad points straight at the monetised site); omit for both",
        -  "enum": [
        -    "tracker",
        -    "direct"
        -  ],
        -  "type": "string"
        -}
      • removedInput schema / properties / sa_verdict
        Removed value: -{
        -  "description": "detection confidence (OR): confirmed or probable; omit for both",
        -  "items": {
        -    "enum": [
        -      "confirmed",
        -      "probable"
        -    ],
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
    • Changedsearch_creatives4 fields changed
      • removedInput schema / properties / sa_evidence_min
        Removed value: -{
        -  "description": "minimum evidence share of the site, 0 to 1 (e.g. 0.8): the fraction of the site's checked pages that showed the network's markers; higher means a more certain verdict. Implies search_arbitrage.",
        -  "maximum": 1,
        -  "minimum": 0,
        -  "type": "number"
        -}
      • removedInput schema / properties / sa_link
        Removed value: -{
        -  "description": "how the ad reaches the site: tracker (a network tracking/redirect link that carries the phrase) or direct (the ad points straight at the monetised site). Omit for both. Implies search_arbitrage.",
        -  "enum": [
        -    "tracker",
        -    "direct"
        -  ],
        -  "type": "string"
        -}
      • removedInput schema / properties / sa_verdict
        Removed value: -{
        -  "description": "detection confidence (OR): confirmed (network markers found on the site) or probable. Omit for both. Implies search_arbitrage.",
        -  "items": {
        -    "enum": [
        -      "confirmed",
        -      "probable"
        -    ],
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • changedInput schema / properties / search_arbitrage / description
        Previous value: -"SEARCH ARBITRAGE filter: true = keep only creatives of search-arbitrage ads — ads whose landing page earns from search-ads clicks (Google RSOC/AFS through networks such as Tonic or Visymo, Yahoo/Bing feeds) instead of selling a product. Every sa_* filter implies it. Omit or false = no search-arbitrage filter. Valid sa_* values and counts: search_arbitrage_facets; the phrases behind them: search_arbitrage_phrases."New value: +"SEARCH ARBITRAGE filter (confirmed search-arbitrage sites only): true = keep only creatives of search-arbitrage ads — ads whose landing page earns from search-ads clicks (Google RSOC/AFS through networks such as Tonic or Visymo, Yahoo/Bing feeds) instead of selling a product. Every sa_* filter implies it. Omit or false = no search-arbitrage filter. Valid sa_* values and counts: search_arbitrage_facets; the phrases behind them: search_arbitrage_phrases."
    • Changedsearch_shops4 fields changed
      • removedInput schema / properties / sa_evidence_min
        Removed value: -{
        -  "description": "minimum evidence share of the site, 0 to 1 (e.g. 0.8): the fraction of the site's checked pages that showed the network's markers; higher means a more certain verdict. Implies search_arbitrage.",
        -  "maximum": 1,
        -  "minimum": 0,
        -  "type": "number"
        -}
      • removedInput schema / properties / sa_link
        Removed value: -{
        -  "description": "how the ad reaches the site: tracker (a network tracking/redirect link that carries the phrase) or direct (the ad points straight at the monetised site). Omit for both. Implies search_arbitrage.",
        -  "enum": [
        -    "tracker",
        -    "direct"
        -  ],
        -  "type": "string"
        -}
      • removedInput schema / properties / sa_verdict
        Removed value: -{
        -  "description": "detection confidence (OR): confirmed (network markers found on the site) or probable. Omit for both. Implies search_arbitrage.",
        -  "items": {
        -    "enum": [
        -      "confirmed",
        -      "probable"
        -    ],
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • changedInput schema / properties / search_arbitrage / description
        Previous value: -"SEARCH ARBITRAGE filter: true = keep only search-arbitrage sites — domains that earn from search-ads clicks (Google RSOC/AFS through networks such as Tonic or Visymo, Yahoo/Bing feeds) instead of selling a product. Every sa_* filter implies it. Omit or false = no search-arbitrage filter. Valid sa_* values and counts: search_arbitrage_facets; the phrases behind them: search_arbitrage_phrases."New value: +"SEARCH ARBITRAGE filter (confirmed search-arbitrage sites only): true = keep only search-arbitrage sites — domains that earn from search-ads clicks (Google RSOC/AFS through networks such as Tonic or Visymo, Yahoo/Bing feeds) instead of selling a product. Every sa_* filter implies it. Omit or false = no search-arbitrage filter. Valid sa_* values and counts: search_arbitrage_facets; the phrases behind them: search_arbitrage_phrases."
    • Changedsearch_webmasters4 fields changed
      • removedInput schema / properties / sa_evidence_min
        Removed value: -{
        -  "description": "minimum evidence share of the site, 0 to 1 (e.g. 0.8): the fraction of the site's checked pages that showed the network's markers; higher means a more certain verdict. Implies search_arbitrage.",
        -  "maximum": 1,
        -  "minimum": 0,
        -  "type": "number"
        -}
      • removedInput schema / properties / sa_link
        Removed value: -{
        -  "description": "how the ad reaches the site: tracker (a network tracking/redirect link that carries the phrase) or direct (the ad points straight at the monetised site). Omit for both. Implies search_arbitrage.",
        -  "enum": [
        -    "tracker",
        -    "direct"
        -  ],
        -  "type": "string"
        -}
      • removedInput schema / properties / sa_verdict
        Removed value: -{
        -  "description": "detection confidence (OR): confirmed (network markers found on the site) or probable. Omit for both. Implies search_arbitrage.",
        -  "items": {
        -    "enum": [
        -      "confirmed",
        -      "probable"
        -    ],
        -    "type": "string"
        -  },
        -  "type": [
        -    "null",
        -    "array"
        -  ]
        -}
      • changedInput schema / properties / search_arbitrage / description
        Previous value: -"SEARCH ARBITRAGE filter: true = keep only webmasters (affiliate networks) whose ads lead to search-arbitrage pages — pages that earn from search-ads clicks (Google RSOC/AFS through networks such as Tonic or Visymo, Yahoo/Bing feeds) instead of selling a product. Every sa_* filter implies it. Omit or false = no search-arbitrage filter. Valid sa_* values and counts: search_arbitrage_facets; the phrases behind them: search_arbitrage_phrases."New value: +"SEARCH ARBITRAGE filter (confirmed search-arbitrage sites only): true = keep only webmasters (affiliate networks) whose ads lead to search-arbitrage pages — pages that earn from search-ads clicks (Google RSOC/AFS through networks such as Tonic or Visymo, Yahoo/Bing feeds) instead of selling a product. Every sa_* filter implies it. Omit or false = no search-arbitrage filter. Valid sa_* values and counts: search_arbitrage_facets; the phrases behind them: search_arbitrage_phrases."
  3. 4 tool updates
    • Changedget_trends11 fields changed
      • addedInput schema / properties / sa_country
        Added value: +{
        +  "description": "ISO-2 codes of the countries the ads are shown in (OR), e.g. US, GB, DE — NOT the visitor country of the site. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_evidence_min
        Added value: +{
        +  "description": "minimum evidence share of the site, 0 to 1 (e.g. 0.8): the fraction of the site's checked pages that showed the network's markers; higher means a more certain verdict. Implies search_arbitrage.",
        +  "maximum": 1,
        +  "minimum": 0,
        +  "type": "number"
        +}
      • addedInput schema / properties / sa_lang
        Added value: +{
        +  "description": "ISO 639-1 language codes of the search phrases (OR), e.g. en, de, es. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_link
        Added value: +{
        +  "description": "how the ad reaches the site: tracker (a network tracking/redirect link that carries the phrase) or direct (the ad points straight at the monetised site). Omit for both. Implies search_arbitrage.",
        +  "enum": [
        +    "tracker",
        +    "direct"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / sa_network
        Added value: +{
        +  "description": "search-arbitrage network slugs (OR): the search-ads network the site monetises through, e.g. tonic, visymo, medianet, cortex, predicto, codefuel, brandclick, system1. Live list with counts: search_arbitrage_facets. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_phrase
        Added value: +{
        +  "description": "exact search phrases (OR), lower-case, as returned by search_arbitrage_phrases; a phrase containing a comma cannot be used here. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_pub
        Added value: +{
        +  "description": "Google publisher account ids (OR), e.g. pub-1902826156353358: the AdSense/AFS account the site earns under — one account usually means one operator. A bare number or ca-pub-… is accepted. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_source
        Added value: +{
        +  "description": "how the site earns from search (OR): rsoc (Google related-search ads through a partner), afs (Google AdSense for Search), yahoo_feed, bing_feed or other. Implies search_arbitrage.",
        +  "items": {
        +    "enum": [
        +      "rsoc",
        +      "afs",
        +      "yahoo_feed",
        +      "bing_feed",
        +      "other"
        +    ],
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_topic
        Added value: +{
        +  "description": "topic slugs of the search phrases the sites push (OR); live list with counts: search_arbitrage_facets. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_verdict
        Added value: +{
        +  "description": "detection confidence (OR): confirmed (network markers found on the site) or probable. Omit for both. Implies search_arbitrage.",
        +  "items": {
        +    "enum": [
        +      "confirmed",
        +      "probable"
        +    ],
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / search_arbitrage
        Added value: +{
        +  "description": "SEARCH ARBITRAGE filter, every dimension except apps: true = build the ranking only from search-arbitrage ads — ads whose landing page earns from search-ads clicks (Google RSOC/AFS through networks such as Tonic or Visymo, Yahoo/Bing feeds) instead of selling a product. Every sa_* filter implies it. Omit or false = no search-arbitrage filter. Valid sa_* values and counts: search_arbitrage_facets; the phrases behind them: search_arbitrage_phrases.",
        +  "type": "boolean"
        +}
    • Changedsearch_ads11 fields changed
      • addedInput schema / properties / sa_country
        Added value: +{
        +  "description": "ISO-2 codes of the countries the ads are shown in (OR), e.g. US, GB, DE — NOT the visitor country of the site. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_evidence_min
        Added value: +{
        +  "description": "minimum evidence share of the site, 0 to 1 (e.g. 0.8): the fraction of the site's checked pages that showed the network's markers; higher means a more certain verdict. Implies search_arbitrage.",
        +  "maximum": 1,
        +  "minimum": 0,
        +  "type": "number"
        +}
      • addedInput schema / properties / sa_lang
        Added value: +{
        +  "description": "ISO 639-1 language codes of the search phrases (OR), e.g. en, de, es. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_link
        Added value: +{
        +  "description": "how the ad reaches the site: tracker (a network tracking/redirect link that carries the phrase) or direct (the ad points straight at the monetised site). Omit for both. Implies search_arbitrage.",
        +  "enum": [
        +    "tracker",
        +    "direct"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / sa_network
        Added value: +{
        +  "description": "search-arbitrage network slugs (OR): the search-ads network the site monetises through, e.g. tonic, visymo, medianet, cortex, predicto, codefuel, brandclick, system1. Live list with counts: search_arbitrage_facets. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_phrase
        Added value: +{
        +  "description": "exact search phrases (OR), lower-case, as returned by search_arbitrage_phrases; a phrase containing a comma cannot be used here. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_pub
        Added value: +{
        +  "description": "Google publisher account ids (OR), e.g. pub-1902826156353358: the AdSense/AFS account the site earns under — one account usually means one operator. A bare number or ca-pub-… is accepted. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_source
        Added value: +{
        +  "description": "how the site earns from search (OR): rsoc (Google related-search ads through a partner), afs (Google AdSense for Search), yahoo_feed, bing_feed or other. Implies search_arbitrage.",
        +  "items": {
        +    "enum": [
        +      "rsoc",
        +      "afs",
        +      "yahoo_feed",
        +      "bing_feed",
        +      "other"
        +    ],
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_topic
        Added value: +{
        +  "description": "topic slugs of the search phrases the sites push (OR); live list with counts: search_arbitrage_facets. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_verdict
        Added value: +{
        +  "description": "detection confidence (OR): confirmed (network markers found on the site) or probable. Omit for both. Implies search_arbitrage.",
        +  "items": {
        +    "enum": [
        +      "confirmed",
        +      "probable"
        +    ],
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / search_arbitrage
        Added value: +{
        +  "description": "SEARCH ARBITRAGE filter: true = keep only search-arbitrage ads — ads whose landing page earns from search-ads clicks (Google RSOC/AFS through networks such as Tonic or Visymo, Yahoo/Bing feeds) instead of selling a product. Every sa_* filter implies it. Omit or false = no search-arbitrage filter. Meta source only. Valid sa_* values and counts: search_arbitrage_facets; the phrases behind them: search_arbitrage_phrases.",
        +  "type": "boolean"
        +}
    • Changedsearch_advertisers12 fields changed
      • changedInput schema / properties / query / description
        Previous value: -"advertiser 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"New value: +"advertiser 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. With search_arbitrage / sa_* the query is optional and matches a name substring or one exact numeric page id; pasted links are NOT resolved there."
      • addedInput schema / properties / sa_country
        Added value: +{
        +  "description": "ISO-2 codes of the countries the ads are shown in (OR), e.g. US, GB, DE — NOT the visitor country of the site. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_evidence_min
        Added value: +{
        +  "description": "minimum evidence share of the site, 0 to 1 (e.g. 0.8): the fraction of the site's checked pages that showed the network's markers; higher means a more certain verdict. Implies search_arbitrage.",
        +  "maximum": 1,
        +  "minimum": 0,
        +  "type": "number"
        +}
      • addedInput schema / properties / sa_lang
        Added value: +{
        +  "description": "ISO 639-1 language codes of the search phrases (OR), e.g. en, de, es. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_link
        Added value: +{
        +  "description": "how the ad reaches the site: tracker (a network tracking/redirect link that carries the phrase) or direct (the ad points straight at the monetised site). Omit for both. Implies search_arbitrage.",
        +  "enum": [
        +    "tracker",
        +    "direct"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / sa_network
        Added value: +{
        +  "description": "search-arbitrage network slugs (OR): the search-ads network the site monetises through, e.g. tonic, visymo, medianet, cortex, predicto, codefuel, brandclick, system1. Live list with counts: search_arbitrage_facets. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_phrase
        Added value: +{
        +  "description": "exact search phrases (OR), lower-case, as returned by search_arbitrage_phrases; a phrase containing a comma cannot be used here. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_pub
        Added value: +{
        +  "description": "Google publisher account ids (OR), e.g. pub-1902826156353358: the AdSense/AFS account the site earns under — one account usually means one operator. A bare number or ca-pub-… is accepted. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_source
        Added value: +{
        +  "description": "how the site earns from search (OR): rsoc (Google related-search ads through a partner), afs (Google AdSense for Search), yahoo_feed, bing_feed or other. Implies search_arbitrage.",
        +  "items": {
        +    "enum": [
        +      "rsoc",
        +      "afs",
        +      "yahoo_feed",
        +      "bing_feed",
        +      "other"
        +    ],
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_topic
        Added value: +{
        +  "description": "topic slugs of the search phrases the sites push (OR); live list with counts: search_arbitrage_facets. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_verdict
        Added value: +{
        +  "description": "detection confidence (OR): confirmed (network markers found on the site) or probable. Omit for both. Implies search_arbitrage.",
        +  "items": {
        +    "enum": [
        +      "confirmed",
        +      "probable"
        +    ],
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / search_arbitrage
        Added value: +{
        +  "description": "SEARCH ARBITRAGE filter: true = list only advertisers whose ads lead to search-arbitrage pages — pages that earn from search-ads clicks (Google RSOC/AFS through networks such as Tonic or Visymo, Yahoo/Bing feeds) instead of selling a product — ordered by total ads. Every sa_* filter implies it. Omit or false = the plain name/page-id typeahead. Valid sa_* values and counts: search_arbitrage_facets; the phrases behind them: search_arbitrage_phrases.",
        +  "type": "boolean"
        +}
    • Changedsearch_arbitrage_facets8 fields changed
      • addedOutput schema / properties / country / items / properties / network_label
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / lang / items / properties / network_label
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / link / items / properties / network_label
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / network / items / properties / network_label
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / pub / items / properties / network_label
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / source / items / properties / network_label
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / topic / items / properties / network_label
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / verdict / items / properties / network_label
        Added value: +{
        +  "type": "string"
        +}
  4. 5 tool updates
    • Addedsearch_arbitrage_facets
    • Addedsearch_arbitrage_phrases
    • Changedsearch_creatives11 fields changed
      • addedInput schema / properties / sa_country
        Added value: +{
        +  "description": "ISO-2 codes of the countries the ads are shown in (OR), e.g. US, GB, DE — NOT the visitor country of the site. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_evidence_min
        Added value: +{
        +  "description": "minimum evidence share of the site, 0 to 1 (e.g. 0.8): the fraction of the site's checked pages that showed the network's markers; higher means a more certain verdict. Implies search_arbitrage.",
        +  "maximum": 1,
        +  "minimum": 0,
        +  "type": "number"
        +}
      • addedInput schema / properties / sa_lang
        Added value: +{
        +  "description": "ISO 639-1 language codes of the search phrases (OR), e.g. en, de, es. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_link
        Added value: +{
        +  "description": "how the ad reaches the site: tracker (a network tracking/redirect link that carries the phrase) or direct (the ad points straight at the monetised site). Omit for both. Implies search_arbitrage.",
        +  "enum": [
        +    "tracker",
        +    "direct"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / sa_network
        Added value: +{
        +  "description": "search-arbitrage network slugs (OR): the search-ads network the site monetises through, e.g. tonic, visymo, medianet, cortex, predicto, codefuel, brandclick, system1. Live list with counts: search_arbitrage_facets. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_phrase
        Added value: +{
        +  "description": "exact search phrases (OR), lower-case, as returned by search_arbitrage_phrases; a phrase containing a comma cannot be used here. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_pub
        Added value: +{
        +  "description": "Google publisher account ids (OR), e.g. pub-1902826156353358: the AdSense/AFS account the site earns under — one account usually means one operator. A bare number or ca-pub-… is accepted. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_source
        Added value: +{
        +  "description": "how the site earns from search (OR): rsoc (Google related-search ads through a partner), afs (Google AdSense for Search), yahoo_feed, bing_feed or other. Implies search_arbitrage.",
        +  "items": {
        +    "enum": [
        +      "rsoc",
        +      "afs",
        +      "yahoo_feed",
        +      "bing_feed",
        +      "other"
        +    ],
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_topic
        Added value: +{
        +  "description": "topic slugs of the search phrases the sites push (OR); live list with counts: search_arbitrage_facets. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_verdict
        Added value: +{
        +  "description": "detection confidence (OR): confirmed (network markers found on the site) or probable. Omit for both. Implies search_arbitrage.",
        +  "items": {
        +    "enum": [
        +      "confirmed",
        +      "probable"
        +    ],
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / search_arbitrage
        Added value: +{
        +  "description": "SEARCH ARBITRAGE filter: true = keep only creatives of search-arbitrage ads — ads whose landing page earns from search-ads clicks (Google RSOC/AFS through networks such as Tonic or Visymo, Yahoo/Bing feeds) instead of selling a product. Every sa_* filter implies it. Omit or false = no search-arbitrage filter. Valid sa_* values and counts: search_arbitrage_facets; the phrases behind them: search_arbitrage_phrases.",
        +  "type": "boolean"
        +}
    • Changedsearch_shops11 fields changed
      • addedInput schema / properties / sa_country
        Added value: +{
        +  "description": "ISO-2 codes of the countries the ads are shown in (OR), e.g. US, GB, DE — NOT the visitor country of the site. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_evidence_min
        Added value: +{
        +  "description": "minimum evidence share of the site, 0 to 1 (e.g. 0.8): the fraction of the site's checked pages that showed the network's markers; higher means a more certain verdict. Implies search_arbitrage.",
        +  "maximum": 1,
        +  "minimum": 0,
        +  "type": "number"
        +}
      • addedInput schema / properties / sa_lang
        Added value: +{
        +  "description": "ISO 639-1 language codes of the search phrases (OR), e.g. en, de, es. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_link
        Added value: +{
        +  "description": "how the ad reaches the site: tracker (a network tracking/redirect link that carries the phrase) or direct (the ad points straight at the monetised site). Omit for both. Implies search_arbitrage.",
        +  "enum": [
        +    "tracker",
        +    "direct"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / sa_network
        Added value: +{
        +  "description": "search-arbitrage network slugs (OR): the search-ads network the site monetises through, e.g. tonic, visymo, medianet, cortex, predicto, codefuel, brandclick, system1. Live list with counts: search_arbitrage_facets. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_phrase
        Added value: +{
        +  "description": "exact search phrases (OR), lower-case, as returned by search_arbitrage_phrases; a phrase containing a comma cannot be used here. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_pub
        Added value: +{
        +  "description": "Google publisher account ids (OR), e.g. pub-1902826156353358: the AdSense/AFS account the site earns under — one account usually means one operator. A bare number or ca-pub-… is accepted. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_source
        Added value: +{
        +  "description": "how the site earns from search (OR): rsoc (Google related-search ads through a partner), afs (Google AdSense for Search), yahoo_feed, bing_feed or other. Implies search_arbitrage.",
        +  "items": {
        +    "enum": [
        +      "rsoc",
        +      "afs",
        +      "yahoo_feed",
        +      "bing_feed",
        +      "other"
        +    ],
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_topic
        Added value: +{
        +  "description": "topic slugs of the search phrases the sites push (OR); live list with counts: search_arbitrage_facets. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_verdict
        Added value: +{
        +  "description": "detection confidence (OR): confirmed (network markers found on the site) or probable. Omit for both. Implies search_arbitrage.",
        +  "items": {
        +    "enum": [
        +      "confirmed",
        +      "probable"
        +    ],
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / search_arbitrage
        Added value: +{
        +  "description": "SEARCH ARBITRAGE filter: true = keep only search-arbitrage sites — domains that earn from search-ads clicks (Google RSOC/AFS through networks such as Tonic or Visymo, Yahoo/Bing feeds) instead of selling a product. Every sa_* filter implies it. Omit or false = no search-arbitrage filter. Valid sa_* values and counts: search_arbitrage_facets; the phrases behind them: search_arbitrage_phrases.",
        +  "type": "boolean"
        +}
    • Changedsearch_webmasters11 fields changed
      • addedInput schema / properties / sa_country
        Added value: +{
        +  "description": "ISO-2 codes of the countries the ads are shown in (OR), e.g. US, GB, DE — NOT the visitor country of the site. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_evidence_min
        Added value: +{
        +  "description": "minimum evidence share of the site, 0 to 1 (e.g. 0.8): the fraction of the site's checked pages that showed the network's markers; higher means a more certain verdict. Implies search_arbitrage.",
        +  "maximum": 1,
        +  "minimum": 0,
        +  "type": "number"
        +}
      • addedInput schema / properties / sa_lang
        Added value: +{
        +  "description": "ISO 639-1 language codes of the search phrases (OR), e.g. en, de, es. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_link
        Added value: +{
        +  "description": "how the ad reaches the site: tracker (a network tracking/redirect link that carries the phrase) or direct (the ad points straight at the monetised site). Omit for both. Implies search_arbitrage.",
        +  "enum": [
        +    "tracker",
        +    "direct"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / sa_network
        Added value: +{
        +  "description": "search-arbitrage network slugs (OR): the search-ads network the site monetises through, e.g. tonic, visymo, medianet, cortex, predicto, codefuel, brandclick, system1. Live list with counts: search_arbitrage_facets. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_phrase
        Added value: +{
        +  "description": "exact search phrases (OR), lower-case, as returned by search_arbitrage_phrases; a phrase containing a comma cannot be used here. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_pub
        Added value: +{
        +  "description": "Google publisher account ids (OR), e.g. pub-1902826156353358: the AdSense/AFS account the site earns under — one account usually means one operator. A bare number or ca-pub-… is accepted. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_source
        Added value: +{
        +  "description": "how the site earns from search (OR): rsoc (Google related-search ads through a partner), afs (Google AdSense for Search), yahoo_feed, bing_feed or other. Implies search_arbitrage.",
        +  "items": {
        +    "enum": [
        +      "rsoc",
        +      "afs",
        +      "yahoo_feed",
        +      "bing_feed",
        +      "other"
        +    ],
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_topic
        Added value: +{
        +  "description": "topic slugs of the search phrases the sites push (OR); live list with counts: search_arbitrage_facets. Implies search_arbitrage.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / sa_verdict
        Added value: +{
        +  "description": "detection confidence (OR): confirmed (network markers found on the site) or probable. Omit for both. Implies search_arbitrage.",
        +  "items": {
        +    "enum": [
        +      "confirmed",
        +      "probable"
        +    ],
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedInput schema / properties / search_arbitrage
        Added value: +{
        +  "description": "SEARCH ARBITRAGE filter: true = keep only webmasters (affiliate networks) whose ads lead to search-arbitrage pages — pages that earn from search-ads clicks (Google RSOC/AFS through networks such as Tonic or Visymo, Yahoo/Bing feeds) instead of selling a product. Every sa_* filter implies it. Omit or false = no search-arbitrage filter. Valid sa_* values and counts: search_arbitrage_facets; the phrases behind them: search_arbitrage_phrases.",
        +  "type": "boolean"
        +}
  5. 6 tool updates
    • Addedaccept_pricing_terms
    • Addedestimate_cost
    • Changedfind_similar_ads1 field changed
      • addedOutput schema / properties / data / items / properties / multilang_black_missing
        Added value: +{
        +  "type": [
        +    "null",
        +    "boolean"
        +  ]
        +}
    • Changedget_ad1 field changed
      • addedOutput schema / properties / data / properties / multilang_black_missing
        Added value: +{
        +  "type": [
        +    "null",
        +    "boolean"
        +  ]
        +}
    • Changedget_media1 field changed
      • addedOutput schema / properties / items / items / properties / multilang_black_missing
        Added value: +{
        +  "type": [
        +    "null",
        +    "boolean"
        +  ]
        +}
    • Changedsearch_ads1 field changed
      • addedOutput schema / properties / data / items / properties / multilang_black_missing
        Added value: +{
        +  "type": [
        +    "null",
        +    "boolean"
        +  ]
        +}
  6. 1 tool update
    • Changedget_usage1 field changed
      • addedOutput schema / properties / pricing
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "active_factor": {
        +      "type": "integer"
        +    },
        +    "consent_status": {
        +      "type": "string"
        +    },
        +    "filter_rule": {
        +      "type": "string"
        +    },
        +    "search_row_price": {
        +      "additionalProperties": {
        +        "type": "integer"
        +      },
        +      "type": "object"
        +    },
        +    "terms_url": {
        +      "type": "string"
        +    },
        +    "terms_version": {
        +      "type": "string"
        +    },
        +    "threshold": {
        +      "type": "integer"
        +    },
        +    "threshold_factor": {
        +      "type": "integer"
        +    }
        +  },
        +  "required": [
        +    "terms_version",
        +    "terms_url",
        +    "consent_status",
        +    "filter_rule",
        +    "threshold",
        +    "threshold_factor",
        +    "active_factor",
        +    "search_row_price"
        +  ],
        +  "type": [
        +    "null",
        +    "object"
        +  ]
        +}
  7. 1 tool update
    • Changedsearch_shops1 field changed
      • changedInput schema / properties / limit / description
        Previous value: -"max results (default 20; each delivered result costs 1 token)."New value: +"max results (default 20, at most 200; each delivered result costs 1 token). Without a Shops subscription the catalogue answers a free sample of a few rows whatever the limit: params.normalized then reports limit as requested→delivered, note says the page is a free sample and has_more stays true while total exceeds offset+rows."
  8. 2 tool updates
    • Changedget_shop2 fields changed
      • addedInput schema / properties / products_limit
        Added value: +{
        +  "description": "number of embedded products per page (default 20, maximum 50); all other shop profile fields remain present on each page",
        +  "type": "integer"
        +}
      • addedInput schema / properties / products_offset
        Added value: +{
        +  "description": "zero-based offset into the embedded products list; use products_page.next_offset to retrieve the next page",
        +  "type": "integer"
        +}
    • Changedsearch_ads1 field changed
      • changedInput schema / properties / limit / description
        Previous value: -"max ad rows to return (maximum 200). Meta defaults to 20 at 1 token per delivered row; TikTok defaults to 10 at 100 tokens per delivered row."New value: +"max ad rows per page: Meta returns at most 20 (larger legacy requests are normalized to 20); follow pagination.next_cursor for the rest, with all row fields intact. TikTok defaults to 10 at 100 tokens per delivered row. Meta costs 1 token per delivered row."
  9. 1 tool update
    • Changedget_usage1 field changed
      • addedOutput schema / properties / purchased
        Added value: +{
        +  "type": "integer"
        +}

Related MCP Connectors

Related MCP Servers

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.