Skip to main content
Glama
README.md
# likes-store-mcp

MCP-сервер likes-store для агентств. Подключает ИИ-ассистента (Claude Desktop, Claude Code, Cursor или любой другой MCP-клиент) к вашему аккаунту likes-store: ассистент видит каталог с вашими ценами и баланс, считает точную стоимость заказа, оформляет его после вашего согласия и следит за статусами. Лайки, просмотры, подписчики и комментарии в Instagram\*, TikTok, ВКонтакте, Telegram и на других площадках из каталога можно заказывать обычной фразой в чате, не открывая кабинет.

Сервер работает поверх API для агентств (`/api/v1`) и умеет ровно то, что открывает ключ API. Весь сервер — один файл на Node.js без единой зависимости.

## Что умеет

| Инструмент | Что делает |
| --- | --- |
| `list_services` | Каталог услуг с ценой для вашего аккаунта: границы количества, цена за штуку, скидки за объём, подсказки к ссылке. Фильтры по площадке, типу и строке поиска. |
| `get_balance` | Баланс: основной и подарочный. |
| `list_projects` | Проекты агентства, по одному на клиента. Можно вместе с архивными. |
| `quote_order` | Примерка заказа: проверяет ссылку и количество, считает сумму со всеми скидками и говорит, хватает ли денег. Ничего не списывает. |
| `place_order` | Оформляет заказ по примерке и списывает деньги с баланса. |
| `get_order` | Заказ по номеру: статус, сколько выполнено, сколько вернулось на баланс. |
| `list_orders` | Заказы постранично, с фильтрами по статусу, проекту и периоду. |
| `topup_link` | Ссылка на форму пополнения баланса в кабинете. |

У каждого инструмента заданы все четыре подсказки из спецификации MCP (`readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`), по которым клиент решает, когда спрашивать ваше подтверждение. Семь инструментов только читают; `place_order` помечен как необратимый (`destructiveHint: true`), потому что тратит деньги, и как безопасный для повтора (`idempotentHint: true`), потому что повтор второго заказа не ставит.

## Как устроен заказ

Заказ проходит в три шага, и третий без первых двух невозможен.

1. `quote_order` делает примерку: сайт проверяет ссылку, количество и потолки и возвращает точную сумму. Ассистент показывает вам строку вроде «5 000 шт. «Лайки» (Instagram\*) по ссылке https://instagram.com/p/… за 1 350 ₽ (скидка за объём 23 %), с баланса спишется 1 350 ₽».
2. Вы соглашаетесь или нет. Описание `place_order` прямо требует от ассистента дождаться вашего явного согласия на эту сумму.
3. `place_order` принимает только номер примерки (`quoteId`), поэтому заказать то, чего вы не видели, ассистент не может.

Цена из примерки уходит в API как верхняя граница (`maxPrice`). Если за время раздумий цена выросла, заказ не оформится и деньги не спишутся; ассистент сделает новую примерку и снова покажет сумму.

Номер примерки уходит заголовком `Idempotency-Key`, и это защищает от двойного списания. Повторный `place_order` с тем же `quoteId` вернёт уже оформленный заказ, а не поставит второй. На этом держится и поведение при сбоях: если сеть оборвалась, сайт не ответил за 30 секунд или прокси вернул 502, сервер один раз повторяет запрос с тем же ключом. Когда исход так и остаётся неизвестным, ассистент получает прямой текст: «заказ мог оформиться, повторите с тем же quoteId — второго не будет».

Примерка живёт 15 минут в памяти сервера. После перезапуска сервера или по истечении срока нужна новая примерка, а значит, и новое согласие.

## Где взять ключ

Ключ выпускается в кабинете, раздел «API»: `https://likes-store.com/dashboard/api`. Раздел открыт аккаунтам со статусом агентства, заявка на статус — на странице `https://likes-store.com/agency`. Ключ показывается один раз, сразу после выпуска.

Выпустите для ассистента отдельный ключ, не тот, на котором работают ваши скрипты: его можно отозвать, ничего больше не сломав. Ассистенту, который только смотрит, дайте ключ «только чтение» и запускайте сервер с `LS_READONLY=1`. Ассистенту, который заказывает, задайте у ключа дневной потолок трат: тогда даже ошибка обойдётся не дороже потолка.

## Установка

Нужен Node.js версии 18 или новее (в нём есть встроенный `fetch`). Проверить: `node --version`.

Дальше есть два пути.

**Ничего не устанавливать.** Запускать прямо из GitHub:

```
npx -y github:trueblackat/likes-store-mcp
```

**Скачать репозиторий себе.** Так запуск быстрее и не зависит от сети:

```
git clone https://github.com/trueblackat/likes-store-mcp.git
cd likes-store-mcp
node likes-store-mcp.mjs
```

Запущенный без флагов сервер ничего не печатает и ждёт команд MCP-клиента на стандартном вводе. Так и должно быть: запускает его сам клиент. Остановить: Ctrl+C.

## Проверить ключ

```
LS_API_KEY=ls_... npx -y github:trueblackat/likes-store-mcp --check
```

Из скачанной папки то же самое: `LS_API_KEY=ls_... node likes-store-mcp.mjs --check`.

С рабочим ключом сервер напечатает:

```
Адрес: https://likes-store.com
Ключ рабочий.
Баланс: 12 500 ₽, подарочный: 300 ₽
Услуг доступно: 142
```

и завершится с кодом 0. Если ключа нет, он отозван или сайт недоступен, будет понятная причина и код 1.

## Подключить

### Claude Desktop

Откройте файл настроек: в самом Claude Desktop это «Settings → Developer → Edit Config», а на диске он лежит в `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) или `%APPDATA%\Claude\claude_desktop_config.json` (Windows). Добавьте блок `mcpServers`:

```json
{
  "mcpServers": {
    "likes-store": {
      "command": "npx",
      "args": ["-y", "github:trueblackat/likes-store-mcp"],
      "env": {
        "LS_API_KEY": "ls_..."
      }
    }
  }
}
```

Если репозиторий скачан, вместо `npx` укажите `node` и абсолютный путь к файлу:

```json
{
  "mcpServers": {
    "likes-store": {
      "command": "node",
      "args": ["/абсолютный/путь/likes-store-mcp/likes-store-mcp.mjs"],
      "env": {
        "LS_API_KEY": "ls_..."
      }
    }
  }
}
```

На Windows обратные косые черты в пути удваиваются: `"C:\\mcp\\likes-store-mcp\\likes-store-mcp.mjs"`. После правки перезапустите Claude Desktop. Если Claude Desktop пишет, что не находит `npx` или `node` (так бывает, когда Node.js поставлен через nvm), укажите в `command` полный путь из `which npx` или `which node`.

### Claude Code

Одной командой:

```
claude mcp add --env LS_API_KEY=ls_... --transport stdio likes-store -- npx -y github:trueblackat/likes-store-mcp
```

Или из скачанной папки: `claude mcp add --env LS_API_KEY=ls_... --transport stdio likes-store -- node /абсолютный/путь/likes-store-mcp/likes-store-mcp.mjs`.

Порядок важен: имя сервера (`likes-store`) не должно стоять сразу после `--env LS_API_KEY=…`, иначе Claude Code прочтёт его как ещё одну переменную и откажется добавлять сервер.

Чтобы сервер был доступен во всех проектах, а не только в текущем, добавьте `--scope user` перед именем сервера:

```
claude mcp add --env LS_API_KEY=ls_... --transport stdio --scope user likes-store -- npx -y github:trueblackat/likes-store-mcp
```

### Cursor

Тот же блок `mcpServers`, что и для Claude Desktop, в файле `~/.cursor/mcp.json` (для всех проектов) или `.cursor/mcp.json` в папке проекта.

### Другие клиенты

Подойдёт любой клиент, который запускает локальные MCP-серверы по stdio: команда `npx` с аргументами `-y github:trueblackat/likes-store-mcp` (или `node` и путь к файлу), ключ — в переменной окружения `LS_API_KEY`. Сервер понимает обе версии протокола: с рукопожатием `initialize` (2024-11-05 … 2025-11-25) и без него (2026-07-28).

## Примеры запросов

Названия инструментов ассистенту знать не нужно, достаточно сказать, что сделать.

- **«Сколько будут стоить 10 000 лайков на этот пост? https://instagram.com/p/…»** — `list_services` находит услугу, `quote_order` считает сумму со скидкой за объём и проверяет, хватает ли денег.
- **«Оформляй»** — `place_order` по только что показанной примерке.
- **«Что с заказами клиента „Кофейня“ за эту неделю?»** — `list_projects` находит проект, `list_orders` выбирает его заказы с понедельника.
- **«Хватит ли денег на 50 000 просмотров в Telegram?»** — `quote_order`; если не хватает, `topup_link` даёт ссылку на пополнение и называет недостающую сумму.

## Переменные окружения

| Переменная | Обязательна | Значение |
| --- | --- | --- |
| `LS_API_KEY` | да | Ключ API агентства. Без него инструменты отвечают подсказкой, где взять ключ. |
| `LS_API_URL` | нет | Адрес сайта, в кабинете которого вы выпустили ключ. По умолчанию `https://likes-store.com`. От него строятся ссылки на пополнение и на раздел «API». |
| `LS_READONLY` | нет | `1` — без инструмента заказа: `place_order` не появляется в списке вовсе. |
| `LS_TIMEOUT_MS` | нет | Таймаут одного запроса, по умолчанию 30 000 мс. |
| `LS_QUOTE_TTL_MS` | нет | Сколько живёт примерка, по умолчанию 900 000 мс (15 минут). |

## Чего сервер не умеет и почему

- **Пополнять баланс и выводить деньги.** Деньги заводит и выводит человек, в кабинете, своей картой. `topup_link` только даёт ссылку на форму, а сумму называет словами: подставить её в форму по ссылке нельзя.
- **Заказывать свои комментарии**, то есть комментарии с вашим текстом. Писать тексты от имени живых людей ассистенту мы не поручаем, поэтому такие услуги в каталоге сервера не показываются; заказать их можно в кабинете. Обычные комментарии без своего текста в каталоге есть.
- **Отменять заказы.** В API такой операции нет. Если заказ не выполнится целиком, невыполненная часть вернётся на баланс сама.
- **Подключаться как удалённый коннектор по адресу.** Сервер локальный: он запускается на вашем компьютере, и ключ уходит только на адрес из `LS_API_URL`.

## Ключ и безопасность

Ключ открывает заказы от имени вашего аккаунта и трату денег с его баланса. Не отправляйте его в чаты, не коммитьте в git и не вставляйте в сам разговор с ассистентом: ключ нужен только в настройках клиента. Сервер ключ не печатает ни в ответах, ни в журнале. Если ключ всё-таки утёк, отзовите его в кабинете (раздел «API») и выпустите новый.

Частота запросов ограничена сайтом: 60 в минуту на ключ. Если ассистент упрётся в лимит, сервер подождёт, сколько попросит сайт (не дольше 10 секунд), и повторит запрос один раз.

## Разработка

```
npm test
```

Тесты запускают сервер отдельным процессом и говорят с ним по stdio, как настоящий MCP-клиент, а вместо сайта поднимают поддельное API на `node:http`. Ни сеть, ни ключ не нужны; зависимостей нет, всё на встроенном `node:test`.

## Лицензия

MIT, полный текст — в [LICENSE](LICENSE).

---

\* Instagram и Facebook принадлежат Meta, признанной в России экстремистской организацией.