Skip to main content
Glama
README.md
# transport_gzm

MCP server wrapping the GTFS-RT live transit feed for **GZM (Górnośląsko-Zagłębiowska Metropolia)** — the Silesian Metropolis public transport operator in Poland.

Provides a small, focused set of tools so AI agents can answer questions like:

- "What buses/trams are currently running on route X?"
- "Is vehicle Y delayed? Where is it right now?"
- "What alerts are currently active (delays, disruptions, works)?"
- "When does the next departure of line 6 arrive at stop Z?"

## How it works

GZM publishes a public GTFS-RT feed at
`https://gtfsrt.transportgzm.pl:5443/gtfsrt/gzm` (no auth, CC-BY licensed).
It exposes three logical sub-feeds:

| Path                       | Content                              |
|----------------------------|--------------------------------------|
| `/gtfsrt/gzm/all`          | full bundle (all three sub-feeds)    |
| `/gtfsrt/gzm/vehiclePositions` | live GPS positions of every vehicle |
| `/gtfsrt/gzm/tripUpdates`  | arrival-time deltas and stop-skips   |
| `/gtfsrt/gzm/alerts`       | service alerts (works, delays, etc.) |

This server fetches the protobuf, decodes it, and exposes it as **9 tools** that
return JSON-friendly structures sized for LLM context windows.

### Static GTFS join (why it matters)

The GZM GTFS-RT feed is *minimal*: trip descriptors carry only a `trip_id`
(no `route_id`), and stop-time updates carry only relative delays — no
absolute times and no `stop_id`. To answer "which line is this bus" or
"when does the next tram leave stop X", the server additionally loads:

- **Static GTFS** — daily mirror at
  `github.com/TransportGZM-GTFS-mirror/TransportGZM-GTFS-extended-ver`
  (same id space as the RT feed; verified). Downloaded once and cached for
  `GZM_STATIC_TTL_HOURS` (default 24 h).
- **SDIP live departures** — GZM's own passenger-information system behind
  `rj.transportgzm.pl`, which powers the real departure boards. The stop
  directory (`/api/v2/stops/data/`, ~7 150 poles) is coordinate-matched to
  GTFS stops at load time.

## Quick start

### Run with Docker (recommended)

```bash
docker run -i --rm ghcr.io/wiktor102/transport-gzm:latest
```

Wire it into your MCP client (Claude Desktop, opencode, …):

```json
{
  "mcpServers": {
    "transport-gzm": {
      "command": "docker",
      "args": ["run", "-i", "--rm", "ghcr.io/wiktor102/transport-gzm:latest"]
    }
  }
}
```

### Run from source

```bash
pip install -e .
transport-gzm
```

…or with `uv`:

```bash
uv run --with mcp[cli] --with gtfs-realtime-bindings --with httpx \
  python -m transport_gzm.server
```

## Tools

| Tool                | Purpose                                                  |
|---------------------|----------------------------------------------------------|
| `health`            | Check feed availability + report feed age                |
| `feed_summary`      | Counts of vehicles, trips, alerts currently in the feed  |
| `vehicles`          | Search/filter live vehicle positions (by route, stop)    |
| `vehicle_by_id`     | Get a single vehicle's current position                  |
| `trip_updates`      | Arrival predictions; filter by route, stop, or trip      |
| `next_departures`   | **Live** departure board per stop (GZM SDIP, minutes)    |
| `search_stops`      | Find stops by name → `rj_stop_id` / `gtfs_stop_id`       |
| `alerts`            | Active service alerts (works, delays, detours)           |
| `alert_by_id`       | One alert by id                                          |

See [`docs/tools.md`](docs/tools.md) for full parameter documentation and
output schemas.

## Configuration

| Env var                 | Default                                     | Purpose                              |
|-------------------------|---------------------------------------------|--------------------------------------|
| `GZM_FEED_BASE_URL`     | `https://gtfsrt.transportgzm.pl:5443/gtfsrt/gzm` | Override the base URL           |
| `GZM_HTTP_TIMEOUT`      | `10`                                        | HTTP timeout in seconds              |
| `GZM_CACHE_TTL`         | `10`                                        | In-process feed cache TTL in seconds |
| `GZM_MAX_VEHICLES`      | `200`                                       | Default cap for `vehicles()`         |
| `GZM_MAX_TRIPS`         | `200`                                       | Default cap for `trip_updates()`     |
| `GZM_MAX_ALERTS`        | `100`                                       | Default cap for `alerts()`           |
| `GZM_USER_AGENT`        | `transport-gzm-mcp/0.1 (+https://github.com/Wiktor102/transport-gzm)` | Outgoing UA |
| `GZM_STATIC_DATASET_URL`| GitHub mirror ZIP of the extended GTFS      | Static schedule source (must share the RT trip-id space) |
| `GZM_STOP_DIRECTORY_URL`| `https://rj.transportgzm.pl/api/v2/stops/data/` | SDIP stop directory |
| `GZM_SDIP_BASE_URL`     | `https://rj.transportgzm.pl/api/-`          | Live departures board base URL |
| `GZM_STATIC_TTL_HOURS`  | `24`                                        | How long to cache the static GTFS index |
| `GZM_COORD_MATCH_TOLERANCE_M` | `20`                                  | Max distance for rj→GTFS stop matching |
| `LOG_LEVEL`             | `INFO`                                      | `DEBUG` / `INFO` / `WARNING` / `ERROR` |

## License

MIT. GTFS-RT data © Górnośląsko-Zagłębiowska Metropolia, CC-BY 4.0.

TDQS

A4.2/5.0

Scored across 8 tools

Disambiguation5/5

Each tool has a distinct purpose: alerts vs alert_by_id, vehicles vs vehicle_by_id, next_arrivals for stop-specific predictions, trip_updates for delay info, feed_summary for metadata, and health for system status. No two tools overlap in functionality.

Naming Consistency4/5

Tools follow a clear pattern: plural names for list operations (alerts, vehicles, trip_updates) and 'by_id' for single items (alert_by_id, vehicle_by_id). feed_summary and health are unique but descriptive. next_arrivals deviates slightly but remains intuitive.

Tool Count5/5

With 8 tools, the server is well-scoped for a transit data API. It covers all necessary operations without redundancy or bloat, making it efficient for agents to navigate.

Completeness4/5

The tool set covers core real-time transit data: vehicle positions, alerts, trip updates, stop arrivals, and system health. Missing static data like route or stop listings, but for live monitoring, it is sufficiently complete.

Maintenance

ActivitySlowing
ResponsivenessNo issues