Typed TypeScript client and MCP server for the Transport for London API with friendly wrappers, full raw coverage, static station sequences, and UI helpers for official line colours.
tfl-ts MCP server presents a well-structured tool collection with strong naming conventions and comprehensive parameter schemas. All 7 tools follow verb_noun patterns (get_*, resolve_*, plan_*), descriptions are consistently present and informative (avg ~100 chars), and input schemas are formally defined with JSON Schema. Parameter descriptions are detailed and include practical guidance (e.g., 'resolve_stop_id' explains the 490G hub expansion for bus mode; 'docs' includes operation guidance). However, there are notable gaps: (1) Output schemas are entirely undocumented, no tool specifies what fields the response will contain, breaking pattern:tool and pattern:response-shaper; (2) Error handling is minimal, no error recovery guidance, no retryable vs fatal classification; (3) No tool annotations (readOnlyHint, destructiveHint, idempotentHint) present despite all tools being read-only; (4) Some parameter relationships are undocumented (e.g., 'docs' anyOf constraints could be clearer); (5) Missing batch/pagination patterns on list operations. Tools are clearly callable and well-named, but the absence of documented output structure is a significant production gap.
Read tfl-ts bundled agent docs offline (same catalogue as `tfl docs`). No TfL API call, no credentials. Prefer list → find → read; use grep to locate symbols across docs. Large files are paginated by line.
Get compact live arrivals for one stop ID: line, towards, minutes, platform. Optional lineIds filter. Cached 15s.
Get compact live line status (id, name, status, optional reason). Provide lineIds or modes (at least one). Set issuesOnly=true to hide Good Service lines. Cached 60s.
List transport modes bundled with tfl-ts. Static metadata only — no TfL API call.
Plan a journey and return a compact summary (duration, fare, natural-language legs). Cached 2 minutes.
Resolve a line name to canonical lowercase TfL line IDs. Exact matches rank first. Static metadata only — no TfL API call. Prefer this before get_line_status.
Output schemas completely absent. No tool documents its response structure. LLMs cannot plan downstream operations or extract specific fields.
No error handling documented. Tools do not specify what errors can occur, what conditions are retryable, or what recovery steps the agent should take.
No tool annotations. All tools are read-only (no state modification), but readOnlyHint is not declared. Agents cannot optimize caching/retry strategy without this metadata.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 67 | 2026-07-28+ | v2 |
Search TfL for a stop name or NaPTAN / SMS code and return compact stop matches. Cached 24h. For modes: ["bus"] this expands 490G… hubs so a street name returns boarding stops, not two raw search hits. Use the returned id with get_arrivals.
Input format flexibility not validated. 'plan_journey' accepts from/to as 'stop ID, postcode, or latitude/longitude' but the parameter schema is just type:string with no format hints, patterns, or validation rules. LLMs will pass invalid formats.
Pagination not offered on list-like tools. 'docs' with operation=list and 'resolve_stop_id' could return large result sets, but neither supports limit/offset or cursor-based pagination.