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

ActivityInactive
ResponsivenessNo recent community issues