Skip to main content

Русский English 中文

Ozon MCP Server

License: MIT Python MCP tools PyPI Transport

Run your Ozon stores straight from a chat with an AI assistant: prices, promos, advertising, orders, returns, reviews, finances — 151 tools on top of the Ozon Seller API and Performance API (Ozon is Russia's largest marketplace; the Seller API covers catalogue and operations, the Performance API covers paid ads). Built for sellers who run more than one store: every call takes a shop_id, and API keys stay encrypted on your own server — nothing leaves it. What sets it apart from other Ozon MCP servers: it covers advertising as well as the Seller API, and its built-in diagnostics tell you which Ozon endpoints broke before your assistant runs into them.

Selling on Wildberries too? There is the same server for WB — wb-mcp-server.

This is the author's own working tool: more than five months of daily use, around twenty seller accounts, 151 tools. It gets updated when he needs it updated — see Updates and support for what that means for you.

The per-client installation guides in docs/ are currently Russian only. The configuration in them is ready-to-paste JSON, which reads the same in any language: file paths, the URL http://localhost:8000/sse, and the header Authorization: Bearer <MCP_AUTH_TOKEN>.

You: Which of my products is Ozon planning to pull into a promo?
You: Show ad campaign spend for the week and stop the ones burning money.
You: Which products have a worse price index than their competitors?
You: Reply with a thank-you to every new 5-star review.

Ozon MCP Server dashboard

What it does

Group Tools What's inside
Promotions and discounts 14 Ozon promotions (list, candidates, join/leave), seller's own promotions, "I want a discount" buyer requests
Prices and pricing strategies 14 setting prices and the minimum price, price index, minimum-price timer, automatic strategies that track competitors
Advertising (Performance API) 22 "Trafarety" CPC campaigns (Ozon's sponsored-placement format), bids and budgets, "Pay per order" (CPO), per-product and daily statistics
Products 21 listings and cards, attributes, stock, import and bulk updates, media, archive, certificates
FBS and FBO orders 17 unfulfilled orders, packing (v4), labels, cancellations, handover acts, country of origin
Returns and cancellations 10 unified FBO+FBS returns list, rFBS claims that need a seller decision, cancellation requests
Reviews, questions, chats 13 reviews and replies, buyer questions, chat conversations (v3)
Warehouses and reports 8 FBS warehouses, delivery methods, generating and downloading reports
Finances 7 balance, transactions, accruals, realization report, mutual settlements, cash flow
Categories, brands, certificates 7 category tree, attributes and their allowed values, certificates
Analytics 5 SKU analytics, stock and turnover, product positions in Ozon search, top search queries
FBO supplies 4 supply orders (v3), counters, timeslots
Rating 2 current seller rating and its history
Diagnostics 2 self-check of Ozon API availability, degradation detector
Notifications 2 push webhook subscriptions and the event-type reference
Company 2 seller details and tariffs
Stores 1 list of connected stores and their shop_id

FBO and FBS are Ozon's fulfilment models: FBO ships from Ozon's warehouses, FBS from yours, rFBS is FBS with your own delivery.

The full numbered list, with a description and the parameters of every tool, is in docs/tools.md. It is generated from ozon_mcp/server.py (the TOOLS constant) — the same thing tools/list returns to any MCP client.

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:

uvx ozon-mcp-server

Or via pip:

pip install ozon-mcp-server
ozon-mcp

Client configuration (for example claude_desktop_config.json):

{
  "mcpServers": {
    "ozon": {
      "command": "uvx",
      "args": ["ozon-mcp-server"],
      "env": {
        "OZON_CLIENT_ID": "your Client-Id",
        "OZON_API_KEY": "your API key",
        "DATA_DIR": "~/.ozon-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, Ozon API diagnostics and browser-based store management. Five commands:

git clone https://github.com/DeviceIngineering/ozon-mcp-server.git
cd ozon-mcp-server
cp .env.example .env               # fine as-is for a trusted local network
docker compose up -d --build       # builds the image, serves on port 8000
open http://localhost:8000/shops   # add a store and its Ozon API keys

What each step does:

  • .env — every variable is optional. Store keys are easier to enter in the web UI than here. The one thing worth setting up front, if the server is reachable by anyone but you, is MCP_AUTH_TOKEN (generate one with openssl rand -hex 32).
  • docker compose up -d --build — builds the image from the Dockerfile, maps port 8000:8000 and creates the ozon_data volume for stores, keys, call statistics and diagnostics history. restart: unless-stopped brings the container back up after a reboot.
  • /shops — the add-store form: shop_id (the handle you'll use in chat), a display name, Client-Id + Api-Key for the Seller API, and Client-Id + Client-Secret for the Performance API. The "Проверить" (Test) button makes a live request to Ozon and tells you whether the keys were accepted.

Once it's running:

Address What it is
http://localhost:8000/ dashboard: call counters, errors, degradations
http://localhost:8000/shops stores and keys
http://localhost:8000/diagnostics Ozon API diagnostics
http://localhost:8000/api/health health endpoint, JSON
http://localhost:8000/sse the MCP endpoint — this is what clients point at

Note that the web UI is in Russian.

To stop: docker compose down (the data stays in the ozon_data volume). Logs: docker compose logs -f.

Without Docker

python3 -m venv .venv && source .venv/bin/activate
pip install .
DATA_DIR=./data PORT=8000 ozon-mcp-web

DATA_DIR defaults to /data, so when running locally be sure to point it at a directory you can write to.

Installing into clients

The transport is SSE at http://<host>:8000/sse. SSE support differs between clients: some speak it directly, others need the mcp-remote bridge. There is one guide per client, with config paths for macOS, Linux and Windows and ready-made JSON — in Russian, but the JSON blocks are language-neutral:

Client SSE directly Guide
Claude Code yes docs/install-claude-code.md
Claude Desktop no, mcp-remote bridge docs/install-claude-desktop.md
Cursor yes docs/install-cursor.md
Windsurf / Devin Desktop yes docs/install-windsurf.md
VS Code (GitHub Copilot) yes docs/install-vscode-copilot.md
Cline yes docs/install-cline.md
Continue.dev yes docs/install-continue.md
Zed unconfirmed, bridge recommended docs/install-zed.md
JetBrains AI Assistant / Junie yes docs/install-jetbrains.md
Gemini CLI yes docs/install-gemini-cli.md
OpenAI Codex CLI no, mcp-remote bridge docs/install-codex.md

The shortest example, Claude Code:

claude mcp add --transport sse ozon http://localhost:8000/sse \
  --header "Authorization: Bearer <MCP_AUTH_TOKEN>"

Client summary and the bridge reference: docs/README.md.

Multi-store and security

Stores are added in the web UI, and every tool takes a required shop_id; ozon_list_shops tells you which ones exist. In chat it looks like this: "show me the stock in store alpha".

The real gain is not the switching itself but that a strategy is written once and rolled out to every account: a rule about prices, review replies or ad bids applies to all stores at once — no logging in and out of seller accounts, no copying keys between client configs.

The price you pay is a shared IP. Every account talks to Ozon from one address: the server the MCP runs on. Ozon's rate limits are counted per address among other things, so the more accounts you have and the harder your strategies work them, the closer the combined traffic gets to the threshold where throttling or a block kicks in.

  • there is no limit on the number of stores in the code;
  • the real ceiling comes from Ozon's per-IP limits, not from this server;
  • around twenty accounts is the author's own estimate of where the traffic still stays in the safe zone;
  • beyond that, spread the stores across several servers with different addresses.

You can see the limit approaching, and the place to see it is the web UI: failed pings and diagnostics warnings start piling up, and the error share in the call statistics jumps. The dashboard also tells the two cases apart — mass throttling looks like many tools degrading at once, a broken endpoint like a single one.

How keys are stored:

  • on first use, .encryption_key — a Fernet key — is created in DATA_DIR;
  • store keys are encrypted with it and kept in DATA_DIR/shops.json;
  • the web UI shows keys masked (abc***xyz), and saving a masked value does not overwrite the real one;
  • under Docker all of this lives in the ozon_data volume. To move to another machine, copy the whole volume — otherwise you lose the encryption key (see DEPLOY.md, Russian).

What to know about access:

  • MCP_AUTH_TOKEN protects only /sse. Pass it as the Authorization: Bearer … header or as a ?token=… query parameter.
  • An empty MCP_AUTH_TOKEN means no authentication at all. Only acceptable on a trusted network.
  • The web UI (/, /shops, /diagnostics) and /api/* are not behind the token: anyone who can reach the port sees the dashboard and can add stores.
  • Do not expose port 8000 to the internet directly. 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 the void: the assistant did something, but what exactly, how long it took and what error it hit is known only to the assistant. Here every call gets a line in the log, and every broken tool gets a marker on the dashboard. For a tool that moves real money in a store, that is not decoration — it is the condition for trusting it.

The call statistics and check history are not synthetic: they come from more than five months of daily use across roughly twenty seller accounts. The list of caught Ozon API changes in the limitations section comes from the same place — it was read off the degradation log, not copied from the documentation.

Dashboard /

The screenshot is at the top of this page.

  • Four counters at the top: total calls, calls today, errors, and average call duration in milliseconds.
  • Top 10 tools: call count, average duration, and how many of those calls failed.
  • A feed of the last 50 calls: timestamp, shop_id, tool name, duration, success or failure, and the error text.
  • A per-store filter (/?shop=alpha) — the same figures for a single account.
  • Two banners surface at the top: degraded tools, and "the last Ozon API check found problems".

Stores /shops

Stores page

Accounts are added and removed right in the browser, with no file editing and no container restart. The "Проверить" (Test) button makes a live request to both APIs (POST /api/shops/{shop_id}/test), so keys are verified when you add them rather than during the first real call in the middle of a task. Tokens are encrypted with Fernet, the encryption key lives in DATA_DIR/.encryption_key, and the UI shows keys masked.

Diagnostics /diagnostics

Diagnostics page

(the screenshot shows a demo store with deliberately invalid keys, which is why every probe is red)

  • Per store: whether keys are set, Ozon host availability, 12 Seller API category probes, and a Performance API key check.
  • A background check every HEALTH_CHECK_INTERVAL_MIN minutes (30 by default, 0 disables it), plus a "Проверить сейчас" (Check now) button for an immediate run (POST /api/diagnostics/run).
  • Check history: time, store, status, number of failed pings, number of failed probes, and the warning texts. The UI shows the last 30 entries; up to 1000 are kept in the database with automatic rotation.
  • The same data is available from chat through the ozon_diagnostics tool.

Degradation detector

The server notices on its own that Ozon broke or switched off an endpoint — not from the documentation and not from work that failed, but from its own statistics. A tool whose last three calls in a row failed while earlier calls succeeded lands in the degradation list, which shows the tool name, the time of the last successful call, the number of consecutive errors, and the text of the latest one. On the dashboard that is a red banner; on the diagnostics page, a table.

What this buys you: a change on Ozon's side becomes visible the day it happens, not a week later when you discover prices haven't been updating. The same list is available from chat via ozon_degradations.

JSON for external monitoring

All of the above can be scraped programmatically, not just looked at:

Endpoint What it returns
GET /api/health service status, whether authentication is on, recent checks, degraded tools
GET /api/stats the same summary as the dashboard; ?shop= narrows it to one store
GET /api/diagnostics/{shop_id} a full live diagnostic run for one store

That is enough to wire the server into Zabbix, Uptime Kuma, or a plain curl in cron.

How it works

A single Docker container running a FastAPI application that is both the MCP server and the web UI.

  • ozon_mcp/server.py — the MCP server itself. The TOOLS list describes all 151 tools (name, description, JSON schema for the arguments) and the call_tool handler routes each call to the right Ozon client method. Clients are pooled per shop_id, so switching stores reconnects nothing.
  • ozon_mcp/client.py — two HTTP clients: OzonSellerClient (Client-Id / Api-Key headers) and OzonPerformanceClient (a client_credentials token that lives 30 minutes and refreshes itself).
  • ozon_mcp/app.py — FastAPI: the /sse endpoint on top of SseServerTransport, Bearer-token checking, the dashboard/stores/diagnostics pages, and the background health-check task.
  • ozon_mcp/settings.py — stores and keys: Fernet encryption, masking for the UI, picking up keys from environment variables as a store called default, and migrating the old single-store settings.json into shops.json.
  • ozon_mcp/diagnostics.py — probes: pinging Ozon hosts plus lightweight real requests across 12 Seller API categories, and a Performance API key check.
  • ozon_mcp/stats.py — SQLite via aiosqlite: every tool call with its duration and outcome, health-check history, degradation calculation.

The hosts the server talks to:

API Base URL Authorization
Seller API api-seller.ozon.ru Client-Id and Api-Key headers
Performance API (ads) api-performance.ozon.ru OAuth client_credentials, 30-minute token

Non-obvious things:

  • Ozon returns ad bids and budgets in micro-rubles: 1000000 = 1 ₽. Don't be surprised by seven-digit numbers.
  • A 403 on reviews and questions is not a breakage — it means no Premium Plus subscription. Diagnostics does not count those as errors.
  • Ozon API keys carry no expiry date; you only learn one expired from a 401 in the probes.
  • Asynchronous ad statistics: one report at a time, ≤10 campaigns, ≤62 days. The tool waits up to about 2 minutes for the report to be ready.
  • Supply-order statuses in API v3 are integers 1–8, not strings.

Environment variables

Variable Default Purpose
MCP_AUTH_TOKEN empty Bearer token for /sse. Empty = no authentication
HEALTH_CHECK_INTERVAL_MIN 30 background diagnostics interval, 0 disables it
PORT 8000 HTTP server port
DATA_DIR /data directory holding shops.json, stats.db, .encryption_key
OZON_CLIENT_ID, OZON_API_KEY empty Seller API keys for the default store, if you'd rather not use the UI
OZON_PERF_CLIENT_ID, OZON_PERF_CLIENT_SECRET empty the same for the Performance API

Known Ozon API limitations (as of June 2026)

  • Advertising: the API can only create "Trafarety" CPC campaigns; budgets and bids are in micro-rubles; there is no official way to read the ad account balance.
  • "Pay per order": bids have been fixed since February 2025 — you can only turn the promotion on or off.
  • Reviews, questions and part of analytics require a Premium Plus subscription (error code 7).
  • Funnel metrics in ozon_analytics are marked deprecated by Ozon — use ozon_product_queries for search positions.
  • /v3/finance/transaction/* is being switched off on 2026-07-06; the replacements are already wired in (ozon_finance_cash_flow, ozon_finance_accruals).
  • ozon_product_stocks_by_warehouse uses v2 because v1 is switched off on 2026-04-07.
  • Digital FBS handover acts were removed by Ozon on 2026-03-22 — the regular act is used instead.
  • The Ozon API has no "edit a review reply" method: the reply is deleted and written again.

This list is not a rewrite of the reference: it comes from the degradation log and five months of daily calls, cross-checked against docs.ozon.ru as of June 2026.

What changed in version 2.0

A full revision against the June 2026 Ozon API, verified by running real requests rather than reading docs: the unified returns list, cancellations v2, realization v2, ship v4, supply-order v3, real pricing strategies and "I want a discount", the seller's own promotions, the new advertising model (Trafarety CPC + "Pay per order"), diagnostics with a degradation detector, and authentication on the MCP endpoint.

Project layout

ozon-mcp-server/
├── docker-compose.yml   # port 8000, ozon_data volume
├── Dockerfile           # python:3.12-slim, uvicorn
├── DEPLOY.md            # deploying to a dedicated machine, moving data
├── docs/                # client connection guides + tool reference
└── ozon_mcp/
    ├── server.py        # MCP server: 151 tools, multi-store
    ├── client.py        # Seller API + Performance API
    ├── app.py           # FastAPI: SSE, web, auth, health loop
    ├── diagnostics.py   # category probes, degradation detector
    ├── settings.py      # stores and keys (Fernet)
    ├── stats.py         # call statistics and check history (SQLite)
    └── templates/       # dashboard, diagnostics, shops

Deploying to a dedicated machine and moving stores across: DEPLOY.md (Russian).

The same server for Wildberries

wb-mcp-server is the same tool for the other marketplace (Wildberries is the other large Russian marketplace): same architecture, same web UI with dashboard and diagnostics, same multi-store model via shop_id, same SSE transport, same ways of connecting clients.

Ozon MCP Server WB MCP Server
Port 8000 8001
Tools 151 202
API Ozon Seller API + Performance API (ads) Wildberries Seller API

In practice that means two things:

  • The second server takes no new learning. Once you have set up one, the other starts the same way; only the port (8001 instead of 8000) and the tool set differ.
  • You can run both on one machine. Different ports, data in separate Docker volumes, no conflict. In your client they are simply two MCP servers: ozon at http://localhost:8000/sse and wb at http://localhost:8001/sse.

Sharing one machine does not hurt on rate limits either: both go out from the same IP, but Ozon and Wildberries count limits on their own side — they are different marketplaces. The cap on the number of seller accounts described in the multi-store section applies within each marketplace separately.

Updates and support

Ozon changes its API constantly: endpoints get added, renamed and switched off (the limitations section above lists what has been caught so far). This server is the author's working tool, and it gets updated when he needs it updated — that is, when a change breaks something in his own stores. More than five months of daily use, and commits appear when Ozon breaks something, not on a schedule: a gap between commits usually means everything is working. The upside is that the code is proven by real daily use rather than published and forgotten; the downside is that there is no release schedule and no commitment on turnaround.

If you need a fix urgently, write to d0371153@gmail.com. Issues and pull requests are welcome too, and they do get read.

License

MIT — see LICENSE.

MCP Registry

Published in the official MCP Registry:

mcp-name: io.github.DeviceIngineering/ozon-mcp-server

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ozon_mcp_server-2.0.1.tar.gz (248.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ozon_mcp_server-2.0.1-py3-none-any.whl (59.9 kB view details)

Uploaded Python 3

File details

Details for the file ozon_mcp_server-2.0.1.tar.gz.

File metadata

  • Download URL: ozon_mcp_server-2.0.1.tar.gz
  • Upload date:
  • Size: 248.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for ozon_mcp_server-2.0.1.tar.gz
Algorithm Hash digest
SHA256 0e4665d828a4ea41222163445c1c160d2203ac1380c21e62faf24376a1b85325
MD5 db01d23f39d40c0294d2b01c8154a52a
BLAKE2b-256 7730e8cc3d47dc08db61d1b440b8cd1f0b2c969c9fdd2912cb6205472be99945

See more details on using hashes here.

Provenance

The following attestation bundles were made for ozon_mcp_server-2.0.1.tar.gz:

Publisher: publish.yml on DeviceIngineering/ozon-mcp-server

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ozon_mcp_server-2.0.1-py3-none-any.whl.

File metadata

  • Download URL: ozon_mcp_server-2.0.1-py3-none-any.whl
  • Upload date:
  • Size: 59.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for ozon_mcp_server-2.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 8d933c24fb06a87e8c57d7324c782a45e44c1c3aa09f73f6a8306e6d6c5d487c
MD5 74240dcf4a38de25f3a7640ead5e6a2f
BLAKE2b-256 e2f5991a05b8243ef0fbd45bc3938c9355897708ac9b2bc3f0069eab73542039

See more details on using hashes here.

Provenance

The following attestation bundles were made for ozon_mcp_server-2.0.1-py3-none-any.whl:

Publisher: publish.yml on DeviceIngineering/ozon-mcp-server

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

2.0.2

2 files

This release

2.0.1 This release

2 files

2.0.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page