db-fahrplan
This server gives live Deutsche Bahn timetable, journey planning, fare, and station information to MCP clients like Claude or Cursor.
Plan journeys with live times, delays, duration, changes, and prices
Get fare options and cheapest time bands for a travel day
Show live departure and arrival boards with cancellations and platform changes
Retrieve full trip details: all stops, live status, amenities, running days
Get coach sequence and platform sectors for long-distance trains
Search stations by name or find stations near GPS coordinates
Filter journeys by BahnCard, children, bike, max transfers, via stations, first class, or Deutschlandticket
Return results as compact text or structured JSON
Provides access to live Deutsche Bahn timetable data, including station search, journey planning, departure and arrival boards, platforms, delays, Flexpreis fares, and disruption notices.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@db-fahrplanShow me trains from Munich to Frankfurt tomorrow morning."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
db-fahrplan-mcp
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-mcpWhat it can answer
Question | Tool |
"Krefeld to Köln Messe, there by 8 on Sunday" |
|
"…with my BahnCard 50, two kids, bike, max one change, via Düsseldorf" |
|
"Only Deutschlandticket trains" |
|
"What tickets exist for that 09:35, and what do they cost?" |
|
"When is it cheapest to go to Berlin on the 12th?" |
|
"What leaves Köln Hbf in the next 30 min?" |
|
"Where is ICE 555 right now? Does it still stop at Hagen?" |
|
"Which sector do I stand in for 1st class on ICE 109?" |
|
"Stations near 50.94, 6.96" |
|
"Is 'Frankfurt Flughafen' the Fernbahnhof or Regionalbahnhof?" |
|
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: ÖPNV MCP Server
Install
Claude Code
claude mcp add db-fahrplan -s user -- uvx db-fahrplan-mcpClaude 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 8000Binds 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 ausformat="text" is compact and cheap in tokens; format="json" (default) is structured.
Configuration
Env var | Default | |
|
| Token-bucket limit on requests to bahn.de |
|
| HTTP timeout, seconds |
|
| Log level (stderr) |
|
| 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 . && mypyCI 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. 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-Agentand 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.
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.0) [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 = {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.
Available Tools
9 toolsdb_arrivalsArrival boardCRead-onlyIdempotent
Live arrival board, same shape as db_departures (direction = origin).
| Name | Required | Description | Default |
|---|---|---|---|
| when | No | 'YYYY-MM-DD HH:MM' Europe/Berlin; omit for now | |
| format | No | json | |
| minutes | No | ||
| station | Yes | Station name, EVA number, or bahn.de id | |
| rail_only | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the operation read-only and idempotent, so the description does not need to repeat those. It adds useful context by calling the board 'live' and clarifying that direction is interpreted as origin, which helps distinguish arrival semantics from departures. Beyond that, no additional behavioral traits such as pagination or data freshness are disclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single concise sentence with no filler and is easy to parse. However, the brevity comes at the cost of missing parameter and usage details, so it is under-specified rather than optimally concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With five parameters and a low schema coverage, the description should provide more context than it does. The pointer to db_departures helps, but the description still leaves key invocation details such as time window, format, rail-only filtering, and when-to-use semantics to be inferred.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 40%, and the description does not compensate by explaining minutes, format, rail_only, or station. The phrase 'same shape as db_departures' may hint at output structure, but it adds little meaning to the actual parameters and leaves several fields underspecified.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the tool as a live arrival board and distinguishes it from the sibling db_departures by adding 'direction = origin'. However, it relies on a noun phrase rather than a specific action verb like 'list' or 'retrieve', so it is clear but not maximally explicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to use this tool versus alternatives. The reference to db_departures implies a relationship, but it does not state when arrivals are appropriate, when departures should be used, or any exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
db_best_priceCheapest fares across a dayARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| date | Yes | 'YYYY-MM-DD' — the travel day | |
| adults | No | ||
| bahncard | No | ||
| to_station | Yes | ||
| first_class | No | ||
| from_station | Yes | ||
| children_ages | No | ||
| regional_only | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, and idempotentHint, covering safety and repeatability. The description adds useful behavioral context: results are organized by discrete time bands, include the applicable connection, and are most meaningful for long-distance advance bookings. It does not contradict the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with the core behavior, then gives a usage cue and an applicability caveat. The opening German word 'Bestpreissuche' is somewhat redundant and could confuse an English-only agent, but the rest of the description earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The core behavior, use case, and a practical limitation are clear, and the output schema covers return shape. However, with eight parameters and very low schema coverage, the description does not compensate for missing guidance on optional parameters, station input format, or how filters like regional_only affect the search.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 13%, and the description provides no parameter-level guidance beyond the implicit from/to/date purpose. Optional parameters such as bahncard, first_class, children_ages, and regional_only are left entirely unexplained in both the description and the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific operation: find the cheapest available fare in each time band of a day, including the connection it applies to. This clearly distinguishes it from sibling tools like db_journeys or db_departures, which focus on journey listings or departures rather than cheapest fares by time band.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says to use this tool for 'when is it cheapest to go' and notes it is typically only meaningful for long-distance routes booked in advance. However, it does not explicitly name alternatives or state when not to use this tool versus sibling tools like db_journey_offers.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
db_departuresDeparture boardARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| when | No | 'YYYY-MM-DD HH:MM' Europe/Berlin; omit for now | |
| format | No | json | |
| minutes | No | Window length | |
| station | Yes | Station name, EVA number, or bahn.de id | |
| rail_only | No | Trains and S-Bahn only; false adds bus/tram/U-Bahn |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds meaningful behavioral context beyond the readOnly/idempotent/openWorld annotations: data is live and delay-aware, platforms are real-time with a platform_changed flag, and cancellations/disruptions are surfaced. This complements the annotations and does not contradict them. It does not discuss data freshness limits or empty-result behavior, but the live qualifier covers the key trait.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One front-loaded sentence states the purpose and enumerates the important output fields without redundancy. Parentheticals such as 'real-time, with delay' and 'real-time, platform_changed flag' are compact, and the journey_id cross-reference is a useful single mention.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the rich input schema, the safety annotations, and the presence of an output schema, the description fills the remaining gap by specifying live/real-time behavior and the link to db_trip_details. Nothing needed to invoke the tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 80%, so the schema already explains when, format, minutes, station, and rail_only. The description focuses on output fields rather than adding parameter-level semantics, and with high schema coverage it does not need to compensate. The journey_id reference is about linking to db_trip_details, not about parameter meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies a live departure board and enumerates the data it exposes: time with delay, line, destination, platform with platform_changed, cancellation, disruption notes, and journey_id. It is unambiguous about the resource, but it lacks an explicit verb like 'retrieves' and does not directly contrast itself with db_arrivals or db_journeys.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Intended use is only implied by 'Live departure board' and the real-time departure fields. The description does not explicitly say when to use this tool instead of db_arrivals or db_journeys, nor does it state exclusion criteria. The reference to journey_id for db_trip_details hints at downstream usage but not at tool selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
db_journey_offersFare options for one journeyARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| adults | No | ||
| bahncard | No | '25', '50', '100', 'business25', 'business50', or None | |
| first_class | No | ||
| recon_token | Yes | `recon_token` from a db_journeys result | |
| children_ages | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, and idempotentHint, so the safety profile is known. The description adds useful behavioral context: fares are 're-checked live' and are informational only, not a booking. This goes beyond the structured annotation data without contradicting it.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three purposeful sentences: scope and fare types first, usage trigger second, informational caveat third. No filler, and every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 5-parameter tool with an output schema and safety annotations, the description is largely complete: it identifies the required recon_token, explains sequencing, and sets expectations about live pricing and non-booking. The only notable gap is that it does not explicitly distinguish itself from db_best_price, but the wording 'all fares' vs 'best price' mostly covers that.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 40%; only recon_token and bahncard get explicit descriptions. The description reinforces that recon_token comes from a db_journeys result and mentions 'class', which loosely maps to first_class, but it does not compensate for the undocumented adults, first_class, and children_ages parameters. Parameter semantics remain mostly left to inference.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource: it returns all fares for ONE specific connection, with concrete fare types (Super Sparpreis, Sparpreis, Flexpreis, regional day tickets) and includes price and class. This distinguishes it from journey search and from a best-price-only tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says to use it after db_journeys when the user asks 'how much' or 'cheapest ticket', which gives clear invocation context. It also states prices are informational and not a booking, but it does not explicitly name or exclude the alternative db_best_price.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
db_journeysPlan a journeyARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| via | No | Optional intermediate station the route must pass through | |
| bike | No | Require bike carriage | |
| when | No | 'YYYY-MM-DD HH:MM' Europe/Berlin local time. Omit for now. No relative words. | |
| adults | No | ||
| format | No | 'text' = compact human table (best for chat); 'json' = structured | json |
| bahncard | No | '25', '50', '100', 'business25', 'business50', or None. Affects prices only. | |
| arrive_by | No | If true, `when` is the LATEST ARRIVAL time instead of earliest departure | |
| seat_only | No | Only trains where a seat reservation is possible | |
| to_station | Yes | Destination: station name, EVA number, or bahn.de id | |
| first_class | No | Price 1st class instead of 2nd | |
| max_results | No | ||
| from_station | Yes | Origin: station name, EVA number, or bahn.de id | |
| children_ages | No | Ages of accompanying children, e.g. [4, 9]. Affects prices. | |
| max_transfers | No | ||
| regional_only | No | Exclude ICE/IC/EC (Deutschlandticket-compatible trains) | |
| min_transfer_min | No | Minimum minutes for each change | |
| deutschlandticket | No | Only connections fully valid with the Deutschlandticket (implies regional_only, no price) |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond readOnlyHint, openWorldHint, and idempotentHint, the description discloses live bahn.de data, real-time delay notation ('(+7)', '(+1d)'), real-time platforms with `*_platform_changed`, cancellations, and the meaning of `alternative` as DB's re-route around a disruption. This adds substantial behavioral context that annotations alone do not provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The first sentence is a strong front-loaded purpose statement. The second is a dense but purposeful field glossary using backticks and clear separators. It is long, but nearly every clause adds operational meaning for a complex output, so there is minimal waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 17-parameter tool that already has an output schema and annotations, the description focuses on what structured data cannot express: real-time semantics, delay/platform-change notation, follow-up token usage, and the `alternative` reroute flag. Nothing essential for invoking the tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 82%, so the baseline is 3. The description adds only marginal parameter insight: price is 'None with Deutschlandticket' and depends on travellers/BahnCard, which is largely already captured in the schema descriptions. It does not meaningfully clarify the remaining input parameters beyond what the schema already documents.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource: 'Plan train connections between two stations with live bahn.de data.' It clearly distinguishes itself from station-board siblings like db_departures and db_arrivals by emphasizing origin-to-destination journeys, and it references downstream sibling tools (db_journey_offers, db_trip_details), making its role in the tool family unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The first sentence gives clear context: this tool is for planning train connections between two stations. It does not explicitly enumerate when-not-to-use alternatives such as db_departures, db_arrivals, or db_best_price, but the description's focus on connections plus the recon_token/journey_id handoffs provides partial routing guidance. This is clear context without formal exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
db_nearbyStations near coordinatesARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| latitude | Yes | ||
| radius_m | No | ||
| longitude | Yes | ||
| rail_only | No | Only stops served by trains/S-Bahn | |
| max_results | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover readOnlyHint, openWorldHint, and idempotentHint, so the safety profile is established. The description adds that the returned bahn.de id is usable in every other tool, which is useful context, but it does not disclose behavior like sorting, pagination, or filter defaults. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence with no redundancy: the core purpose is front-loaded, and the chaining detail about the returned id is valuable and compact. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a moderately simple tool with 5 parameters and an output schema, the description is adequate but leaves gaps around optional parameters like radius_m, max_results, and rail_only. The output schema covers return fields, but the description doesn't explain how these optional parameters shape results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is only 20%, yet the description only explains that latitude/longitude form a 'GPS position'. It does not add meaning for radius_m (units, default), max_results (cap), or rail_only (beyond the schema's existing one-line description). The description fails to compensate for the schema's low coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a precise verb and resource: 'Stations and stops around a GPS position — 'stations near me''. This clearly differentiates it from sibling db_search_station (name-based lookup) and explains the key output fields including the chaining id.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'around a GPS position' implicitly tells an agent when to use this tool, but it never explicitly names alternatives or states when not to use it. The cross-tool id note guides downstream usage, not tool selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
db_search_stationSearch stationsARead-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).
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Station name or fragment, e.g. 'Köln Messe' or 'Frankfurt Flughafen' | |
| include_stops | No | Also return bus/tram stops and addresses |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, and idempotentHint, so safety is covered. The description adds useful behavioral context beyond those annotations by detailing the return fields (name, EVA number, products, full bahn.de id) and the fact that the returned id is accepted by other tools. This gives the agent actionable integration knowledge, though it does not touch on limits, sorting, or error behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each earning its place: the core action, the precise usage condition, and the return-value interoperability detail. There is no redundant repetition of the title or schema, and the most important scoping rule is front-loaded immediately after the action statement.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has strong annotations, a 100% documented schema, and an output schema, so the definition does not need to re-explain structured data. The description adds the selection criterion and cross-tool compatibility context, making it complete for an agent to decide when and how to invoke this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3; the schema already explains both 'query' and 'include_stops' with examples. The description reinforces that the query is a name/fragment lookup and frames it as a disambiguation step, but it does not add new parameter-level meaning beyond what the schema already provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description begins with a specific verb and resource: 'Find Deutsche Bahn stations by name.' It clearly differentiates this tool from its siblings by explaining that the other tools accept plain station names directly, so this tool is specifically for ambiguous or rejected names. The purpose is immediately obvious and not a tautology.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use guidance: 'Call this only when a name is ambiguous or another tool rejected it.' It also states the alternative clearly—'the other tools accept plain station names directly'—so an agent knows exactly when to avoid this tool. This is exemplary usage routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
db_train_formationCoach sequence (Wagenreihung)ARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| when | Yes | Scheduled departure 'YYYY-MM-DD HH:MM' at that station (Europe/Berlin) | |
| train | Yes | Long-distance train, e.g. 'ICE 610' or 'IC 2013' | |
| station | Yes | Station where it departs — name or EVA number |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already carry readOnlyHint, openWorldHint, and idempotentHint. The description adds the important detail that the platform and sectors are real-time, which reinforces the open-world nature, and it narrows applicability to ICE/IC/EC. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two efficient sentences. Core purpose is front-loaded, and the use case and availability restriction each add necessary selection information without filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-value details are covered elsewhere. The description covers purpose, domain, constraints, and a concrete use case. It does not explicitly contrast with alternatives, but given sibling names and context signals, the selection boundary is clear enough.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
All three parameters have schema descriptions, so the baseline is 3. The description adds meaningful constraints beyond the schema: it clarifies that 'train' must be an ICE/IC/EC long-distance service, and ties 'station' and 'when' to the departure context at that station.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states exactly what the tool provides: coach order and platform sectors (A–G) for 1st class, bistro, bike, and quiet coaches, plus the real-time platform. It also explicitly scopes to ICE/IC/EC trains, which clearly distinguishes it from sibling tools about journeys, departures, or offers.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description identifies the intended user question ('where do I stand on the platform') and gives a clear exclusion ('not available for regional trains'). It does not name specific sibling tools as alternatives, but the context is sufficient for an agent to select this tool over the listed siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
db_trip_detailsTrip details (all stops, live)ARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| format | No | json | |
| journey_id | Yes | `journey_id` from a db_journeys leg or a board row |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool as read-only, idempotent, and open-world. The description adds valuable behavioral context by emphasizing the live/real-time nature of the data and listing what the response covers, including platform, load, notes, amenities, and running days. This goes beyond the annotations without contradicting them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core object and packs the resource, data scope, practical examples, and additional return fields into one efficient sentence. Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only detail tool with an output schema and annotations already covering safety and idempotence, the description is sufficiently complete. It explains what the tool returns, the live aspect, and the practical questions it answers, leaving no critical gap for an agent to select and call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already documents journey_id as coming from a db_journeys leg or board row and format as an enum. The description reinforces that the tool targets one specific train run, but it adds little new parameter-level detail. With 50% schema coverage, this is adequate though not exceptional.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the resource ('one specific train run') and the exact data returned: scheduled and real-time times, platform, load, notes, amenities, and running days. This distinguishes it from station-level tools like db_departures and db_arrivals without requiring the agent to open the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The illustrative use cases ('where is this train now, is my stop still served, which platform at my stop') give strong contextual guidance for when to call this tool. It does not explicitly name excluded alternatives, but the 'all stops of one train run' framing makes the intended usage clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
TDQS
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.
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.
Nine tools is well-scoped for a rail travel information server. Each tool covers a distinct user need without unnecessary duplication or overwhelming breadth.
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
Related MCP Connectors
Swiss Transport MCP — wraps Transport Open Data API (free, no auth)
iRail MCP — Belgian rail (SNCB/NMBS) real-time via the community iRail API
Canonical SwissTrip MCP — independent SBB/CFF/FFS schedules, prices, and ticket links by SwissTrip.
Amtrak MCP — live Amtrak train tracking via the community Amtraker API
Related MCP Servers
- AlicenseAqualityDmaintenanceProvides access to Deutsche Bahn train timetables, station information, and schedule changes through Model Context Protocol tools and resources.48317MIT
- FlicenseAqualityDmaintenanceMCP server for querying German public transport information, including station search, live departures/arrivals, and journey planning.5
- AlicenseAqualityDmaintenanceProvides access to Deutsche Bahn's timetable data through MCP, enabling real-time train schedules, station search, and change tracking for German railway stations.483MIT
- FlicenseNot gradedqualityDmaintenanceMCP server for real-time German public transport data (HAFAS/VBN network). Enables querying departures, arrivals, journeys, and nearby stops using natural language.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/capraCoder/db-fahrplan-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server