Skip to main content
Glama
README.md
# lux-nav

Open navigation for Luxembourg, built for people **and AI agents**: walking,
cycling, e-bike, Vel'OH! bike share and public transport, with hill-aware
timings, because Luxembourg is hilly.

- **MCP endpoint for AI agents:** `https://lux-nav.lisel-hub.workers.dev/mcp`
  (Streamable HTTP, stateless, no sign-up)
- **REST API:** the same host, under `/v1/…`

> **Unofficial project.** Not affiliated with mobiliteit.lu, the public
> transport administration, Vel'OH!/JCDecaux or the City of Luxembourg.

## For AI agents

Add the MCP endpoint as a remote MCP server in Claude, ChatGPT or any MCP
client. The server supplies its own instructions; places can be names
("Hamilius", "Maison du Savoir, Belval") or `lat,lon`.

| Tool | What it does |
| --- | --- |
| `plan_trip` | Compares walking, cycling, e-bike, Vel'OH! and public transport between two places: time, distance, climbing, live bikes and docks, next departures. |
| `get_route` | Turn-by-turn walking, cycling or e-bike directions, with climb, descent and elevation range. |
| `search_places` | Addresses, stops, buildings and landmarks in and around Luxembourg. |
| `bike_share_near` | Nearest Vel'OH! stations with live bikes, e-bikes and free docks. |
| `departures_near` | Live departures from the nearest bus, tram or train stop. |

Example prompt: *"I'm at the Gare and need to be at the Philharmonie in 20
minutes. Should I walk or take a Vel'OH!?"*

## REST API

```
GET /v1/places?q=Hamilius&lang=en
GET /v1/reverse?at=lat,lon
GET /v1/plan?from=49.6000,6.1334&to=49.6185,6.1440[&modes=walk,bike,ebike,bikeshare,transit]
GET /v1/route?from=lat,lon&to=lat,lon&mode=walk|bike|ebike
GET /v1/bikeshare[?near=lat,lon]
GET /v1/departures?near=lat,lon
```

Responses are JSON. CORS is open, and each client may make 30 requests per
minute.

## How it works

lux-nav runs on Cloudflare Workers. It doesn't run its own routing engine;
it combines open services and caches their responses:

| Data | Source |
| --- | --- |
| Places | [Photon](https://photon.komoot.io) (OpenStreetMap) |
| Walking and cycling routes | [FOSSGIS OSRM](https://routing.openstreetmap.de) (OpenStreetMap foot and bike profiles) |
| Elevation and climbing | [Open-Meteo Elevation API](https://open-meteo.com/en/docs/elevation-api) |
| Vel'OH! availability | [CityBikes](https://api.citybik.es) |
| Live departures | [mobiliteit-lu-mcp](https://github.com/dataoli22/mobiliteit-lu-mcp) (mobiliteit.lu open data), called over MCP |

Durations add an uphill penalty: about 1 minute per 10 m climbed on foot, per
12 m by bike, and per 40 m on an e-bike. E-bike riding is estimated 20 %
faster than a regular bike. Vel'OH! bikes are electric-assisted and are timed
that way.

### Known limits

- **Public transport:** mobiliteit.lu's open data provides departures but no
  journey planner, so lux-nav shows the nearest stop and its live departures,
  not a full bus or train itinerary.
- **Fair use:** the upstream services are free, shared and rate-limited.
  At scale, lux-nav should run its own routing and geocoding instances; the
  provider modules in `src/providers/` are built to be swapped.

## Development

```sh
npm install
npx wrangler types
npm test
npx wrangler dev
```

Live departures need `MOBILITEIT_MCP_TOKEN` (a `wrangler secret`) for the
endpoint configured in `MOBILITEIT_MCP_URL`.

## Licence

Code: [Apache-2.0](./LICENSE). Data © OpenStreetMap contributors (ODbL) and
the respective providers.