traintracker
Provides tools for querying GB National Rail train information, including live departures and arrivals, departure platforms, timetables, service details, and journey planning with connections and live status overlays.
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., "@traintrackerwhen's the next train to Sudbury?"
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.
traintracker
An MCP server that lets Claude answer questions about GB (National Rail) trains: "when's the next train to Sudbury?", "is the 13:00 from Liverpool Street on time?", "how do I get from Cambridge to Sudbury next Saturday morning?"
It runs locally on your Mac over stdio and plugs into the Claude desktop app.
flowchart LR
Claude[Claude desktop] <-->|stdio| TT[traintracker]
subgraph Live["Live, next ~2 hours"]
D[Darwin<br/>Rail Data Marketplace]
end
subgraph Local["Local, any future date"]
NR[Network Rail<br/>SCHEDULE feed] -->|daily download| DB[(timetable.sqlite)]
end
subgraph Optional["Optional, paid"]
RTT[Realtime Trains API]
end
TT --> D
TT --> DB
TT -.-> RTTTools
Tool | Answers | Data |
| "Which Sudbury?" Station names ↔ CRS codes | Bundled station list |
| Next trains, expected times, platforms, delays, cancellations | Darwin; if it's not set up or fails, RTT, then booked times |
| "Which platform is the 13:00 to Colchester?" One train's platform, flagged | Darwin (paged); booked platform from the local timetable until the live one is announced |
| "What are the next three trains from platform 7?" | Same as |
| Trains arriving in the next ~2 hours | Darwin arrivals; if not set up or failing, RTT, then booked times |
| Booked departures/arrivals at a station on any date | Local timetable → RTT |
| Every stop for one train | Whichever source issued the ID |
| A to B with changes (up to | Local timetable + Darwin live overlay |
| What's configured, timetable freshness, what's missing | — |
Every tool accepts station names or CRS codes. Ambiguous names ("Sudbury", "Harrow") return the candidates so Claude can ask which one you meant.
Related MCP server: railinfo-mcp
Accounts you need
# | Account | Needed? | Cost | What it provides | Used for |
1 | Rail Data Marketplace — Live Departure Board product | Yes for live times | Free | Darwin: National Rail's real-time feed. Departure boards for the next 2 hours with expected times, platforms, delay/cancellation reasons, calling points, station alerts. The same data as station screens. |
|
2 | Network Rail Open Data (NTROD) — SCHEDULE feed | Yes for timetables and planning | Free | The full GB passenger timetable from Network Rail's planning system, including short-term changes (engineering works, extra trains, cancellations) once published. Refreshed daily. |
|
3 | Rail Data Marketplace — Service Details product | Optional | Free | Full live calling pattern for a train seen on a Darwin board. |
|
4 | Rail Data Marketplace — Live Arrival Board product | Optional | Free | Darwin arrivals boards. Without it, arrivals fall back to RTT or booked times. |
|
5 | Realtime Trains API | Optional | Paid | Live and historical running for any date, detailed calling patterns. Off unless a token is set. | Fallback for live tools and |
1. Rail Data Marketplace (Darwin)
Create an account at raildata.org.uk.
In the product catalogue, search "Live Departure Board" (the LDBWS product, not "Live Fastest Departure Boards") and subscribe. Approval for the free tier ranges from instant to a few days.
Open the subscribed product → Specification tab. Copy the Consumer key (not the secret) into
DARWIN_API_KEY.Check the base URL on that tab matches
DARWIN_DEPARTURES_URLin.env.example. If it differs, setDARWIN_DEPARTURES_URLto your value (everything before/GetDepBoardWithDetails).(Optional) Subscribe to Service Details and Live Arrival Board the same way. Each product has its own key and URL: set
DARWIN_SERVICE_API_KEY/DARWIN_SERVICE_URLandDARWIN_ARRIVALS_API_KEY/DARWIN_ARRIVALS_URL.
2. Network Rail Open Data (SCHEDULE)
Register at the Network Rail data feeds portal. Activation can take a while.
Sign in and check that SCHEDULE appears under Static feeds.
Put your portal username and password in
NR_USERNAMEandNR_PASSWORD.If the portal gives a different download link for the full daily extract, all operators, JSON than
NR_SCHEDULE_URLin.env.example, setNR_SCHEDULE_URLto it.
The server downloads the feed in the background when the local timetable is missing or older than 26 hours. It checks this on start-up and on every tool call, so a server left running for days stays current. If a download fails it keeps serving the old timetable, and data_status shows the error. You can also run traintracker refresh by hand (see Commands).
5. Realtime Trains (optional)
Get a token at api-portal.rtt.io. You'll receive either a long-life access token (RTT_ACCESS_TOKEN) or a refresh token (RTT_REFRESH_TOKEN); the server handles both. RTT's old v1 API (api.rtt.io/api/v1) shuts down on 30 Sep 2026; this server only uses the new API at data.rtt.io.
How each source is used
flowchart TD
Q{What's being asked?}
Q -->|next ~2 hours| L[live_departures / live_arrivals]
Q -->|a future date| T[timetable]
Q -->|A to B| P[plan_journey]
Q -->|one train| S[service_details]
L --> L1{Darwin key?}
L1 -->|yes| Darwin
Darwin -->|error or timeout| L2
L1 -->|no| L2{RTT token?}
L2 -->|yes| RTT
RTT -->|error or timeout| TT
L2 -->|no| TT[(Local timetable<br/>booked times, flagged)]
T --> TT
TT -.->|no timetable yet| RTT
P --> CSA[Connection Scan<br/>over the day's timetable]
CSA --> OV{Today, departing<br/>within 2 hours?}
OV -->|yes| Darwin2[Darwin expected times<br/>+ tight-connection flag]
S --> ID{ID prefix}
ID -->|darwin:| Darwin3[Darwin Service Details]
ID -->|tt:| TT
ID -->|rtt:| RTTSource | Freshness | Coverage | Cached for | Limits to know |
Darwin | Real time | Now → +2 hours | 20 s | Darwin service IDs expire soon after the train runs |
Local timetable | Daily (Network Rail publishes ~06:00) | Two days back → end of the published timetable (usually months) | Until the next rebuild | Booked times only; last-minute changes show up in Darwin, not here |
Realtime Trains | Real time | Past and future, per your token's entitlements | 30 s (near now), 10 min (further out) | Rate limited (e.g. 30/min); paid |
What the local timetable keeps
The SCHEDULE feed is large (all trains, freight included). On import, traintracker keeps only what a passenger needs:
Passenger categories only (trains, replacement/timetabled buses, ships). Freight and empty stock are dropped, except overlay and cancellation records, which can stop a passenger train running on a given day.
Stops with a public time only; junctions and passing points are dropped.
Schedules that ended more than two days ago are dropped.
For each date it applies Network Rail's precedence rules per train: cancellation (C) beats new (N), which beats overlay (O), which beats permanent (P), and it honours each schedule's running days and date range. Bank-holiday running flags are not applied yet, so on bank holidays check the live board.
Journey planning
plan_journey uses a round-based Connection Scan over every train hop of the day: round n finds the earliest arrival using at most n trains. That gives the fastest journey and the slower options with fewer changes in one pass, up to max_changes. It repeats from just after each departure to find the next few options, then drops any option that another beats on departure, arrival and changes at once, so you're never told to leave earlier than necessary. Results are ordered by arrival, and the fewest-changes option is always included.
Minimum change time: 5 minutes between trains by default (
MIN_INTERCHANGE_MINUTES). Walk/Tube links already include time to get in and out of stations, so no extra change time is added after them.Cross-London: the Tube isn't in the rail timetable, so transfers between London terminals (Kings Cross, Liverpool Street, Waterloo, etc.) are approximated: walks under 0.8 km at walking pace plus 5 minutes, otherwise Tube at ~12 minutes plus 3.5 minutes per km. They're labelled
tube (approx.).Live overlay: for today's legs departing within two hours, Darwin's expected times and platforms are added, and
connection_at_riskis set if a delay or cancellation eats into a change, including one made via a walk/Tube link. If Darwin is down, the plan is still returned without live times.The search covers the service day (trains running into the early hours are included); it doesn't carry over to the next morning. Station boards do include trains just after midnight.
Install
Requires uv and Python 3.11+.
git clone git@github.com:hugorodgerbrown/traintracker.git
cd traintracker
uv sync
cp .env.example .env # fill in your keys (.env is git-ignored)
uv run traintracker refresh # first timetable download (a few minutes)
uv run traintracker statusAdd to the Claude desktop app
Edit ~/Library/Application Support/Claude/claude_desktop_config.json. Use the full path to uv (run which uv), because the app doesn't use your shell's PATH:
{
"mcpServers": {
"traintracker": {
"command": "/Users/hugo/.local/bin/uv",
"args": ["--directory", "/Users/hugo/Projects/traintracker", "run", "traintracker"]
}
}
}--directory makes the project folder the working directory, so the server reads your keys from .env there. Keys can go in an "env" block in this file instead; real environment variables take precedence over .env.
Restart the Claude app, then ask "what's the status of traintracker's data sources?" to check everything is connected.
Configuration
All configuration is by environment variable, read from .env in the project folder if present. See .env.example.
Variable | Default | Purpose |
| — | Live Departure Board consumer key |
| RDM LDBWS URL | Override if your Specification tab differs |
| board key / RDM URL | Service Details product |
| — | Live Arrival Board product |
| — | Network Rail data feeds login |
| full daily JSON extract | Override if the portal gives a different link |
| — | Realtime Trains (optional) |
|
| Where |
|
| Re-download when older than this |
|
| Minimum change time for planning |
|
| Upstream request timeout |
Commands
Command | Does |
| Run the MCP server on stdio (what Claude runs) |
| Download the SCHEDULE feed and rebuild the timetable |
| Build the timetable from a feed file you downloaded yourself |
| Show configured sources and timetable details |
Logs go to stderr; stdout carries the MCP protocol.
Limitations
Past running times ("was the 08:00 late yesterday?") need Realtime Trains. Darwin only covers now → +2 hours, and the timetable is booked times.
Fares aren't included.
Tube/bus/tram aren't in the timetable beyond the approximate London terminal links.
Engineering works appear in the timetable once Network Rail publishes them (usually well ahead), and in Darwin on the day.
Development
tox runs formatting, lint, type and test checks on Python 3.11 from uv.lock (via the tox-uv plugin):
uvx --with tox-uv tox # all environments: format, lint, type, tests
uvx --with tox-uv tox -e tests # one environment
uvx --with tox-uv tox -e tests -- -k platform # arguments after -- go to the toolEnvironment | Runs |
|
|
|
|
|
|
|
|
Tests use a synthetic SCHEDULE feed in Network Rail's JSON format (tests/feedgen.py) and API fixtures shaped on the published Darwin and RTT schemas. They aren't live recordings, so the first run against real services is the final check.
src/traintracker/
server.py MCP tools, source fallback, live overlay, CLI
timetable.py SCHEDULE importer and SQLite queries (STP resolution)
planner.py Connection Scan journey planner, London links
darwin.py Rail Data Marketplace LDBWS client
rtt.py Realtime Trains client (optional)
stations.py Station search and name resolution
models.py Output models shared by all sourcesData and licences
Darwin data via the Rail Data Marketplace, and Network Rail data feeds, are used under the terms you accept when you subscribe. Check those terms before redistributing any output.
The bundled station list comes from davwheat/uk-railway-stations under the Open Database License (ODbL).
Realtime Trains tokens must not be embedded in distributed apps; this server keeps them in your local environment only.
Code: MIT.
Available Tools
9 toolsdata_statusB
Which data sources are configured, how fresh the timetable is, and what to set up.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden of behavioral disclosure. It clearly conveys that this is an introspection/status tool covering three specific facts, which implies a read-only nature. However, it does not state whether authentication is required, whether it calls external systems, or any side effects. It adds useful context but omits behavioral details.
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 sentence and wastes no words, front-loading the main point about data source configuration. The phrasing is slightly awkward ("what to set up" is a bit unclear), but the overall length and structure are appropriate for the tool's simplicity.
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 zero parameters, an output schema, and low complexity, the description covers the essential purpose well: it names the three kinds of information the tool provides. It does not need to explain return values because an output schema exists. The only missing element is a brief note on when the status should be checked, which is a usage-guidance gap rather than a completeness failure.
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 tool has zero parameters and the schema coverage is 100%, so there is nothing for the description to add on parameter meaning. Per the baseline for a parameterless tool, this scores a 4. The description correctly avoids inventing parameters that do not exist.
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 what the tool reports: configured data sources, timetable freshness, and setup instructions. While the verb is implicit rather than explicit ("get" or "show" is missing), the resource and scope are specific enough to distinguish it from the travel-data siblings. It could be stronger with an explicit verb, but it is not vague or tautological.
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 no guidance about when to use this tool versus alternatives. The sibling tools are clearly about live travel data, so context implies that data_status is for configuration and health checks, but no when-to-use or when-not-to-use conditions are stated. An agent must infer the use case without explicit direction.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
departure_platformA
Which platform one train leaves from. Live platforms are often announced only ~10 minutes before departure at large stations; until then the booked (timetable) platform is returned and flagged as 'booked'.
| Name | Required | Description | Default |
|---|---|---|---|
| to | No | Only trains calling at this station. | |
| time | No | Booked departure HH:MM (24h). Default: the next train. | |
| station | Yes | Station name or CRS code. |
Output Schema
| Name | Required | Description |
|---|---|---|
| note | Yes | |
| service | Yes | |
| station | Yes | |
| platform | No | |
| platform_source | No | |
| minutes_to_departure | No | From now to the expected (else booked) departure. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It explains the key behavioral nuance: before the live platform is announced, the booked timetable platform is returned and flagged as 'booked'. This is valuable context beyond a simple 'get platform' statement.
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 brief and front-loads the core purpose, followed by an important timing caveat. It is slightly awkwardly phrased ('Which platform one train leaves from') but remains efficient and free of unnecessary 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?
Given that an output schema exists and the parameter schema is fully described, the description covers the essential behavioral context. It explains the live-versus-booked distinction, which is the main nuance an agent needs. It could mention how the train is identified via station and time, but the schema already provides this.
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 schema already documents all three parameters. The description does not add much parameter-level detail beyond what the schema provides, which is acceptable given the high 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 clearly states the tool's purpose: returning the platform from which a single train departs. It also distinguishes the live vs booked platform behavior, which helps differentiate it from sibling tools like platform_departures, though it does not explicitly name any sibling.
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 useful context about when live platforms become available (~10 minutes before departure) and that booked platforms are returned otherwise. However, it does not explicitly state when to use this tool versus alternatives such as platform_departures or live_departures, leaving some inference to the agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_stationB
Look up GB railway stations by name or CRS code, best match first.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes | Station name, partial name or 3-letter CRS code. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must carry the behavioral disclosure. It does state that results are ordered by 'best match first', which is useful, but it omits other behaviors like case sensitivity, handling of partial matches, or error conditions. For a simple lookup, this is minimal but not severely lacking.
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, front-loaded sentence that efficiently states the purpose and ordering behavior. No filler or redundant phrasing.
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 tool's low complexity and the presence of an output schema, the description is adequate but not rich. It covers the core lookup behavior but does not mention result format, case sensitivity, or limit semantics. For a straightforward station lookup, it is minimally complete.
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 50%: the query parameter has a description, but limit has none. The tool description reiterates that query accepts name or CRS code, adding little beyond the schema. It provides no clarification for the limit parameter, leaving it 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 states the tool looks up GB railway stations by name or CRS code and returns best match first. This specifies a verb, resource, and search criteria, but it does not explicitly differentiate from sibling tools like live_departures or plan_journey, so it misses the top score.
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 is given on when to use this tool versus alternatives. The description implies it is for station lookup, but there is no explicit mention of when to prefer it over other tools or any exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
live_arrivalsB
Live arrivals for the next ~2 hours. Uses Darwin's arrivals product if configured, then RTT, then booked timetable times.
| Name | Required | Description | Default |
|---|---|---|---|
| rows | No | ||
| station | Yes | Station name or CRS code. | |
| from_station | No | Only trains that called at this station earlier. | |
| include_calling_points | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| date | Yes | |
| board | Yes | |
| filter | No | |
| source | Yes | |
| station | Yes | |
| messages | No | Station/network alerts. |
| services | Yes | |
| platform_available | No | False if the live feed publishes no platforms for this station. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral burden. It discloses a meaningful data-source precedence and that results are approximated to the next ~2 hours. This is beyond what the schema or annotations would show, though it leaves other live-data behaviors (update cadence, cancellation handling) unstated.
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?
Two sentences deliver the core purpose and the data-source fallback with no filler. The main limitation is jargon ('RTT'), but the structure itself is appropriately sized and front-loaded.
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 presence of an output schema excuses return-value detail, and the description covers purpose and behavior. However, it does not orient the agent relative to the sibling tools or explain the acronym, leaving moderate context gaps for a 4-parameter tool with no annotations.
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 description adds no parameter-level semantics; station, rows, from_station, and include_calling_points are left entirely to the schema. Schema description coverage is only 50%, so the description should compensate for the undocumented parameters but does not.
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 identifies the resource ('arrivals') and the time window ('next ~2 hours'), and the tool name reinforces a station-level live arrivals lookup. It stops short of a verb form and does not explicitly contrast with live_departures, so it loses a point.
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 when-to-use guidance is provided. The fallback chain ('Darwin's arrivals product if configured, then RTT, then booked timetable times') describes data sourcing, not when to choose this tool over live_departures, timetable, or service_details. None of the sibling tools are mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
live_departuresA
Live departure board for the next ~2 hours: expected times, platforms, delays, cancellations. Uses Darwin (National Rail); falls back to RTT or the timetable.
| Name | Required | Description | Default |
|---|---|---|---|
| to | No | Only trains calling at this station. | |
| rows | No | ||
| station | Yes | Station name or CRS code. | |
| offset_minutes | No | Shift the board start (e.g. 30 = from +30 min). | |
| include_calling_points | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| date | Yes | |
| board | Yes | |
| filter | No | |
| source | Yes | |
| station | Yes | |
| messages | No | Station/network alerts. |
| services | Yes | |
| platform_available | No | False if the live feed publishes no platforms for this station. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the transparency burden. It usefully discloses the ~2-hour window, the types of information returned, and the data-source fallback chain, which are meaningful behavioral traits beyond the schema.
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: it states the core purpose first, then adds a concise data-source note. Every sentence earns its place with no redundant wording.
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 description covers core behavior and data provenance, and an output schema exists, so return structure is not a gap. However, it lacks sibling differentiation and does not compensate for the undocumented parameters, making it only partially complete for a 5-parameter 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 60%, so the schema already explains several parameters. The description adds a time-window frame but does not clarify rows, include_calling_points, or how offset_minutes interacts with the board, leaving some parameter semantics under-specified.
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 with a specific time horizon and output content (expected times, platforms, delays, cancellations). It is distinct from live_arrivals, though it does not explicitly differentiate itself from departure_platform or platform_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?
No explicit guidance is given about when to use this tool over siblings like live_arrivals, platform_departures, or timetable. The mention of Darwin/RTT/timetable fallback provides data-source context but not usage routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
plan_journeyA
Plan journeys between two stations, with changes up to max_changes. Returns the fastest options first plus the fewest-changes option. Cross-London transfers between terminals are included as approximate walk/Tube links. For today's trains in the next two hours, live Darwin times are added and at-risk connections flagged.
| Name | Required | Description | Default |
|---|---|---|---|
| via | No | Force a change at this station. | |
| date | No | YYYY-MM-DD, 'today' or 'tomorrow'. | |
| live | No | Overlay Darwin live times for today. | |
| time | No | Depart at or after HH:MM. Default now. | |
| count | No | ||
| origin | Yes | Start station name or CRS code. | |
| destination | Yes | End station name or CRS code. | |
| max_changes | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| notes | No | |
| origin | Yes | |
| journeys | Yes | |
| destination | Yes | |
| searched_from | Yes | |
| interchanges_considered | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral burden. It discloses meaningful operational traits: results are ordered fastest-first, cross-London transfers are approximate walk/Tube links, live Darwin times are only added for today's trains within the next two hours, and at-risk connections are flagged. This goes beyond a typical terse description, though it does not address read-only/side-effect behavior explicitly.
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 purpose, the output ordering and approximation caveat, and the live-data behavior. It is front-loaded with the most decision-relevant information and contains no filler or repetition.
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 tool's complexity, the description covers the essential choices an agent must make: output ordering, change limits, cross-London transfer approximations, and live data conditions. The presence of an output schema relieves the description of explaining return fields in detail. It is slightly incomplete only in not clarifying count's meaning and not naming sibling alternatives, but it is otherwise robust.
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 75%, so most parameters are already documented. The description adds useful prose meaning for max_changes and live, but count remains undocumented in both the schema and the description, leaving its role as the number of returned journey options implicit rather than explicit. This partial compensation keeps it at the baseline rather than above it.
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 and resource: 'Plan journeys between two stations, with changes up to max_changes.' It also states the output ordering and the fewest-changes option, clearly differentiating it from sibling tools like live_departures and timetable, which cover station departures or single services rather than end-to-end journey planning.
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 clear context: use this tool when a journey between two stations is needed, including changes and cross-London transfers. It does not explicitly name alternatives or state when not to use it, so it stops short of the highest bar, but the intended use case is unmistakable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
platform_departuresA
The next trains leaving from one platform in the next ~2 hours. A train whose live platform isn't announced yet is matched on its booked platform (platform_source 'booked'), which can still change.
| Name | Required | Description | Default |
|---|---|---|---|
| count | No | ||
| station | Yes | Station name or CRS code. | |
| platform | Yes | Platform, e.g. '4' or '9B'. |
Output Schema
| Name | Required | Description |
|---|---|---|
| date | Yes | |
| board | Yes | |
| filter | No | |
| source | Yes | |
| station | Yes | |
| messages | No | Station/network alerts. |
| services | Yes | |
| platform_available | No | False if the live feed publishes no platforms for this station. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral transparency burden. It usefully discloses the live-vs-booked platform matching logic and the caveat that a booked platform can change. It doesn't cover every possible behavioral aspect like authentication or error cases, but for a simple read-style query tool this is strong disclosure.
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?
Two sentences with no filler. The primary scope and time window are front-loaded, and the important matching caveat is added in the second sentence. Every part 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 domain nuance (platform assignment can change) is disclosed, and an output schema exists to define return values. It could be more explicit about choosing this over related sibling tools, but for a single-platform departure query it provides enough context for correct selection and invocation.
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 'station' and 'platform' with meaningful descriptions, while 'count' has constraints but no explicit semantic description. The tool description adds no parameter-level detail beyond what the schema provides, and schema coverage is moderate at 67%, so this is adequate but not enriched.
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 resource ('one platform') and behavior ('next trains leaving') with a clear time horizon ('next ~2 hours'). This distinguishes it from sibling tools like live_departures, which imply station-wide departures, and departure_platform, which focuses on determining a train's platform.
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 clearly implies usage: use this when you need departures from a specific platform within about two hours. However, it does not explicitly state when not to use it or name alternatives such as live_departures or departure_platform, so the guidance is implied rather than prescribed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
service_detailsA
All stops for one train, with live times where available.
| Name | Required | Description | Default |
|---|---|---|---|
| service_id | Yes | A service_id from another tool (darwin:…, tt:… or rtt:…). |
Output Schema
| Name | Required | Description |
|---|---|---|
| date | No | |
| mode | No | |
| origin | Yes | |
| reason | No | |
| source | Yes | |
| headcode | No | |
| operator | No | |
| cancelled | No | |
| service_id | Yes | |
| destination | Yes | |
| calling_points | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden of behavioral disclosure. It does disclose the key caveat that live times are only provided 'where available' and implies a read-only lookup. However, it does not address failure behavior, data source freshness, or whether historical services are supported; the output schema covers return structure.
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 sentence with the core purpose front-loaded and the live-times caveat appended. Every word earns its place, and there is no redundant or filler content.
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 one-parameter read tool with an output schema, the description plus schema is largely sufficient for an agent to call it correctly. The only notable gap is the lack of explicit usage guidance relative to sibling tools, but that is already captured in the usage_guidelines dimension.
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%, and the parameter description already explains the accepted service_id formats. The tool description adds no new parameter-level meaning beyond implying the ID identifies a train service, so the baseline of 3 is appropriate.
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 train') and the content ('all stops'), and the 'live times where available' qualifier distinguishes it from a static timetable. It lacks an explicit verb, but the intent is unambiguous and it is easily differentiated from siblings like live_departures and timetable.
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 'for one train' implies when to use this tool, but there is no explicit guidance on when to prefer it over alternatives such as timetable or live_departures. No exclusions or alternative tool names are mentioned, leaving the agent to infer the appropriate context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
timetableA
Booked train times at a station for any date the timetable covers (usually months ahead). Use for future trips; for right now prefer live_departures.
| Name | Required | Description | Default |
|---|---|---|---|
| to | No | Only trains later calling here. | |
| date | No | YYYY-MM-DD, 'today' or 'tomorrow'. | |
| rows | No | ||
| time | No | Start time HH:MM (24h). Default: now today, else the whole day. | |
| board | No | departures | |
| station | Yes | Station name or CRS code. | |
| from_station | No | Only trains earlier calling here. | |
| window_minutes | No | ||
| include_calling_points | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| date | Yes | |
| board | Yes | |
| filter | No | |
| source | Yes | |
| station | Yes | |
| messages | No | Station/network alerts. |
| services | Yes | |
| platform_available | No | False if the live feed publishes no platforms for this station. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden, and it does add meaningful context: 'booked' signals this is the planned timetable rather than real-time, and the horizon ('usually months ahead') is disclosed. However, it does not say how out-of-coverage dates are handled, whether live disruption is reflected, or what the response shape implies, so the behavioral disclosure remains partial.
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?
Two short sentences with zero filler. Purpose and scope are front-loaded first, and the usage caveat follows immediately; 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?
An output schema exists, so return values need no explanation. The description handles the primary use case well, but for a 9-parameter tool it leaves unaddressed the arrivals board, row/window controls, and calling-point behavior, relying on the schema to carry those details.
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 56%, so the description is expected to partially compensate. It reinforces the two core parameters ('at a station' for station, 'any date the timetable covers' for date) and adds the horizon semantics. But rows, window_minutes, include_calling_points, and board have no schema descriptions and the description offers nothing for them, so the gap persists.
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 and resource ('Booked train times at a station') and clarifies the temporal scope ('any date the timetable covers, usually months ahead'). It explicitly differentiates from the closest sibling by pointing to live_departures for real-time queries, so an agent can tell them apart without opening schemas.
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 clear when-to-use guidance ('for future trips') and an explicit when-not-to with a named alternative ('for right now prefer live_departures'). It does not, however, address other overlapping siblings such as live_arrivals (given the board=arrivals option) or plan_journey, leaving some routing to inference.
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.
9 tool updates
v0.1.0- First observed
data_status - First observed
departure_platform - First observed
find_station - First observed
live_arrivals - First observed
live_departures - First observed
plan_journey - First observed
platform_departures - First observed
service_details - First observed
timetable
TDQS
Scored across 9 tools
Each tool targets a distinct station/service/platform resource, and the descriptions clearly separate live departures, platform departures, and a train's platform. The main risk is the departure_platform/platform_departures name pair, which could be confused, but the descriptions disambiguate them well.
Names are consistently snake_case and readable, but they mix noun-style resources (timetable, service_details, data_status) with verb-style actions (plan_journey, find_station). The departure_platform/platform_departures swapped-word pair also breaks a clear naming pattern.
Nine tools is well-scoped for a UK rail information server. Each tool covers a meaningful query type without bloat, and the set feels appropriately sized for both departure boards and journey planning.
The read-only rail domain is well covered: station lookup, live arrivals/departures, platform data, future timetable, per-service details, and journey planning are all present. The data_status tool also gives agents a way to diagnose missing or stale data sources, avoiding dead ends.
Maintenance
Related MCP Connectors
Plan trips directly into TravelOwl from a conversation with Claude.
Ask Claude about Goose shows: setlists, jams, venues, song history. Live from ElGoose.net.
Ask Claude about Phish shows: setlists, song gaps, jams, venues. Live from Phish.net.
Search award flights and cash fares, optimize points, and predict fares inside ChatGPT and Claude.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceA modular Python wrapper for the SNCF API that integrates with Claude Desktop, enabling intelligent journey planning and train information retrieval across France's railway network.19-
- FlicenseNot gradedqualityDmaintenanceEnables real-time Indian Railways information retrieval, including live train running status, station schedules, and upcoming arrivals/departures.-
- AlicenseNot gradedqualityDmaintenanceA Claude skill + MCP server that tells you how Deutsche Bahn delays will affect your trip — not just whether your train is late.MIT
- AlicenseNot gradedqualityBmaintenanceProvides real-time Belgian rail (SNCB/NMBS) data via the iRail API, enabling AI agents to query train schedules and live information.3 npmMIT