ttc-mcp
This server provides access to Toronto Transit Commission (TTC) data via the Model Context Protocol. Capabilities include:
Fare information: Retrieve current fares for different rider categories (adult, senior, youth, child) and payment types (PRESTO, cash, day pass, monthly), plus the 2‑hour transfer rule. Supports filtering by category and/or type.
Static schedules: Look up subway, streetcar, and bus routes, stops, and timetables.
Real‑time data: Get live vehicle positions and real‑time arrival predictions for buses and streetcars (subway real‑time is not published).
Service alerts: Read disruptions across all TTC modes.
Trip planning: Plan multi‑modal trips with transfers (in active development).
Deployment: Self‑hostable via Docker or Vercel, using stdio or Streamable HTTP transports.
Click on "Install 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., "@ttc-mcpShow me the next streetcar arrivals at Queen and Spadina."
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.
ttc-mcp
A Model Context Protocol server for the Toronto Transit Commission (TTC). Exposes subway, streetcar, and bus schedules, live vehicle positions, real-time arrivals, and service alerts to LLM clients — plus multi-modal trip planning with transfers.
Built entirely on TTC's official open feeds — no API key required:
Static GTFS (routes, stops, schedules) from open.toronto.ca
GTFS-Realtime (vehicle positions, trip updates, service alerts) from
bustime.ttc.ca
TypeScript · stdio + Streamable HTTP transports · self-hostable via Docker or Vercel.
Sibling project to go-planning-mcp (GO Transit / Metrolinx).
Status: in active development. Tracked via a wayfinder map under
.wayfinder/— most of the static-schedule surface (stops, routes, schedules) is implemented; real-time tools andplan_tripare landing incrementally. See the repo's open issues for exact status.
Scope notes
Real-time coverage (live positions & arrivals) is bus + streetcar only — TTC does not publish subway real-time. Subway is served from the static schedule plus service alerts.
Fares are a flat PRESTO fare with a 2-hour transfer window (no machine-readable fare data in the feed).
Related MCP server: BVG MCP Server
Self-hosting
Quick start (Docker)
docker run -p 3000:3000 ghcr.io/emilsoleymani/ttc-mcp:latestOr with the provided docker-compose.yml:
docker compose up -dThe image bakes a local libSQL file from TTC's live GTFS feed at build time, so it's self-contained — no external database needed. Once running, connect an MCP client to http://localhost:3000/mcp (Streamable HTTP), or curl http://localhost:3000/health for a liveness check.
Configuration
Var | Purpose | Default |
| Schedule DB connection: a |
|
| Turso auth token (only needed when | — |
| Overridable GTFS-Realtime base URL |
|
| Coalescing cache window for decoded RT feeds |
|
| Set |
|
| HTTP transport port |
|
Updating
The Docker image is self-contained, so picking up newer TTC schedule data means pulling a freshly-built image (the upstream GTFS Refresh workflow rebuilds and republishes on a weekly cadence, or trigger your own rebuild):
docker compose pull && docker compose up -dIf you instead point LIBSQL_URL at a shared Turso database, data freshness follows that database directly — no image update needed.
Building from source
git clone https://github.com/EmilSoleymani/ttc-mcp.git
cd ttc-mcp
npm ci
npm run ingest # downloads the live TTC feed, builds ./data/ttc.db
npm run build
npm run start:http # or: npm run start:stdioLicense
MIT © 2026 Emil Soleymani
Available Tools
1 toolget_fareGet TTC faresA
The current TTC fare table (adult/senior/youth/child by payment type) plus the 2-hour transfer rule. Fares are a flat, hand-maintained table — TTC publishes no machine-readable fare data. Optionally filter by category and/or fare_type.
| Name | Required | Description | Default |
|---|---|---|---|
| category | No | Optional rider category filter (adult, senior, youth, child). | |
| fare_type | No | Optional payment-type filter (presto, cash, day_pass, monthly). |
Output Schema
| Name | Required | Description |
|---|---|---|
| fares | Yes | |
| notes | Yes | |
| transfer | Yes | |
| source_url | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full burden for behavioral disclosure. It explicitly states that fares are a flat, hand-maintained table and that TTC publishes no machine-readable data, which informs the agent about data freshness and limitations. This is valuable context beyond obvious read behavior.
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 succinct with two sentences: the first defines the tool's core purpose, and the second adds filtering options and a note about data source. Every sentence is meaningful, and there is no extraneous information.
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 presence of an output schema (not shown), the description appropriately avoids explaining return values. It covers the main elements (fare types, transfer rule, filters) but does not mention error handling or edge cases, which is acceptable for a simple retrieval 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?
The input schema has 100% coverage with descriptions for both parameters. The description adds that filtering is optional, but this does not significantly enhance the schema's existing detail. Thus, the description provides minimal added value beyond the schema.
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 retrieves the current TTC fare table and the 2-hour transfer rule, specifying the rider categories and payment types. It uses a specific verb and resource, and although no siblings are present, the description is unambiguous about its scope.
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 mentions optional filtering by category and/or fare_type, providing clear guidance on how to use the tool. However, it does not specify when not to use it or provide alternatives, which is acceptable given the absence of sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
TDQS
With only one tool, there is no risk of ambiguity or confusion.
The single tool follows a clear verb_noun pattern, consistent with common conventions.
A single tool for a transit server like TTC is extremely limited; typical servers would include many more tools for routes, schedules, stops, etc.
Only fare information is provided; there are obvious gaps for routes, schedules, real-time updates, and other transit data.
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 Connectors
Model Context Protocol server for Studex tools, notifications, and profile integrations
Model Context Protocol server for todo.vu task management and time tracking.
A Model Context Protocol (MCP) server for Selise Blocks Cloud integration
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceA Model Context Protocol (MCP) server that provides cached access to Munich Public Transport (MVG) disruption data.Creative Commons Zero v1.0 Universal
- AlicenseNot gradedqualityDmaintenanceAn MCP server for interacting with the Berlin Public Transport (BVG) API to search for locations and plan journeys. It provides real-time access to departures, arrivals, trip details, and vehicle tracking within Berlin's transit network.MIT
- AlicenseAqualityBmaintenanceMCP server for Atlanta MARTA real-time transit data, enabling queries about train arrivals and bus positions via natural language.4MIT
- AlicenseCqualityBmaintenanceMCP server for the UK Bus Open Data Service, enabling timetable queries, stop search, route discovery, journey planning, and real-time bus tracking.16MIT
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/EmilSoleymani/ttc-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server