trackmcp
Back to directory
DeviceIngineering

wb-mcp-server

View on GitHub

MCP server for the Wildberries Seller API: 202 tools for prices, promotions, ads, orders, supplies, reviews, finance and analytics. Multi-store, web dashboard, self-diagnostics. Context budget measured on a live account: a 27-response corpus trimmed from 770k to 75k tokens. Docker, SSE, MIT.

3 stars PythonOthers Updated Sep 4, 2026
ai-agentsclaudeecommercefastapimarketplacemcpmcp-servermodel-context-protocolpythonseller-apissewildberriesdockerrussiaself-hostedwildberries-api

Documentation

WB MCP Server

License: MIT
Python
MCP tools
PyPI
Transport

Run your Wildberries stores from a chat with an AI assistant.

202 tools covering the Wildberries Seller API — product cards, prices, ads, shipments,

reviews, finance, analytics — exposed to Claude, Cursor, Copilot, Gemini CLI and any

other MCP client. Built for WB sellers (Wildberries is Russia's largest marketplace)

who run one or several seller accounts and would rather ask a question than click

through the seller portal.

Selling on Ozon too? There is the same server for Ozon.

The server has been in daily use for more than five months across roughly twenty WB seller

accounts, with 202 tools. It is the author's own working tool and is updated as the author

needs it — details here.

code
You: Which of my product cards are blocked, and why?
You: Show ad cost share for every campaign this week and pause the ones above 15%.
You: Which warehouses currently have an intake coefficient of 0 or 1?
You: Reply to every new 5-star review with a thank-you note.
WB MCP Server dashboard

What it can do

202 tools, grouped by Wildberries Seller API area.

The full numbered list with a description of each one is in **docs/tools.md**.

AreaToolsWhat it covers
Product cards26card list and details, create and update, SEO text, attributes, barcodes, media, tags, trash bin, cards with errors and blocks
Prices and discounts7current prices, setting prices and discounts, price quarantine, WB Club (WB's paid membership discounts), B2B, upload status
Promotions7promotion calendar, auto-promotions, an audit of "where WB has already enrolled your products", joining and leaving a promotion
Advertising22campaign list and creation, statistics and ad cost share, bids and bid recommendations, keyword clusters and negative phrases, balance and top-ups
Analytics25sales funnel v3 (per-product views → cart → order conversion), day-by-day history, stock, anti-fraud, paid intake, measurement penalties, brand share, sales by region, search queries
Statistics3sales, orders, stock (statistics-api)
FBS orders29new and all assembly tasks, statuses, cancellation, labels, supplies, boxes, warehouse passes, KIZ marking codes (Russia's mandatory product marking). FBS = fulfilled by seller from WB warehouse pickup
DBS orders10delivery by seller: orders, statuses, actions, delivery dates, metadata
Click & collect9pickup orders, buyer identity confirmation, actions and metadata
FBW supplies6shipments into WB warehouses, goods in a shipment, warehouses, intake coefficients for the next 14 days
Seller warehouses and stock8seller warehouses, updating and reading stock
Finance7sales reports, detailed breakdown, acquiring, balance, seller profile
Tariffs and storage6box and pallet tariffs, return tariffs, commissions, FBW transit, paid storage
Reviews and questions18reviews and questions, replies, per-period counters, archive, pinned reviews, seller rating
Returns3return requests, answering a request, returns report
Buyer chats4chats, events, sending messages, downloading attachments
Documents4document categories, list, single and bulk download
Users2staff members and invitations
WB Jam1WB Jam subscription status (WB's paid analytics add-on)
Shops1list of connected seller accounts
Diagnostics4self-diagnostics, token inspection, tool degradations, WB API news

Three things similar servers usually do not have:

  • Multi-store. Every call takes a `shop_id`, so two WB seller accounts live in one

conversation. With a single store you can omit `shop_id` entirely.

  • WB API diagnostics. The server pings WB hosts by itself, sends one cheap probe

request per API category, decodes the token's expiry and scopes, and highlights

"degradations": a tool that used to work and now fails consistently — a reliable sign

that WB changed the API.

  • Encrypted tokens. WB tokens are stored encrypted (Fernet), not in your client's config.

Quick start

Option 1: one command, no Docker

The server speaks stdio, which is how Claude Desktop, Cursor, VS Code and other

MCP clients connect to it. Nothing to build:

bash
uvx wb-mcp-server

Or via pip:

bash
pip install wb-mcp-server
wb-mcp

Client configuration (for example `claude_desktop_config.json`):

json
{
  "mcpServers": {
    "wildberries": {
      "command": "uvx",
      "args": ["wb-mcp-server"],
      "env": {
        "WB_API_TOKEN": "your Wildberries API token",
        "DATA_DIR": "~/.wb-mcp"
      }
    }
  }
}

Point `DATA_DIR` at any writable directory — it holds stores, keys and statistics.

The default is `/data`, which is the path used inside Docker.

Option 2: Docker with the web dashboard

Use this if you want the dashboard, WB API diagnostics and browser-based store

management. You need Docker (Docker Desktop or OrbStack) and a Wildberries Seller

API token.

bash
git clone https://github.com/DeviceIngineering/wb-mcp-server.git
cd wb-mcp-server
cp .env.example .env          # fine as-is for a local run
docker compose up -d --build

Check:

bash
curl -s http://localhost:8001/api/health
# {"status":"ok","auth_enabled":false,"health_check_interval_min":30,...}

What you now have:

AddressWhat it is
dashboard: tool calls, errors, response times
stores: add a WB seller account, test its token
diagnostics: tokens, WB host pings, probes, history
JSON summary for external monitoring
`http://localhost:8001/sse`the MCP endpoint — this is what you give to the client

Next:

1. Open → Добавить магазин (Add store) → paste the WB

token → Проверить (Test). The token comes from the WB Seller Portal

(seller.wildberries.ru): Настройки → Доступ к API → Создать токен

(Settings → API access → Create token). It is valid for 180 days; the remaining

lifetime is shown on the diagnostics page.

2. Connect an MCP client — see the next section.

3. Ask your assistant: "list my Wildberries stores" — the `wb_list_shops` tool should fire.

The start command, flag by flag:

FlagWhy
`up`start the service described in `docker-compose.yml`
`-d`in the background, without holding the terminal
`--build`build the image from `Dockerfile` — needed on the first run and after code updates

Stop it with `docker compose down` (data stays in the `wb_data` volume).

Logs: `docker compose logs -f`.

Running without Docker

bash
git clone https://github.com/DeviceIngineering/wb-mcp-server.git
cd wb-mcp-server
python3 -m venv .venv && source .venv/bin/activate
pip install .
DATA_DIR=./data PORT=8001 python -m wb_mcp.app

`DATA_DIR` is mandatory here: by default the server writes to `/data`, a path that only

exists inside the container.

Installing into clients

The server speaks MCP over SSE: `GET /sse` is the event stream, `POST /messages`

carries the client's messages. SSE support differs from client to client, so each one

has its own guide — with config paths for macOS, Linux and Windows, ready-to-paste JSON,

and variants with and without an auth token.

> The per-client guides in `docs/` are currently in Russian only. The configuration

> in them is ready-made JSON with file paths and flags, which is readable regardless

> of language.

ClientSSE directlyGuide
Claude Codeyesdocs/install-claude-code.md
Claude Desktopno → `mcp-remote` bridge or local stdiodocs/install-claude-desktop.md
Cursoryesdocs/install-cursor.md
Windsurfyesdocs/install-windsurf.md
VS Code (GitHub Copilot)yesdocs/install-vscode-copilot.md
Clineyesdocs/install-cline.md
Continue.devyesdocs/install-continue.md
Zedby URL; SSE support is not officially stateddocs/install-zed.md
JetBrains AI Assistantyes (SSE as legacy)docs/install-jetbrains.md
Gemini CLIyesdocs/install-gemini-cli.md
Codex CLIno → `mcp-remote` bridgedocs/install-codex.md

Overview and compatibility table: docs/README.md.

Where a client has a command that configures the connection by itself, the guide starts with

that command and treats editing JSON as the second option. The shortest setup of all —

Claude Code:

bash
claude mcp add --transport sse wildberries http://localhost:8001/sse
claude mcp list      # expected: wildberries ... ✔ Connected

Multi-store and security

Several seller accounts. Stores are added on `/shops`; each one gets its own `shop_id`.

`wb_list_shops` returns the list, and 200 of the 202 tools take `shop_id` as their first

parameter (the exceptions are `wb_list_shops` and `wb_degradations`).

With a single store the parameter can be omitted — the server substitutes the only one available.

The point is not "it supports two accounts" but that **a strategy is written once and rolled

out to every account**: a pricing rule, a review-reply template, an advertising bid ceiling

apply to all stores inside one conversation — no account switching, no scattering API keys

across different clients' configs.

How many accounts you can connect. There is no limit in the code: `shops.json` is a plain

dictionary, add as many as you like. The ceiling is set by Wildberries, not by this server:

all accounts reach WB from a single IP address — the one running this server — and rate

limits are counted per address as well. The author's own estimate: around twenty accounts per

address stay in the safe zone. Beyond that, split them across several servers with different

addresses.

Why this matters more than it looks — see the WB limits:

several methods allow 3 requests per minute, and any 4XX response counts as 10 requests.

With a dozen accounts on one server, a handful of malformed requests in a row burns the quota

ten times faster — and every store hits the wall at once, not just the one that erred.

There are ways to watch for it:

  • Background diagnostics send one `/ping` per host per run (the limit is 3 requests per

30 seconds per host) and record failed checks and warnings into a history. You see the limit

approaching in advance, instead of learning about it from a block.

  • The degradation detector tells two cases apart: many tools degrading at once means

per-address throttling, while a single tool degrading means one WB endpoint broke.

The dashboard makes the difference obvious at a glance.

Where the tokens live. In the `wb_data` volume (`/data` inside the container):

  • `shops.json` — stores, with tokens encrypted using Fernet;
  • `.encryption_key` — the encryption key, generated on first start;
  • `stats.db` — SQLite with call statistics and diagnostics history.

The key sits next to the encrypted data, so the encryption protects against an accidental

leak of the single `shops.json` file (a backup, a copy-paste) but not against anyone who

gets access to the whole volume. Move the data as a whole volume — see DEPLOY.md.

MCP authorization. The `MCP_AUTH_TOKEN` variable in `.env`:

bash
openssl rand -hex 32   # put the value into .env → MCP_AUTH_TOKEN=
docker compose up -d
  • empty (the default) — `/sse` is open to anyone with network access to the port;
  • set — the client must send `Authorization: Bearer ` or `?token=`

in the URL. The second form rescues clients that cannot send custom headers.

The token is checked on both MCP endpoints — on `GET /sse` and on `POST /messages`.

What the server does not do:

  • The web UI (`/`, `/shops`, `/diagnostics`) is not protected by the token — it is open

to anyone with network access to the port.

  • Port 8001 is not meant to be exposed to the internet. For remote access use Tailscale or a VPN.
  • The server does not terminate HTTPS. If you need TLS from outside, put a reverse proxy in front.

The web UI: every call is visible

With a typical MCP server, calls vanish into thin air: you cannot see what the assistant

actually did, how long it took or what the marketplace answered, and you learn about a problem

only when something fails. Here every call has a record and every store has a state.

For a tool that moves real money in a real shop, this is a precondition for trust,

not decoration. Five months of daily use across some twenty accounts is precisely what

filled these pages — and produced the WB limits section further down.

Dashboard — `/`

The screenshot is at the top of this page.

A summary of all tool calls (`stats.get_summary()`):

  • total calls, calls today, number of errors, average call duration;
  • top 10 tools: call count, average time, error count;
  • a feed of the last 50 calls: timestamp, store, tool, duration in milliseconds,

success or failure, error text;

  • a per-store filter — an "All / specific account" switch above the summary.

Stores — `/shops`

The stores page

Accounts are added and removed right in the browser, with no file editing and no container

restart. Each store has a Проверить ("Test") button: it makes one cheap real request to WB

and tells you immediately whether the token is alive — instead of letting you find out during

the first real call. Tokens are shown masked in the list (`abc***xyz`).

Tokens are encrypted with Fernet and stored in `shops.json` inside the data volume; the key

is in `.encryption_key` next to it. The HTTP client pool is reset when a store is saved or

deleted, so a new token takes effect immediately.

Diagnostics — `/diagnostics`

The diagnostics page

*(the screenshot shows a demo store with a made-up token: WB answers `401` to every ping and

every probe, so the whole page is red. That is what a failed check looks like — the server

itself is fine. With a working token the "Проверка …" line reads `ping 13/13, пробы 20/20`

and the store status is "✅ Здоров".)*

A background check every `HEALTH_CHECK_INTERVAL_MIN` minutes (30 by default), per store:

  • the token — expiry, access categories, read-only and sandbox flags;
  • pings of 13 WB API hosts — availability and latency of each;
  • 20 probes — one cheap real GET per API category. These are what catch

"the endpoint returns 404 because WB renamed it";

  • warnings in plain language: "the token expires in N days",

"Content: 404 on /content/v2/... — WB may have changed the API";

  • check history with automatic rotation (the last 1000 records are kept);
  • a "check now" button to run everything immediately.

The degradation detector

The most useful thing the accumulated statistics give you. The server finds, by itself, tools

that used to work and now fail consistently: the last three calls failed while successful

calls exist in the history. For each such tool it shows the time of the last successful call,

the number of consecutive errors, the text of the latest error and the moment things broke.

In other words, the server detects from its own statistics that Wildberries broke or switched

off an endpoint — and tells you before you run into it at work. Next to the

section on limits and endpoint shutdown dates this is its practical

continuation: that section lists what WB announced, this one catches what WB did quietly.

You can look at it on the dashboard, or call `wb_degradations` straight from the chat.

JSON for external monitoring

Everything visible to a human is also readable by a machine:

EndpointWhat it returns
`GET /api/health`service status, whether authorization is on, the check interval, the last 5 health checks, the list of degraded tools
`GET /api/stats`the same summary as the dashboard; accepts `?shop=`
`POST /api/diagnostics/run`run diagnostics for all stores now and return the result
`GET /api/diagnostics/`full live diagnostics of a single store

So the server can be wired into Uptime Kuma, Zabbix or any other monitoring system, and you

learn about a dead token before the assistant tells you about it.

Context budget

Two things are paid in tokens: tool definitions, loaded once per session, and tool

responses, paid on every call. Both were measured on a live seller account rather

than estimated — `scripts/collect_corpus.py` takes a snapshot of read-only tools

(PII masked before anything is written to disk, the corpus stays out of the repo),

`scripts/measure_corpus.py` reports what it costs.

Definitions. 202 tools cost 17 700 tokens with a single store configured,

down from 27 460. Descriptions are one sentence each, `shop_id` is dropped from the

schemas when only one store exists (the server fills it in), and empty schema fields

are not serialised.

Responses. The real problem turned out to be a handful of giant payloads:

toolbeforeafter
`wb_tariffs_commission` — the whole 7 408-category reference621 80223 023
`wb_cards_list` — 78 % of the weight is photo URLs and descriptions73 8273 232
`wb_finance_report` — 90 fields per row23 5407 156
`wb_advert_list` — 110 campaigns with timestamps20 52812 084
corpus of 27 live responses770 50674 947

What the server does about it:

  • `view: compact | full`. Heavy tools return the fields they are called for;

`view="full"` gives the raw API response. Which fields were hidden is stated in

the response itself, so the model knows what it can ask for.

  • Truncation signal. When exactly `limit` records come back, the answer carries

a warning that the data is partial. Without it the model reasons about a slice

and presents it as the whole catalogue.

  • Size guard. A response that would not fit the client's output ceiling

(`MAX_MCP_OUTPUT_TOKENS`, 25 000 by default in Claude Code) is cut server-side,

saying how many records are left out of how many — instead of being silently

truncated on arrival.

  • Server-side filters where the API has none. WB returns the commission

reference in full; the `subject` parameter narrows it here.

Notes arrive as separate content blocks rather than a field inside the JSON: half

of the WB endpoints return an array at the top level, and wrapping it would break

every path into the data.

Tool profiles. A client without tool search pays for the whole catalogue on

every request. `WB_TOOLSETS` keeps only the profiles you use — they are cut along

working tasks, not along WB documentation sections, because auditing promotions

needs promotions, prices and the price quarantine at once:

`WB_TOOLSETS`toolstokens
empty (default)20218 011
`pricing,ads`494 925
`pricing,ads,analytics`737 313
`orders`715 801

The `core` profile — stores, diagnostics, degradations, token info — is always on:

diagnostics are needed exactly when something is broken. Disabled profiles are

listed in the `wb_list_shops` description, and calling a disabled tool answers

which profile contains it — so the assistant names the reason instead of saying

"this is not possible".

Claude Code needs none of this: it has tool search enabled by default and loads

schemas on demand. Cursor, Cline, Continue and Claude Desktop fetch `tools/list`

whole — profiles are for them.

Design decisions

  • 202 narrow tools, not a few generic ones. Collapsing them into `action`-style

endpoints would save definition tokens and change the class of failure: instead of

"no such tool" you get a wrong call with a side effect, and some of these tools set

prices and start ad campaigns.

  • Dispatch through dictionaries, not an if-chain. `NO_CLIENT_DISPATCH`,

`CLIENT_DISPATCH` and `SHOP_DISPATCH` map names to handlers, and a test asserts that

every tool has one and no handler is orphaned. With 202 tools an if-chain rots quietly.

  • The server diagnoses itself. `wb_diagnostics` pings every WB host and runs a

light real request per API category; `wb_degradations` reports which tools used to

work and now fail steadily. Marketplace APIs change without notice — the question

"is it my token or did WB move the endpoint" has to be answerable in one call.

  • `compact` is the default for heavy tools. The corpus showed the hidden fields

are photo URLs, promo history and warehouse timetables — not the data decisions are

made from. The response says what was hidden, so nothing is lost silently.

  • `shop_id` disappears from schemas with one store. The same parameter block

repeated across 200 schemas cost 3 400 tokens per session for no information;

the server substitutes the only store and puts the parameter back as soon as a

second one appears.

  • `mcp=1.0.0,` — full diagnostics of a single store.

Project layout

code
wb-mcp-server/
├── docker-compose.yml          # port 8001, wb_data volume
├── Dockerfile                  # python:3.12-slim
├── pyproject.toml
├── DEPLOY.md                   # deploying to a dedicated machine, moving the data
├── docs/                       # client setup guides + tool reference
└── wb_mcp/
    ├── server.py       # MCP server: 202 tools, dispatch tables, stdio mode
    ├── client.py       # HTTP clients for the 14 Wildberries APIs
    ├── app.py          # FastAPI: SSE + web UI + auth + health loop
    ├── diagnostics.py  # pings, JWT decoder, probes, API news
    ├── settings.py     # stores and keys (Fernet)
    ├── stats.py        # call statistics and check history (SQLite)
    └── templates/      # PicoCSS: dashboard, diagnostics, shops

Deployment

Moving the server to a dedicated machine, migrating stores, setting up autostart —

see **DEPLOY.md** (in Russian).

The same server for Ozon

**DeviceIngineering/ozon-mcp-server**

is the same tool for the other marketplace (Ozon is Russia's other large marketplace):

same architecture, same web UI with dashboard and diagnostics, same multi-store handling via

`shop_id`, same SSE transport, same ways of connecting clients. Once you have set up one,

the second one follows the same instructions; only the port and the tool set differ.

WB MCP ServerOzon MCP Server
Port80018000
Tools202151
APIWildberries Seller APIOzon Seller API + Performance API (advertising)

They can run side by side on one machine: different ports, different Docker volumes,

no conflict.

Living on the same server does not hurt on the rate-limit side either: both go out through

one IP, but Wildberries and Ozon count their limits separately — they are different

platforms. The per-address ceiling on the number of accounts, described in the multi-store

section, applies within each platform on its own.

Updates and support

Wildberries changes its API constantly: endpoints are added, renamed and switched off —

the limits section above lists what has already been caught in practice.

This server is the author's working tool: more than five months of daily use across roughly

twenty seller accounts. It is updated as the author needs it — when the next change breaks

something in his own stores, not on a schedule. That is why the gaps between commits can be

long: it means WB broke nothing in the meantime. There is no commitment on timing.

If you need a fix urgently, write to d0371153@gmail.com.

Issues and pull requests are welcome and do get reviewed.

Version history: CHANGELOG.md.

License

MIT — see LICENSE.

MCP Registry

Published in the official MCP Registry:

code
mcp-name: io.github.DeviceIngineering/wb-mcp-server

Frequently asked questions

What is wb-mcp-server?

wb-mcp-server is MCP server for the Wildberries Seller API: 202 tools for prices, promotions, ads, orders, supplies, reviews, finance and analytics. Multi-store, web dashboard, self-diagnostics. Context budget measured on a live account: a 27-response corpus trimmed from 770k to 75k tokens. Docker, SSE, MIT.

How do I install wb-mcp-server?

Open the GitHub repository and follow its README. Most MCP servers are added to your client's MCP config, then called by your agent.

Is wb-mcp-server open source?

Yes — it is hosted on GitHub at https://github.com/DeviceIngineering/wb-mcp-server and has 3 stars.

Related MCP tools

Run your own MCP server? See who uses it and what to fix.

Measure it with TrackMCP