In most European languages the word for railway means iron road: Eisenbahn,
jernbane, järnväg, chemin de fer, ferrovia,
raudtee. English is one of the few exceptions. Ironway is a
Model Context Protocol server for
European railway data, built on each country's own public API rather than on a
scraped aggregate.
Endpoint
https://ironway.msge.no/mcp
Coverage
What each country can answer, and what it cannot. This is generated from the
adapters themselves, so it cannot drift from the code.
Rail only. Unlike Estonia and Norway this source never returns a bus, tram or metro, and never a flight either, so there is nothing here for ADR 0006's exclusion to do: every leg this adapter returns is a train, on NMBS/SNCB or on an international operator sharing its tracks.
Real-time is genuine only for a 'right now' question: get_departures, which takes no date of its own, and a plan_journey called with neither date nor time. The instant either is supplied, iRail's `delay` field is not documented well enough to tell a live prediction from a placeholder zero, verified by asking for a connection three weeks out and getting `delay: 0` on every leg with nothing else to back it up. Those answers report scheduled times only. See ADR 0007.
UIC numbers are filled in from the station id itself, which really does embed them (verified against Brussels-Midi's real UIC code), the way Switzerland's ids do. One station in the feed ships the number without its usual zero-padding; both shapes are read the same way.
No field distinguishes a Eurostar or Thalys service from an ordinary NMBS train: every vehicle id is namespaced BE.NMBS regardless of who actually runs it, so `operator` is left unset here rather than naming NMBS for a train it does not operate.
Disruptions are nationwide only, with no per-stop filter and no severity field at all, so a stop id passed to get_service_alerts is ignored rather than silently narrowing the answer. A resolution window is sometimes stated in the operator's own prose, which is not parsed into a start or end time.
An unknown stop id is rejected by iRail itself with an HTTP 400 rather than answered with an empty body, so it surfaces here as `unavailable` rather than as a distinct 'no such stop' error the way Estonia and Norway can report one.
Data from iRail (api.irail.be), a keyless, volunteer-run API in front of NMBS/SNCB's own real-time data. iRail asks every client to identify itself with a descriptive User-Agent, which this service sends built from its contact address, and to stay under 3 requests a second. No licence is stated for the API itself; treat it, like Switzerland's community service, as offered for light use rather than as a licensed commercial dependency.
Covers every mode in the national feed, not only rail: a journey between two towns will often be answered with a bus, which is usually the right answer but is not a train.
Realtime exists but is partial. Tallinn city transport reports it; ELRON's national rail departures come back as scheduled, so a rail board here is usually a timetable rather than a prediction. Read the `basis` field on each time rather than assuming.
Stop search is a substring match over stop names and returns platforms and bus stops that share a name with a station. The `modes` field on each result is how to tell a railway platform from the bus stop outside it.
Data from Transpordiamet via peatus.ee, keyless. The national feed is published as open data; the API's own terms of use are not stated on the endpoint, so treat the quota as unpublished and stay modest.
Rail only, and passenger rail only: cargo trains, locomotive moves, shunting and on-track maintenance machinery share this feed and are filtered out of every board and search result, because a traveller has no use for a gravel train's timetable. No buses or trams at all, even though several passenger announcements describe a replacement bus for a cancelled train segment; that bus is not a stop or a board entry here.
A departure's `basis` distinguishes all three of Digitraffic's states: `planned` when it has no live knowledge yet, `realtime` for a live prediction in `expected`, and `recorded` for a train that has already left or arrived, whose `actual` time is what was observed rather than what was forecast. A `recorded` row carries no `expected` at all, because there is nothing left to predict.
No routing. Digitraffic answers what is happening at a station or to a train, never how to get from A to B; Fintraffic's own trip planner and Digitransit's routing graph are separate, keyed products this server does not call.
Alerts are passenger-information announcements scoped to one train or one station — track work, replacement buses, platform changes — not a severity-graded nationwide feed like Norway's. A nationwide request is capped and most results concern a single corridor rather than the whole country.
No international UIC number, despite Digitraffic publishing a field called `stationUICCode`: its values are Finnish national station numbers, 1 to 99998, so Finland waits for the same crosswalk as Norway and Estonia rather than passing one of those off as a UIC code.
`operator` is the short code Digitraffic publishes (`vr`), not a full company name; Fintraffic does not return one in this feed.
Digitraffic publishes a structured reason for each delay (`causes`, with official Finnish category names such as 'Etuajassakulku'). This adapter does not surface it: there is no field for it on a departure, and inventing one for a single country is left for a later pass rather than done quietly here.
Data from Fintraffic's Digitraffic rail API (rata.digitraffic.fi), keyless, licensed Creative Commons Attribution 4.0. Required attribution, verbatim from Fintraffic's terms of service: "Source: Fintraffic / digitraffic.fi, license CC 4.0 BY". Every request identifies this service with a Digitraffic-User header derived from IRONWAY_CONTACT, never a person's name or address, per Fintraffic's own instructions.
The national network: TGV, TER, Intercités, Transilien and RER, plus the buses, coaches and trams in SNCF's own coverage. Each row's `mode` says which.
Realtime is stated rather than inferred here, which is unusual in this server. SNCF marks every departure `base_schedule` or `realtime` in its own right, so a `planned` row is the source declining to predict and a `realtime` row with a zero delay is a train genuinely running to time. Coverage is partial: one of twelve sampled departures from Paris Nord was live.
Journeys exclude cars and bicycles. This source will route you by private car if asked without restriction, which is not an answer a railway server should give; trains, trams, buses, coaches and rail shuttles stay in.
Times are French local time with no UTC offset attached, because the source publishes none. Read them as the clock on the platform.
Disruptions are national and plentiful, over a thousand active at once, and are returned most recent first. They carry a severity and a GTFS-RT effect of their own, such as a delayed or cancelled trip, which most sources in this family do not publish. More than half carry no text at all — internal records of an added or replaced service — and those are counted in a note rather than listed as alerts nobody can read.
Station ids carry UIC numbers, so a French station found here can be matched against the same station as Belgium or Switzerland describes it. SNCF publishes them with a trailing eighth digit that is not part of the UIC code, which this server drops.
Data from SNCF's open API (api.sncf.com), which runs Navitia over SNCF's own timetable and realtime feeds. Used under a free self-serve key with a published allowance of 5 000 requests a day. The key is sent as HTTP Basic with the key as username, the convention for this API family, so it never reaches a URL. Navitia itself is open source, by Hove.
Heavy and suburban rail only: Iarnród Éireann's own network, DART included, plus the cross-border Enterprise service to Belfast. The station list carries several Northern Ireland stops served by that one joint service, given an 'ie:' id like every other stop here, because this is one railway's own list rather than a jurisdiction boundary.
There is no journey planner in this source at all, so plan_journey has no method here and does not accept IE — not a narrower version of the tool, an absent one.
There is no disruption or alerts feed either, so get_service_alerts does not accept IE for the same reason it does not accept CH.
Realtime is genuine where it exists, but partial: the source names several lines with weaker signalling coverage where a query returns the scheduled time only. The one flag that says which is true for a given row is a free-text Status field, not a boolean; only "En Route" is read here as a live prediction, so a widened wording the source starts using later would read as schedule-only rather than as realtime by accident.
No platform or track number is published for a departure, and no operator name is either, even for the Belfast services run jointly with NI Railways.
No cancellation flag exists in this source, so `cancelled` is never set; a cancelled working is more likely to simply disappear from the board than to be marked as one.
The board answers a fixed window, roughly the next 90 minutes, with no way to ask for more; `limit` here only trims what already came back.
Data from Iarnród Éireann's own realtime service, keyless. In the service's own words: "Irish Rail provides this information as is and do not offer any support." No licence is published for it anywhere this adapter found; an as-is disclaimer is a disclaimer of liability, not a grant of rights, so this is used as informally offered rather than as licensed open data. See ADR 0008.
The whole country and every mode reported into the national registry, so a board at a railway station also shows the buses outside it. Each row's `mode` says which.
Journeys exclude flights on purpose. Entur's planner is happy to route Bergen to Oslo by aeroplane, which is not an answer a railway server should give; ferries, coaches and trams stay in, so a fjord crossing is still routable.
Realtime is genuine and widespread here, and Entur publishes the timetable and the prediction as two separate times. So a `delay_minutes` of 0 on a `realtime` row means the train is running to time, rather than meaning that nothing is known. A departure Entur has already observed reads `recorded` instead, with the observed time in `actual`: that is what happened rather than what was predicted.
Alerts can be narrowed to one stop, which most sources in this family cannot do. Without a stop id the answer is the most serious of several hundred nationwide notices, most of which concern bus stops.
Stop search returns only individual stop places, never the station groups Entur also publishes: a group's id looks identical and silently answers nothing on a departure board, so those are filtered out rather than handed over.
Data from Entur, keyless, under NLOD (Norwegian Licence for Open Government Data). Entur requires every client to identify itself with an ET-Client-Name header and may block one that does not; this service sends a name derived from its contact address.
The whole country and every mode in the national timetable, not only rail: a board at Stockholm Centralstation carries the metro, trams and buses around it as well as the trains, and each row's `mode` says which.
Realtime here means something different from the other countries served by this server. ResRobot omits its realtime field entirely when it knows nothing, rather than echoing the timetable into it, so a row with `basis: planned` is a row nobody is tracking and a `delay_minutes` of 0 on a `realtime` row is a genuine 'running to time'. On a sampled Stockholm board, 16 departures of 134 were tracked.
Itineraries are ordered by when they leave, not by how long they take, so the first one back is the next departure rather than the best journey. Stockholm to Göteborg asked for one result gives a coach leaving at 09:00 and arriving in 5 h 52 m; ask for a few and the 3 h 32 m train at 09:15 is among them. Ask for more than one whenever the fastest route matters.
Journeys are planned over surface public transport, ferries included, which matters here because Gotland is an island. No flights appear in Swedish results in any case: this source does not appear to model air travel at all, and Arlanda is described purely by the trains and buses that serve it.
Times are Swedish local time with no UTC offset attached, because the source publishes none on these rows. Read them as the clock on the platform.
A journey can include a walk between two stops, and a change between two services is reported the same way: the leg from the train at Nynäshamn to the Gotland ferry is a walk with a distance, not a gap in the itinerary.
A departure board covers the whole station complex, so rows can belong to neighbouring stops: asking Stockholm Centralstation returns departures from eight distinct stop ids, each row naming its own.
No disruption endpoint, so get_service_alerts does not cover Sweden. Trafikverket publishes Swedish deviation data under a separate key that this adapter does not hold.
Data from Trafiklab's ResRobot v2.1, operated by Samtrafiken. Used under a free Trafiklab key; the key travels in an Authorization header rather than the `accessId` query parameter their examples use, so it never reaches a URL. Trafiklab's terms are silent on redistribution and reserve the right to withdraw access at any time, which is worth knowing before depending on this.
Every mode in the Swiss timetable, not only rail: trams, buses, funiculars and boats appear in the same results, and the `mode` field on a departure or a leg is what separates them.
Realtime only reaches a few hours ahead. A board for now usually carries a prognosis; anything further out is timetable, and the `basis` field says which. A `delay` of null means unknown, never zero.
No disruption data at all. This source publishes no alerts endpoint, so get_service_alerts does not cover Switzerland; check the operator's own channels for a strike or a closed line.
Station ids here are UIC numbers with the country prefix folded in, so 8500010 is Basel SBB and its UIC number is the same digits.
Data from transport.opendata.ch, a community service built on the Swiss public timetable. It publishes no licence of its own and is offered for light use, which is an honestly unclear basis: attribute it, stay within the rate limit, and do not build a commercial dependency on it. The official, licensed route is opentransportdata.swiss, which is phase 3.