avito-mcp
v1.2.0
Published
Universal MCP server for the Avito API — 148 tools across 18 domains, safe-by-default with dry-run, idempotency, structured errors, MCP resources/prompts and cross-process token lock. Runs over stdio or a remote OAuth 2.1-secured HTTP endpoint, with a bui
Maintainers
Readme
avito-mcp
Дайте вашим AI-агентам руки и ноги в Avito. MCP-сервер, через который Claude, Cursor, Cline и любой другой AI-ассистент делает реальную работу на Avito за вас — отвечает клиентам, ведёт объявления, запускает продвижение, обрабатывает заказы, анализирует статистику. 138 tools по Swagger-операциям + 3 локальных/convenience tools + 7 meta-tools = до 148 MCP tools из 18 официальных API Avito. Работает локально по stdio или как общий удалённый MCP по HTTP (OAuth 2.1), со встроенным приёмником webhook для событий чатов в реальном времени. Установка одной командой
npx.
Новое в v1.2.0 — полный security- и contract-hardening: token cache привязан к аккаунту, mutation-safe retry, строгие OAuth scope/resource и ownership сессий, webhook только на URL оператора, race-safe confirmation/idempotency, descriptor-safe upload, ограниченные response/state stores, coverage всего
srcи OpenAPI contract check всех 138 endpoint wrappers. Миграционные детали — в CHANGELOG.
Что это
Avito — крупнейший classifieds-маркетплейс России (~250M посетителей в месяц). Продажи там — это десятки повторяющихся операций каждый день: ответить в чате, обновить объявление, поднять VIP, выписать этикетку, посмотреть статистику.
avito-mcp отдаёт каждый публичный метод Avito API как инструмент, который ваш AI-агент может вызвать. Подключаете к любому MCP-клиенту — и агент ведёт вашу витрину на Avito автономно, по обычному диалогу.
- 🔌 Универсальный — работает с 15+ MCP-клиентами (Claude Desktop, Cursor, Cline, Continue, Windsurf, Zed, ChatGPT и др.)
- 🔒 Локально по умолчанию — stdio-транспорт, ключи никогда не покидают вашу машину (опционально — удалённый HTTP-режим для командных/общих развёртываний)
- 🤖 Под автономию — dry-run, idempotency-ключи, confirmation flow и risk-теги на tools позволяют безопасно оставлять агента работать без присмотра
- ⚡ Без установки —
npx -y avito-mcp, без git clone, без сборки, без Docker
Быстрый старт (≈90 секунд)
1. Получите OAuth-доступы в личном кабинете Avito API: Client_id, Client_secret и Profile_id (числовой ID аккаунта — виден на той же странице).
2. Добавьте JSON в конфиг вашего MCP-клиента (одинаковый для всех клиентов — отличается только путь к файлу, см. Подключение к AI-клиентам):
{
"mcpServers": {
"avito": {
"command": "npx",
"args": ["-y", "avito-mcp"],
"env": {
"Client_id": "YOUR_CLIENT_ID",
"Client_secret": "YOUR_CLIENT_SECRET",
"Profile_id": "YOUR_PROFILE_ID"
}
}
}
}3. Перезапустите клиент. Спросите агента:
«Какой у меня баланс на Авито и сколько непрочитанных чатов?»
Готово. Два API-вызова — реальный ответ.
Для автономных сценариев
Большинство MCP-серверов рассчитаны на ручной вызов из окна чата. avito-mcp рассчитан на то, чтобы работать сам — его подхватывают multi-agent-runtime'ы и шедулеры, которые выполняются без вашего участия.
Типичные паттерны:
- Реактивный агент — Claude/Cursor открыт постоянно, мониторит новые чаты и отвечает клиентам в вашем стиле. В паре с приёмником webhook реагирует в момент, когда клиент написал, вместо поллинга.
- Cron-агент — runtime поднимает агента каждые N минут: разобрать новые заказы, пополнить бюджеты продвижения, обновить статистику.
- Multi-agent swarm — отдельные агенты под «поддержку», «продвижение», «логистику», у каждого только нужные ему tools (через
AVITO_MCP_ALLOW_TOOLS/ safety-режимы). - Командное / hosted развёртывание — один удалённый MCP-инстанс за OAuth 2.1, общий для нескольких клиентов и людей.
stdio-транспорт оставляет credentials и ответы API на вашей машине. Никаких прокси. Никакого SaaS посередине.
→ Полный список совместимых runtime'ов — modelcontextprotocol.io/clients.
Что включено — до 148 инструментов
| Конфигурация | Видимо tools |
| ------------------------------------------------------- | ------------------------------------------------- |
| По умолчанию (AVITO_MCP_MODE=full_access, без opt-in) | 144 |
| + AVITO_MCP_EXPOSE_AUTH_TOOLS=1 | 147 (+3 auth) |
| + AVITO_MCP_ALLOWED_UPLOAD_DIRS=… | 145 (+1 upload) |
| + Оба opt-in | 148 |
| AVITO_MCP_CONFIRMATION_MODE=off | −3 (скрывает meta_*_action) |
| AVITO_MCP_MODE=read_only | 80 (только risk=read) |
| AVITO_MCP_MODE=guarded | 120 (read + write; скрывает money/public) |
138 tools соответствуют операциям из bundled Swagger один-к-одному, 3 являются локальными/convenience tools, ещё 7 — meta-tools: meta_get_rate_limits, три meta_*_action для confirmation flow, плюс meta_health, meta_auth_status и meta_capabilities для интроспекции. Авторитетный реестр активной policy — dist/manifest.json (перегенерация: npm run generate:manifest).
Каждый публичный endpoint из 18 OpenAPI-спецификаций Avito. Раскрывайте любую группу.
Дата снимка Avito API: 25 мая 2026. Swagger-файлы в
./swaggers/отражают публичный API Avito на эту дату. Avito периодически добавляет новые endpoints или меняет старые — если заметили рассинхрон (404 на известном методе, новый метод не покрыт), заведите issue и мы обновим снимок.
items_get_items_info— список ваших объявлений (фильтры по статусу, категории, пагинация)items_get_item_info— детали одного объявленияitems_post_calls_stats— статистика звонков по объявлениям в разрезе днейitems_post_vas_prices— цены услуг продвижения для заданных объявленийitems_post_item_stats_shallow— базовая статистика (просмотры/контакты/звонки) за периодitems_post_item_analytics— расширенная аналитика с группировкой и сортировкойitems_post_account_spendings— разбивка расходов по типам услугitems_update_price⚠️ — изменение цены объявленияitems_put_item_vas⚠️ — применение одной платной услуги VASitems_put_item_vas_package_v2⚠️ — применение пакета услуг VASitems_apply_vas⚠️ — применение нескольких VAS-slug разом
messenger_get_chats_v2— список чатов (фильтры: непрочитанные, item_ids, типы чатов)messenger_get_chat_by_id_v2— детали одного чатаmessenger_get_messages_v3— история сообщений (пагинация)messenger_get_voice_files— URL аудиофайлов голосовых сообщенийmessenger_get_subscriptions— текущие webhook-подпискиmessenger_post_send_message⚠️ — отправка реального сообщения клиентуmessenger_post_send_image_message⚠️ — отправка изображения (нужен upload)messenger_upload_images— multipart-загрузка, возвращает image_idsmessenger_delete_message⚠️ — удаление сообщенияmessenger_chat_read— отметить чат как прочитанныйmessenger_post_blacklist_v2⚠️ — блокировка пользователей (с кодами причины)messenger_post_webhook_v3⚠️ — подписка на push (нужен публичный URL)messenger_post_webhook_unsubscribe— отпискаmessenger_get_webhook_events— забрать события встроенного приёмника webhookmessenger_get_webhook_status— статистика приёмника: хранится / всего принято / последнее событиеmessenger_register_webhook⚠️ — подписать настроенный публичный URL у Avito одним вызовом
orders_get_orders— список заказов с фильтрамиorders_get_courier_delivery_range— доступные слоты курьераorders_download_label— получить PDF сгенерированной этикеткиorders_markings⚠️ — передача «Честного знака» (маркировка товара)orders_accept_return_order⚠️ — отделение Почты России для возвратаorders_apply_transition⚠️ — изменение статуса (подтвердить/отгрузить/отменить)orders_check_confirmation_code— проверка кода подтверждения выдачиorders_cnc_set_details⚠️ — детали click-and-collect заказаorders_set_courier_delivery_range⚠️ — выбор слота курьераorders_set_tracking_number⚠️ — установка трек-номераorders_generate_labels— генерация этикеток (≤100 заказов)orders_generate_labels_extended— генерация этикеток (≤1000)
Загрузка XML/YML/CSV-фидов, отчёты, маппинг ID, справочник категорий. Включает v1 (deprecated, для совместимости) и v2/v3.
autoload_upload⚠️ — запуск выгрузки (лимит: 1 раз в час)autoload_get_profile_v2,autoload_create_or_update_profile_v2⚠️ — управление профилем фидовautoload_get_reports_v2— список отчётов с пагинациейautoload_get_report_by_id_v3,autoload_get_last_completed_report_v3— детали отчётовautoload_get_report_items_by_id,autoload_get_report_items_fees_by_id— пер-айтемные результатыautoload_get_ad_ids_by_avito_ids,autoload_get_avito_ids_by_ad_ids— маппинг IDautoload_user_docs_tree,autoload_user_docs_node_fields— справочник категорий- 5 legacy-эндпоинтов (deprecated v1 и ранние v2) под их исходными именами
Партнёрский API логистики Avito для служб доставки. Обычным продавцам эти методы почти не нужны — они для СД-партнёров, интегрирующих свою систему с Avito Delivery. Включает production-эндпоинты и sandbox для тестирования. Полный список — в коде: src/domains/delivery.ts.
- BBIP-продвижение (7) — promotion_get_bbip_forecasts_by_items_v1, promotion_create_bbip_order_for_items_v1 ⚠️, promotion_get_order_status_v1, …
- CPA (11) — чаты/звонки по времени, баланс v2/v3, жалобы, телефоны из чатов —
cpa_* - CPA настройка цены (5) —
cpa_target_get_bids,cpa_target_save_auto_bid⚠️,cpa_target_save_manual_bid⚠️, … - CPA-аукцион (2) —
cpa_auction_get_user_bids,cpa_auction_save_item_bids⚠️
- Пользователь (3) —
user_get_user_info_self,user_get_user_balance,user_post_operations_history - Остатки (2) —
stock_get_stocks_info,stock_update_stocks⚠️ - Иерархия (5) — суб-аккаунты, сотрудники, привязка объявлений (для сетей)
- Отзывы (4) —
reviews_get_reviews_v1,reviews_create_review_answer_v1⚠️,reviews_remove_review_answer_v1⚠️,reviews_get_ratings_info_v1
- Тарифы (1) — справочник тарифов в категории Транспорт
- TrxPromo (3) — транзакционное продвижение: commissions / apply / cancel
- CallTracking (3) — записи и аудио звонков
- Рассылка скидок (5, beta) — массовые рассылки скидок в мессенджере
- Auth (3) —
auth_get_access_token(для отладки; сервер сам управляет токенами),auth_get_access_token_authorization_code,auth_refresh_access_token_authorization_code - Meta (1) —
meta_get_rate_limits— отслеживание X-RateLimit-* по всем доменам
⚠️ — методы которые тратят деньги или меняют боевые данные (цены, платные услуги, сообщения клиентам, блокировки). Безопасные read-only методы для первого знакомства:
user_get_user_balance,items_get_items_info,messenger_get_chats_v2,meta_get_rate_limits.
MCP-ресурсы и промпты
Кроме tool-ов сервер отдаёт MCP resources (данные, доступные агенту без вызова API) и prompts (готовые сценарии, которые сами оркестрируют нужные tool-ы в нужном порядке).
Resources
| URI | Тип | Что внутри |
| ------------------------------- | ------------------ | ------------------------------------------------------------------------------------- |
| avito://docs/safety | text/markdown | Гайд по safety-режимам + confirmation |
| avito://manifest | application/json | Live-реестр tools (risk / domain / title / annotations) |
| avito://state/config | application/json | Снимок активного config — секреты redacted |
| avito://state/rate-limits | application/json | Последние X-RateLimit-* по доменам Avito |
| avito://state/pending-actions | application/json | Pending-confirmations — subscribable, шлёт notifications/resources/updated |
| avito://webhook/events | application/json | Буфер событий webhook Avito — subscribable |
| avito://swaggers/{slug} | application/json | По одному resource на каждый файл из swaggers/ (с автодополнением через complete) |
Подписавшись на avito://state/pending-actions, клиент видит каждое создание/подтверждение/отмену/истечение в реальном времени — идеально для UI с индикатором «жду подтверждения». Подписка на avito://webhook/events уведомляет клиента в момент, когда Avito доставляет новое событие чата.
Prompts
| Имя | Аргументы | Что делает |
| -------------------------- | --------------------- | ----------------------------------------------------------------------------- |
| avito_daily_overview | days? (default 7) | Баланс + активные объявления + расходы (read-only, без confirmation) |
| avito_check_unread_chats | limit? (default 20) | Резюме непрочитанных чатов; явный guard "не отправлять / не блокировать" |
| avito_safety_report | — | Самоописание через state/config + manifest + docs/safety |
| avito_explain_tool | tool_name | Развёрнутое описание одного tool: запись в manifest + соответствующий swagger |
| avito_promote_item | item_id | Собрать всё нужное перед платной VAS-покупкой; явный guard «не покупай» |
Структурированный вывод tool-ов
Каждый tool возвращает structuredContent параллельно с текстовым блоком — клиенты могут парсить Avito-ответы как JSON без regex:
- Объекты →
{ status, ...data, http_status }: legacy/API-полеstatusсохраняется, аhttp_statusвсегда содержит HTTP-код - Массивы →
{ status, http_status, items, count } - Бинарные (PDF, аудио) →
{ status, http_status, mimeType, sizeBytes, base64 }; text content также сохраняет base64 для MCP-клиентов до 2025-06-18 - Ошибки →
{ error: { type, message, retryable, retryAfter?, httpStatus? }, error_kind }сisError: true— см. структурированную таксономию ошибок
MCP-logging
Избранные pino-события (смена режима, скрытые tools, lifecycle confirmation, warning-и rate-limit) дублируются клиенту как notifications/message с logger: "avito-mcp", чувствительные поля вырезаются. Клиенты, регулирующие уровень через logging/setLevel, работают как ожидается. Pino → stderr сохраняется.
Универсальные safety-примитивы
Opt-in примитивы, чтобы пакет безопасно жил в любом автоматическом контексте — ручной чат, cron, multi-agent, серверная ферма — без привязки к конкретному оркестратору или backend-у.
Dry-run
Каждый destructive tool (risk: write | money | public) принимает опциональный dryRun: boolean. При true возвращается preview HTTP-запроса, который сервер бы сделал — без обращения к Avito. Полезно и для человека («что агент хочет сделать?»), и для агента, который хочет «подумать перед действием».
{
"name": "items_update_price",
"arguments": { "item_id": 12345, "price": 1400, "dryRun": true }
}→ structuredContent: { dryRun: true, operation: { tool, method, path, ... }, request_preview: { ... } }, fetch не вызывается.
Дефолт можно перевернуть глобально: AVITO_MCP_DRY_RUN_DEFAULT=true или флаг --dry-run. Тогда любой destructive tool сначала отдаёт preview, пока агент явно не передаст dryRun: false.
Idempotency
Каждый destructive tool принимает опциональный idempotencyKey: string. Сервер хранит in-memory ledger по bounded SHA-256 fingerprint от (tool, key) и hash(args); длинные ключи не сохраняются дословно:
- Первый вызов: исполнение, кеш результата.
- Повтор с тем же ключом и теми же args в течение TTL: возвращается кеш с пометкой
structuredContent.idempotent_replay: true. Второй HTTP-вызов НЕ делается. - Повтор с тем же ключом и ДРУГИМИ args: structured-ошибка
IdempotencyConflictError(нарушен контракт дедупа).
Простейшая надёжная защита от дублей при retries, crashes, race conditions между параллельными агентами. TTL — AVITO_MCP_IDEMPOTENCY_TTL_SEC (default 1 час).
Структурированная таксономия ошибок
Все ошибки возвращают и текст, и машинный envelope:
{
"isError": true,
"structuredContent": {
"error": {
"type": "AVITO_RATE_LIMIT",
"message": "Avito API 429 for POST ...",
"retryable": true,
"retryAfter": 60,
"httpStatus": 429
}
}
}type ∈ AVITO_BAD_REQUEST | AVITO_UNAUTHORIZED | AVITO_FORBIDDEN | AVITO_NOT_FOUND | AVITO_RATE_LIMIT | AVITO_SERVER_ERROR | AVITO_API_ERROR | NETWORK_ERROR | TIMEOUT | CONFIG_ERROR | INTERNAL_ERROR.
Агент решает по retryable и retryAfter программно — без regex по тексту.
Health / auth / capabilities meta-tools
| Tool | Что возвращает |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| meta_health | Снимок здоровья: версия, uptime, capabilities, safety mode, счётчики (pending actions, idempotency entries, rate-limit snapshots) |
| meta_auth_status | Только МЕТАДАННЫЕ OAuth токена — tokenPresent, expiresInSec, last error. Сам токен НЕ отдаётся НИКОГДА. С probe: true попробует refresh. |
| meta_capabilities | Машинно-читаемый config: mode, allow/deny counts, feature flags (dryRun, idempotency, confirmation, hardConfirmation, fileUploads, sensitiveAuthTools) |
У всех трёх — строгий outputSchema (zod), клиенты могут валидировать.
Cross-process token lock
Если несколько процессов avito-mcp используют один tokenFile (cron + chat + CLI), они не идут параллельно в Avito /token. Первый берёт {tokenFile}.lock, остальные ждут и читают свежий токен. Lease проверяет owner: lock мёртвого/повреждённого процесса очищается, а lock живого процесса не крадётся по возрасту. Tunable: AVITO_MCP_TOKEN_LOCK_TIMEOUT_MS (default 30s).
CLI флаги
Sugar над env-переменными (env побеждает если задано и то и то):
avito-mcp --readonly # AVITO_MCP_MODE=read_only
avito-mcp --guarded # AVITO_MCP_MODE=guarded
avito-mcp --dry-run # AVITO_MCP_DRY_RUN_DEFAULT=true
avito-mcp --no-confirmation # AVITO_MCP_CONFIRMATION_MODE=off
avito-mcp --http | --both # AVITO_MCP_TRANSPORT=http | both
avito-mcp --health # print JSON health snapshot and exit--health не запускает сервер: это локальная диагностика config/capabilities, а не liveness уже работающего процесса. Встроенный Docker HEALTHCHECK проверяет PID 1 в stdio и живой /readyz в HTTP/webhook режиме. Для Kubernetes/supervisor используйте:
/readyz возвращает 200, только пока listener открыт, HTTP credentials Avito заполнены полностью, token state directory доступен для записи, lease OAuth store исправен и настроенная webhook persistence не завершалась ошибкой. Публичное тело остается только { "ok": boolean }.
httpGet:
path: /readyz
port: 3000Удалённый MCP по HTTP (OAuth 2.1)
По умолчанию avito-mcp говорит по stdio — идеально для локального клиента. Он также может работать как удалённый MCP-сервер: те же 148 tools отдаются по сети через Streamable HTTP, чтобы хостовый агент, команда или клиент с телефона подключались к одному общему инстансу. Доступ закрыт OAuth 2.1 (authorization-code + PKCE + Dynamic Client Registration) с экраном согласия и участием человека.
Включение
AVITO_MCP_TRANSPORT=http # stdio (default) | http | both (CLI: --http)
AVITO_MCP_HTTP_HOST=127.0.0.1 # loopback по умолчанию; TLS терминирует proxy
AVITO_MCP_HTTP_PORT=3000
AVITO_MCP_HTTP_PUBLIC_URL=https://mcp.example.com # your public TLS domain, NO trailing slash
AVITO_MCP_HTTP_AUTH=oauth # oauth (default) | bearer | none
AVITO_MCP_OAUTH_OWNER_PASSWORD=… # REQUIRED, случайный, минимум 32 байта
# Client_id / Client_secret / Profile_id as usual (the Avito credentials the remote server acts with)both поднимает stdio и HTTP одновременно — удобно, когда один процесс обслуживает локального и удалённого клиента сразу.
Как работает OAuth-flow
- Клиент обращается к
/.well-known/oauth-protected-resource/mcp(path-suffixed URL по RFC 9728 — именно на него указывает заголовокWWW-Authenticateв 401), находит authorization server и читает/.well-known/oauth-authorization-server. - Клиент сам регистрируется через Dynamic Client Registration (
POST /register) — без ручной настройки клиента. - Запускает authorization-code + PKCE: открывает
/authorizeв браузере. - Человек подтверждает на
/authorize, вводяAVITO_MCP_OAUTH_OWNER_PASSWORD. Это и есть барьер — без owner-пароля токен не выпускается никогда, а endpoint подтверждения защищён rate-limit'ом от перебора. - Клиент обменивает код на
/tokenна bearer-токен (TTLAVITO_MCP_OAUTH_TOKEN_TTL_SEC, default 3600с), и этот токен защищает каждый запрос к/mcp.
Токен принимается только с точным scope avito:mcp и точным resource URL этого deployment; каждая MCP-сессия привязана к OAuth principal, который её инициализировал. Consent-транзакции и authorization codes короткоживущие и одноразовые.
| Endpoint | Назначение |
| ------------------------------------------- | ----------------------------------------------------------------- |
| /mcp | Streamable HTTP MCP-транспорт (сами tools) |
| /.well-known/oauth-authorization-server | Метаданные OAuth 2.1 AS |
| /.well-known/oauth-protected-resource/mcp | Метаданные resource-server для /mcp (path-suffixed, RFC 9728) |
| /authorize | Экран согласия — человек вводит owner-пароль (с rate-limit) |
| /token | Обмен authorization-code → bearer-токен |
| /register | Dynamic Client Registration (DCR) |
| /revoke | Отзыв токенов (RFC 7009) |
| /healthz | Liveness-проба (без auth — отвечает только {ok, name, version}) |
| /readyz | Readiness-проба (без auth — отвечает только {ok}) |
Все env-переменные HTTP / OAuth
| Переменная | Default | Смысл |
| --------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------- |
| AVITO_MCP_TRANSPORT | stdio | stdio | http | both (CLI-флаг --http) |
| AVITO_MCP_HTTP_HOST | 127.0.0.1 | Bind-адрес — держите loopback за прокси |
| AVITO_MCP_HTTP_PORT | 3000 | Порт прослушивания |
| AVITO_MCP_HTTP_PUBLIC_URL | — | Публичный TLS-базис для построения OAuth issuer / resource metadata. Без завершающего слэша. |
| AVITO_MCP_HTTP_AUTH | oauth | oauth | bearer | none |
| AVITO_MCP_OAUTH_OWNER_PASSWORD | — | Обязательно в oauth, минимум 32 байта. Закрывает /authorize — единственный секрет, выпускающий токен. |
| AVITO_MCP_OAUTH_TOKEN_TTL_SEC | 3600 | Время жизни выпущенного bearer-токена |
| AVITO_MCP_OAUTH_STORE_FILE | — | Опциональный durable store токенов/клиентов. Exclusive process lease: один запущенный сервер на файл |
| AVITO_MCP_HTTP_AUTH_TOKEN | — | Режим bearer: общий секрет(ы), через запятую; каждый минимум 32 байта |
| AVITO_MCP_HTTP_ALLOW_NO_AUTH | 0 | Разрешить auth=none на не-loopback хосте (не рекомендуется) |
| AVITO_MCP_HTTP_ALLOWED_HOSTS | derived | CSV допустимых Host. Выводится из public URL + bind; недостаточно настроенный wildcard bind останавливает startup |
| AVITO_MCP_HTTP_ALLOWED_ORIGINS | derived | CSV допустимых Origin. Та же fail-closed деривация |
| AVITO_MCP_HTTP_MAX_SESSIONS | 100 | Максимум одновременных Streamable HTTP сессий — initialize сверх лимита → 503 |
| AVITO_MCP_HTTP_SESSION_IDLE_SEC | 1800 | Сессии, простаивающие дольше, закрываются (клиент исчез без DELETE) |
Модель безопасности. Node по умолчанию слушает
127.0.0.1и говорит по обычному HTTP. TLS терминирует reverse-proxy (nginx / Caddy) на вашем домене, проксируя наhttp://127.0.0.1:3000. Никогда не выставляйте порт 3000 напрямую в интернет. Host/Origin validation защищает MCP и OAuth routes.auth=noneна публичном хосте отклоняется, пока не заданоAVITO_MCP_HTTP_ALLOW_NO_AUTH=1.
Миграция v1.2.0: OAuth artifacts без точной привязки scope/resource намеренно отклоняются; таким клиентам нужно пройти авторизацию заново.
AVITO_MCP_OAUTH_STORE_FILEтеперь single-writer: каждому параллельному серверу нужен отдельный файл.
Сниппеты reverse-proxy (терминируют TLS для https://mcp.example.com)
Оба проксируют MCP-endpoint, OAuth discovery/flow-эндпоинты и путь webhook, и сохраняют заголовок Host (OAuth-метаданные строятся из него).
server {
listen 443 ssl;
server_name mcp.example.com;
ssl_certificate /etc/letsencrypt/live/mcp.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mcp.example.com/privkey.pem;
# MCP transport + OAuth (discovery, authorize, token, register, revoke) + webhook receiver.
location ~ ^/(mcp|\.well-known/oauth-authorization-server|\.well-known/oauth-protected-resource|authorize|token|register|revoke|avito/webhook|healthz|readyz) {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host; # preserve Host — OAuth metadata depends on it
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Streamable HTTP keeps long-lived responses open:
proxy_buffering off;
proxy_read_timeout 3600s;
}
}mcp.example.com {
# Caddy obtains and renews the TLS cert automatically.
# Caddy preserves the Host header by default (no header_up needed).
reverse_proxy /mcp* http://127.0.0.1:3000
reverse_proxy /.well-known/oauth-authorization-server* http://127.0.0.1:3000
reverse_proxy /.well-known/oauth-protected-resource* http://127.0.0.1:3000
reverse_proxy /authorize* http://127.0.0.1:3000
reverse_proxy /token* http://127.0.0.1:3000
reverse_proxy /register* http://127.0.0.1:3000
reverse_proxy /revoke* http://127.0.0.1:3000
reverse_proxy /avito/webhook* http://127.0.0.1:3000
reverse_proxy /healthz* http://127.0.0.1:3000
reverse_proxy /readyz* http://127.0.0.1:3000
}Проще: режим bearer
Если вы контролируете оба конца и полный OAuth-танец не нужен — задайте AVITO_MCP_HTTP_AUTH=bearer и общий секрет:
AVITO_MCP_TRANSPORT=http
AVITO_MCP_HTTP_PUBLIC_URL=https://mcp.example.com
AVITO_MCP_HTTP_AUTH=bearer
AVITO_MCP_HTTP_AUTH_TOKEN=long-random-secret,another-secret # one or more, comma-separatedКлиенты тогда шлют Authorization: Bearer long-random-secret на /mcp. Та же конфигурация reverse-proxy применима.
Приёмник webhook Avito
Поллинг messenger_get_chats_v2 работает, но для реакций в реальном времени (ответить в момент, когда клиент написал) Avito может пушить события вам. Сервер включает встроенный приёмник: укажите Avito секретный URL — и каждое событие буферизуется, чтобы ваш агент мог его прочитать.
Работает даже в чистом stdio-режиме — Avito нужен лишь публичный URL для POST'а; ваш MCP-клиент его не касается. (Если AVITO_MCP_TRANSPORT=stdio и задан webhook-секрет, сервер всё равно поднимает крошечный HTTP-listener только для приёмника.)
Включение
AVITO_MCP_WEBHOOK_SECRET=… # случайный, минимум 32 байта
AVITO_MCP_WEBHOOK_PUBLIC_URL=https://mcp.example.com # public base Avito POSTs to (defaults to the HTTP public URL)
# AVITO_MCP_WEBHOOK_PATH=/avito/webhook # default
# AVITO_MCP_WEBHOOK_BUFFER=100 # ring-buffer size (events kept in memory)
# AVITO_MCP_WEBHOOK_LOG_FILE=/var/lib/avito-mcp/webhook-events.jsonlAvito доставляет на:
POST {AVITO_MCP_WEBHOOK_PUBLIC_URL}{AVITO_MCP_WEBHOOK_PATH}/{AVITO_MCP_WEBHOOK_SECRET}
→ 200 {"ok":true} (answered in well under Avito's 2-second deadline)Секрет — часть пути, поэтому URL неугадываем; это и есть авторизация. Генерируйте минимум 32 случайных байта. URL должен быть публичным HTTPS. Оба webhook registration tool принимают только точный receiver URL из конфигурации оператора: агент не может перенаправить будущие сообщения на произвольный хост. В dry-run секретный URL редактируется.
| Переменная | Default | Смысл |
| ------------------------------ | ------------------------ | -------------------------------------------------------------------------------------------------------------------- |
| AVITO_MCP_WEBHOOK_SECRET | — | Включает приёмник; случайный сегмент пути минимум 32 байта. Обязателен — без него приёмник выключен |
| AVITO_MCP_WEBHOOK_ENABLED | 1 при заданном секрете | Явный тумблер: 0 выключает приёмник, не убирая секрет. 1 без секрета ничего не включает (warning при старте) |
| AVITO_MCP_WEBHOOK_PUBLIC_URL | (HTTP public URL) | Публичный базис, куда POST'ит Avito |
| AVITO_MCP_WEBHOOK_PATH | /avito/webhook | Префикс пути перед секретным сегментом |
| AVITO_MCP_WEBHOOK_BUFFER | 100 | Размер in-memory ring-буфера |
| AVITO_MCP_WEBHOOK_LOG_FILE | — | Опциональный JSONL 0600 только с нормализованной metadata, без текста/raw payload; ротация при 10 MiB, один backup |
Чтение событий
| Поверхность | Что даёт |
| ----------------------------------------------------- | ---------------------------------------------------------------------------------- |
| messenger_get_webhook_events (tool, read) | Забрать буфер событий — фильтры chat_id, since, limit |
| messenger_get_webhook_status (tool, read) | Статистика приёмника: хранится / всего принято / последнее событие / размер буфера |
| messenger_register_webhook (tool, ⚠️ public) | Подписать только настроенный оператором URL; по умолчанию требует confirmation |
| avito://webhook/events (resource, subscribable) | Те же события как MCP-resource; resources/subscribe для live-пуша в клиент |
Типичный цикл: подписаться на avito://webhook/events, на каждый notifications/resources/updated прочитать новое событие, составить ответ и (после подтверждения) отправить через messenger_post_send_message.
Подключение к AI-клиентам
JSON из «Быстрого старта» подходит любому MCP-совместимому клиенту — отличается только путь к конфигу. Выбирайте свой:
| ОС | Путь |
| ------- | ----------------------------------------------------------------- |
| macOS | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Windows | %APPDATA%\Claude\claude_desktop_config.json |
| Linux | ~/.config/Claude/claude_desktop_config.json |
Если файла нет — создайте; если есть — добавьте секцию avito в mcpServers. Полностью закройте Claude Desktop (через системный трей) и откройте заново — внизу чата появится индикатор «🔌 avito».
Логи: ~/Library/Logs/Claude/mcp-server-avito.log (macOS).
Самый простой способ — одна команда:
claude mcp add avito npx -y avito-mcp \
-e Client_id=YOUR_CLIENT_ID \
-e Client_secret=YOUR_CLIENT_SECRET \
-e Profile_id=YOUR_PROFILE_IDИли добавьте .mcp.json в корень проекта (JSON из Quick Start плюс "type": "stdio"). Проверка: claude mcp list.
Путь: ~/.cursor/mcp.json (глобально) или <project>/.cursor/mcp.json (per-project). JSON из Quick Start. После сохранения — Cmd/Ctrl + Shift + P → «Reload Window».
OpenAI добавил поддержку MCP в Desktop через Connectors. Settings → Connectors → Add custom MCP server → заполните:
- Name:
Avito - Type:
stdio - Command:
npx - Arguments:
-y avito-mcp - Environment variables:
Client_id,Client_secret,Profile_id
Путь: ~/.codeium/windsurf/mcp_config.json. JSON из Quick Start. Альтернативно через UI: Settings → Cascade → MCP Servers → Add Server.
В VS Code: иконка Cline → ⚙️ → MCP Servers → Edit cline_mcp_settings.json.
| ОС | Путь |
| ------- | --------------------------------------------------------------------------------------------------------------- |
| macOS | ~/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json |
| Windows | %APPDATA%\Code\User\globalStorage\saoudrizwan.claude-dev\settings\cline_mcp_settings.json |
| Linux | ~/.config/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json |
JSON из Quick Start. Cline подхватывает изменения без перезагрузки VS Code.
Добавьте в ~/.continue/config.json:
{
"experimental": {
"modelContextProtocolServers": [
{
"transport": {
"type": "stdio",
"command": "npx",
"args": ["-y", "avito-mcp"],
"env": { "Client_id": "...", "Client_secret": "...", "Profile_id": "..." }
}
}
]
}
}Settings (Cmd+,), найдите блок context_servers:
{
"context_servers": {
"avito": {
"command": {
"path": "npx",
"args": ["-y", "avito-mcp"],
"env": { "Client_id": "...", "Client_secret": "...", "Profile_id": "..." }
}
}
}
}Microsoft добавил поддержку MCP в Copilot Chat в 2025. Создайте .vscode/mcp.json в workspace или используйте Command Palette → «MCP: Add Server». Тот же JSON из Quick Start.
CLI-ассистент OpenAI поддерживает MCP через ~/.codex/config.toml:
[mcp_servers.avito]
command = "npx"
args = ["-y", "avito-mcp"]
env = { Client_id = "...", Client_secret = "...", Profile_id = "..." }Settings → Tools → AI Assistant → MCP → Add server. Те же поля (command npx, args -y avito-mcp, env). Работает в IntelliJ IDEA, PyCharm, WebStorm, GoLand, Rider.
Open-source CLI-агент от Block. goose configure → MCP server → вставьте JSON из Quick Start. Конфиг живёт в ~/.config/goose/config.yaml.
Это форки Cline с теми же путями конфигов — замените saoudrizwan.claude-dev в пути на ID расширения (rooveterinaryinc.roo-cline или kilocode.kilo-code). JSON идентичен.
Отредактируйте librechat.yaml:
mcpServers:
avito:
type: stdio
command: npx
args: ['-y', 'avito-mcp']
env:
Client_id: '...'
Client_secret: '...'
Profile_id: '...'Settings → MCP Servers → Add. Поля UI: name avito, command npx, args -y avito-mcp, env-переменные те же.
Сервер говорит на стандартном stdio MCP. Универсальные параметры:
command:npxargs:["-y", "avito-mcp"]env:{ Client_id, Client_secret, Profile_id }transport:stdio
Свежий список клиентов — MCP clients directory.
Примеры промптов
Скопируйте в свой AI-клиент чтобы увидеть на что он способен:
📊 Анализ
- «Какой у меня баланс на Авито и сколько потратил на продвижение в этом месяце?»
- «Топ-10 объявлений по контактам за неделю — таблицей с просмотрами/контактами/конверсией.»
- «Найди объявления у которых звонки упали на 50%+ по сравнению с прошлой неделей.»
💬 Коммуникация
- «Покажи непрочитанные чаты за последние сутки и ответь каждому: "Здравствуйте! Да, актуально, куда вам удобнее доставку?"»
- «Прочитай полностью переписку в чате X и предложи лучший ответ в моём стиле.»
💰 Продвижение
- «Сделай прогноз BBIP на 1000₽ для объявления 12345 — выгодно?»
- «Установи ручную CPA-ставку 500₽ на топ-10 объявлений в категории "Электроника".»
📦 Заказы
- «Покажи все заказы со статусом
ready_to_shipи сгенерируй этикетки одним PDF.» - «Для заказа ABCD найди доступный слот курьера на завтрашнее утро.»
🤖 Автоматизация
- «Каждый будний день в 9:00 присылай в Telegram: баланс, число новых заказов, число непрочитанных чатов, топ расходов на продвижение.»
- «Если какой-то чат непрочитан 6+ часов — подготовь ответ и попроси меня подтвердить.»
Что НЕ поддерживается
Для следующих вертикалей Avito предоставляет отдельные API — их swagger-спецификации не входят в этот проект:
| Категория | Где искать | | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------ | | 🏷️ Аукцион | Avito Auction API | | 🤖 Автостратегии (автоматическое управление ставками) | Avito Autostrategy API | | 🚗 Автотека (отчёты по истории автомобилей) | Avito Autoteka API | | 💼 Работа / Вакансии | Avito Jobs API | | 📊 Отчёты по недвижимости | Avito Realty Reports API | | 🏠 Краткосрочная аренда (квартиры посуточно) | Avito STR API |
Также вне scope: authorization_code OAuth flow к самому Avito (у локального CLI нет публичного redirect URI) и Avito sandbox (Avito не выдаёт sandbox-credentials — каждый вызов идёт в production).
Безопасность
- Локальное stdio по умолчанию — никаких прокси, remote-эндпоинтов, телеметрии. Опциональный удалённый HTTP-режим — opt-in (
AVITO_MCP_TRANSPORT=http), слушает loopback и закрыт OAuth 2.1 (или bearer-секретом) за вашим собственным TLS-прокси, с включённой по умолчанию защитой от DNS-rebinding. - Credentials живут в блоке
envMCP-клиента или в локальном.env. Никуда не отправляются кромеapi.avito.ru. - OAuth-токены привязаны к API origin/client/profile и кешируются в персональной директории (
0600, parent0700). Cache другого аккаунта и legacy-запись без binding игнорируются:- Linux:
$XDG_STATE_HOME/avito-mcp/token.json(≈~/.local/state/avito-mcp/token.json) - macOS:
~/Library/Application Support/avito-mcp/token.json - Windows:
%APPDATA%\avito-mcp\token.json - Изменить путь — через
AVITO_TOKEN_FILE. Удалите файл, чтобы принудительно обновить токен.
- Linux:
- Три слоя безопасности (каждый opt-in через env vars; defaults не мешают тривиальным чтениям, но харднят всё destructive):
AVITO_MCP_MODE(read_only/guarded/full_access) — фильтр на регистрации. Скрытые tools не появляются вtools/list.read_onlyотдаёт 80 tools,guarded— 120,full_access— 145 обычных tools (плюс 3 sensitive только по явному opt-in).AVITO_MCP_ALLOW_TOOLS/AVITO_MCP_DENY_TOOLS— per-tool фильтр. Deny всегда побеждает allow.AVITO_MCP_CONFIRMATION_MODE(off/money_public(default) /all_destructive) — runtime gate. Destructive tools возвращают{requires_confirmation: true, confirmation_id: ...}; агент должен вызватьmeta_confirm_actionчтобы выполнить. Pending хранится in-memory, с TTL (default 15 мин), одноразовый.AVITO_MCP_CONFIRMATION_SECRETапгрейдит это до hard confirmation — подтвердить может только человек, знающий секрет. Hard-confirm ограничен 20 вызовами в минуту на аутентифицированного principal; пять неверных или отсутствующих секретов удаляют конкретный pending action.AVITO_MCP_EXPOSE_AUTH_TOOLS(default:0) —auth_*tools возвращают OAuth токены; помечены какsensitiveи скрыты по default даже вfull_access.AVITO_MCP_ALLOWED_UPLOAD_DIRS—messenger_upload_imagesчитает файлы с диска; без явного списка директорий tool не регистрируется. Открывается и проверяется один descriptor, parent/final symlink race отклоняется, действуют лимиты количества и общего размера, magic-byte check jpg/jpeg/png/webp, локальные пути редактируются в ошибках.
- Каждый tool помечен одной из пяти категорий риска (
sensitive: 3/read: 80/write: 40/money: 9/public: 16), отдаётся клиенту как MCPToolAnnotationsи_meta.risk, плюс перечислен вdist/manifest.json. Defaultmoney_publicconfirmation покрывает все внешне видимые, платные и необратимые public actions, включая webhook registration, blacklist и CPA complaints. - Env разбирается fail-fast: неизвестные enum/boolean, частично числовые значения, слабые remote secrets и выход за лимиты останавливают startup. Имя
AVITO_MCP_MAX_BINARY_MBсохранено для совместимости, но лимит действует на любой HTTP body, включая JSON/text. - Готовые конфигурации в
docs/safety.md(analytics-only, customer-support с confirmation, listings-only, full admin) + честный разбор что есть и чего нет в confirmation flow (server-side two-step + audit layer, а НЕ криптографический human-approval — если только не добавлен hard-confirmation секрет). - Считайте production каждый tool с
environment: prod. Writes могут тратить деньги или влиять на реальных клиентов. Delivery-операции, которые Swagger Avito объявляет sandbox, помеченыenvironment: sandbox; всё равно проверяйте аккаунт и среду. Безопасные read-only для первого знакомства:user_get_user_balance,items_get_items_info,messenger_get_chats_v2,meta_get_rate_limits. - Нашли уязвимость? Приватный канал — SECURITY.md. Не открывайте публичный issue.
Версионирование и стабильность
Начиная с v1.0.0 публичная поверхность покрыта SemVer:
- Стабильно (breaking change ⇒ major): имена tools и все документированные Avito-valid формы входных данных, имена и дефолты env-переменных, URI ресурсов (
avito://…), имена промптов, модель классификации рисков, структурированная таксономия ошибок и CLI-флаги. - Аддитивно (minor): новые tools при появлении новых эндпоинтов Avito, новые opt-in env-переменные, новые resources/prompts.
- Patch: багфиксы, security-hardening, правки документации, обновления зависимостей.
Исправление контракта или безопасности не гарантирует прием форм, которые bundled-спецификация Avito уже отклоняет. Minor/security-релиз может добавить конечный anti-abuse limit, исправить недооцененный риск операции, ограничить операторский exfiltration destination или исключить EOL-линию Node.js. Такое ужесточение обязано сохранять документированные Avito-valid вызовы, кроме случая, когда именно это поведение является уязвимостью; для каждого исключения нужен явный migration note в changelog. Для остальных несовместимых изменений схем, defaults или модели рисков по-прежнему требуется major-релиз.
Поставляемый снимок Avito swagger — это данные, а не API: его обновление (и tools, которые из него следуют) — minor, пока существующие имена tools продолжают работать.
Сообщество и поддержка
- Баг? Создайте issue.
- Вопрос или идея? Откройте discussion.
- Нужна помощь по выбору tool'а или настройке клиента? Смотрите SUPPORT.md.
- Хотите помочь? Добавить новый swagger Avito — это ~10 минут работы, см. CONTRIBUTING.md.
- Нравится проект? Поставьте звезду и расскажите другому продавцу с Avito, который использует AI.
Установка из исходников
Для разработки, air-gapped установки или если хотите изменить tool. Требуется Node.js >=22.12.0:
git clone https://github.com/elchin92/avito-mcp.git
cd avito-mcp
npm ci
cp .env.example .env # fill in your credentials
npm run build:release # собирает код и генерирует dist/manifest.jsonЗатем укажите в MCP-конфиге:
{ "command": "node", "args": ["/absolute/path/to/avito-mcp/dist/server.js"] }Шаблон конфига — в .mcp.json.example. Для контейнерных развёртываний есть multi-stage Dockerfile.
Для hardened remote deployment через systemd создайте .remote.env, выполните npm run verify:release, затем:
sudo deploy/install-services.sh --startInstaller переносит только allowlisted runtime variables avito-mcp в root-owned /etc/avito-mcp/avito-mcp.env, создаёт read-only versioned release в /opt/avito-mcp/releases/<version>, атомарно переключает /opt/avito-mcp/current, запускает процесс от avito-mcp и проверяет /readyz вместе с версией из /healthz. Deploy сериализован через flock; любая ошибка восстанавливает symlink, config, units, enablement и прежнее состояние процессов. Изменённый код под уже установленной версией намеренно не перезаписывается: сначала увеличьте package version.
Адрес probe выводится из AVITO_MCP_HTTP_HOST/PORT. Для нестандартного network namespace передайте installer переменную AVITO_MCP_DEPLOY_HEALTH_URL=http://reachable-host:port.
CLI-флаги
npx avito-mcp --version # print the installed version
npx avito-mcp --help # show env vars + usageВсе остальные настройки — env-переменные (см. вывод --help или .env.example).
Контрибьютинг
Хотите добавить новый swagger Avito? Один файл в src/domains/ плюс одна строка в src/meta/domain-registry.ts — см. CONTRIBUTING.md. Фабрика в src/core/tool-factory.ts берёт на себя HTTP, OAuth, retry, наблюдаемость rate-limit'ов, маппинг ошибок и автоподстановку Profile_id — вам никогда не придётся писать fetch() внутри tool.
Issues и PR приветствуются.
Лицензия
MIT. Проект не аффилирован с Avito.ru. «Avito» — товарный знак, принадлежащий его правообладателю. Использование Avito API регулируется условиями использования Avito.
