ÖPNV MCP Server
Click on "Deploy 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., "@ÖPNV MCP ServerPlan a journey from Frankfurt to Stuttgart tomorrow at 8:00"
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.
ÖPNV MCP Server
A Model Context Protocol (MCP) server for German public transport information using the v6.db.transport.rest API.
Features
Search stations and stops - Find train stations, bus stops, tram stops across Germany
Live departures/arrivals - Real-time information with delay tracking
Journey planning - Find connections with transfers, platform info, and tight connection warnings
Smart warnings - Highlights delays, cancellations, platform changes, and risky transfers
Supports all transport types: ICE, IC, RE, RB, S-Bahn, U-Bahn, Tram, Bus
Related MCP server: swiss-public-transport-mcp
Installation
npm install
npm run buildUsage
Add to your MCP client configuration. This server uses stdio transport.
Example configuration:
{
"mcpServers": {
"oepnv": {
"command": "node",
"args": ["/absolute/path/to/oepnv-mcp/dist/index.js"]
}
}
}Restart your MCP client to activate the server.
Example Queries
"Find trains from München Hbf to Berlin"
"Show me departures from Alexanderplatz"
"When does the next S-Bahn leave from Marienplatz?"
"Plan a journey from Stuttgart to Hamburg tomorrow at 10:00"
Available Tools
search_station
Search for stations and stops by name.
Parameters:
query(string): Station name (e.g., "München Hbf", "Berlin Alexanderplatz")
get_departures
Get live departures from a station.
Parameters:
stationId(string): Station ID from search resultsduration(number, optional): Time window in minutes (default: 90, max: 120)
get_arrivals
Get live arrivals at a station.
Parameters:
stationId(string): Station ID from search resultsduration(number, optional): Time window in minutes (default: 90, max: 120)
search_journeys
Find journey connections between two stations.
Parameters:
originId(string): Origin station IDdestinationId(string): Destination station IDdepartureTime(string, optional): Departure time inYYYY-MM-DDTHH:MMformat
Development
# Run in development mode
npm run dev
# Build
npm run build
# Start production server
npm startAPI
This server uses the v6.db.transport API (db-vendo-client as backend).
License
MIT
Available Tools
5 toolsget_arrivalsB
Get live arrivals for a station by ID from a station or stop (trains, buses, trams, U-Bahn, S-Bahn)
| Name | Required | Description | Default |
|---|---|---|---|
| duration | No | ||
| stationId | Yes | Station ID from search_station tool |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description bears full responsibility for behavioral disclosure. It mentions 'live' but does not address data freshness, authentication, rate limits, or error handling. The behavioral context is minimal.
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, focused sentence with no superfluous words. It efficiently conveys the core purpose and scope.
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 absence of an output schema, the description does not explain return values. It covers transport modes but omits details like response format, pagination, or how duration affects results. Some context like 'live' is provided, but completeness is moderate.
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 50% (only stationId described as from search_station). The tool description adds no additional parameter semantics or usage context beyond the schema. Duration parameter lacks description in both schema and description.
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 states the tool retrieves live arrivals for a station by ID, specifying transport modes (trains, buses, trams, U-Bahn, S-Bahn). This distinctively separates it from sibling tools like get_departures which handle departures.
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 implies usage for a specific station via ID, but does not explicitly state when to use arrivals over departures or other siblings. No exclusions or alternative recommendations are provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_departuresC
Get live departures for a station by ID from a station or stop (trains, buses, trams, U-Bahn, S-Bahn)
| Name | Required | Description | Default |
|---|---|---|---|
| duration | No | ||
| stationId | Yes | Station ID from search_station tool |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided; the description says 'live departures' but does not disclose whether delays, cancellations, or status details are included. No mention of rate limits, error handling, or required permissions for a read operation.
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?
Single sentence, front-loaded with 'Get live departures'. Efficiently conveys core purpose, but could add more contextual detail without becoming verbose.
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?
No output schema, so description should hint at return format (e.g., list of departure times, lines, delays). It mentions transport modes but does not explain response structure. With siblings like search_journeys and get_arrivals, guidance on when to use this tool 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 50%: stationId has a description in schema and the tool description adds 'from search_station tool' – helpful. Duration parameter has no description in schema or description, leaving its unit (minutes?) and behavior unclear. The description partially compensates for stationId but ignores duration.
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 states 'Get live departures for a station by ID', specifying the verb and resource. It lists transport modes (trains, buses, trams, etc.) but does not differentiate from the sibling tool 'get_arrivals' beyond the obvious verb difference.
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?
No guidance on when to use this tool over siblings like get_arrivals, get_disruptions, or search_journeys. It does not mention prerequisites or when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_disruptionsA
Get current disruptions, warnings, and service information for a station (delays, cancellations, construction work, etc.)
| Name | Required | Description | Default |
|---|---|---|---|
| stationId | Yes | Station ID from search_station tool |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must disclose behavioral traits. It states the tool gets 'current disruptions', but does not mention read-only nature, authentication needs, rate limits, or error handling for invalid station IDs. Significant gaps exist.
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?
Single sentence of 13 words, no fluff. Purpose is front-loaded and every word is meaningful. Highly efficient.
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 simple one-parameter tool without output schema, the description is marginally adequate. However, it lacks guidance on sibling tool differentiation and behavioral details, leaving the agent with unanswered questions.
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 100% with a single parameter 'stationId'. The description adds value by linking it to the 'search_station tool', aiding the agent in sourcing the correct ID. This exceeds the baseline of 3.
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?
Description clearly states the verb 'Get', the resource 'disruptions, warnings, and service information', and the context 'for a station'. It effectively distinguishes from sibling tools like get_arrivals and get_departures which focus on specific events.
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?
Description implies usage for checking current disruptions but provides no explicit guidance on when to use this tool versus alternatives like search_journeys or get_arrivals. No when-not or comparative context is given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_journeysA
Search for journeys between two stations. If the user doesn't specify a departure time, ask them when they want to travel (e.g., 'now', 'tomorrow at 10:00', 'next Monday 14:30').
| Name | Required | Description | Default |
|---|---|---|---|
| originId | Yes | Origin station ID from search_station tool | |
| departureTime | No | Departure time in YYYY-MM-DDTHH:MM format (e.g., '2025-01-20T14:30'). If not provided, defaults to now. | |
| destinationId | Yes | Destination station ID from search_station tool |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden. It discloses that departureTime defaults to 'now' and suggests a user prompt behavior. However, it omits details like read-only nature, result limits, or authentication requirements.
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 concise sentences without extraneous information. The first sentence states the core purpose, and the second provides actionable usage guidance.
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?
While the description covers the main use case and user interaction, it lacks information about the output format or structure, which is not compensated by an output schema. It also could reference that origin and destination come from search_station (though schema mentions it).
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 100%, so the schema already describes all parameters. The description adds only the behavioral hint about asking for departure time, which provides minimal additional semantic value beyond 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 clearly states the verb 'Search for journeys' and the resource 'between two stations', distinguishing it from sibling tools that handle arrivals, departures, disruptions, or station lookup.
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 provides guidance to ask for a departure time if not specified, which helps the agent interact appropriately. However, it does not explicitly contrast with alternatives like get_arrivals/get_departures for single-station queries.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_stationB
Search for train and bus stations in Germany by name
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Station name to search for (e.g., "München Hbf", "Berlin") |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided. The description only states the basic function and does not disclose behavioral traits such as case sensitivity, partial matching, pagination, or error handling.
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?
Single sentence, no unnecessary words, and clearly conveys the tool's purpose.
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?
Adequate for a simple search tool but lacks details about response format (e.g., list of stations with IDs) or any result limitations. With no output schema, more context would be helpful.
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 100% and the schema provides a clear description for the only parameter (query). The tool description adds no additional meaning beyond the schema, meeting the baseline.
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 states 'Search for train and bus stations in Germany by name', specifying the verb (search), resource (stations), and scope (Germany, by name). It distinguishes from siblings like get_arrivals and search_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?
No guidance on when to use this tool versus alternatives. It does not mention when not to use it or provide context like 'to find a station by name' or 'for journey planning use search_journeys'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v1.0.0- First observed
get_arrivals - First observed
get_departures - First observed
get_disruptions - First observed
search_journeys - First observed
search_station
TDQS
Scored across 5 tools
Tools are mostly distinct: arrivals vs departures clearly differentiated by direction, disruptions and station search are unique. Only slight potential confusion between arrivals and departures if context is unclear, but descriptions resolve it.
All tool names follow a consistent `verb_noun` pattern: `get_arrivals`, `get_departures`, `get_disruptions`, `search_journeys`, `search_station`. No mixing of conventions or irregular verbs.
Five tools is well-scoped for a public transport information server. Each tool covers a distinct user need (arrivals, departures, disruptions, journey planning, station lookup) without unnecessary duplication.
Core operations are covered: station search, live arrivals/departures, disruptions, and journey planning. A minor gap is the lack of a tool to retrieve details for a specific journey (e.g., intermediate stops), but the surface is largely complete for typical use cases.
Maintenance
Related MCP Connectors
MCP server for China Railway 12306 ticket availability: schedules and seats by Chinese station name.
Swiss Transport MCP — wraps Transport Open Data API (free, no auth)
MCP server for Travel & Transportation
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceAn MCP server for interacting with the Berlin Public Transport (BVG) API to search for locations and plan journeys. It provides real-time access to departures, arrivals, trip details, and vehicle tracking within Berlin's transit network.MIT
- AlicenseAqualityDmaintenanceMCP server for Swiss public transport — connections, stationboards, real-time delays, and direct booking links for SBB.41MIT
- AlicenseAqualityCmaintenanceProvides access to Deutsche Bahn's timetable data through MCP, enabling real-time train schedules, station search, and change tracking for German railway stations.447 npmMIT
- FlicenseNot gradedqualityDmaintenanceMCP server for real-time German public transport data (HAFAS/VBN network). Enables querying departures, arrivals, journeys, and nearby stops using natural language.-