livo-ge-mcp
# livo-ge-mcp
MCP-сервер над [livo.ge](https://livo.ge) - порталом недвижимости группы tnet
(бывший myhome.ge).
Прозрачный stateless-прокси: один вызов инструмента = один-несколько живых запросов.
Между вызовами кешируются только два справочника (локации и словари, TTL 6 часов);
объявления не кешируются никогда.
У livo.ge нет публичного API. Контракт восстановлен реверс-инжинирингом бандлов
Next.js и проверен живыми запросами - разбор в [`docs/API.md`](docs/API.md).
## Установка
```bash
claude mcp add livo-ge --scope user -- npx -y livo-ge-mcp@1
```
Нужен Node >= 20. Клонировать и ставить вручную ничего не надо: `npx` сам скачает пакет
из npm и закеширует. `@1` фиксирует мажорную версию, обновления внутри неё приезжают
сами, а ломающий релиз молча не подменит сервер.
Проверить, что сервер подключился: `claude mcp list`.
Для клиентов с JSON-конфигом (Claude Desktop, Cursor, Windsurf):
```json
{
"mcpServers": {
"livo-ge": {
"command": "npx",
"args": ["-y", "livo-ge-mcp@1"],
"env": { "LIVO_LOCALE": "ru" }
}
}
}
```
<details>
<summary>Из исходников</summary>
```bash
git clone https://github.com/nosuchip/livo-ge-mcp && cd livo-ge-mcp && npm install
claude mcp add livo-ge --scope user -- node "$PWD/src/index.mjs"
npm test # смоук-тест, ходит в сеть по-настоящему
```
</details>
### Настройки
| Переменная | По умолчанию | Что делает |
|---|---|---|
| `LIVO_LOCALE` | `ru` | `ka` \| `en` \| `ru`. Заголовок переводит **данные**, а не только UI |
| `LIVO_MIN_INTERVAL_MS` | `1000` | Минимальный интервал между запросами, глобально |
Задать при установке: `claude mcp add livo-ge --scope user -e LIVO_LOCALE=en -- npx -y livo-ge-mcp@1`.
## Инструменты
| Инструмент | Что делает |
|---|---|
| `get_skill` | Инструкции: `apartment-search` - как разложить критерии; `criteria-coverage` - что источник знает, а что нет |
| `count` | Число объявлений под фильтр, без выкачивания. Один дешёвый запрос |
| `search` | Поиск. Отдаёт `applied_filters` - эхо API о том, что он реально разобрал |
| `listing` | Полная карточка: описание, удобства, координаты, кадастр, просмотры, настоящая дата публикации |
| `geo` | Города, районы, микрорайоны с id; `query` работает как автодополнение сайта |
| `reference` | Словари id → название для фильтров, которые принимают только id |
| `projects` | Новостройки (проекты застройщиков) - отдельный набор данных |
Фильтр принимает человеческие названия на любом из трёх языков сайта:
`areas: ["Ваке", "Saburtalo"]`, `metro: ["Руставели"]`,
`amenities: ["elevator", "pets-allowed"]`.
## Что этот сервер намеренно делает неудобно
Пять вещей в livo устроены так, что наивная обёртка выдавала бы правдоподобную неправду.
Здесь они вынесены наружу, а не спрятаны.
**Свежесть.** `last_updated` - не дата публикации: livo пишет туда любую правку и любое
платное поднятие, и у объявления 2024 года там регулярно "сегодня". Настоящий возраст
даёт `quantity_of_day`, поэтому сервер отдаёт `age_days` и посчитанный из него
`published`, а `updated` подписан как "правка или поднятие". Проверено сверкой
с `created_at`: сходится день в день.
**Сортировка.** Она не применяется ко всей выдаче: `super_vip`, `vip_plus` и `vip`
закреплены сверху всегда, а `order` работает только внутри тира. Сам `date_desc`
к тому же сортирует по `last_updated`, а не по публикации. Поэтому каждая карточка
несёт `promo_tier` (`null` = обычное объявление), и в ответе прямо сказано, что
позиция в списке про деньги, а не про свежесть.
**Опечатки в фильтре.** API молча игнорирует неизвестные имена полей и отдаёт
неотфильтрованную выдачу: `count` с полем `nonsense_field` возвращает ровно столько же,
сколько без него. Клиент сверяет фильтр с белым списком и падает, а не врёт.
Плюс к этому в ответ кладётся `applied_filters` - эхо самого API.
**Удобства объединяются по ИЛИ.** `[elevator, conditioner]` даёт *больше* результатов,
чем `[elevator]`. "С лифтом И кондиционером" через этот API одним запросом не
выражается, поэтому сервер предупреждает об этом прямо в ответе.
**Охват.** Заголовок `X-Website-Key` выбирает витрину группы tnet, и витрины не равны:
по одному запросу livo отдаёт 53 698 объявлений, myhome.ge - 94 116. Livo - подмножество,
и `criteria-coverage` говорит об этом прямо.
## Темп и вежливость
1 запрос в секунду глобально, честный User-Agent (`livo-ge-mcp/…`), без подделки под
браузер. На 429 и на "настоящий" 403 предохранитель размыкается и остаётся разомкнутым:
это сигнал перестать ходить. `robots.txt` на обоих API-хостах ничего не запрещает.
## Лицензия
MIT, см. [`LICENSE`](LICENSE).
TDQS
Scored across 7 tools
Each tool has a clearly distinct purpose: geo handles location hierarchy, reference provides filter dictionaries, count/search/listing cover different levels of listing retrieval, projects covers developer data, and get_skill provides meta-instructions. The relationships between similar tools like count vs search and search vs listing are explicitly clarified.
Tool names are short, readable, and all lowercase, but they mix noun-style resources such as geo, reference, projects, and listing with imperative verbs like search and count, plus one snake_case verb_noun tool, get_skill. This is not chaotic, but there is no consistent naming pattern across the set.
Seven tools are well-scoped for a read-only real estate search server. Each tool serves a necessary part of the workflow: reference data, geographic lookup, counting, searching, detail retrieval, project data, and guided instructions. There is no obvious bloat or missing essential category.
For its stated purpose of searching and exploring Livo.ge listings, the tool surface is complete: search and count cover filtering, listing provides full details, geo and reference support valid filter construction, projects covers developer data, and get_skill documents workflow and known limitations. No significant dead ends or missing read-side operations are apparent.