No description
  • Python 90.4%
  • Nix 9.6%
Find a file
Aleksandr 3c07349684 rzd_route: перебор дат внутри инструмента (date_to/weekdays)
Маршрутизатор умел только одну дату — на «маршрут ближе к выходным»
модель была вынуждена звать rzd_route по разу на каждый день, что и
медленно (перебор хабов на дату), и упирается в потолок итераций хода.

Переношу перебор внутрь, как в rzd_search: date_to/weekdays раскрываются
в список дат, каждая считается своим изолированным клиентом (RID-механика
завязана на cookie-сессию — конкурентно на одном клиенте рвётся), даты
идут параллельно с ограничением конкурентности. Ответ сгруппирован по
датам с днём недели. Окно капается ≤8 — перебор хабов тяжёлый.

Co-Authored-By: Eva
2026-07-22 16:24:02 +03:00
rzd_mcp rzd_route: перебор дат внутри инструмента (date_to/weekdays) 2026-07-22 16:24:02 +03:00
.gitignore rzd-mcp: планировщик поездок по РЖД 2026-07-22 15:37:39 +03:00
flake.lock rzd-mcp: планировщик поездок по РЖД 2026-07-22 15:37:39 +03:00
flake.nix rzd-mcp: планировщик поездок по РЖД 2026-07-22 15:37:39 +03:00
pyproject.toml rzd-mcp: планировщик поездок по РЖД 2026-07-22 15:37:39 +03:00
README.md rzd_route: перебор дат внутри инструмента (date_to/weekdays) 2026-07-22 16:24:02 +03:00

rzd-mcp — планировщик поездок по РЖД 🚂

MCP-сервер, которым Ева планирует дорогу по железной дороге: ищет прямые поезда, ловит дни, когда редкий поезд реально ходит, и собирает пересадочные маршруты, когда прямых нет.

Работает поверх неофициального API pass.rzd.ru (тот, что дёргает сам сайт РЖД). Официального открытого API у РЖД нет — покупку билетов не делаем, только поиск и планирование; кнопку «купить» Господин жмёт сам на ticket.rzd.ru.

Инструменты

  • rzd_stations(query) — станции по части названия и их коды. Для уточнения, если вокзалов несколько.
  • rzd_search(origin, destination, date, date_to?, weekdays?) — прямые поезда. date — YYYY-MM-DD. Перебор дат делает сам сервер, не модель:
    • date_to — искать по всему окну (прямой может ходить не каждый день);
    • weekdays — фильтр дней недели (0=Пн … 6=Вс), напр. [5,6] «ближе к выходным»: окно хоть месяц, проверяются только нужные дни (≤16 запросов). Возвращает поезда, сгруппированные по датам, где они реально есть.
  • rzd_seats(origin, destination, date, train_number, depart_time) — разбивка мест поезда по вагонам: верхние/нижние (и боковые), с ценами, числом свободных и номерами мест. Номер поезда и время бери из rzd_search. Общий поиск даёт лишь суммарные места по типу вагона — этот инструмент для «нижнее в купе».
  • rzd_route(origin, destination, date, date_to?, weekdays?, budget?, max_transfers?) — маршрут с пересадками, когда прямых нет или они дороже бюджета. Перебирает узловые станции (Москва, СПб, Ростов, Воронеж…), склеивает рейсы по времени (прибытие + запас ≤ отправление) и ранжирует по времени в пути и цене. budget — потолок суммарной цены, руб. date_to/ weekdays — как в rzd_search: окно дат перебирается внутри инструмента (даты считаются параллельно, изолированными сессиями), один вызов на «ближе к выходным». Окно капается ≤8 дат — перебор хабов на дату тяжёлый.

Как это устроено

  • client.py — HTTP-клиент. Станции: /suggester (важно: РЖД матчит только ВЕРХНИЙ регистр, отдаёт широкий список — клиент сам берёт точное/префиксное совпадение по приоритету). Поиск: /timetable двухшагово через RID (первый запрос отдаёт id, по нему опрашиваем готовый результат).
  • route.py — склейка пересадок через хабы, ранжирование.
  • server.py — MCP-инструменты (FastMCP, транспорт stdio).

Запуск

nix run .              # или: nix build && ./result/bin/rzd-mcp

Прокси (если хост не видит pass.rzd.ru напрямую) — через переменную RZD_PROXY=socks5h://….

Подключение к ядру Евы

MCP-сервер stdio, ядро спавнит его само. В конфиге ядра:

mcp:
  servers:
    rzd:
      command: ["rzd-mcp"]
      # env: { RZD_PROXY: "socks5h://127.0.0.1:1080" }

На NixOS — nixosModules.default кладёт пакет в систему и (опционально) пробрасывает RZD_PROXY; подключение к ядру настраивается в infra.

Ограничения

  • Не покупает билеты (авторизация + капча + оплата — вне зоны).
  • Перебор диапазона капается (≤16 запросов), чтобы не долбить РЖД.
  • Хабы для пересадок — фиксированный список крупных узлов; экзотические стыковки через мелкие станции не строятся.