Skip to main content

Check Retailer Coverage (Market)

mdmcp-get_retailer_coverage

Assess data coverage — completeness AND freshness — for one or more retailers over a date range. The "can I trust the market data for these retailers over this window?" tool. Run it after resolving slugs with search_retailers and before trusting a market_data_table / market_data_options_search aggregate over the same window: a clean average can be silently wrong if the retailer had a no_data gap or a stretch of low_recency in the range.

Input: retailers (slugs from search_retailers, 1..N), start_date / end_date (YYYY-MM-DD), granularities (one or more of daily, weekly, monthly; default ["daily"]), and an optional vertical. start_date must be on or before end_date; supported range is the past two years (730 days), inclusive.

retailers takes region-specific retailer slugs from search_retailers (e.g. levi-uk, zara-us) — NOT brand slugs from search_brands. These are separate id spaces: a name like "Levi's" surfaces under both searches, but its brand slug (levis) is not a valid retailer here and will match no coverage. Pass the search_retailers slug, not the search_brands one.

vertical (apparel | beauty | homeware) is optional. When omitted it resolves to the account's default vertical (reported as default_vertical by market_data_entitlements) and scopes the access contract. Coverage is reported on the same data stream the query tools read, in every vertical — including homeware — so a coverage verdict and a market_data_table / market_data_options_search result always describe the same dataset. Available verticals vary by account; requesting one you are not entitled to returns an error — call market_data_entitlements to see yours.

Verdicts come from md-quality UNCHANGED — the tool only summarizes them into gaps. Per retailer, each requested granularity returns a block keyed daily / weekly / monthly with:

  • periods_assessed, healthy_periods, health_pct — counts over md-quality's per-period verdicts at that granularity;
  • gap_episodes — contiguous runs of non-healthy periods, each \{start_date, end_date, period_count, reasons, min_volume_score, min_recency_score}. reasons is the union of md-quality's non-healthy reasons across the run; min_* are its worst scores in the run (min_recency_score is null when no documents);
  • verdict — a one-line string for direct inclusion in an answer; it appends the worst relevant score to each episode (e.g. min recency 0.83) so severity is visible at a glance. Disallowed / unknown / deprecated retailers come back inline as a per-retailer error (no_access / unknown_retailer / deprecated_retailer), never a hard failure for the whole call.

Reasons (from md-quality): no_data = zero documents that day; low_volume = anomalous drop vs. the retailer's own baseline; low_recency = documents exist but are going stale; healthy = none of the above. no_data states an absence, not a cause: zero documents can mean EDITED did not track that retailer/market/vertical combination during the requested window (tracking may have started after, or stopped before, it), or collection was genuinely interrupted — this tool cannot tell those apart. Never present no_data as the crawler being down (even if the user assumes so); report it neutrally — "EDITED has no data for this retailer over this window" — and, if asked why, offer the range of possible causes. Scores (from md-quality): volume_score ∈ [0,1] = fraction of the retailer's historical norm of documents seen (1.0 normal, 0.3 ≈ 30% of expected, 0 none); recency_score ∈ [0,1] | null = freshness (1.0 seen today, 0.0 ≥ 6 days old, null = no documents that day).

How to read a verdict: a low health_pct, or any no_data / low_recency gap episode overlapping an analytics window, is a signal to caveat or narrow that analysis — exclude the affected retailer, narrow the date range to the healthy stretch, or surface the gap in the answer. Do NOT flag on health_pct alone: the percentage collapses severity, so a retailer with two isolated barely-stale weeks (low_recency, min recency ≈ 0.83) can score the same as one with sustained no_data gaps. Judge each episode by its reasons and min_volume_score / min_recency_score before calling coverage a problem. Weigh severity before alarming: at monthly a single flagged period is 0% healthy by construction, so a low_recency month with a high min recency (near 1.0) is only mildly stale, NOT a hard gap — say so rather than reporting it as unusable. Request daily to pinpoint exact gap dates and monthly for an at-a-glance trend; both come back from a single call.

Parameters​

NameTypeRequiredConstraintsDescription
retailersstring[]yes—Retailer slugs (from search_retailers), 1..N.
start_datestringyes—Inclusive start of the window (YYYY-MM-DD). Must be on or before end_date and within the past two years (730 days).
end_datestringyes—Inclusive end of the window (YYYY-MM-DD). Within the past two years (730 days).
granularitiesstring[]nodefault: ["daily"]One or more of daily, weekly, monthly — a gap summary is returned per requested granularity from a single backend call.
verticalstringno—Optional. apparel | beauty | homeware. When omitted it resolves to the account's default vertical (see market_data_entitlements).

Try it​

Loading interactive widget…

Code examples​

curl -s https://mcp.edited.com/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "MCP-Protocol-Version: 2025-06-18" \
-H "x-api-key: $MCP_API_KEY" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "mdmcp-get_retailer_coverage",
"arguments": {
"start_date": "example",
"end_date": "example",
"granularities": [
"daily"
],
"vertical": "example"
}
}
}'

Input schema​

{
"type": "object",
"properties": {
"retailers": {
"description": "Retailer slugs (from `search_retailers`), 1..N.",
"examples": [
[
"zara",
"h-and-m"
]
],
"items": {
"type": "string"
},
"minItems": 1,
"type": "array"
},
"start_date": {
"description": "Inclusive start of the window (YYYY-MM-DD). Must be on or before `end_date` and within the past two years (730 days).",
"examples": [
"2026-01-01"
],
"format": "date",
"type": "string"
},
"end_date": {
"description": "Inclusive end of the window (YYYY-MM-DD). Within the past two years (730 days).",
"examples": [
"2026-03-31"
],
"format": "date",
"type": "string"
},
"granularities": {
"default": [
"daily"
],
"description": "One or more of `daily`, `weekly`, `monthly` — a gap summary is returned per requested granularity from a single backend call.",
"examples": [
[
"daily"
],
[
"daily",
"monthly"
]
],
"items": {
"enum": [
"daily",
"weekly",
"monthly"
],
"type": "string"
},
"type": "array"
},
"vertical": {
"description": "Optional. `apparel` | `beauty` | `homeware`. When omitted it resolves to the account's default vertical (see `market_data_entitlements`).",
"enum": [
"apparel",
"beauty",
"homeware"
],
"type": "string"
}
},
"required": [
"retailers",
"start_date",
"end_date"
]
}

Output schema​

Describes both branches of the envelope — result on success, error on a refusal. Validate against this rather than pattern-matching the prose above; see Concepts → Response shape.

{
"type": "object",
"properties": {
"result": {
"description": "Top-level tool result. ``retailers`` carries one entry per requested slug\n(ok or error), keyed by slug.",
"properties": {
"vertical": {
"type": "string"
},
"granularities": {
"items": {
"enum": [
"daily",
"weekly",
"monthly"
],
"type": "string"
},
"type": "array"
},
"start_date": {
"format": "date",
"type": "string"
},
"end_date": {
"format": "date",
"type": "string"
},
"retailers": {
"additionalProperties": {
"description": "Per-retailer entry. ``status=\"ok\"`` carries one summary block per\nrequested granularity (the others stay ``None``); ``status=\"error\"`` carries\na ``reason`` and no summaries.",
"properties": {
"status": {
"enum": [
"ok",
"error"
],
"type": "string"
},
"reason": {
"anyOf": [
{
"enum": [
"unknown_retailer",
"deprecated_retailer",
"no_access"
],
"type": "string"
},
{
"type": "null"
}
],
"default": null
},
"daily": {
"anyOf": [
{
"description": "Gap summary for one retailer at one granularity.\n\n``periods_assessed`` / ``healthy_periods`` / ``health_pct`` are counts over\nmd-quality's per-period verdicts. ``verdict`` is a one-line string suitable\nfor direct inclusion in an answer.",
"properties": {
"periods_assessed": {
"type": "integer"
},
"healthy_periods": {
"type": "integer"
},
"health_pct": {
"type": "number"
},
"gap_episodes": {
"items": {
"description": "A maximal contiguous run of non-healthy periods (run-length encoded).\n\n``reasons`` is the union of md-quality's non-healthy reasons across the run;\n``min_*`` are md-quality's worst (minimum) scores within it. ``daily``\nepisodes have ``start_date == end_date`` per period; weekly/monthly episodes\nspan the run's first/last period bounds.",
"properties": {
"start_date": {
"format": "date",
"type": "string"
},
"end_date": {
"format": "date",
"type": "string"
},
"period_count": {
"type": "integer"
},
"reasons": {
"items": {
"enum": [
"no_data",
"low_volume",
"low_recency"
],
"type": "string"
},
"type": "array"
},
"min_volume_score": {
"type": "number"
},
"min_recency_score": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
]
}
},
"required": [
"start_date",
"end_date",
"period_count",
"reasons",
"min_volume_score",
"min_recency_score"
],
"type": "object"
},
"type": "array"
},
"verdict": {
"type": "string"
}
},
"required": [
"periods_assessed",
"healthy_periods",
"health_pct",
"gap_episodes",
"verdict"
],
"type": "object"
},
{
"type": "null"
}
],
"default": null
},
"weekly": {
"anyOf": [
{
"description": "Gap summary for one retailer at one granularity.\n\n``periods_assessed`` / ``healthy_periods`` / ``health_pct`` are counts over\nmd-quality's per-period verdicts. ``verdict`` is a one-line string suitable\nfor direct inclusion in an answer.",
"properties": {
"periods_assessed": {
"type": "integer"
},
"healthy_periods": {
"type": "integer"
},
"health_pct": {
"type": "number"
},
"gap_episodes": {
"items": {
"description": "A maximal contiguous run of non-healthy periods (run-length encoded).\n\n``reasons`` is the union of md-quality's non-healthy reasons across the run;\n``min_*`` are md-quality's worst (minimum) scores within it. ``daily``\nepisodes have ``start_date == end_date`` per period; weekly/monthly episodes\nspan the run's first/last period bounds.",
"properties": {
"start_date": {
"format": "date",
"type": "string"
},
"end_date": {
"format": "date",
"type": "string"
},
"period_count": {
"type": "integer"
},
"reasons": {
"items": {
"enum": [
"no_data",
"low_volume",
"low_recency"
],
"type": "string"
},
"type": "array"
},
"min_volume_score": {
"type": "number"
},
"min_recency_score": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
]
}
},
"required": [
"start_date",
"end_date",
"period_count",
"reasons",
"min_volume_score",
"min_recency_score"
],
"type": "object"
},
"type": "array"
},
"verdict": {
"type": "string"
}
},
"required": [
"periods_assessed",
"healthy_periods",
"health_pct",
"gap_episodes",
"verdict"
],
"type": "object"
},
{
"type": "null"
}
],
"default": null
},
"monthly": {
"anyOf": [
{
"description": "Gap summary for one retailer at one granularity.\n\n``periods_assessed`` / ``healthy_periods`` / ``health_pct`` are counts over\nmd-quality's per-period verdicts. ``verdict`` is a one-line string suitable\nfor direct inclusion in an answer.",
"properties": {
"periods_assessed": {
"type": "integer"
},
"healthy_periods": {
"type": "integer"
},
"health_pct": {
"type": "number"
},
"gap_episodes": {
"items": {
"description": "A maximal contiguous run of non-healthy periods (run-length encoded).\n\n``reasons`` is the union of md-quality's non-healthy reasons across the run;\n``min_*`` are md-quality's worst (minimum) scores within it. ``daily``\nepisodes have ``start_date == end_date`` per period; weekly/monthly episodes\nspan the run's first/last period bounds.",
"properties": {
"start_date": {
"format": "date",
"type": "string"
},
"end_date": {
"format": "date",
"type": "string"
},
"period_count": {
"type": "integer"
},
"reasons": {
"items": {
"enum": [
"no_data",
"low_volume",
"low_recency"
],
"type": "string"
},
"type": "array"
},
"min_volume_score": {
"type": "number"
},
"min_recency_score": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
]
}
},
"required": [
"start_date",
"end_date",
"period_count",
"reasons",
"min_volume_score",
"min_recency_score"
],
"type": "object"
},
"type": "array"
},
"verdict": {
"type": "string"
}
},
"required": [
"periods_assessed",
"healthy_periods",
"health_pct",
"gap_episodes",
"verdict"
],
"type": "object"
},
{
"type": "null"
}
],
"default": null
}
},
"required": [
"status"
],
"type": "object"
},
"type": "object"
}
},
"required": [
"vertical",
"granularities",
"start_date",
"end_date",
"retailers"
],
"type": "object"
},
"error": {
"type": "object",
"description": "Present instead of `result` when the call was rejected. Branch on `code`; never string-match `message`.",
"properties": {
"code": {
"type": "string",
"enum": [
"invalid_input",
"not_entitled",
"upstream_unavailable",
"internal"
]
},
"message": {
"type": "string"
},
"field": {
"type": "string",
"description": "Offending parameter, when the failure is attributable to one."
},
"details": {
"type": "object",
"additionalProperties": true
}
},
"required": [
"code",
"message"
]
}
},
"oneOf": [
{
"required": [
"result"
]
},
{
"required": [
"error"
]
}
],
"x-fastmcp-wrap-result": true
}