Skip to main content
Glama

deutschebahn_mcp

An MCP (Model Context Protocol) server for the Deutsche Bahn OpenBoards + OpenStation APIs. It lets an LLM agent look up live German train departures/arrivals by station name — no EVA numbers required, typos and umlauts tolerated.

What it does

  • getDepartureBoard — departure board for a station: time, line, destination, platform, delay (minutes), cancellation flag, notice count.

  • getArrivalBoard — same, for arrivals (origin instead of destination).

  • findStation — resolves a station name to its station record (name, EVA, DHID, StaDa). Returns a single match, a short list of options if the name is ambiguous (e.g. "Frankfurt" — Frankfurt (Main) Hbf vs. Frankfurt (Oder) are different cities), or "not found".

Station names are resolved automatically inside getDepartureBoard/getArrivalBoard too — you never need to look up an EVA number yourself. If a name is ambiguous, the tool returns the list of options instead of guessing, unless there's exactly one obvious main station ("Hbf") among same-city variants.

Optional filters on the board tools: ziel (destination/direction, substring match), zugart (fern / regio / sbahn), linie (line/train number, substring match).

Every result carries the source attribution Daten: DB InfraGO / Deutsche Bahn (OpenBoards API).

Related MCP server: ruter-connector

Example

You:    When does the next ICE leave Köln Hbf?
Claude: The next ICE from Köln Hbf is ICE 77 at 18:50, platform 1, running on time.

No EVA number, no manual lookup — Claude resolves "Köln Hbf" through the findStation logic built into getDepartureBoard and filters the board down to ICE services for you.

Requirements

  • Node.js >= 22

  • An account at the DB API Marketplace with an active subscription to both:

    • OpenBoards (departure/arrival boards)

    • OpenStation (station directory — needed for name resolution; without it you'd have to pass raw EVA numbers)

Getting DB API credentials

  1. Create an account at developers.deutschebahn.com.

  2. Go to Applications → Create new application and give it any name.

  3. On the application page, subscribe to the OpenBoards product.

  4. On the same application page, also subscribe to the OpenStation product (easy to miss — without it, station-name lookups won't work).

  5. Copy the generated Client ID and Client Secret for that application — these go into DB_OPENBOARDS_CLIENT_ID / DB_OPENBOARDS_CLIENT_SECRET below.

Install

git clone https://github.com/janoschLC/deutschebahn_mcp.git
cd deutschebahn_mcp
npm install
npm run build

Configure

Copy .env.example to .env and fill in your credentials, or set the environment variables directly in your MCP client config:

Variable

Required

Description

DB_OPENBOARDS_CLIENT_ID

yes

DB API Marketplace client ID

DB_OPENBOARDS_CLIENT_SECRET

yes

DB API Marketplace client secret

DB_OPENBOARDS_BASE_URL

no

Override the OpenBoards base URL

DB_OPENSTATION_BASE_URL

no

Override the OpenStation NeTEx endpoint

DB_OPENBOARDS_CACHE_PATH

no

Where the station-name cache is stored (default: ~/.cache/deutschebahn-mcp/stations.json)

DB_OPENBOARDS_DEFAULT_STATION

no

Station used when no station argument is given (default: Frankfurt Hbf)

The legacy variable names DB_TIMETABLE_CLIENT_ID / DB_TIMETABLE_CLIENT_SECRET are still accepted as a fallback for backward compatibility, but the DB_OPENBOARDS_* names above are the primary ones.

Add to your MCP client

Replace /absolute/path/to/deutschebahn_mcp with the path where you cloned this repo, and fill in your own credentials.

Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "deutschebahn": {
      "command": "node",
      "args": ["/absolute/path/to/deutschebahn_mcp/dist/index.js"],
      "env": {
        "DB_OPENBOARDS_CLIENT_ID": "your-client-id",
        "DB_OPENBOARDS_CLIENT_SECRET": "your-client-secret"
      }
    }
  }
}

Claude Code (.mcp.json in your project, or claude mcp add):

{
  "mcpServers": {
    "deutschebahn": {
      "command": "node",
      "args": ["/absolute/path/to/deutschebahn_mcp/dist/index.js"],
      "env": {
        "DB_OPENBOARDS_CLIENT_ID": "your-client-id",
        "DB_OPENBOARDS_CLIENT_SECRET": "your-client-secret"
      }
    }
  }
}

Cursor (.cursor/mcp.json):

{
  "mcpServers": {
    "deutschebahn": {
      "command": "node",
      "args": ["/absolute/path/to/deutschebahn_mcp/dist/index.js"],
      "env": {
        "DB_OPENBOARDS_CLIENT_ID": "your-client-id",
        "DB_OPENBOARDS_CLIENT_SECRET": "your-client-secret"
      }
    }
  }
}

Generic mcp_servers-style config (e.g. Hermes Agent):

mcp_servers:
  db_openboards:
    command: node
    args: ["/absolute/path/to/deutschebahn_mcp/dist/index.js"]
    env:
      DB_OPENBOARDS_CLIENT_ID: "your-client-id"
      DB_OPENBOARDS_CLIENT_SECRET: "your-client-secret"
      DB_OPENBOARDS_DEFAULT_STATION: "your-home-station"   # optional, see below

Set DB_OPENBOARDS_DEFAULT_STATION to whichever station you personally use most — just be aware that your default station lives only in your own private config, not in this repo. This project ships with a neutral example (Frankfurt Hbf) on purpose.

How it works

  • Station names → IDs: on first use, the server downloads the full German station directory from OpenStation (NeTEx XML, paginated) and caches it locally for 30 days — this keeps you far under the API's daily rate limit. Matching is typo- and umlaut-tolerant (Koeln → Köln, Tuebingen → Tübingen, no need to type Hbf).

  • Ambiguity handling: if a name matches multiple stations, the server returns the options unless exactly one of them is clearly the main station of that name (same-city satellite stops like Frankfurt-Nied or Frankfurt (Main) Süd don't block the automatic pick; a different city that happens to share the name, like Frankfurt (Oder), does).

  • Known DB quirk: a handful of large hubs (e.g. Hamburg, Frankfurt) have two valid EVA numbers for the same station — OpenStation and OpenBoards don't always agree on which one they report. The server tries both automatically when resolving destination/origin names back to text.

  • Known limitation: destinations outside Germany are not in the OpenStation directory, so they're shown as a raw EVA number instead of a name.

Development

npx tsc --noEmit
npm run build

This repository ships without a test suite.

License

MIT

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      C
      maintenance
      Provides real-time Belgian rail (SNCB/NMBS) data via the iRail API, enabling AI agents to query train schedules and live information.
      118 npm
      MIT
    • A
      license
      A
      quality
      C
      maintenance
      Enables AI agents to search for stops and stations across all Norwegian public transport and to fetch real-time departure data — planned versus expected times, delays, platform, operator, and disruption messages — with no API key required. Covers bus, tram, metro, train, and ferry nationwide through Entur's open APIs, with filtering by line, destination, and future departure time.
      2
      MIT
    • F
      license
      Not graded
      quality
      C
      maintenance
      Wraps four public railway APIs as 13 tools, 7 prompts and 5 resources, enabling an LLM client to answer live questions about station master data, timetables and timetable changes, elevator and escalator outages, and parking facilities and prognoses.
      2
      -
    • A
      license
      Not graded
      quality
      C
      maintenance
      Lets an AI assistant plan public transport journeys across Germany and other countries, with legs, platforms, delays and alerts, plus stop departures, full trip details, place search, and live DB station boards. Tickets and prices are not included.
      AGPL 3.0