UK Bus Departures MCP Server
by vandamd
README.md
# UK Bus Departures MCP Server
An MCP (Model Context Protocol) server for UK bus departures and nearby bus stop discovery.
## Features
- 🚌 Real-time bus departure information for UK stops via bustimes.org
- 📍 Nearby bus stop lookup from a place name or coordinates
- 🔍 ATCO code validation
- ⚡ Built-in caching and respectful rate limiting
- 🗄️ Cloudflare D1-backed local stop lookup using NaPTAN
- 🌐 Cloudflare Workers compatible
## Tools
### `get_bus_departures`
Fetches real-time bus departures for a UK bus stop.
**Parameters**
- `stop_code` (string): UK bus stop ATCO code
- `date` (optional string): `YYYY-MM-DD`
- `time` (optional string): `HH:MM`
**Example**
```json
{
"tool": "get_bus_departures",
"arguments": {
"stop_code": "0100BRP90023"
}
}
```
### `find_nearby_bus_stops`
Finds the nearest active UK bus stops and their ATCO codes.
Provide either:
- `query` for free-text search such as `"Ada Lovelace Building"` or a postcode
- or `latitude` and `longitude`
Optional parameters:
- `radius_m` default `750`, max `5000`
- `limit` default `5`, max `10`
**Example: free-text**
```json
{
"tool": "find_nearby_bus_stops",
"arguments": {
"query": "Ada Lovelace Building",
"limit": 5
}
}
```
**Example: coordinates**
```json
{
"tool": "find_nearby_bus_stops",
"arguments": {
"latitude": 51.4545,
"longitude": -2.5879,
"radius_m": 1000
}
}
```
**Response shape**
```json
{
"resolved_location": {
"name": "Ada Lovelace Building, Upper Richardson, Tithebarn, Broadclyst, Exeter, Devon, EX5 2FN, United Kingdom",
"latitude": 50.7330647,
"longitude": -3.4595234,
"source": "nominatim"
},
"alternatives": [],
"used_radius_m": 750,
"expanded_search": false,
"stops": [
{
"atco_code": "0100BRP90311",
"naptan_code": "bstgwpm",
"stop_name": "Temple Meads Stn",
"indicator": "T7",
"locality_name": "Temple Meads",
"distance_m": 184,
"latitude": 51.45014,
"longitude": -2.5856
}
]
}
```
### `validate_atco_code`
Validates an ATCO code format and returns stop metadata if valid.
## D1 Setup
`find_nearby_bus_stops` requires a D1 database bound as `bustimes_mcp_db`.
1. Create the database:
```bash
bunx wrangler d1 create bustimes-mcp-db
```
2. The repo is already configured with your `database_id` in [wrangler.jsonc](/Users/vandam/Developer/bustimes-mcp/wrangler.jsonc).
3. Apply migrations locally:
```bash
npm run d1:migrate:local
```
4. Apply migrations remotely:
```bash
npm run d1:migrate:remote
```
5. Import NaPTAN bus stops locally:
```bash
npm run import:naptan -- --database bustimes_mcp_db --local
```
6. Import NaPTAN bus stops remotely:
```bash
npm run import:naptan -- --database bustimes_mcp_db --remote
```
The import script downloads the national NaPTAN CSV, filters to active bus stops, and loads them into the `stops` table.
## Development
### Prerequisites
- Node.js 18+
- Wrangler CLI
### Local Development
```bash
npm install
npm run d1:migrate:local
npm run import:naptan -- --database bustimes_mcp_db --local
npm run dev
```
### Deployment
```bash
npm run deploy
```
### Type Checking
```bash
npm run type-check
```
## Connect to Claude Desktop
```json
{
"mcpServers": {
"uk-bus-departures": {
"command": "npx",
"args": [
"mcp-remote",
"http://localhost:8787/sse"
]
}
}
}
```
## Technical Details
### Data Sources
- **bustimes.org API**: stop metadata
- **bustimes.org HTML**: real-time departures via scraping
- **NaPTAN**: UK stop index used for nearby stop lookup
- **Nominatim**: free-text geocoding for place-name search
### Nearby Stop Lookup
- NaPTAN data is loaded into D1 and queried locally at runtime
- Free-text location search is resolved with Nominatim and cached in D1 for 30 days
- Nearby stop lookup uses a bounding-box SQL prefilter and Haversine distance sorting
- If no stops are found within the requested radius and the radius is below 2000m, the search expands once to 2000m
### Rate Limiting and Caching
- 2-second delay between bustimes.org requests
- 5-minute in-memory cache for bustimes stop metadata
- 30-day D1 cache for Nominatim geocoding results
## Nominatim Notes
- This integration is for end-user-triggered lookups only
- Do not use it for autocomplete or background/systematic geocoding
- The server sends a custom `User-Agent` and caches results
- If you surface geocoded results to end users, include OpenStreetMap attribution where appropriate
## Limitations
- **UK only**: text geocoding is constrained to Great Britain
- **Nearby stops require D1**: the tool will fail until the D1 binding is configured, migrated, and populated
- **HTML dependency**: departures scraping is fragile to bustimes.org layout changes
- **Geocoding ambiguity**: building names can resolve to multiple plausible matches; alternatives are returned for inspection
- **No combined departures-by-nearby-stop tool**: v1 stops at discovery of nearby stops and ATCO codes
## License
MIT License
## Disclaimer
This server uses public data from bustimes.org, NaPTAN, and OpenStreetMap/Nominatim. Use responsibly and respect each upstream service's terms and usage policies.
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues