# norway-location-transport-mcp [Health: Active]

**Category:** 💻 Developer Tools  
**Repository:** https://github.com/trondbjoroy/norway-location-transport-mcp  
**GitHub Stars:** 0  
**npm Downloads (last month):** 220  
**Views:** 0  
**Installs:** 0  
**Upvotes:** 0  
**Directory Page:** https://allmcps.com/mcp/norway-location-transport-mcp

## Description
Norwegian transport (Entur) and geodata (Kartverket): trips, departures, addresses, elevation.

## Tools
Capabilities this server exposes over MCP:

- **valid**

## Claude Desktop Quick Installation
Install path detected from listing signals. Uses `npx` (confidence: high):

```json
"mcpServers": {
  "norway-location-transport-mcp": {
    "command": "npx",
    "args": ["-y","wrangler"]
  }
}
```

## Documentation & README

# norway-location-transport-mcp

An MCP server that gives AI agents structured access to Norwegian **public transport** and **geospatial** data, through the free [Entur](https://developer.entur.org/) and [Kartverket / Geonorge](https://www.kartverket.no/api-og-data) APIs.

The two sources compose: trip planning needs geocoding, elevation needs address resolution, and admin lookups tie coordinates to places. One server answers practical local questions — "how do I get from here to Bergen?", "what is the elevation along this hike?", "which kommune is this address in?", "are there e-scooters nearby?".

Both data sources are free with no paid tiers and no API keys. Entur requires only a self-identifying `ET-Client-Name` header (see below); Kartverket requires nothing.

## Tools

### Location & geodata (Kartverket)

- `search_address(query?, street?, number?, postal_code?, municipality_number?, max_results)` — search official addresses by free text or fields; supports the `*` wildcard. Returns coordinates and cadastral numbers.
- `find_addresses_near(latitude, longitude, radius_m, max_results)` — all addresses within a radius of a point, with distances.
- `validate_address(address)` — validate and normalize a free-text address (fuzzy). Returns `valid`, the normalized match, and alternatives.
- `search_place_names(query, max_results)` — search official place names; returns feature type (Fjell, Innsjø, …), municipality, county, and coordinates. Supports `*`.
- `find_place_names_near(latitude, longitude, radius_m, max_results)` — nearest named features to a point, with distances.
- `get_elevation(latitude, longitude)` — terrain elevation from the national elevation model (DTM).
- `get_elevation_profile(path, samples)` — elevation sampled along a path; returns the profile plus total distance, ascent, and descent.
- `transform_coordinates(x, y, from_epsg, to_epsg)` — convert between reference systems (e.g. WGS84 4326 → UTM33 25833).
- `lookup_admin_unit(latitude?, longitude?, address?)` — which kommune and fylke a coordinate or address falls in, with official codes.
- `lookup_property(address?, latitude?, longitude?, max_results)` — cadastral (matrikkel) identifiers (kommune / gnr / bnr / fnr) via the open address register.

### Public transport (Entur)

- `resolve_stop_place(query, max_results)` — resolve a place or address to Entur Stop Place IDs.
- `find_stops_near(latitude, longitude, radius_m, max_results)` — reverse-geocode a coordinate to the nearest stop places.
- `plan_trip(from_place?/from_latitude/from_longitude, to_place?/to_latitude/to_longitude, date_time?, arrive_by?, transport_modes?, walk_speed?, num_trip_patterns)` — plan a point-to-point journey; filter by mode and walk speed. Returns trip patterns with legs, modes, durations, and realtime times.
- `get_departures(stop_place_id, count)` — next departures from a stop, with realtime delays, cancellations, and platform.
- `get_realtime_status(stop_place_id? | line_id?)` — realtime health: for a stop, on-time/delayed/cancelled counts; for a line, active vehicles and delays.
- `get_stop_accessibility(stop_place_id)` — per-quay wheelchair access and a summary. (See the accessibility note below.)
- `list_quays(stop_place_id)` — all quays (platforms) at a stop, with codes and coordinates.
- `get_fare_zones(stop_place_id)` — the fare (tariff) zone(s) a stop belongs to.
- `find_shared_vehicles(latitude, longitude, range_m, form_factors?, count)` — free-floating shared vehicles (bikes, e-scooters, cars, mopeds) across all operators.
- `find_docking_stations(latitude, longitude, range_m, count)` — docking stations with available vehicle and free-dock counts.
- `get_vehicle_positions(codespace_id?, line_id?, max_results)` — live vehicle positions with bearing, speed, and delay.

Tool definitions live in `src/kartverket.ts` and `src/entur.ts`, combined in `src/tools.ts` and shared by both the stdio and HTTP entry points.

## Setup

```bash
npm install
npm run build
npm test
```

`npm test` spawns the server over stdio and calls every tool against the live APIs.

### Run it

Over **stdio** (for most MCP clients):

```bash
node dist/index.js
```

Over **Streamable HTTP** (for HTTP-based clients):

```bash
node dist/http.js
# listens on http://localhost:3000/mcp  (override with PORT)
```

## The Entur client-name requirement

Entur's terms require every request to carry an identifying `ET-Client-Name` header, formatted like `company-app`. This server sends one on every Entur request. Set your own value with the `ET_CLIENT_NAME` environment variable:

```bash
ET_CLIENT_NAME="acme-travelbot" node dist/index.js
```

If unset, a package default is used. Kartverket needs no header or key.

## Use with Claude Code

```bash
claude mcp add norway -- node C:\Users\trond\norway-location-transport-mcp\dist\index.js
```

Then ask, for example: "Plan a trip from Oslo S to Bergen and tell me the elevation of Galdhøpiggen."

## Remote version (Cloudflare Workers)

`worker/` holds a remote deployment: the same 21 tools served over MCP Streamable HTTP, so the server can be added as a claude.ai connector. It shares the tool definitions with the local server (`src/tools.ts` takes `z` as a parameter, so it works with both the local MCP SDK v1 / zod 3 and the worker's SDK v2 / zod 4).

```bash
cd worker
npm install
npm run dev     # local test at http://127.0.0.1:8787/mcp
node test-http.mjs
```

Deploy it (needs a Cloudflare account and `wrangler login`):

```bash
cd worker
npm run deploy
```

Set your Entur client name as a worker variable:

```bash
cd worker
npx wrangler secret put ET_CLIENT_NAME
```

After deploy, add the `remotes` entry with your `workers.dev` URL to `server.json`.

## Example calls

Get the next departures from Oslo S:

```json
{ "name": "get_departures", "arguments": { "stop_place_id": "NSR:StopPlace:59872", "count": 5 } }
```

Plan a bus/tram-only trip with a set walk speed:

```json
{ "name": "plan_trip", "arguments": {
  "from_place": "NSR:StopPlace:59872",
  "to_latitude": 59.95, "to_longitude": 10.78,
  "transport_modes": ["bus", "tram"], "walk_speed": 1.4
} }
```

Elevation profile along a short path:

```json
{ "name": "get_elevation_profile", "arguments": {
  "path": [{ "latitude": 61.636, "longitude": 8.312 }, { "latitude": 61.64, "longitude": 8.32 }],
  "samples": 20
} }
```

Convert a WGS84 coordinate to UTM33:

```json
{ "name": "transform_coordinates", "arguments": { "x": 10.7461, "y": 59.9127, "from_epsg": 4326, "to_epsg": 25833 } }
```

## Notes and limits

- **Coordinates** are WGS84 latitude/longitude everywhere. The Kartverket APIs are queried with EPSG 4326 so the numbers match; EUREF89 (4258) differs by well under a metre in Norway.
- **Accessibility**: Entur's free JourneyPlanner exposes wheelchair access per quay. Deeper equipment detail (elevators, tactile guidance) lives only in Entur's authenticated Stop Register API and is not available here; the tool says so.
- **Rate limiting** from either source is surfaced as a clear error asking the agent to retry.
- **Attribution**: data from Kartverket / Geonorge and Entur is under NLOD. Credit the sources when you show the data.

## How it works

- `src/index.ts` speaks MCP over stdio (JSON-RPC on stdin/stdout). `src/http.ts` speaks MCP over Streamable HTTP with session management. Both build the same server via `src/server.ts`.
- Each tool declares a Zod input schema with descriptions the LLM reads directly — no external docs needed to call a tool.
- Results are JSON text trimmed to what an agent needs, not the raw upstream payloads.
- Never write to stdout with `console.log`; it corrupts the stdio protocol. Log to stderr.

## License

MIT © Trond Bjørøy. Data © Kartverket and Entur, under NLOD.

