Skip to main content
Glama
kimhjort

aria-mcp-drivetime-dk

by kimhjort
README.md
# aria-mcp-drivetime-dk

A [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server that computes car driving time and distance between two places in Denmark, plus a "leave by" time for appointments. Built for [ARIA](https://github.com/kimhjort/aria) and shareable with the community.

**Fully keyless** — uses public OpenStreetMap services with no API key required.

Example output ARIA might give Kim:
> *Horsens → Billund Lufthavn er ~48 min (67 km) — kør senest 11:02 for at nå 12:00 (inkl. 10 min buffer)*

## Data Sources

| Source | What | Policy / Attribution |
|---|---|---|
| [Nominatim](https://nominatim.openstreetmap.org) | Geocoding — place name → lat/lon | © [OpenStreetMap contributors](https://www.openstreetmap.org/copyright) (ODbL). [Usage policy](https://operations.osmfoundation.org/policies/nominatim/): max 1 req/s, descriptive User-Agent required |
| [OSRM demo server](https://router.project-osrm.org) | Road routing — distance + duration | © OpenStreetMap contributors. [Demo server](https://router.project-osrm.org): ~1 req/s, non-commercial use only |

**No live traffic.** Duration is typical free-flow routing time. For production or traffic-aware routing, self-host OSRM or use a paid provider (e.g. Google Maps Routes API, HERE, Mapbox).

## Install & Run

```bash
npx aria-mcp-drivetime-dk
```

Or install globally:

```bash
npm install -g aria-mcp-drivetime-dk
aria-mcp-drivetime-dk
```

Requires Node.js 20 or later.

## Tools

### `drive_time`

Compute car driving distance and typical travel time between two Danish places.

**Parameters:**

| Name | Type | Required | Description |
|---|---|---|---|
| `from` | string | Yes* | Origin — place name, address, or `"lat,lon"` |
| `to` | string | Yes | Destination — place name, address, or `"lat,lon"` |
| `arriveBy` | string | No | Arrival time — ISO datetime (`"2026-06-12T12:00"`) or `"HH:MM"` for today (Copenhagen time) |
| `bufferMin` | number | No | Extra buffer minutes for leave-by (default `DEFAULT_BUFFER_MIN`, typically 10) |

*Not required when `DEFAULT_ORIGIN` env var is set.

**Returns:**

```json
{
  "fromResolved": "Horsens, Horsens Kommune, Region Midtjylland, Danmark",
  "toResolved": "Billund Lufthavn, ...",
  "distanceKm": 67.4,
  "durationMin": 48,
  "leaveByLocal": "2026-06-12T11:02",
  "arriveByLocal": "2026-06-12T12:00",
  "bufferMin": 10,
  "notice": "Duration is typical/free-flow driving time from OSRM routing — does NOT include live traffic. Allow extra time during rush hours or adverse weather."
}
```

`leaveByLocal`, `arriveByLocal`, and `bufferMin` are only present when `arriveBy` is given.

---

### `geocode`

Resolve a Danish place name or address to geographic coordinates.

**Parameters:**

| Name | Type | Required | Description |
|---|---|---|---|
| `query` | string | Yes | Place name or address to look up |

**Returns:**

```json
{
  "lat": 55.8607,
  "lon": 9.8502,
  "displayName": "Horsens, Horsens Kommune, Region Midtjylland, Danmark"
}
```

---

### `leave_by`

Convenience wrapper — same as `drive_time` but requires `arriveBy` explicitly and is named to signal intent.

**Parameters:** `from` (optional with default), `to`, `arriveBy` (required), `bufferMin` (optional)

**Returns:** Same as `drive_time` with `arriveBy` — always includes `leaveByLocal`.

---

## Environment Variables

| Variable | Default | Description |
|---|---|---|
| `DEFAULT_ORIGIN` | *(none)* | Default origin place (e.g. `"Horsens"`). Makes `from` optional in `drive_time` and `leave_by`. |
| `DEFAULT_BUFFER_MIN` | `10` | Buffer minutes subtracted when computing `leaveByLocal`. |
| `NOMINATIM_URL` | `https://nominatim.openstreetmap.org` | Override Nominatim base URL (for self-hosting). |
| `OSRM_URL` | `https://router.project-osrm.org` | Override OSRM base URL (for self-hosting or a traffic-aware provider). |

## ARIA MCP Config

Add to your ARIA credentials / MCP config to use with ARIA:

```json
{
  "command": "npx",
  "args": ["-y", "aria-mcp-drivetime-dk"],
  "env": {
    "DEFAULT_ORIGIN": "Horsens"
  }
}
```

With this config, `from` defaults to Horsens in all tools. Kim can ask ARIA "Hvornår skal jeg køre for at nå Billund Lufthavn til 12:00?" without specifying an origin.

## Important Caveats

- **No live traffic.** OSRM demo server provides free-flow routing only. Actual travel time may differ significantly during rush hours, holidays, road works, or bad weather.
- **Demo server limits.** The public Nominatim and OSRM demo servers are rate-limited (~1 req/s) and intended for light, non-commercial use. For production workloads, self-host or use a commercial routing API.
- **Self-hosting.** Set `NOMINATIM_URL` and `OSRM_URL` environment variables to point at your own instances.

## Development

```bash
git clone https://github.com/kimhjort/aria-mcp-drivetime-dk
cd aria-mcp-drivetime-dk
npm install
npm run build
npm test
```

## License

MIT — see [LICENSE](LICENSE).

Map data © [OpenStreetMap contributors](https://www.openstreetmap.org/copyright), licensed under the [Open Database Licence (ODbL)](https://opendatacommons.org/licenses/odbl/).

TDQS

A4/5.0

Scored across 3 tools

Disambiguation3/5

drive_time and leave_by overlap significantly, as leave_by is explicitly a wrapper for drive_time with arriveBy. However, the descriptions clarify their relationship and distinct use cases, so an agent can differentiate them with careful reading.

Naming Consistency2/5

Naming is inconsistent: 'drive_time' and 'leave_by' use underscores, while 'geocode' does not. The verb styles also differ (verb_noun, verb_preposition, single verb), making the pattern unpredictable.

Tool Count5/5

Three tools is appropriate for the domain: geocode for place resolution, drive_time for core computation, and leave_by as a convenience wrapper. Each tool serves a clear purpose and no tool is redundant.

Completeness4/5

The tool set covers the essential workflow: resolving addresses, computing drive time, and arriving by a deadline. Minor gaps exist, such as lack of batch or alternative routes, but these are not critical for the primary use case.

Maintenance

ActivityMaintained
ResponsivenessSyncing