Moscow Transport MCP
by zavorateam
README.md
# moscow-transport-mcp
[](https://python.org)
[](https://fastapi.tiangolo.com)
[](https://modelcontextprotocol.io)
[](#тестирование)
[](#сквозное-тестирование-агента-agent_testpy)
**Moscow Transport MCP** — интеллектуальный гибридный шлюз для AI-агентов (MCP) и микросервисов (REST), агрегирующий данные пассажирского транспорта **Москвы и Московской области** в реальном времени.
Шлюз непрерывно склеивает данные из трёх независимых систем, устраняет расхождения, выбирает нужные павильоны при многостороннем движении и предоставляет агентам детерминированные инструменты для планирования поездок, мониторинга автопарка и информирования пассажиров.
---
## 🧭 Архитектура и источники данных
```text
┌────────────────────────────────────────────────────────┐
│ AI-АГЕНТ (Claude / Cursor / LLM) │
└───────────────────────────┬────────────────────────────┘
│ (MCP / REST)
▼
┌──────────────────────────────────────────────────────────────────────────────────────────────┐
│ Moscow Transport MCP │
│ │
│ ┌───────────────────────────┬───────────────────────────┬──────────────────────────────┐ │
│ │ 1. Discovery & Search │ 2. Fleet & Amenities │ 3. Fusion & Dispatch │ │
│ │ (Поиск остановок, BBox, │ (GPS, скорость, кондей, │ (Сверка табло, расчет ETA, │ │
│ │ умный выбор платформы) │ низкий пол, госномер) │ live vs static график) │ │
│ └─────────────┬─────────────┴─────────────┬─────────────┴──────────────┬───────────────┘ │
└─────────────────┼───────────────────────────┼────────────────────────────┼───────────────────┘
│ │ │
▼ ▼ ▼
┌────────────────────┐ ┌───────────────────┐ ┌───────────────────┐
│Московский транспорт│ │ РНИС Мособласть │ │ Яндекс.Транспорт │
│ (ГУП Мосгортранс) │ │ (Балашиха и МО) │ │ │
└────────────────────┘ └───────────────────┘ └───────────────────┘
```
1. **Московский транспорт (ГУП «Мосгортранс» / data.mos.ru):**
- Локальный реестр `bus_stops_all.geojson` (12 500+ остановок Москвы с распаковкой `properties.attributes`).
- Официальный API `stop_v2` и `qr-stop` (секундные прогнозы прибытия по датчикам телеметрии).
2. **РНИС Московской области (Минтранс МО):**
- Прямой доступ к телеметрии бортов (3 500+ онлайн-автобусов в реальном времени).
- Поиск остановок по географическому BoundingBox (`stop_point.list`).
- Официальные табло остановок МО (`stop_point.routes`) с оставшимися остановками и ETA.
- Паспортные характеристики бортов: наличие кондиционера, низкий пол/пандус, электронные табло, валидаторы.
3. **Яндекс.Транспорт (Masstransit API):**
- Живой трекинг физических бортов, расчет курса (азимута), скорости и координат.
- Независимый геокодинг и топология маршрутов.
---
## ⚡ Ключевые возможности
- **Интроспекция для LLM (`get_filter_options`):** Агент может заранее запросить реестр перевозчиков, марок ТС и доступных опций, исключая галлюцинации в фильтрах.
- **Умный выбор павильона (Platform Disambiguation):** Если у остановки несколько платформ в разные стороны (например, «Метромост» в центр и от центра), шлюз автоматически выберет павильон, через который проходит запрошенный маршрут.
- **Бесшовное объединение Москвы и Подмосковья:** Если остановки нет в московском GeoJSON, шлюз на лету находит её в РНИС МО (по UUID или BBox).
- **Сверка прогнозов (Reconciliation):** Сравнение официального времени прибытия оператора с фактическим положением борта на карте с приоритизацией достоверного источника.
- **Non-destructive Data Policy:** Никакие данные не отбрасываются. Если у борта отсутствует госномер или статус кондиционера, возвращается `null`, а живые координаты и скорость сохраняются.
---
## 🛠️ Набор инструментов агента (Tooling / API)
| Инструмент | REST Эндпоинт | Назначение |
| :--- | :--- | :--- |
| `get_filter_options` | `GET /filter-options` | Автокомплит и списки доступных перевозчиков, марок, удобств. |
| `search_stops` | `POST /stops`, `GET /stops` | Поиск остановок по названию, маршруту, координатам, BBox, павильону. |
| `get_stop_board` | `POST /schedule`, `GET /schedule` | Живое табло остановки (все прибывающие рейсы, прогноз, `is_realtime`). |
| `get_bus_eta` | `POST /eta`, `GET /eta` | Точечный ETA конкретного автобуса со сверкой источников. |
| `search_online_buses` | `POST /buses`, `GET /buses` | Поиск бортов на карте (GPS, скорость, кондей, низкий пол, радиус). |
| `get_route_details` | `GET /routes/{route}` | Трасса маршрута: цепочка остановок и активные автобусы на нитке. |
| `get_vehicle_card` | `GET /vehicle` | Досье на конкретный борт по госномеру или UUID. |
| `get_system_status` | `GET /count` | Мониторинг онлайна телеметрии и загруженных справочников. |
---
## Быстрый старт
### 1. Клонирование и установка зависимостей
```bash
git clone <repo-url>
cd transport-mcp
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```
> **Требования к окружению:** Python 3.10+, `fastapi`, `uvicorn`, `httpx`, `pydantic`, `pytest`, `pytest-asyncio`, `mcp` (опционально для MCP-сервера).
### 2. Конфигурация окружения (`.env`)
Создайте файл `.env` в корне проекта (или скопируйте `.env.example`):
```ini
# Сервер
HOST=0.0.0.0
PORT=8000
LOG_LEVEL=DEBUG
# Путь к московскому реестру остановок
STOPS_GEOJSON_PATH=bus_stops_all.geojson
# РНИС МО (Московская область)
RNIS_BASE_URL=https://portal.rnis.mosreg.ru/busajax/request
RNIS_CACHE_TTL_SECONDS=900
RNIS_REQUEST_INTERVAL=0.5
# Московский транспорт
MOSCOW_STOP_V2_URL=https://api.moscowapp.mos.ru/v8.2/stop_v2
MOSCOW_QR_STOP_URL=https://api.moscowapp.mos.ru/v8.2/qr-stop
# Яндекс.Транспорт (опционально)
YANDEX_CSRF_TOKEN=6c4fbb2d14d555fb31c4d420225cb2120dc8fa4f:1789035145
YANDEX_SESSION_ID=1789035145230215-15377882495539827877-balancer-l7leveler-kubr-yp-klg-220-BAL
YANDEX_S_VEHICLES=1226992667
YANDEX_S_STOPS=3155859244
YANDEX_COOKIE=
# Параметры алгоритмов оркестратора
DEFAULT_LAT=55.2518
DEFAULT_LON=37.7173
DEFAULT_SEARCH_RADIUS_KM=6.0
DEFAULT_AVERAGE_SPEED_KMH=18.0
RECONCILIATION_THRESHOLD_SECONDS=180
```
### 3. Запуск сервера
#### Вариант А: REST API (для тестирования через curl / веб)
```bash
python server.py --http
```
Документация Swagger/OpenAPI доступна по адресу: [http://localhost:8000/docs](http://localhost:8000/docs)
#### Вариант Б: MCP-сервер (режим stdio для AI-агентов)
```bash
python server.py
```
---
## 🤖 Подключение к AI-агентам (MCP Setup)
### Claude Desktop
Добавьте блок в файл конфигурации `claude_desktop_config.json`:
```json
{
"mcpServers": {
"transit-agent": {
"command": "/путь/к/проекту/.venv/bin/python",
"args": ["/путь/к/проекту/server.py"],
"env": {
"PYTHONPATH": "/путь/к/проекту"
}
}
}
}
```
### Cursor / Windsurf
В настройках `Features` → `MCP Servers` добавьте сервер:
- **Type:** `command`
- **Command:** `python server.py` (с указанием виртуального окружения).
---
## Примеры запросов (curl)
### 1. Интроспекция фильтров
```bash
# Получить список перевозчиков, содержащих слово "авто"
curl -s -G 'http://localhost:8000/filter-options' \
--data-urlencode 'category=carriers' \
--data-urlencode 'query=авто' | jq .
```
### 2. Поиск остановок
```bash
# Москва: найти павильоны «Метромост»
curl -s -X POST 'http://localhost:8000/stops' \
-H 'Content-Type: application/json' \
-d '{"query": "Метромост"}' | jq .
# Область: радиусный поиск остановок в МО через РНИС BBox
curl -s -X POST 'http://localhost:8000/stops' \
-H 'Content-Type: application/json' \
-d '{"lat": 55.7971, "lon": 37.9398, "radius_km": 2.0}' | jq .
```
### 3. Табло остановки
```bash
# Живое табло остановки «пл. Славы» в Балашихе
curl -s 'http://localhost:8000/schedule?stop_id=a6466a64-eb47-11e7-90c9-136fdbe30654' | jq .
```
### 4. Точный ETA автобуса
```bash
# Запрос ETA для маршрута 22к в Балашихе с привязкой ближайшего борта
curl -s -X POST 'http://localhost:8000/eta' \
-H 'Content-Type: application/json' \
-d '{"route": "22к", "stop_id": "a6466a64-eb47-11e7-90c9-136fdbe30654"}' | jq .
# Запрос по маршруту 49 на Верхних котлах
curl -s -X POST 'http://localhost:8000/eta' \
-H 'Content-Type: application/json' \
-d '{"route": "49", "stop_name": "Верхние котлы"}' | jq .
```
### 5. Поиск активных автобусов на карте
```bash
# Показать только автобусы с кондиционером на маршруте 110
curl -s 'http://localhost:8000/buses?route=110&air_conditioned_only=true' | jq .
# Поиск бортов в радиусе 5 км с автоматической сортировкой по возрастанию расстояния
curl -s 'http://localhost:8000/buses?lat=55.7971&lon=37.9398&radius_km=5&limit=5' | jq .
```
### 6. Досье конкретного автобуса
```bash
curl -s -G 'http://localhost:8000/vehicle' \
--data-urlencode 'state_number=у342ат790' | jq .
```
---
## 🧪 Тестирование
### Unit-тестирование (pytest)
Проект покрыт подробными тестами, проверяющими логику геометрии, rate-лимитеры, нормализацию идентификаторов и сверку расписаний:
```bash
pytest -s
```
Конфигурация `pytest.ini`:
```ini
[pytest]
asyncio_mode = auto
log_cli = true
log_cli_level = DEBUG
log_cli_format = %(asctime)s [%(levelname)-8s] %(name)s: %(message)s
log_cli_date_format = %H:%M:%S
addopts = -ra -q
pythonpath = .
```
### Сквозное тестирование агента (`agent_test.py`)
Для проверки работоспособности на **живой боевой телеметрии** разработан скрипт `agent_test.py`, который просто имитирует REST запросы на одинаковых случайновыбранных данных:
```bash
# Запуск сквозного прогона (36 сценариев)
python agent_test.py
# Подробный вывод каждого запроса и тела ответов
python agent_test.py -v
# Экспорт всех curl-команд в исполняемый bash-скрипт run_curls.sh
python agent_test.py --dump-sh
```
---
## 📂 Структура репозитория
```text
├── config.py # Типизированная конфигурация на Pydantic Settings
├── bus_stops_all.geojson # Реестр остановочных пунктов Москвы (data.mos.ru)
├── stops_repository.py # Поисковый индекс остановок (Spatial, ID, StationName)
├── transport_service.py # Оркестратор и бизнес-логика инструментов агента
├── server.py # Точка входа: FastAPI + MCP сервер
├── agent_test.py # Автоматизированный E2E-сьют проверки curl-сценариев
├── pytest.ini # Конфигурация запуска тестов
├── requirements.txt # Зависимости проекта
├── clients/ # Изолированные клиенты внешних транспортных API
│ ├── __init__.py
│ ├── moscow_transport_client.py # Клиент stop_v2 и qr-stop Московского транспорта
│ ├── rnis_client.py # Клиент РНИС МО (каталог, GPS, stop_point.list/routes)
│ └── yandex_client.py # Клиент Яндекс.Карт (Masstransit API)
└── tests/ # Набор модульных тестов
├── test_moscow_transport_client.py
├── test_rnis_client.py
├── test_stops_repository.py
├── test_transport_service.py
└── test_yandex_client.py
```
## Лицензия
MIT License. Свободно для использования, модификации и интеграции в AI-агентов.
---
### Перспективы
- Сделать нормальный `transport_service.py`, так как текущая реализация неэффективно работает со всеми тремя источникамиThis server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues