[!NOTE] vibe-coded ✨
hafasmcp
MCP server for real-time German public transport data via HAFAS. Lets Claude (or any MCP client) query departures, arrivals, journeys, and nearby stops — currently configured for the VBN network (Lower Saxony / Bremen).
No API key needed. Uses the same public HAFAS API as fahrplaner.vbn.de.
Tools
| Tool | Description | |------|-------------| | locations | Search stops, addresses, or POIs by name | | departures | Upcoming departures from a stop | | arrivals | Upcoming arrivals at a stop | | journeys | Route planning between two locations | | nearby | Find stops near a coordinate |
Quick Start
With Claude Code (stdio)
Add to your MCP config:
{
"mcpServers": {
"hafas": {
"command": "node",
"args": ["dist/index.js"],
"cwd": "/path/to/hafasmcp"
}
}
}
With Docker (HTTP + OAuth 2.1)
cp .env.example .env
docker compose up -d
This starts the HTTP server on port 3000 with a Cloudflare quick tunnel for remote access.
Local Development
npm install
npm run build
npm start # stdio mode
npm run start:http # HTTP mode with OAuth 2.1
Environment Variables
| Variable | Default | Description | |----------|---------|-------------| | PORT | 3000 | HTTP server port | | ISSUER_URL | http://localhost:$PORT | OAuth 2.1 issuer URL |
How It Works
The server wraps hafas-client with the VBN profile and exposes it as MCP tools. Two transport modes:
- Stdio — for local MCP clients like Claude Code, zero config
- HTTP — for remote access, with full OAuth 2.1 (dynamic client registration, PKCE, auto-approve)
Example
Ask Claude:
"Wann fährt die nächste Straßenbahn vom Hauptbahnhof Bremen?"
Claude will use locations to find the stop ID, then departures to get real-time data — all in under a second.
Stack
TypeScript, Node.js, hafas-client, @modelcontextprotocol/sdk, Express 5
License
ISC












