Skip to main content
Glama
yagaMI-Reverse

vibe-agent-mcp

vibe-agent-mcp

Автономный ИИ-агент для Agent API «Вайб-Маркетолог», живущий на тарифах Claude Code (без отдельных платных API-токенов модели) — второе тестовое задание для компании.

Первое тестовое (детерминированный линтер их генератора, ad-preflight) принято на 90/100 и названо основателем «одной из самых сильных работ кампании»: он нашёл, что 34% сгенерированных заголовков превышают лимит Яндекс.Директа (58–59 знаков при лимите 56). Это тестовое — тот же линтер, но встроенный в автономный цикл: сгенерировать → проверить → переформулировать → остановиться, с MCP-сервером сверху, чтобы Claude Code мог сам дёргать API.

Что это

  • mcp_server/server.py — MCP-сервер, 8 инструментов поверх Agent API (5 бесплатных read-only/локальных, 3 платных write).

  • orchestrator/run_agent.py — автономный цикл с бюджетным гейтом: генерирует объявления → прогоняет через preflight → механически чинит локально то, что чинится обрезкой (превышение длины) → если остались содержательные дефекты (непроверенные обещания), переформулирует utp и повторяет → останавливается по чистоте выдачи или по бюджету/итерациям.

  • vendor/ad-preflight — git submodule на первый тестовый проект; чек-логика (check_ad, лимиты Директа, ст. 5 ФЗ «О рекламе», сверка обещаний с лендингом) переиспользуется напрямую, не переписана.

  • cosmetics-demo-shop — отдельный демо-магазин косметики (свой, не чужой реальный сайт), чтобы проверить решение не только на лендинге самой платформы. Живой сайт.

Related MCP server: agent1st-ads-mcp

Важные поправки к брифу (найдено на живом API, не в документации)

  1. Нет бесплатного /generate/estimate для direct/*. Он бесплатен только для общей мультимедиа-фабрики (image/video/text/voice/music) и для brand_id-полей. У direct/ads-generate (49₽), direct/landing-audit (39₽), direct/sitelinks (29₽), direct/forecast (49₽) цена фиксированная и известна заранее из /capabilities.direct_tools. Бюджетный гейт в этом решении сравнивает потрачённое с этой таблицей цен, а не делает pre-flight dry-run запрос перед каждым платным вызовом.

  2. /api/agent/brands реально работает (0 брендов на аккаунте), но direct/ads-generate принимает только url/utp, не brand_id — бренд не пробрасывается в генератор напрямую.

  3. /agent/list, /agent/message, safety-check недоступны этому токену (404 not_found, не вопрос скоупа) — это Bitrix24-инбокс и риск- оценка реальных кампаний Директа, по документации «предоставляются по партнёрскому соглашению». Не используются в решении.

Подробности проверки — в docs/boundaries.md.

Как запустить

git clone --recurse-submodules <URL этого репо>
cd vibe-agent-mcp
pip install -r requirements.txt

Токен: VIBE_API_TOKEN в окружении или файл C:/Users/Ilay/vibe_token.txt (в репозиторий не коммитится, см. .gitignore). Пример — .env.example.

Отладка без реальных денег

python orchestrator/run_agent.py --url https://vibemarketolog.ru --dry-run \
    --max-iterations 3 --out runs/test/report.md

--dry-run вообще не бьёт в платное API — гоняет весь цикл (гейт, генерация, preflight, переформулировка, отчёт) на fixtures/raw_response_sample.json (реальный платный ответ с первого тестового). Это позволяет отладить всю логику на 0₽ перед тем, как тратить реальный баланс.

Реальный автономный прогон

python orchestrator/run_agent.py --url <лендинг> --max-iterations 3 --audit \
    --out runs/<дата>/report.md

Регистрация MCP-сервера в Claude Code

claude mcp add vibe -- python <абсолютный путь>/mcp_server/server.py

MCP-инструменты (8)

Инструмент

Стоимость

Что делает

account_status

бесплатно

баланс, дневной лимит и остаток

price_table

бесплатно

фиксированные цены direct/* из /capabilities

list_brands

бесплатно

список брендов/товаров аккаунта

get_brand

бесплатно

профиль одного бренда

preflight_check

бесплатно, локально

вердикты ГОДНО/ИСПРАВИМО/БРАК/ГАЛЛЮЦИНАЦИЯ по пакету объявлений

generate_ads

49₽

direct/ads-generate — пакет объявлений

audit_landing

39₽

direct/landing-audit — аудит лендинга

generate_sitelinks

29₽

direct/sitelinks — быстрые ссылки и уточнения (бонус, не в брифе)

Проверено: MCP-протокол end-to-end (01.08.2026)

claude mcp add vibe -- python mcp_server/server.py + claude mcp list✔ Connected — но это только health-check хендшейка. Сделал более строгую проверку: поднял настоящий MCP-клиент (mcp.client.stdio, тот же протокол, что использует сам Claude Code) и прогнал реальный цикл initializetools/listtools/call:

TOOLS: ['account_status', 'price_table', 'list_brands', 'get_brand',
        'generate_ads', 'audit_landing', 'generate_sitelinks', 'preflight_check']
account_status -> {"balance": 72, ..., "daily_spend_remaining": 363, ...}
price_table    -> {"direct/landing-audit": 39, "direct/ads-generate": 49, ...}

Все 8 инструментов видны по протоколу, вызов реально бьёт в живой API и возвращает актуальные данные — не заглушку. Это подтверждает, что сервер работает не только как импортируемый Python-модуль (как было проверено раньше), а как настоящий MCP-сервер по stdio.

Локальный фиксер длины — почему это сработало, а переформулировка нет

Прогон 31.07 (ниже) показал: просьба словами «заголовок ≤56 знаков» в utp не работает. Вместо неё — механическая обрезка по границе слова для объявлений, у которых единственная причина брака — превышение длины (orchestrator/run_agent.py:apply_local_fixes). Ничего не генерируется заново, ничего не оплачивается — просто пересчитывается вердикт после обрезки. Результат на живых данных 01.08.2026 (лендинг cosmetics-demo-shop):

Итерация

utp

стоимость

ГОДНО

ИСПРАВИМО

БРАК

ГАЛЛЮЦИНАЦИЯ

починено локально

1

(пусто)

49₽

135

3

0

9

81

2

«упоминай только реальные скидки/сроки/гарантии с лендинга»

49₽

136

11

0

0

66

Итерация 1: из 147 объявлений фиксер локально почистил 81 (были бы БРАК из-за длины) — остались только 9 содержательных ГАЛЛЮЦИНАЦИЯ (выдуманные подробности, не обрезкой не почини). Итерация 2: переформулировка utp для этого класса дефекта сработала — 0 галлюцинаций. Итог: 0 БРАК, 0 ГАЛЛЮЦИНАЦИЯ, 2 итерации вместо 3, 137₽ вместо безуспешных 186₽, и впервые цикл реально сходится к чистой выдаче, а не просто честно останавливается по лимиту с браком на руках.

Полные материалы: runs/2026-07-31_cosmetics-demo/.

Честно: обрезка по границе слова иногда обрывает мысль на полуслове («…нейросетей для фото баннеров и креативов в одном» вместо «…в одном месте») — грамматически и по лимитам корректно, но не отредактировано человеком. Для реального запуска кампании это годится как «прошло технический контроль», не как финальная редактура текста.

Результат первого живого прогона — 31.07.2026 (до фиксера)

Полные материалы: runs/2026-07-31_live/report.md, console_log.txt (полный stdout прогона).

Лендинг: vibemarketolog.ru. Бюджет: 3 генерации + 1 аудит (186₽ из 453₽ на балансе). Баланс до прогона — 453₽, после — 267₽ (проверено через /balance независимо от лога прогона): списано ровно 186₽ = 3×49 + 39.

Итерация

utp

стоимость

ГОДНО

ИСПРАВИМО

БРАК

ГАЛЛЮЦИНАЦИЯ

1

(пусто)

49₽

45

12

90

0

2

«каждый заголовок ≤56 знаков…»

49₽

32

4

111

0

3

«каждый заголовок ≤56 знаков…»

49₽

15

0

153

0

Остановка: исчерпаны 3 итерации, брак остаётся (программа честно не рапортует успех, которого не было).

Честная находка: переформулировка utp с текстовой инструкцией про длину заголовка не снизила брак, а увеличила его — 90→111→153. Разбор причины и вывод — в docs/boundaries.md, раздел 1. Это не баг цикла: гейт и критерий остановки отработали корректно (не зациклились, не приукрасили результат), проблема в самой стратегии «попроси генератор словами исправить формат» для этого типа дефекта.

Что сделано с этой находкой дальше: не выброшена, а исправлена — см. раздел выше «Локальный фиксер длины». Переформулировка utp осталась только для содержательных дефектов (галлюцинации), для длины теперь механическая обрезка. На новом прогоне это дало 0 БРАК за 2 итерации вместо честного поражения за 3.

Бонус: direct/sitelinks (29₽) — вне брифа, для полноты MCP-инструментов

Живой вызов на том же лендинге вернул 8 корректных sitelinks (title≤30, description≤60) — сырой ответ: runs/2026-07-31_live/raw/sitelinks.json.

Честно про этот вызов: он оплачен дважды (58₽ вместо 29₽) — я тестировал скрипт демо-вызова, он упал на отсутствующей папке runs/…/raw/ уже ПОСЛЕ успешного платного POST, я пересоздал папку и перезапустил, оплатив ещё раз. Баланс упал 267₽ → 209₽ вместо ожидаемых 267₽ → 238₽. Вывод для реального использования: любой скрипт с платным вызовом обязан гарантировать существование выходной директории (или писать во временный файл) до запроса, а не полагаться на то, что запись после него не упадёт. Мелочь, но именно так на реальных деньгах теряются 29₽ по невнимательности — а не из-за API.

Границы решения

Полный честный список — docs/boundaries.md: что проверено вживую, что нет, где решение сломается и почему.


Илья Шаповалов · ilya-proof.vercel.app · github.com/yagaMI-Reverse

Related MCP Connectors

Related MCP Servers