Ozon Seller API принимает запросы только сервер-сервер: браузерные вызовы блокируются с мая 2025 года. MCP-сервер решает эту задачу, превращая официальный API в набор инструментов, которые агент вызывает сам. Ниже четыре инструмента на Python, авторизация по Client-Id и Api-Key и проверка в официальном инспекторе MCP.
Зачем агенту MCP-сервер: кабинет в работе без выгрузок
Продавец каждое утро делает одно и то же: скачивает отчёт, смотрит остатки, проверяет новые заказы и отвечает на отзывы. Пока позиций десятки, это терпимо. На сотнях SKU появляются ошибки: где-то не обновилась цена, где-то закончился товар, а заказ уже принят.
MCP-сервер закрывает разрыв между моделью и кабинетом. Агент не «ходит на сайт» и не разбирает интерфейс, а вызывает описанные инструменты: список товаров, остатки, заказы. Внутри эти инструменты обращаются к официальному API по ключу, который лежит на сервере и не попадает в контекст модели.
Протокол MCP описан в открытой документации modelcontextprotocol.io. Клиентом может быть Claude Desktop, Cursor или собственное приложение на Python. Сервер один, клиентов сколько угодно.
Авторизация: два заголовка, которые живут только на сервере
Ozon использует простую схему: в каждом запросе передаются заголовки Client-Id и Api-Key. Оба значения продавец получает в личном кабинете. Ключ показывается один раз при создании, восстановить его нельзя, только выпустить новый.
Проверить связку можно любым HTTP-клиентом. Если ключей нет, официальный API отвечает кодом 401 и заголовком www-authenticate: Client-Id and Api-Key headers are required. Это не ошибка интеграции, а нормальный ответ на запрос без авторизации.
curl -X POST "https://api-seller.ozon.ru/v3/product/list" \
-H "Client-Id: 123456" \
-H "Api-Key: ваш-ключ" \
-H "Content-Type: application/json" \
-d '{"filter": {"visibility": "ALL"}, "last_id": "", "limit": 10}'
Есть два условия, о которых легко забыть. Первое: оферта продавца должна быть принята, иначе API вернёт 403 с формулировкой про неподписанную оферту. Второе: с 16 мая 2025 года запросы разрешены только сервер-сервер, поэтому вызывать API напрямую из браузерного приложения нельзя.
Время в API — UTC. Если агент строит отчёт «за сегодня», границы суток нужно считать по UTC, иначе вечерние заказы попадут не в тот день.
Одиннадцать эндпоинтов, которых хватает большинству агентов
Для рабочего контура не нужен весь API. Достаточно чтения каталога, остатков, заказов и отзывов. Ниже методы, которые проверены запросом к официальному хосту: без ключа они отвечают 401, то есть существуют и ждут авторизацию.
| Метод | Эндпоинт | Что делает |
|---|---|---|
| Информация о кабинете | /v1/seller/info | Название компании, валюта, подключённые сервисы |
| Список товаров | /v3/product/list | Все SKU с пагинацией по last_id |
| Карточки товаров | /v3/product/info/list | Детали по product_id и offer_id |
| Остатки | /v4/product/info/stocks | Сколько доступно к продаже |
| Цены | /v5/product/info/prices | Текущая цена и цена до скидки |
| Обновление цен | /v1/product/import/prices | Массовая загрузка новых цен |
| Заказы FBS | /v3/posting/fbs/list | Отправления со склада продавца |
| Заказы FBO | /v2/posting/fbo/list | Отправления со склада Ozon |
| Отзывы | /v1/review/list | Тексты отзывов и оценки |
| Аналитика | /v1/analytics/data | Показатели продаж за период |
| Склады | /v1/warehouse/ozon/list | Список складов FBO и возвратных |
Полное описание полей и лимитов лежит в официальной документации docs.ozon.com/api/seller. Там же есть консоль для проверки запросов и раздел про лимиты по каждому методу.
Сервер — это файл на Python, где каждый метод API становится инструментом
Актуальный SDK протокола во второй версии переименовал класс: вместо FastMCP теперь MCPServer. Код ниже собран под эту версию и проверен запуском.
import os
import httpx
from mcp.server import MCPServer
BASE = "https://api-seller.ozon.ru"
mcp = MCPServer("ozon-seller")
async def post(path: str, payload: dict):
headers = {
"Client-Id": os.environ["OZON_CLIENT_ID"],
"Api-Key": os.environ["OZON_API_KEY"],
"Content-Type": "application/json",
}
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.post(f"{BASE}{path}", json=payload, headers=headers)
if response.status_code == 401:
return None, "Ozon отклонил ключи (401)"
if response.status_code == 429:
return None, "Превышен лимит запросов (429)"
response.raise_for_status()
return response.json(), None
@mcp.tool()
async def list_products(limit: int = 50) -> str:
"""Список товаров кабинета. limit — максимум 1000."""
data, error = await post("/v3/product/list", {
"filter": {"visibility": "ALL"}, "last_id": "", "limit": limit,
})
if error:
return f"Не удалось получить данные: {error}"
items = data.get("result", {}).get("items", [])
return "\n".join(f"{i['offer_id']} · {i['product_id']}" for i in items)
if __name__ == "__main__":
mcp.run(transport="stdio")
Ключи читаются из переменных окружения. В коде их нет, в git они не попадают, в контекст модели они тоже не уходят: агент видит только результат инструмента.
Дальше по той же схеме добавляются остатки, заказы и отзывы. Каждый инструмент — это один эндпоинт и понятное описание. Описание важно: по нему модель решает, когда вызывать инструмент, поэтому фраза «сколько товара доступно к продаже» работает лучше, чем «метод stocks».
Проверка в официальном инспекторе вместо веры в «должно работать»
Инспектор MCP — официальный отладочный клиент. Он запускает сервер, показывает список инструментов и даёт вызвать любой из них вручную. На скриншоте видно четыре инструмента: информация о кабинете, товары, остатки и заказы FBS.
Карточка инструмента показывает схему параметров и кнопку запуска. Если параметр описан как limit: int, модель понимает, что можно попросить меньше строк, и не тянет весь каталог в контекст.
Проверка на живом API без ключей даёт ожидаемый результат: инструмент возвращает текст «не заданы OZON_CLIENT_ID и OZON_API_KEY». Цепочка клиент — сервер — HTTP-запрос собрана правильно, не хватает только доступа.
Подключение: одна запись в конфиге клиента
Claude Desktop и другие локальные клиенты запускают сервер сами по команде из конфигурационного файла. На macOS он лежит в ~/Library/Application Support/Claude/claude_desktop_config.json, на Windows — в %APPDATA%\Claude\claude_desktop_config.json.
{
"mcpServers": {
"ozon-seller": {
"command": "/root/mcp-venv/bin/python",
"args": ["/opt/mcp-ozon/server.py"],
"env": {
"OZON_CLIENT_ID": "123456",
"OZON_API_KEY": "ключ-из-кабинета"
}
}
}
}
После перезапуска клиента инструменты появляются в списке. Ключи хранятся в конфиге клиента или в переменных окружения системы. Второй вариант лучше: файл конфигурации часто попадает в бэкапы и синхронизацию.
Лимиты и ошибки: чем прототип отличается от рабочего сервера
У каждого метода свой лимит запросов. Когда он исчерпан, Ozon отвечает кодом 429, и повторять запрос сразу бессмысленно: нужна пауза и повтор с задержкой. Агент должен получать эту информацию текстом, а не падать с исключением, иначе модель начнёт придумывать ответ вместо того, чтобы подождать.
Ошибка 403 почти всегда означает одно из двух: не принята оферта или у ключа нет прав на метод. Проверять это нужно в кабинете, а не в коде. Ошибка 404 на существующем методе чаще всего связана с опечаткой в версии эндпоинта: у Ozon версии меняются, например цены сейчас живут на /v5/product/info/prices, а старые пути отвечают 404.
Отдельная история — пагинация. Список товаров отдаётся страницами по last_id, и агент должен уметь пройти весь каталог, а не остановиться на первой сотне. Иначе отчёт будет выглядеть полным, но охватит десятую часть ассортимента.
Безопасность: минимальные права, ключи вне кода, журнал вызовов
Ключ Ozon даёт доступ к деньгам и товарам, поэтому к нему относятся как к паролю. Четыре правила закрывают почти все риски. Ключ хранится в переменных окружения или в защищённом хранилище, но не в репозитории и не в переписке. Для сервера создаётся отдельный ключ с минимальными правами: только чтение, если агент не должен менять цены.
Дальше — журнал. Каждый вызов инструмента стоит логировать: кто, что и когда запросил. Это помогает и при разборе инцидентов, и при оценке стоимости: по логам видно, какие методы агент дёргает чаще всего.
И последнее: не пытайтесь обходить ограничения API. Ozon прямо запрещает браузерные вызовы и ограничивает частоту запросов; парсинг закрытых разделов кабинета вместо официального метода повышает риск блокировки аккаунта.
Итог: один сервер превращает кабинет в инструменты агента
MCP-сервер для Ozon Seller собирается за вечер: четыре инструмента, ключи в окружении, запуск через stdio. Главная работа начинается после — описать сценарии, настроить повторы при 429 и решить, что агент делает сам, а что показывает человеку.
Для бизнеса ценность не в самом протоколе, а в том, что кабинет перестаёт быть ручной работой. Остатки, заказы и отзывы приходят агенту в понятном виде, а продавец занимается решениями, а не выгрузками.