- Python 95%
- Nix 5%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
Три задачи: найти ближайшее место, перевести адрес в координаты и обратно, объяснить дорогу словами. Главное — последнее. Навигаторская лента («через 180 м направо») человеку неудобна: метры на глаз он не меряет, зато видит вывески. Поэтому каждый поворот привязывается к заметному объекту у перекрёстка и к стороне, с которой тот окажется, а названия улиц склоняются. Источники спрятаны за общим протоколом. OSM (Nominatim, Overpass, OSRM) работает без ключей и стоит по умолчанию; Яндекс пока заготовка — написан по документации и вживую не проверялся. Co-Authored-By: Eva |
||
| maps_mcp | ||
| scripts | ||
| .gitignore | ||
| AGENTS.md | ||
| CHANGELOG.md | ||
| flake.lock | ||
| flake.nix | ||
| pyproject.toml | ||
| README.md | ||
maps-mcp
MCP-сервер карт: найти ближайшее место, перевести адрес в координаты и обратно, объяснить дорогу человеческими словами.
Главное здесь — последнее. Навигаторская лента («через 180 м направо») человеку неудобна: метры на глаз он не меряет, зато видит вывески. Поэтому сервер привязывает каждый поворот к заметному объекту у перекрёстка и к стороне, с которой тот окажется:
Проезжай 500 м по улице Льва Толстого — справа будет электроника «Miele»,
там поверни направо на Зубовскую улицу.
Едь 1,2 км по улице Пречистенка — по пути слева останется супермаркет
«Азбука daily» — слева будет остановка Метро «Кропоткинская»,
там возьми правее на Соймоновский проезд.
...
Ты на месте: Красная площадь. Ориентир — одежда «Bosco».
Инструменты
| Инструмент | Что делает |
|---|---|
maps_search |
Места вокруг точки: «аптека», «ближайшая пятёрочка», «кофейня». Ближайшие первыми, с адресом, часами и расстоянием. |
maps_geocode |
Адрес словами → координаты, разобранные по частям. |
maps_reverse |
Координаты → адрес. |
maps_route |
Дорога словами: directions — готовые фразы, steps — те же шаги числами. |
maps_providers |
Какие источники подключены и какой основной. |
maps_route принимает и адрес, и название места, и координаты строкой
(«55.7336, 37.5875»). Режимы: walk (по умолчанию), car, bike.
Общественного транспорта нет — его не умеет ни один из источников.
Источники
Выбираются переменной MAPS_PROVIDER, в отдельном вызове — параметром
provider.
osm (по умолчанию) — Nominatim, Overpass и OSRM. Ключей не требует.
База заведений в России неровная: сетевые точки местами не размечены, часы
работы есть не у всех. Публичные инстансы Overpass ограничивают частоту
запросов, поэтому зеркала перебираются по очереди, а неудача не роняет
маршрут — он просто описывается без ориентиров, и об этом сообщает поле note.
yandex — заготовка. Геокодер, Поиск по организациям и Router API v2
написаны по документации и вживую не проверялись: ключей не было. Прежде чем
включать, сверь разбор ответов с реальными. Отдельно учти, что Router API
отдаёт голую геометрию — ни манёвров, ни улиц в его ответе нет, поэтому
повороты вычисляются из ломаной, а улицы дозапрашиваются обратным геокодером.
Ориентиры и там берутся из Overpass: он отдаёт вывески вдоль всей ломаной
одним бесплатным запросом.
Настройки
| Переменная | Смысл |
|---|---|
MAPS_PROVIDER |
osm (по умолчанию) или yandex. |
MAPS_CITY |
Город, к которому привязан поиск без координат. |
MAPS_ORIGIN |
Точка «где я» (55.7336,37.5875) для поиска и старта маршрутов. |
MAPS_NOMINATIM_URL, MAPS_OVERPASS_URL, MAPS_OSRM_URL |
Свои инстансы вместо публичных. У Overpass — список через запятую. |
MAPS_USER_AGENT |
Кем представляться публичным сервисам. |
YANDEX_API_KEY |
Общий ключ Яндекса; отдельные — YANDEX_GEOCODER_KEY, YANDEX_PLACES_KEY, YANDEX_ROUTER_KEY. |
MAPS_ORIGIN стоит задать: без него «ближайшее» отсчитывается от центра
города, а маршруту без origin просто неоткуда стартовать.
MAPS_OSRM_URL ожидает раскладку FOSSGIS — сервер отвечает по путям
/routed-foot, /routed-car, /routed-bike. Демо-сервер router.project-osrm.org
не подходит: у него собран только автомобильный профиль, а пеший и
велосипедный он молча считает машиной.
Установка
Флейк даёт пакет, devShell и NixOS-модуль:
services.maps-mcp = {
enable = true;
city = "Москва";
origin = "55.7336,37.5875";
};
Модуль лишь ставит пакет и прокидывает настройки в окружение — сам сервер
работает по stdio, его запускает ядро (mcp.servers.maps.command = "maps-mcp").
Как устроено
maps_mcp/
server.py инструменты MCP
narrate.py пересказ маршрута словами: ориентиры, стороны, склейка шагов
morph.py склонение названий улиц («по Большому Чудову переулку»)
geo.py расстояния, курсы, стороны света, человеческие метры
models.py Place, Address, RouteStep, Route
providers/ источники за общим протоколом
Маршрут проходит через три стадии. Источник отдаёт шаги, compress_steps
склеивает те, между которыми ничего не происходит (маршрутизатор рвёт улицу на
каждой смене имени), затем enrich одним запросом добирает вывески у поворотов
и названия улиц для безымянных перегонов — пеший маршрут идёт по тротуарам, а
тротуар в OSM почти всегда безымянный. После этого narrate собирает фразы.
Ориентир выбирается не по близости, а по заметности: сетевую вывеску видно через дорогу, безымянную парикмахерскую — только вплотную. Один объект называется в маршруте один раз, иначе всю дорогу будешь «поворачивать у той же самой Пятёрочки».
Проверка
Тестов нет — всё интересное живёт в чужих API:
nix develop -c python scripts/smoke.py
Скрипт дёргает инструменты по настоящим картам и печатает ответы: глазами видно, не уехал ли формат и не развалился ли пересказ.