MCP server for Ireland's NTA public transport — focused, queryable tools with human-readable output. Inspired by ireland-nta-mcp.
Project description
mcp-nta
An MCP server for Ireland's National Transport Authority (NTA) public transport data. Provides focused, queryable tools that return small, human-readable results — not raw feed dumps.
Built with FastMCP. Inspired by ireland-nta-mcp and tfi-gtfs.
Tools
| Tool | Description |
|---|---|
search_stops |
Find stops by name. Returns IDs, locations, routes served. |
search_routes |
Find routes by number or name. |
get_stop_departures |
Real-time departures from a stop, filtered by route/time window. |
get_vehicle_positions |
Live vehicle positions filtered by route or proximity. |
get_service_alerts |
Active service alerts filtered by route or stop. |
get_route_stops |
Ordered list of stops on a route. |
nearby_stops |
Find the nearest stops to a location, optionally filtered by route. |
Installation
# Using uv
uvx mcp-nta
# Or install with pip
pip install mcp-nta
python -m mcp_nta
Configuration
Environment variables
| Variable | Required | Default | Description |
|---|---|---|---|
NTA_API_KEY |
Yes | — | API key from the NTA developer portal |
NTA_ROUTES |
No | (all routes) | Comma-separated whitelist of routes to index (see Route filtering) |
NTA_REFRESH_HOURS |
No | 24 |
How often to re-download GTFS data (in hours) |
NTA_TRANSPORT |
No | stdio |
Transport protocol: stdio, http (streamable HTTP), or sse |
NTA_HOST |
No | 0.0.0.0 |
Bind address (http/sse only) |
NTA_PORT |
No | 8000 |
Port (http/sse only) |
Claude Desktop / Claude Code (stdio)
{
"mcpServers": {
"nta": {
"command": "uvx",
"args": ["mcp-nta"],
"env": {
"NTA_API_KEY": "YOUR_KEY",
"NTA_ROUTES": "37,39a,DART,Green"
}
}
}
}
Remote access (HTTP)
NTA_API_KEY=YOUR_KEY NTA_TRANSPORT=http NTA_PORT=8000 mcp-nta
The server will be available at http://localhost:8000/mcp. Any MCP client that supports streamable HTTP can connect to this URL.
SSE (legacy)
NTA_API_KEY=YOUR_KEY NTA_TRANSPORT=sse NTA_PORT=8000 mcp-nta
Available at http://localhost:8000/sse. Maintained for backward compatibility — prefer http for new deployments.
Route filtering
By default, the server indexes every route in the NTA GTFS feed — over 1,000 routes, ~7 million schedule entries. This works fine but produces a ~400 MB cache and takes a couple of minutes on first start.
Setting NTA_ROUTES restricts the index to only the routes you care about. This dramatically reduces build time, disk usage, and memory:
| No filter | 37,39a,DART |
|
|---|---|---|
| Cache size | ~400 MB | ~6 MB |
| First build | ~2 min | ~1 min |
| Memory (build) | ~120 MB | ~40 MB |
Each entry in NTA_ROUTES is matched case-insensitively against either:
- Route short name — the public-facing route number/name (e.g.
37,39a,102,Green,DART) - Route type —
bus,rail, ortramto include all routes of that type
Examples:
# Just a few bus routes
NTA_ROUTES="37,39a,46a"
# All rail + a specific bus
NTA_ROUTES="rail,37"
# All trams (Luas Green and Red lines)
NTA_ROUTES="tram"
# Everything (default when unset)
NTA_ROUTES=""
Only stops served by whitelisted routes are kept. If the filter changes between runs, the database is automatically rebuilt.
Architecture
Static data
On first run, the server downloads two datasets from Transport for Ireland:
- GTFS schedule — routes, stops, trips, stop times, and service calendars
- NaPTAN stop points — supplementary stop metadata (street names)
These are parsed and stored in a SQLite database at ~/.cache/mcp-nta/gtfs.db. On subsequent starts, the server opens the existing database with no parsing — startup is instant. The database is rebuilt automatically when it expires (controlled by NTA_REFRESH_HOURS) or when the route filter changes.
The SQLite approach means the server never loads the full dataset into memory. Queries read only the specific rows they need via indexed lookups.
Real-time data
Real-time feeds (GTFS-RT) are fetched from the NTA API on demand and cached in memory for 30 seconds:
- TripUpdates — delays and predicted arrival times
- VehiclePositions — live GPS positions of vehicles
- ServiceAlerts — disruption notices
Each tool combines a targeted SQLite query against the static schedule with the relevant real-time feed to produce a concise, human-readable answer.
Example
"What buses are due at Oaktree Green for the 37?"
The LLM calls search_stops(query="Oaktree Green"), gets back stop IDs, then calls get_stop_departures(stop_id="8240DB001682", route="37") and gets:
Upcoming departures from Oaktree Green (stop 8240DB001682) for route 37:
1. 37 -> Wilton Terrace | Due: 14:22 (in 4 min) — scheduled 14:20, +1 min late
2. 37 -> Wilton Terrace | Due: 14:40 (in 22 min) — on time
3. 37 -> Wilton Terrace | Due: 15:03 (in 45 min) — scheduled (no live data)
Two tool calls, two small responses, complete answer.
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mcp_nta-0.2.0.tar.gz.
File metadata
- Download URL: mcp_nta-0.2.0.tar.gz
- Upload date:
- Size: 104.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7542b7a385b9ac3ca9de954785ebcbd944cf292adeac5e0b4468355c6f1840ff
|
|
| MD5 |
648a7577308dd48e5a1e71e25ce7b4a6
|
|
| BLAKE2b-256 |
c8126a106aac02db806a7eedc81efc6c2f0849ddcea9b7b5ef8c6abc15b28f5d
|
Provenance
The following attestation bundles were made for mcp_nta-0.2.0.tar.gz:
Publisher:
publish.yml on dmarkey/mcp-nta
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mcp_nta-0.2.0.tar.gz -
Subject digest:
7542b7a385b9ac3ca9de954785ebcbd944cf292adeac5e0b4468355c6f1840ff - Sigstore transparency entry: 1067615443
- Sigstore integration time:
-
Permalink:
dmarkey/mcp-nta@a8cc5cfdc8ef70e6a3f43cbe7f83f1c1e57b70ad -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/dmarkey
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@a8cc5cfdc8ef70e6a3f43cbe7f83f1c1e57b70ad -
Trigger Event:
release
-
Statement type:
File details
Details for the file mcp_nta-0.2.0-py3-none-any.whl.
File metadata
- Download URL: mcp_nta-0.2.0-py3-none-any.whl
- Upload date:
- Size: 25.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d12e082c817923ef241a94c10d9edaf549ae548a2592d01dd1cdb3dcfef9de30
|
|
| MD5 |
bde0da99563f2e95caff7893afdad6e7
|
|
| BLAKE2b-256 |
43b4df1f48e960df96426ece262fcfec4001df7a5df67601611b7d387d8c5df1
|
Provenance
The following attestation bundles were made for mcp_nta-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on dmarkey/mcp-nta
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mcp_nta-0.2.0-py3-none-any.whl -
Subject digest:
d12e082c817923ef241a94c10d9edaf549ae548a2592d01dd1cdb3dcfef9de30 - Sigstore transparency entry: 1067615508
- Sigstore integration time:
-
Permalink:
dmarkey/mcp-nta@a8cc5cfdc8ef70e6a3f43cbe7f83f1c1e57b70ad -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/dmarkey
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@a8cc5cfdc8ef70e6a3f43cbe7f83f1c1e57b70ad -
Trigger Event:
release
-
Statement type: