sape-mcp
# sape-mcp
MCP-сервер ([Model Context Protocol](https://modelcontextprotocol.io)) для работы с [sape.ru](https://www.sape.ru) через XML-RPC API. Позволяет любому MCP-совместимому LLM-боту (Claude Desktop, Hermes, Cursor и др.) читать список проектов, смотреть ссылки и бюджеты, искать площадки по заданию и докупать ссылки.
## Возможности
- чтение баланса, информации об аккаунте и расходах;
- список проектов и параметров каждого проекта;
- URL-ы проектов, анкоры, размещённые ссылки и их статусы;
- поиск страниц площадок по фильтрам (тема, цена, тИЦ/PR и др.) — «задание» на покупку;
- покупка ссылки (одиночная и пакетная) с ограничением максимальной цены;
- универсальный вызов любого метода [XML-RPC API sape.ru](https://api.sape.ru/xmlrpc/) (`sape_call`).
Встроен rate-limiter: не более 115 запросов/мин (лимит sape.ru — 120), автоматическая авторизация по токену и повторный login при разрыве сессии.
## Установка
```bash
pip install .
```
## Получение токена
1. Зайдите на https://passport.sape.ru/security/token/ под своим аккаунтом.
2. Сгенерируйте API-токен.
Примечание: для авторизации API используется логин аккаунта (то, чем вы входите в интерфейс sape.ru). E-mail и user_id не подходят — API принимает только пару логин + токен; активен ровно один токен на аккаунт (перегенерация в Паспорте).
## Конфигурация (переменные окружения)
| Переменная | Обязательна | По умолчанию | Описание |
|---|---|---|---|
| `SAPE_LOGIN` | да | — | логин входа в sape.ru (**именно логин, не e-mail и не user_id** — API принимает только логин; ID пользователя возвращается как результат `sape.login`, а не передаётся) |
| `SAPE_TOKEN` | да | — | API-токен |
| `SAPE_API_URL` | нет | `https://api.sape.ru/xmlrpc/` | адрес API |
| `SAPE_MAX_CALLS_PER_MINUTE` | нет | `115` | троттлинг запросов |
## Подключение к агенту
Два способа — выберите один.
### Вариант A: удалённый MCP-сервер (рекомендуется, сервер живёт в Docker)
Поднимите контейнер (см. раздел «Запуск в Docker» ниже), затем подключите endpoint `http://<host>:8080/mcp`.
Клиенты с поддержкой удалённых MCP (Claude Desktop «Add custom connector», Cursor, Cline и др.):
```json
{
"mcpServers": {
"sape": {
"url": "http://localhost:8080/mcp"
}
}
}
```
Плюсы: один постоянный процесс, одна cookie-сессия к API, честный rate-limit, обновление сервера без правки конфигов агентов.
### Вариант B: локальный stdio (сервер запускается клиентом)
Требуется установленный пакет: `pip install sape-mcp` (после публикации на PyPI) или `pip install git+https://github.com/sshra/sape-mcp.git`.
Универсальный формат (Claude Desktop, Cursor, Cline, большинство MCP-клиентов):
```json
{
"mcpServers": {
"sape": {
"command": "sape-mcp",
"env": {
"SAPE_LOGIN": "ваш_логин",
"SAPE_TOKEN": "ваш_токен"
}
}
}
}
```
Если `sape-mcp` не в PATH — укажите полный путь (`C:\\Python313\\Scripts\\sape-mcp.exe`) или запускайте через Python:
```json
{
"mcpServers": {
"sape": {
"command": "python",
"args": ["-m", "sape_mcp"],
"env": { "SAPE_LOGIN": "...", "SAPE_TOKEN": "..." }
}
}
}
```
Для stdio-клиентов доступен и гибрид: клиент сам поднимает контейнер на сессию:
```json
{
"mcpServers": {
"sape": {
"command": "docker",
"args": ["run", "--rm", "-i", "--env-file", "/абсолютный/путь/.env", "sape-mcp"],
"env": { "SAPE_TRANSPORT": "stdio" }
}
}
}
```
(образ собирается один раз: `docker build -t sape-mcp https://github.com/sshra/sape-mcp.git#master:docker`)
### Переменные окружения
| Переменная | Обязательна | По умолчанию | Описание |
|---|---|---|---|
| `SAPE_LOGIN` | да | — | логин входа в sape.ru (**именно логин, не e-mail и не user_id** — API принимает только логин; ID пользователя возвращается как результат `sape.login`, а не передаётся) |
| `SAPE_TOKEN` | да | — | API-токен с https://passport.sape.ru/security/token/ (активен один на аккаунт) |
| `SAPE_API_URL` | нет | `https://api.sape.ru/xmlrpc/` | адрес API |
| `SAPE_MAX_CALLS_PER_MINUTE` | нет | `115` | троттлинг запросов (лимит sape.ru — 120) |
| `SAPE_TRANSPORT` | нет | `stdio` | `stdio` или `streamable-http` (режим Docker) |
| `SAPE_HOST` / `SAPE_PORT` | нет | `0.0.0.0` / `8000` | адрес HTTP-сервера в Docker-режиме |
### Hermes Agent
```yaml
mcp_servers:
sape:
url: http://localhost:8080/mcp # вариант A
# либо вариант B:
# command: sape-mcp
# env: { SAPE_LOGIN: "...", SAPE_TOKEN: "..." }
```
## Инструменты
| Инструмент | Назначение |
|---|---|
| `get_balance` | баланс (полный и доступный) |
| `get_user` | аккаунт, расходы за сутки/неделю, бюджет |
| `list_projects` | список проектов с числом урлов/ссылок |
| `get_project` | параметры проекта и расходы |
| `list_urls` | URL-ы проекта |
| `get_url_anchors` | анкоры URL-а и лимиты использования |
| `get_project_links` | все ссылки проекта со статусами |
| `get_url_links` | ссылки конкретного URL-а |
| `search_pages` | поиск площадок/страниц по фильтрам (задание на покупку) |
| `create_placement` | покупка ссылки (⚠️ тратит деньги; есть max_price) |
| `create_placements` | пакетная покупка (до 200 за вызов) |
| `sape_call` | универсальный вызов любого метода API |
## Пример сценария для бота
> «Покажи мои проекты. Для проекта X найди до 20 площадок по теме "ремонт" не дороже 50 руб. и докупи по 1 ссылке, но не трать больше 500 руб. за всё»
Бот: `list_projects` → `list_urls` → `search_pages` (фильтр по теме/цене) → `create_placements` с `max_price`.
## Безопасность
- Токен хранится только в переменных окружения вашего MCP-клиента, не пишется в логи.
- Покупка ссылок расходует реальные средства: используйте `max_price` для ограничения цены, а бюджет — инструмент `get_balance`.
- API sape.ru ограничен 120 запросами/мин на аккаунт; сервер троттлит на 115.
## Запуск в Docker (независимый контейнер)
Docker-файлы живут в папке [docker/](docker/) и собирают образ **из этого репозитория** — локальные исходники не нужны.
Вариант 1 — одной командой (контекст сборки — git-репозиторий):
```bash
docker build -t sape-mcp https://github.com/sshra/sape-mcp.git#master:docker
```
Вариант 2 — через compose (нужен только .env рядом с папкой docker):
```bash
git clone https://github.com/sshra/sape-mcp.git && cd sape-mcp
cp .env.example .env # заполнить SAPE_LOGIN и SAPE_TOKEN
docker compose -f docker/docker-compose.yml up -d
```
Сервер поднимется в режиме streamable-http, MCP-endpoint: `http://localhost:8080/mcp`.
Подключение клиентов, поддерживающих удалённые MCP-серверы:
```json
{
"mcpServers": {
"sape": {
"url": "http://localhost:8080/mcp"
}
}
}
```
Для клиентов, которые умеют только stdio, контейнер можно использовать без compose-сети:
```json
{
"mcpServers": {
"sape": {
"command": "docker",
"args": ["run", "--rm", "-i", "--env-file", "/путь/к/.env", "sape-mcp"],
"env": { "SAPE_TRANSPORT": "stdio" }
}
}
}
```
(образ собирается один раз: `docker build -t sape-mcp .` — либо вариант 1 выше: сборка напрямую из GitHub)
Логи: `docker compose logs -f sape-mcp`.
## Разработка
```bash
pip install -e .[dev]
pytest
```
## Лицензия
MIT
TDQS
Scored across 12 tools
Most tools have clearly distinct scopes: account, projects, URLs, anchors, page search, and placement creation. Minor overlap exists between get_balance and get_user, and between get_project_links and get_url_links, but descriptions clarify project-level versus URL-level scope. sape_call overlaps by design as a fallback but is explicitly framed that way.
The set mostly follows a predictable snake_case verb_noun convention: get_*, list_*, search_pages, create_placement, create_placements. The main deviations are the generic sape_call and the singular/plural pair create_placement/create_placements, which is readable but slightly easy to confuse.
Twelve tools is well within the appropriate range for a focused Sape integration. The set covers reads, search, single and batch purchases, plus a generic fallback without becoming bloated.
Core workflows are covered: account balance, user info, projects, URLs, anchors, existing links, page search, and link purchase. Dedicated update/delete operations for placements and project/URL lifecycle management are missing, but sape_call provides a generic escape hatch for unsupported API methods.