No description
  • Python 90.5%
  • Nix 9.5%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-07-28 16:28:00 +03:00
rzd_mcp rzd-mcp: _meta иконки и brief-шаблоны для всех инструментов 2026-07-28 16:28:00 +03:00
.gitignore rzd-mcp: планировщик поездок по РЖД 2026-07-22 15:37:39 +03:00
AGENTS.md rzd-mcp: _meta иконки и brief-шаблоны для всех инструментов 2026-07-28 16:28:00 +03:00
CHANGELOG.md rzd-mcp: _meta иконки и brief-шаблоны для всех инструментов 2026-07-28 16:28:00 +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-mcp: _meta иконки и brief-шаблоны для всех инструментов 2026-07-28 16:28:00 +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 дат — перебор хабов на дату тяжёлый.

Каждый инструмент возвращает поле _meta с иконкой (dev.eva/icon) и шаблоном показа (dev.eva/brief).

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

  • 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 запросов), чтобы не долбить РЖД.
  • Хабы для пересадок — фиксированный список крупных узлов; экзотические стыковки через мелкие станции не строятся.