Metadata-Version: 2.5
Name: db-fahrplan-mcp
Version: 0.2.2
Summary: MCP server for live Deutsche Bahn timetables: journeys, fares, boards, delays, platforms, coach sequence, disruptions. Talks to bahn.de directly, no API key. Unofficial.
Project-URL: Homepage, https://github.com/capraCoder/db-fahrplan-mcp
Project-URL: Repository, https://github.com/capraCoder/db-fahrplan-mcp
Project-URL: Issues, https://github.com/capraCoder/db-fahrplan-mcp/issues
Project-URL: Changelog, https://github.com/capraCoder/db-fahrplan-mcp/blob/main/CHANGELOG.md
Author: capraCoder
License-Expression: MIT
License-File: LICENSE
Keywords: bahn,claude,deutsche-bahn,fahrplan,llm-tools,mcp,model-context-protocol,railway,timetable,train
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: End Users/Desktop
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: httpx<1,>=0.25
Requires-Dist: mcp<3,>=1.10
Requires-Dist: pydantic>=2
Requires-Dist: tzdata; sys_platform == 'win32'
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == 'dev'
Requires-Dist: mypy>=1.11; extra == 'dev'
Requires-Dist: pytest-httpx>=0.30; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Requires-Dist: twine>=6; extra == 'dev'
Description-Content-Type: text/markdown

# db-fahrplan-mcp

[![PyPI](https://img.shields.io/pypi/v/db-fahrplan-mcp)](https://pypi.org/project/db-fahrplan-mcp/)
[![Python](https://img.shields.io/pypi/pyversions/db-fahrplan-mcp)](https://pypi.org/project/db-fahrplan-mcp/)
[![CI](https://github.com/capraCoder/db-fahrplan-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/capraCoder/db-fahrplan-mcp/actions/workflows/ci.yml)
[![bahn.de canary](https://github.com/capraCoder/db-fahrplan-mcp/actions/workflows/canary.yml/badge.svg)](https://github.com/capraCoder/db-fahrplan-mcp/actions/workflows/canary.yml)
[![License: MIT](https://img.shields.io/pypi/l/db-fahrplan-mcp)](LICENSE)

Live Deutsche Bahn timetables for Claude, Cursor, and any [MCP](https://modelcontextprotocol.io) 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.

## Install

**Claude Code**

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

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

```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**

```bash
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

```bash
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.

## Legal, honestly

Full text: [DISCLAIMER.md](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. Cloud/VPN IPs are sometimes blocked (HTTP 403).
- **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](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 0.2.2) [Software]. https://github.com/capraCoder/db-fahrplan-mcp

```bibtex
@software{capracoder_db_fahrplan_mcp_2026,
  author  = {{capraCoder}},
  title   = {db-fahrplan-mcp: Deutsche Bahn timetables as an MCP server},
  version = {0.2.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.
