vladimir-human / mpstats-connector
Use this skill for MPStats sales/stock analytics on a specific Ozon or Wildberries item — per-day sales, current price and stock, FBS/FBO warehouse split, seller/brand identity, and a rolling orders-per-day average. Trigger on "продажи товара на озон", "аналитика ozon sku", "mpstats по артикулу", "продажи за 30 дней", or English equivalents. Requires a paid MPStats account (MPSTATS_MP_AUTH env). Skip raw catalog price checks — use wb_/ozon_ connectors (no account needed).
MPStats Connector
Paid-account sales/stock analytics for Ozon and Wildberries items, via the
MPStats browser-plugin API (plugin.mpstats.io/pluginapi). Unlike the
anonymous catalog connectors in this workspace, this one is optional: it
needs a paid MPStats account configured as the MPSTATS_MP_AUTH env var (the
raw mp_auth JWT cookie from a logged-in browser plugin session at
mpstats.io). Without it the server boots cleanly, every tool returnsauth_missing, and no other connector is affected — like every source here,
it is a pleasant extra you opt into, not a requirement.
When to use
- Per-SKU 30-day sales analytics — orders graph, price graph, stock graph
- Current price and stock for an item (today's reading off the graph tail)
- Warehouse stock split — FBS (seller warehouse) vs FBO (marketplace warehouse)
- Seller/brand identity and a rolling orders-per-day average
- Sales-trend comparison across several SKUs in one batched call
When NOT to use
- Bare price/availability checks with no account — use
wb_card/ozon_card. Reviews, categories, seller tax identity — MPStats does not surface those; use
the catalog connectors.Search by text or category browsing — MPStats analytics is keyed by SKU, not
by query.
Prerequisites
Set MPSTATS_MP_AUTH to the raw JWT (no mp_auth= prefix, no quotes):
export MPSTATS_MP_AUTH='eyJ0eXAiOiJKV1Qi...' # from a logged-in mpstats.io sessionWithout it, every tool returns an auth_missing error (retryable: false) and
the server still boots cleanly. Treat the token as a secret: it identifies a
paid, quota-billed account. Never log it, never commit it.
Tools available
mpstats_item(skus, place, oz_fbs=True)— per-SKU 30-day analytics. Up to 100
SKUs per call. Returns, per SKU:seller,seller_id,brand,stock_now,price_avg_rub,orders_per_day,days_on_stocks,totals(orders/sum/
sumprev), and four per-day graphs (`ordersgraph,prices_graph`,count_graph,rubrics_graph).mpstats_warehouses(skus, place)— per-SKU warehouse stock split:fbs
count,fbototal (collapsed from the upstream per-warehouse list), the rawfbo_warehouseslist, and the upstreamlast_updatetimestamp.
Not an MCP tool: mpstats_selfcheck() is a tri-state health canary:success, drift_detected (reachable but unparseable — code change needed), orinconclusive (transport failure / missing auth — says nothing about the
parsers). It is CLI-only — marketplace-mcp doctor runs every connector's canary
at once.
Marketplace parameter
place is "ozon" or "wildberries". oz_fbs is an Ozon-specific
Fulfilled-by-Seller flag (default true); harmless for wildberries.
Workflow patterns
Sales snapshot for one Ozon item by SKU:
mpstats_item([5107857210], place="ozon")— current price/stock + 30-day graphsRead
price_avg_rubandstock_nowfor today; sumorders_graphfor the
window total; comparetotals.sumvstotals.sum_prevfor trend.
Compare a basket of SKUs:
mpstats_item([sku1, sku2, ...], place="ozon")— batched, request-order
preserved. A SKU MPStats has no data for surfaces as ameta.warningsentry,
not a silent gap.
Stock split (where the units physically sit):
mpstats_item([...], place="ozon")forstock_now(total)mpstats_warehouses([...], place="ozon")for the FBS/FBO split andlast_update(when MPStats last refreshed the snapshot).
Graph semantics (gotchas)
Graphs are length
days(default 30), oldest-first; the final cell is
"today". The current price or stock is the last non-zero cell.Price and stock diverge on an all-zero graph, deliberately.
price_avg_rub
becomesNone, because a false0.0would rank a delisted item as the
cheapest.stock_nowbecomes0, because "none in stock" is a real reading.
An empty graph givesNonefor both — that one is genuinely no data.A zero cell means "no data for that day", not "the value was zero".
Sum the graph for a real total; do not read a single cell as the answer.totals.orders/totals.sumare MPStats' own aggregates over the window —
prefer them over hand-summing unless you need a custom sub-window.A missing value is always
None, never0: a zero would rank a dead listing
as the top seller — the exact bug this connector's parsers exist to prevent.
Error format
On failure, raises ToolError with a JSON body: `{"error": "<code>",
"message": "...", "retryable": <bool>}. Codes:auth_missing` (no/expired
token — not retryable), bad_request (bad SKU/place), rate_limited
(retryable, honours retry_after_s), transport_down, parser_drift
(upstream shape changed — code change needed), not_found (no analytics for
any SKU). Partial data (some SKUs missing) stays a success with meta.warnings
and meta.healthy: false — silence never reads as success here.
DSH activation
In DeepSeek Harness, the default profile exposes only compare_prices andcompare_sources through the cheap compare mount. Per-marketplace tools andmarketplace_sources require RU_MARKETPLACE_MCP_FULL=1 and a profile restart;
do not call them in the default mode.