Skip to main content
Glama

db-fahrplan-mcp

PyPI Python CI bahn.de canary License: MIT Glama score

Status, 2026-10-13: currently blocked by bahn.de. bahn.de answers this tool's requests (station search, departure boards, journeys) with HTTP 403 OPS_BLOCKED, from a residential connection too. The tool reports the block with bahn.de's reference and does not work around it: this project stays an honest client (see Legal, honestly). Until bahn.de lets it through again, use bahn.de or the DB Navigator app.

Live Deutsche Bahn timetables for Claude, Cursor, and any MCP client: connections, every fare option, cheapest time of day, departure boards, delays, platform changes, all stops of a train, coach sequence, stations near you.

It talks directly to the JSON endpoints behind bahn.de — the same ones the website uses. No API key. No proxy. No third-party mirror to go down. You get what bahn.de shows, including real-time data.

uvx db-fahrplan-mcp

What it can answer

Question

Tool

"Krefeld to Köln Messe, there by 8 on Sunday"

db_journeys (arrive_by)

"…with my BahnCard 50, two kids, bike, max one change, via Düsseldorf"

db_journeys (bahncard, children_ages, bike, max_transfers, via)

"Only Deutschlandticket trains"

db_journeys (deutschlandticket)

"What tickets exist for that 09:35, and what do they cost?"

db_journey_offers — Super Sparpreis / Sparpreis / Flexpreis / regional day tickets

"When is it cheapest to go to Berlin on the 12th?"

db_best_price — per time band of the day

"What leaves Köln Hbf in the next 30 min?"

db_departures / db_arrivals — live, with delay, platform change, cancellation

"Where is ICE 555 right now? Does it still stop at Hagen?"

db_trip_details — every stop, live

"Which sector do I stand in for 1st class on ICE 109?"

db_train_formation — coach sequence and platform sectors

"Stations near 50.94, 6.96"

db_nearby

"Is 'Frankfurt Flughafen' the Fernbahnhof or Regionalbahnhof?"

db_search_station

Every journey carries a recon_token (→ fares), every leg and board row a journey_id (→ stops). Times are Europe/Berlin wherever the server runs; (+7) means 7 minutes late; (+1d) means after midnight. Occupancy (load), amenities (WiFi, bike, step-free, quiet zone…), real-time platforms and disruption notes are included.

Related MCP server: webharvest

Install

Claude Code

claude mcp add db-fahrplan -s user -- uvx db-fahrplan-mcp

Claude Desktop / Cursor / any MCP client — claude_desktop_config.json:

{
  "mcpServers": {
    "db-fahrplan": {
      "command": "uvx",
      "args": ["db-fahrplan-mcp"]
    }
  }
}

No uv? pipx install db-fahrplan-mcp or pip install db-fahrplan-mcp, then use "command": "db-fahrplan-mcp".

Remote / HTTP

db-fahrplan-mcp --transport streamable-http --host 127.0.0.1 --port 8000

Binds to localhost by default. Put it behind a reverse proxy with auth before exposing it.

Example

Krefeld Hbf → Köln Messe/Deutz, arrive by 08:00 Sunday

db_journeys("Krefeld Hbf", "Köln Messe/Deutz", "2026-08-30 08:00", arrive_by=true, format="text")

Krefeld Hbf → Köln Messe/Deutz, arrive by 2026-08-30 08:00 (Europe/Berlin)

06:35 → 07:23 · 48 min · 0× change · 25.80 €
   RE7       Krefeld Hbf 06:35 Gl.5 → Köln Messe/Deutz 07:23 Gl.1

…and on a bad day (real output, signal-box failure at Montabaur):

15:53 → 17:09 · 76 min · 0× change
   ICE 125   Köln Hbf 15:53 Gl.2 A-C → Frankfurt(Main)Hbf 17:09 Gl.1 CANCELLED
      ! Ein defektes Stellwerk im Raum Montabaur beeinträchtigt den Bahnverkehr …
   ! Verbindung fällt aus

format="text" is compact and cheap in tokens; format="json" (default) is structured.

Configuration

Env var

Default

DB_FAHRPLAN_RATE_PER_MIN

30

Token-bucket limit on requests to bahn.de

DB_FAHRPLAN_TIMEOUT

30

HTTP timeout, seconds

DB_FAHRPLAN_LOG

WARNING

Log level (stderr)

DB_FAHRPLAN_BASE_URL

https://www.bahn.de/web/api

For testing against a mock

How it compares

db-fahrplan-mcp

DB API Marketplace servers¹

transport.rest wrappers²

API key

none

client id + secret

none (shared 100 req/min)

Journey planning

✅

❌ (timetables only)

✅

Prices, fare breakdown, best-price day

✅

❌

❌

BahnCard / children / via / bike / max changes

✅

❌

partial

Occupancy, amenities, coach sequence

✅

❌

❌

Real-time delays, platform changes, cancellations

✅

✅

✅

Runs offline tests, weekly live canary

✅

–

–

¹ e.g. PaulvonBerg/db-mcp-server, jorekai/db-timetable-mcp. ² e.g. AnythingMCP's DB connector.

Development

git clone https://github.com/capraCoder/db-fahrplan-mcp && cd db-fahrplan-mcp
python -m pip install -e ".[dev]"
pytest              # offline, replays recorded bahn.de responses (tests/fixtures)
pytest -m live      # hits bahn.de — Krefeld→Garmisch multi-modal trip, fares, best price, boards
ruff check . && mypy

CI runs on Linux + Windows, Python 3.10–3.13, on both MCP SDK 1.x and 2.x. A weekly canary runs the live tests and opens an issue if bahn.de changes something.

Full text: DISCLAIMER.md. The short version:

  • Unofficial. Not affiliated with, endorsed by, or supported by Deutsche Bahn AG. "Deutsche Bahn" and "DB" are trademarks of Deutsche Bahn AG. The software ships no DB data and performs no systematic extraction — each query fetches only what the user asked for.

  • Undocumented endpoints. bahn.de can change or block them at any time. The canary will notice within a week; please open an issue with the raw response if you hit it first.

  • bahn.de's terms of use restrict automated access. This is a personal, non-commercial tool with an honest User-Agent and a rate limiter (30 req/min by default). Use it for yourself; do not build a scraping farm on it. bahn.de can refuse requests (HTTP 403) from cloud/VPN addresses or from this tool itself, on any network. The tool reports the block with bahn.de's reference and stops; it does not work around blocks.

  • Prices are informational, as bahn.de quotes them for the given travellers at that moment. Booking happens on bahn.de.

  • Timetable changes (mid-December, mid-June) can make far-future queries temporarily odd.

  • No liability for missed connections or wrong fares — see DISCLAIMER.md.

Citing

If this server is part of published work, cite it (metadata in CITATION.cff; GitHub's "Cite this repository" button renders it):

capraCoder (2026). db-fahrplan-mcp: Deutsche Bahn timetables as an MCP server (Version 1.0.1) [Software]. https://github.com/capraCoder/db-fahrplan-mcp

@software{capracoder_db_fahrplan_mcp_2026,
  author  = {{capraCoder}},
  title   = {db-fahrplan-mcp: Deutsche Bahn timetables as an MCP server},
  version = {1.0.1},
  year    = {2026},
  url     = {https://github.com/capraCoder/db-fahrplan-mcp}
}

Release artifacts carry OpenTimestamps proofs (*.ots, Bitcoin-anchored): existence and integrity are provable without any third-party archive.

Licence

MIT.

Available Tools

9 tools
db_arrivalsArrival boardC
Read-onlyIdempotent

Live arrival board, same shape as db_departures (direction = origin).

Inputs: station (required), when, format, minutes, +1 more. Returns: result

db_best_priceCheapest fares across a dayA
Read-onlyIdempotent

Bestpreissuche: the cheapest available fare in each time band of a day (00–07, 07–10, 10–13, 13–16, 16–19, 19–24) with the connection it applies to. Use for 'when is it cheapest to go'. Typically only meaningful for long-distance routes booked in advance.

Inputs: date (required), to_station (required), from_station (required), adults, +4 more. Returns: result

db_departuresDeparture boardA
Read-onlyIdempotent

Live departure board: time (real-time, with delay), line, destination, platform (real-time, platform_changed flag), cancellation, disruption notes, and journey_id for db_trip_details.

Inputs: station (required), when, format, minutes, +1 more. Returns: result

db_journey_offersFare options for one journeyA
Read-onlyIdempotent

All fares bahn.de offers for ONE specific connection (Super Sparpreis, Sparpreis, Flexpreis, regional day tickets…) with price and class, re-checked live. Use after db_journeys when the user asks 'how much' or 'cheapest ticket'. Prices are informational, not a booking.

Inputs: recon_token (required), adults, bahncard, first_class, +1 more. Returns: result

db_journeysPlan a journeyA
Read-onlyIdempotent

Plan train connections between two stations with live bahn.de data.

Each connection: dep/arr (real-time; '(+7)' = 7 min late, '(+1d)' = next day), duration, changes, price in EUR for the given travellers/BahnCard (None with Deutschlandticket), load (occupancy) per class, recon_token (pass to db_journey_offers for Sparpreis/Flexpreis breakdown), and per leg: line, platforms (real-time, with *_platform_changed), stops count, amenities (WiFi, bike, step-free…), cancellations, journey_id (pass to db_trip_details), and disruption notes. A journey flagged alternative is DB's re-route around a disruption.

Inputs: to_station (required), from_station (required), via, bike, +13 more. Returns: result

db_nearbyStations near coordinatesA
Read-onlyIdempotent

Stations and stops around a GPS position — 'stations near me'. Returns name, EVA number, products, and the bahn.de id usable in every other tool.

Inputs: latitude (required), longitude (required), radius_m, rail_only, +1 more. Returns: result

db_search_stationSearch stationsA
Read-onlyIdempotent

Find Deutsche Bahn stations by name. Call this only when a name is ambiguous or another tool rejected it; the other tools accept plain station names directly. Returns name, EVA number (eva), products served, and the full bahn.de id (also accepted by other tools).

Inputs: query (required), include_stops. Returns: result

db_train_formationCoach sequence (Wagenreihung)A
Read-onlyIdempotent

Coach order and platform sectors for a long-distance train at a station: which sector (A–G) 1st class, bistro, bike and quiet coaches stop at, and the real-time platform. Answers 'where do I stand on the platform'. ICE/IC/EC only; not available for regional trains.

Inputs: when (required), train (required), station (required). Returns: result

db_trip_detailsTrip details (all stops, live)A
Read-onlyIdempotent

Every stop of one specific train run with scheduled and real-time arrival/departure, platform (real-time), load, and notes — i.e. 'where is this train now, is my stop still served, which platform at my stop'. Also returns train amenities and running days.

Inputs: journey_id (required), format. Returns: result

Tool Schema Changelog

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

Loading tool schema changelog…

    TDQS

    A3.8/5.0

    Scored across 9 tools

    Disambiguation4/5

    Each tool targets a distinct task: station search, journey planning, fare offers, best-price search, departures, arrivals, trip details, nearby stations, and train formation. The only mild overlap is between db_journey_offers and db_best_price (both fare-related), but their specific purposes and usage cues keep them distinguishable.

    Naming Consistency4/5

    All tools consistently use the `db_` prefix and clear domain vocabulary. Minor inconsistency: `db_search_station` is verb-based while most others are noun phrases (`db_journeys`, `db_departures`), but the overall pattern is still predictable and readable.

    Tool Count5/5

    Nine tools is well-scoped for a rail travel information server. Each tool covers a distinct user need without unnecessary duplication or overwhelming breadth.

    Completeness5/5

    The tool set covers the full journey information workflow: station discovery by name or GPS, journey planning, fare comparison, live departures/arrivals, per-trip stop details, and train formation. There are no obvious dead ends or significant missing operations for the stated domain.

    Maintenance

    ActivityMaintained
    ResponsivenessLimited data

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      Not graded
      quality
      D
      maintenance
      Enables MCP-compatible clients to scrape and extract data from live websites using a headless Chromium browser, with support for CSS selectors, link extraction, table extraction, and Amazon product pages.
      -
    • A
      license
      B
      quality
      B
      maintenance
      Enables MCP clients to run live web searches, fetch and navigate readable web pages, search images, capture PDF screenshots, and retrieve finance, weather, sports, and world-time data through a zero-configuration authenticated backend.
      11
      8 npm
      MIT