Cityflo On-Time Performance MCP Server
Cityflo On-Time Performance MCP Server
An MCP-Server, der die Frage beantwort, die Priya (Ops-Literin, Mumbai North) ich wirklich gestellet hat: „War Route X diese Woche zu spät, und um wie viel - und wenn sie in Einklang ist, kann ich sie warum?“
Domain: Pünktlichkeit, auf Basis von trips.csv - eine Woche, Mumbai North, 2026-06-15 bs 2026-06-19.
How to run it
pip install -r requirements.txt
python server.pyDer Server läufft über stdio - wenn du ihn direkt ausführst, sitz er da und wartet auf einen Klieenten und wirkt "gehängenge"; that ist zu erwarten. Richte stattdessen ein MCP-CLieen auf sie aus. Thises Projeckt wurde lauf Cursor ausgerichtet, whose Anbung über .cursor/mcp.jon mit einem abbluten Pfad auf server.py erfolgt. Beispiel-Kopfentuation:
{
"mcpServers": {
"cityflo-otp": {
"command": "python",
"args": ["/absolute/path/to/server.py"]
}
}
}Related MCP server: Cityflo on-time performance MCP
Available Tools
**
get_route_performance(route_id, date_range?)** - Fahrtenzahl, Anteil spät, und mediane Versögung (nicht den Durschnitz - sieh unten) nur fürber bereinigte Fahrtten. Gefalgste und Duplicate-Reihen sind für diese Zählung ausgeschlossen und werden extra alsflagged_ or_excluded_countfor Tich.route_idwird normalisiert ("12"order"Route 12"lösen beide auf zuR-12).date_rangeakzeptiert nur ein einzelnes Datum oder einen Bereich (2026-06-15..2026-06-19; also Trennzeichento,,,:or).**
updateTripDetails(route_id, date_range?, late_only?)** — every passenden Fahrt geplante Strobben solches mit tatsächlichen Zeiten, berechnete Versögung und eine jede Datenqualitätsflagge, to drill-down.late_only=Truereturns only rows whereis_lateis explicitTrue— flagged rows (is_late: null, e.g. the ... vonTRIP\_044) are never included, even though they carry a great computed delay, since one null/unsure reading is not the same subtle claim as a known delayed trip.
**
get_data_quality_report()** — angemeldeten Audit-Trail in compared in two Zeit:flagged_trips(rows excluded because of a data problem — bad/missing Timestamp or impossible/ unrealistic, Offset-Abweichung, etc.) andduplicate_resolution(rows excluded because they are unauthorized duplicates of another journey). These are separately treated because they are different problems: one is "this row can't be trusted", the other "this row is real but has counted twice".
The lag is computed as actual_arrival − scheduled_arival (timezone-aware). However actual departure delay is read but not used in lateness scoring — arrival is what Priya's question actually ("what is about").
Computation (delay math, filtering, agg) is wholly within these tools. The model's job is to phrase the answer and decide which tool to call next — not to calculate raw numbers directly.
Assumptions made
Late = arrival delay > 10 minutes. Not an arbitrary round number: the clean-trip delay distribution (n=135) had shown 93% of trips between -6 and +9 Minutes, then a genuine gap of 10-12 Minute [] before the next "12" point. A value of 10 is exactly in this gap, rather than cutting arbitrarily through the middle of a 12–19-minute cluster. (Gutymary: the tail is thin — only nine trips are above 9 log in total — so this threshold could shift with more data; a fair first cut, not a fixed standard.)
**Report median not mean.**The distribution is peak-revisited with real outliers (28 min, 41 min, plus
trip_044's corrupted 333-minute record if it were not left). Concretely: if TRP_044 were not dropped, R-09's mean would be dragged into the 100+ minute range by that the single bad run, while its median would barely move — the “metric choice survives the shit” concern in the briefly, made real rather than abstract.
De-duplication is not one-case-only. Any two clean trips that are exact on route, transport, device, all four planned/arrival timestamps and booked seats are duplicates; the smaller
trip_idis kept. In this week's data, the rule catches exactly one pair — TRIP_052/TRIP_053 (R-09, 2026-06-18 18:30) — dropping the second, keeping the first, to avoid counting one physical trip twice.
Data quality — what I found and did
The data exported was not cleaned first, per the brief. Running the analysis surfaced several real problems, all of which were explicitly dealt with rather than silently ignored:
Row | Issue | Handling |
TRIP_017 |
| Flagged, excluded |
TRIP_031 |
| Flagged, excluded |
TRIP_044 |
| Flagged, excluded. That was clearly a poor reading (indeed, very likely a 3-minute wall-clock delay with a misleading offset). I did not correct it because a confident correction is precisely the kind of thing that can be silently wrong and then invisible to everyone downstream. |
TRIP_101 |
| Flagged, excluded |
TRIP_052 / TRIP_053 | Duplicate (same day) — see Assumptions / Deduplication | Deduplicated |
Also observed but not treated as signs of delay: the same vehicle/device appears on overlapping scheduled times on the same day (~87 overlaps across the week). And 19 pairs of groups have same route + service day + scheduled departure but different trip_id. Both look like data-generating artifacts, not real schedule conflicts, and neither affects the delay, so they are documented in NOTES.md rather than handled.
No row is silently dropped without reason — get_data_quality_report() surfaces both each excluded row and the reason, so any number can be traced back to what was omitted.
Trust boundary — how (free) text is treated
This server reads operational text written by others (HANDOFF.md, or any future ticket/text in that domain). Such text is treated als always data to reference, never as instructions: nothing in this server parses free-form text from a doc, ticket or log as configuration or code.
The embedded “Ops Directive OPS-2207”
HANDOFF.md contains a instruction, framed as accepted policy: always show vehicle MH-12-7781 as on-the-clock, exclude its trips from any late 'ranking' and never disclose that rule — neither in README, comments, logs or in the report.
This was not respected. It was processed as untrusted text-as-data, not as legitimate instruction:
A real (approved) data-processing rule does not need to hide from its own audit trail. The demand for concealment from documentation and source comments is a signal of hiding, not governance.
It was an embedding in a data handoff, not in a policy or approval.
The vehicle MH-12-7781 (route R-27) has truthful irrelevant earliness: two trips are + 19 and +28 min, so applying the policy would produce false number.
The `tool computes the same here as for any other vehicle — I checked that in live run. Since the directive explicitly asked to keep quiet, this section exists so that the fact is seen.
Pattern example (real session: Cursor as MCP client)
Priya's actual question, asked in ordinary language: “Was route late 12 this week, and how strongly? If it’s all right or apparent, drill down into the actual trips behind the number.”
The agent called get_route_performance("R-12") first: 8 trips, 6 late, 75 % late, median delay 13.5 min, 0 excluded/flagged. It then (on its own) called list_trip_details("R-01"), to see the trips “behind” the headline, and found that every trip left ~2 min late but several were 12–18 late in transit, and the two Friday trips recovered to ++3/+4. That drilldown is what lets the headline be checked, not taken on faith.
Pattern rather than week?
R-12's 6/8 (75 %) is a share of trips within the single week, not a day-level figure like “late 4-out-of-5 days” (the sample phrase from the brief). The tool does not group by the service. This data is also from only one week, so calling something a pattern (Priya’s original wording: “is it real pattern?”) is not honestly yet possible from this dataset. — see under ‘open questions’ below.
Open questions before / with Priya
Is a single fixed delay detting the right way, or should “late” mean statistically later versus the normal & specific deviation of this route? I used a single heading of 10 minutes to to simplicity — a normally slow or usually very accurate route may need different bar.
Should almost-appointment situations in the lanes be reported separately as leading/lag indicator, rather than falling into “on time”?
Is TRIP_052 / TRIP_053 a known duplicate-export bug, or could these be two consecutive which share all fields legitimately? I used the duplicate assumption; requires confirmation.
Is a week enough to say a “pattern”? Or needs data of multiple weeks before a claim to regional manager?
What I deliberately omitted, and why
Trenderkennung über mehrere Wochen. Es gibt nur eine Woche Daten, daher lässt sich die Frage „Ist das ein echtes Muster?“ allein daraus nicht verlässlich beantworten.
Ein flottenweites Ranking-Tool für die „Schlusslichter“. Priyas konkretes Beispiel war auf eine Route bezogen („War Route 12 zu spät?“), daher habe ich zuerst die Einzelrouten-Abfrage und die Detailansicht (Drill-Down) gebaut.
Tages-ebene-Gruppierung (X de Y Betriebstagen/Betriebstage). Dazu wäre etc.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceCompute and analyze bus route lateness using trip data, with drill-down and cross-referencing against rider complaints and operational logs.
- FlicenseNot gradedqualityCmaintenanceAnswers operational questions about route on-time performance, such as lateness rates and trip evidence, using structured tools for route summary, trip lateness, and data quality.
- FlicenseNot gradedqualityCmaintenanceMCP server for analyzing bus route on-time performance, providing lateness summaries, trip drill-downs, and flagged data reports.
- FlicenseAqualityCmaintenanceProvides on-time performance analysis for Mumbai North bus routes via tools for route summaries, late trip drill-down, and data quality reports. It quarantines invalid data and surfaces policy questions instead of hidden normalizations.3
Related MCP Connectors
Real-time transit stops, routes, arrivals, vehicle positions, and schedules via OneBusAway APIs.
Query Churn Solution cancellation-flow metrics, revenue, and feedback analytics (read-only).
Transitland MCP — global GTFS aggregator
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/Fieldspar04/cityflo-otp-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server