MCP server providing tools for Winnipeg Transit data and 311 City Services information
Server has 8 tools with explicit registration via FastMCP. All tools have descriptions and input schemas are present for all tools. However, many descriptions are generic and lack WHEN/WHY context that LLMs need for tool selection. Parameter descriptions are minimal, many lack usage guidance, constraints, or examples. Output schemas are not documented anywhere in the source. Error handling is implicit (relies on HTTP status codes) with no recovery guidance. No tool annotations (readOnlyHint, destructiveHint, idempotentHint) present. Overall: average baseline for community MCP servers, with room for improvement in parameter richness and output documentation.
Search for bus stops near a specific geographic coordinate. Useful when you know the location (e.g. from a user's known lat/lon) but need stop IDs. NOTE: Distance is capped at 2000 meters to allow efficient querying.
Get real-time bus arrivals for a specific Winnipeg Transit stop number.
Smart Commute: Get bus arrivals combined with current weather conditions. Helpful for deciding if you need a parka or just a light jacket while waiting.
Get a list of Winnipeg neighborhoods that have had recent 311 activity. Optionally filter by a search_term (e.g., 'Fort').
Plan a multi-stop journey (A -> B -> C ...). Arguments: stops - List of locations (plain text, stop numbers, or formatted keys), optimize - If True, optimized the visit order (TSP) starting from the first stop, date - Optional start date (YYYY-MM-DD or equivalent accepted by API), time - Optional start time (HH:MM).
No output schemas documented for any tool. LLMs cannot predict return structure, field names, or types. Tools return unstructured strings (e.g. 'recent issues in {neighborhood}:\n- [date] type: status') instead of structured JSON with typed fields.
Parameter descriptions lack actionable constraints. E.g. 'distance_meters' has type and default but no explicit max (source says cap 2000 in description text, not in schema constraint). 'stop_number' accepts integer but no range specified. 'date' and 'time' describe format verbally but no regex or format validator present.
No error recovery guidance. Tools return raw HTTP status codes or API errors (e.g. 'City API Error (Status 404)') without actionable next steps. No suggestions for fallback tools or retry strategies.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | C | 60 | 2026-07-28+ | v2 |
| 2026-03-09 | D | 57 | - | v1 |
Plan an optimized itinerary with specific stay durations at each stop. Arguments: stops_config - List of dictionaries. The first stop is the origin. Each item format: {"location": "...", "min_stay": minutes, "max_stay": minutes} (Stay times for the LAST stop are ignored). start_date - YYYY-MM-DD, start_time - HH:MM
Plan a trip between two points using Winnipeg Transit. Arguments 'origin' and 'destination' can be: Plain text addresses or landmarks (e.g. "The Forks", "IKEA", "123 Main St") - Resolved via OSM, Stop numbers (e.g. "10625", "Stop 10541"), Formatted keys: "stops/{key}", "geo/{lat},{lon}", "intersection/{key}"
Search for recent 311 service requests in a specific Winnipeg neighborhood.
Tool descriptions lack discovery context. 'Get real-time bus arrivals for a specific Winnipeg Transit stop number' does not explain WHEN to use this vs get_commute_status or plan_trip. No dependency hints (e.g. 'Call find_stops_near first if you only have a location').
plan_trip and plan_journey accept free-form location strings (addresses, landmarks, stop numbers, formatted keys) without validation or explicit enum. LLMs may hallucinate invalid location formats.
No tool annotations present. All tools are read-only (as documented in tool metadata) but readOnlyHint is not set in schema. This prevents clients from providing UX hints (greying out undo buttons, etc.).
search_311_issues uses raw neighborhood name in SoQL WHERE clause (upper(neighbourhood) = '{neighborhood.upper()}'). This is vulnerable to SQL injection if neighborhood param is not sanitized. LLMs can be tricked via prompt injection into passing malicious payloads.
TRANSIT_API_KEY exposed in config.py as environment variable without server-side injection abstraction. If logs include config or tool calls, the key appears in traces.