Vibe-Marketolog MCP Server
by FloppaProg
README.md
# Vibe-Marketolog Agent API → MCP (POC)
Один инструмент, журнал вызовов, понятная цена цикла.
## Состав
- `vibe_client.py` — клиент к `https://lk.vibemarketolog.ru/api/agent`.
Пишет каждый вызов в `call_log.jsonl` и считает расход за сессию.
- `server.py` — MCP-сервер на FastMCP. Четыре тула: `landing_audit`,
`cycle_cost_summary`, `call_log`, `account_status`. Подключается как
обычный MCP-сервер в Cursor, VS Code или любой MCP-совместимой среде.
- `demo_run.py` — прогон без MCP-клиента: вызов, повтор, журнал, сводка.
- `test_client.py` — 13 тестов на моке HTTP-слоя.
## Запуск
```bash
pip install -r requirements.txt
export VIBE_API_KEY=ваш_ключ_из_раздела_AGI_Агент
python demo_run.py https://ваш-сайт.ru # демонстрация
python server.py # как MCP-сервер
```
Тесты:
```bash
python -m pytest test_client.py -v
```
Версия SDK закреплена как `mcp==1.9.4`: в 2.x нет пути импорта
`mcp.server.fastmcp`, под неё сервер нужно переписывать отдельно.
## Почему landing-audit
Это единственный существующий роут семейства `direct/*`. Проверял
запросами без ключа, живой роут отвечает 401, несуществующий 404:
```
POST /api/agent/direct/landing-audit -> 401 missing_token
POST /api/agent/direct/waste -> 404 not_found
POST /api/agent/direct/search-queries -> 404 not_found
POST /api/agent/direct/campaigns -> 404 not_found
```
Плюс инструменту не нужен ни рекламный кабинет, ни кампания на
платформе, только URL. Значит, POC можно проверить сразу после
получения ключа.
## Журнал вызовов
`call_log.jsonl`, построчно. Пишутся все вызовы, включая упавшие,
иначе цена цикла считается по неполным данным:
```json
{"timestamp": "...", "session_id": "6c90b72e", "tool": "direct/landing-audit", "params": {"url": "..."}, "status": "ok", "cached": false, "price_rub": 39.0, "price_source": "api", "duration_ms": 1240, "note": "новый платный вызов"}
{"timestamp": "...", "session_id": "6c90b72e", "tool": "direct/landing-audit", "params": {"url": "..."}, "status": "ok", "cached": true, "price_rub": 0.0, "price_source": "cache", "duration_ms": 180, "note": "из кеша (бесплатно)"}
{"timestamp": "...", "session_id": "6c90b72e", "tool": "me", "params": {}, "status": "error", "cached": false, "price_rub": 0.0, "price_source": "none", "duration_ms": 519, "note": "HTTP 401 missing_token: Не передан ключ доступа."}
```
`price_source` показывает, откуда цифра: `api` пришла в ответе, `cache`
вызов бесплатный, `unknown` API цену не сообщил.
## Цена цикла
`cycle_cost_summary()` по умолчанию считает только текущий запуск.
Журнал дописывается между запусками, и сумма за всю историю файла это
не цена цикла; за всю историю считает `scope="all"`.
```json
{
"scope": "session",
"session_id": "6c90b72e",
"total_calls": 2,
"paid_calls": 1,
"cached_free_calls": 1,
"unknown_price_calls": 0,
"errors": 0,
"total_spent_rub": 39.0,
"cost_confirmed": true
}
```
`cost_confirmed: false` значит, что по какому-то вызову API не сообщил
цену и сумма занижена. Нулём это не маскируется.
## Границы
Проверено вживую без ключа: базовый URL, `/me`, `/capabilities`,
существование роута `direct/landing-audit`, формат ошибок
`{status, error, message, request_id}`.
Проверено на моке: журнал, подсчёт стоимости, обработка ошибок,
запускаемость MCP-сервера. 13 тестов.
Не проверено — имена полей стоимости и кеша в ответе `landing-audit`.
Документация называет стоимость `cost`, а `/capabilities` этот
инструмент не описывает. Клиент принимает `price_rub`, `cost` и
`charged_rub`, при отсутствии всех трёх помечает цену неизвестной.
Наличие бесплатного кеша на 24 часа тоже не подтверждено: если второй
вызов придёт платным, `demo_run.py` скажет об этом прямо.
Не проверено — хватает ли скоупов промо-ключа на `direct/*`. Раздел
`partner_only` в `/capabilities` относит программную работу с Директом
к партнёрскому соглашению, возможен 403.
Остальные инструменты директолога не обёрнуты, потому что обёртывать
нечего: других роутов `direct/*` в API нет. Слой дельт в MVP не
показан: `landing-audit` не кампанейский, дельте там взяться не из чего.
## Дальше
1. Прогнать `demo_run.py` на реальном ключе, приложить фактический
`call_log.jsonl` и баланс до/после. Это заодно закроет вопрос об
именах полей стоимости и о наличии кеша.
2. Если скоупов на `direct/*` не хватит, перенести тот же контур
(смета, потолок бюджета, журнал, цена цикла) на `/generate`, где
биллинг трёхфазный: `reserved`, `cost`, `refunded`.
3. Слой дельт на том, что реально отдаёт API.
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues