thesammykins/ptv_mcp
If you are the rightful owner of ptv_mcp and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.
The PTV MCP Server provides real-time access to Melbourne's public transport data via the Public Transport Victoria (PTV) Timetable API v3, enabling AI assistants to offer comprehensive train information.
PTV MCP Server š
A Model Context Protocol (MCP) server providing real-time access to Melbourne's public transport data via the Public Transport Victoria (PTV) Timetable API v3. This server enables AI assistants to help users with comprehensive Melbourne train information.
š Features
Three Powerful Tools:
next-train
: Find the next train between any two Melbourne stations with real-time departuresline-timetable
: Get upcoming departures for a specific route and station with platform detailshow-far
: Track approaching trains with real-time vehicle positions and distance estimates
Key Capabilities:
- š Real-time departure information with platform details and disruption alerts
- š Live vehicle tracking with GPS coordinates, bearing, and ETA calculations
- š Intelligent route discovery and validation across Melbourne's train network
- ā” Lightning-fast responses with built-in caching (12-hour TTL for static data)
- š”ļø Comprehensive error handling with actionable user messages
- š Detailed execution metadata for monitoring and debugging
Built with:
- ā” Bun runtime with TypeScript (strict mode)
- š HMAC-SHA1 signature authentication per PTV requirements
- š Automatic retry logic with exponential backoff
- š In-memory TTL caching for optimal performance
- āļø Latest MCP specification compliance
š» Quick Start
Prerequisites
- Bun (latest version)
- PTV Developer Credentials (Developer ID and API Key)
- Register at: PTV Developer Portal
Installation
# Install Bun (if not already installed)
curl -fsSL https://bun.sh/install | bash
# Install from npm (recommended)
npm install @thesammykins/ptv-mcp
# Or clone and setup for development
git clone https://github.com/thesammykins/ptv_mcp.git
cd ptv_mcp
bun install
# Copy environment template
cp .env.example .env
# Edit .env with your PTV credentials
Configuration
Set up your environment variables in .env
:
# Required: PTV API credentials
PTV_DEV_ID=your_developer_id_here
PTV_API_KEY=your_api_key_here
# Optional configuration
PTV_BASE_URL=https://timetableapi.ptv.vic.gov.au
HTTP_TIMEOUT_MS=8000
HTTP_MAX_RETRIES=3
CACHE_TTL_HOURS=12
LOG_LEVEL=info
Development
# Start development server with hot reload
bun run dev
# Run tests
bun test
# Type checking
bun run lint
# Format code
bun run format
# Test tools locally
bun run examples/test-tools.ts
MCP Server Usage
# Start MCP server (for Claude Desktop integration)
bun run mcp:dev
š§® Claude Desktop Integration
Option 1: Use the provided mcp.json (Recommended)
The project includes a ready-to-use mcp.json
configuration file:
# Set your PTV credentials as environment variables
export PTV_DEV_ID="your_developer_id_here"
export PTV_API_KEY="your_api_key_here"
# Copy mcp.json to Claude Desktop config directory
cp mcp.json ~/Library/Application\ Support/Claude/claude_desktop_config.json
The mcp.json
file uses environment variable substitution for secure credential management:
{
"mcpServers": {
"ptv-local": {
"command": "bun",
"args": ["run", "src/mcp/server.ts"],
"cwd": "/path/to/ptv_mcp",
"env": {
"PTV_DEV_ID": "${PTV_DEV_ID}",
"PTV_API_KEY": "${PTV_API_KEY}"
}
}
}
}
Option 2: Manual Configuration
Alternatively, manually add to your Claude Desktop configuration (~/Library/Application Support/Claude/claude_desktop_config.json
):
{
"mcpServers": {
"ptv": {
"command": "bun",
"args": ["run", "src/mcp/server.ts"],
"cwd": "/path/to/ptv_mcp",
"env": {
"PTV_DEV_ID": "YOUR_DEVELOPER_ID",
"PTV_API_KEY": "YOUR_API_KEY"
}
}
}
}
š¦ Publishing & Release
NPM Package Installation
The PTV MCP server is available as a scoped npm package:
# Install the published package
npm install @thesammykins/ptv-mcp
# Use in your project
const { PtvClient } = require('@thesammykins/ptv-mcp');
Release Process
This project uses automated publishing via GitHub Actions:
-
Version Update: Update the version in
package.json
:npm version patch # for bug fixes npm version minor # for new features npm version major # for breaking changes
-
Create Release Tag: Push the version tag to trigger publishing:
git push origin main --tags
-
Automated Workflow: The GitHub Actions workflow will:
- Run all tests (must pass)
- Perform type checking and linting
- Build the project
- Publish to npm registry with provenance
- Create a GitHub release
NPM Registry
- Package Name:
@thesammykins/ptv-mcp
- Registry: https://www.npmjs.com/package/@thesammykins/ptv-mcp
- Install Command:
npm install @thesammykins/ptv-mcp
Publishing Requirements
- All tests must pass (
bun test
) - TypeScript compilation must succeed (
bun run lint
) - Build process must complete (
bun run build
) - Version tag format:
v*.*.*
(e.g.,v1.0.0
,v1.2.3
) - NPM_TOKEN secret must be configured in repository settings
š Documentation
For AI Agents
- - Comprehensive guide for AI agents on how to effectively use the PTV MCP tools, including best practices, error handling, and sample interactions
For Developers
- - System design and module structure
- - PTV API v3 integration details
- - Detailed requirements and implementation notes
š ļø Tool Usage Examples
The PTV MCP supports both Metro and V/Line regional trains - you can query journeys like "Southern Cross to Geelong" alongside metro services.
1. Next Train (next-train
)
Find the next train between two stations:
Input:
{
"origin": "Flinders Street",
"destination": "South Morang",
"time": "2024-03-15T09:00:00Z"
}
Response:
{
"data": {
"route": {
"id": 2,
"name": "Hurstbridge",
"number": "Hurstbridge"
},
"direction": {
"id": 1,
"name": "Up"
},
"departure": {
"scheduled": "2024-03-15T09:15:00Z",
"estimated": "2024-03-15T09:16:00Z",
"platform": "2",
"runRef": "run_12345",
"atPlatform": false,
"scheduledMelbourneTime": "Fri Mar 15, 8:15 PM",
"estimatedMelbourneTime": "Fri Mar 15, 8:16 PM",
"minutesUntilDeparture": 14
},
"origin": {
"id": 1071,
"name": "Flinders Street",
"suburb": "Melbourne"
},
"destination": {
"id": 1155,
"name": "South Morang",
"suburb": "South Morang"
},
"disruptions": [],
"journey": {
"changes": 0
},
"timing": {
"currentTime": "Fri Mar 15, 8:01 PM",
"searchTime": "Fri Mar 15, 8:01 PM",
"within30MinuteWindow": true
}
},
"metadata": {
"executionTime": 245,
"apiCalls": 6,
"cacheHits": 2,
"dataFreshness": "2024-03-15T09:00:15Z",
"routesConsidered": 1,
"departuresFound": 3,
"timezone": {
"systemUTC": "2024-03-15T09:01:00Z",
"melbourneLocal": "15/03/2024, 8:01:00 pm",
"isDST": false,
"offset": "UTC+10 (AEST)"
}
}
}
V/Line Regional Example:
{
"origin": "Southern Cross",
"destination": "Geelong",
"time": "2024-03-15T09:30:00Z"
}
2. Line Timetable (line-timetable
)
Get upcoming departures for a specific route:
Input:
{
"stop": "Southern Cross",
"route": "Belgrave",
"direction": "outbound",
"duration": 90
}
Response:
{
"data": {
"stop": {
"id": 1181,
"name": "Southern Cross",
"suburb": "Melbourne"
},
"route": {
"id": 4,
"name": "Belgrave",
"number": "Belgrave"
},
"departures": [
{
"scheduled": "2024-03-15T09:12:00Z",
"estimated": "2024-03-15T09:13:00Z",
"platform": "8",
"destination": "Belgrave",
"atPlatform": true
},
{
"scheduled": "2024-03-15T09:27:00Z",
"platform": "8",
"destination": "Belgrave"
}
],
"timeWindow": {
"start": "2024-03-15T09:00:00Z",
"end": "2024-03-15T10:30:00Z",
"durationMinutes": 90
}
}
}
V/Line Regional Example:
{
"stop": "Southern Cross",
"route": "Geelong",
"direction": "outbound",
"duration": 120
}
3. How Far (how-far
)
Track approaching trains with real-time positions:
Input:
{
"stop": "Melbourne Central",
"route": "Craigieburn",
"direction": "inbound"
}
Response:
{
"data": {
"stop": {
"id": 1120,
"name": "Melbourne Central",
"suburb": "Melbourne",
"coordinates": {
"latitude": -37.8103,
"longitude": 144.9633
}
},
"route": {
"id": 6,
"name": "Craigieburn",
"number": "Craigieburn"
},
"direction": {
"id": 1,
"name": "City (Flinders Street)"
},
"approachingTrains": [{
"runRef": "run-456",
"destination": "Flinders Street",
"distanceMeters": 850,
"eta": 2.1,
"accuracy": "realtime",
"vehicle": {
"id": "X234",
"operator": "Metro Trains",
"description": "X'Trapolis 100",
"lowFloor": true,
"airConditioned": true
},
"realTimePosition": {
"latitude": -37.8050,
"longitude": 144.9633,
"bearing": 180,
"lastUpdated": "2024-03-15T09:00:45Z"
}
}]
},
"metadata": {
"executionTime": 1250,
"apiCalls": 4,
"cacheHits": 1,
"dataFreshness": "2024-03-15T09:00:50Z",
"dataSource": "realtime"
}
}
V/Line Regional Example:
{
"stop": "Southern Cross",
"route": "Geelong",
"direction": "outbound"
}
Note: V/Line trains may have limited real-time vehicle position data, with graceful fallback to schedule-based estimates.
š Project Structure
ptv_mcp/
āāā src/
ā āāā config.ts # Environment configuration
ā āāā mcp/
ā ā āāā server.ts # MCP server entry point
ā āāā ptv/ # PTV API client
ā ā āāā signing.ts # HMAC-SHA1 authentication
ā ā āāā http.ts # HTTP client with retries
ā ā āāā client.ts # API endpoints
ā ā āāā types.ts # TypeScript interfaces
ā ā āāā cache.ts # TTL caching
ā āāā features/ # Tool implementations
ā āāā next_train/
ā āāā line_timetable/
ā āāā how_far/
āāā tests/ # Unit and integration tests
āāā examples/ # Usage examples
āāā docs/ # Documentation
āāā plan.md
āāā architecture.md
āāā apireference.md
š Documentation
- - System design and data flows
- - PTV API v3 integration details
- - Development roadmap
āļø Development
Running Tests
# Run all tests
bun test
# Run specific test
bun test tests/signing.test.ts
# Run with coverage
bun test --coverage
Scripts
Script | Description |
---|---|
bun run dev | Development server with hot reload |
bun run build | Build production bundle |
bun test | Run test suite |
bun run lint | TypeScript type checking |
bun run format | Format code with Prettier |
bun run mcp:dev | Start MCP server |
bun run mcp:validate | Validate schemas and types |
š Security
- ā ļø Never commit real API credentials
- All secrets are loaded from environment variables
- API keys and signatures are redacted from logs
- HMAC-SHA1 signature verification for all PTV API requests
š Troubleshooting
Common Issues
"Invalid signature" errors:
- Verify your
PTV_DEV_ID
andPTV_API_KEY
are correct - Ensure environment variables are properly loaded from
.env
- Check that there are no extra spaces or special characters in credentials
"Stop not found" errors:
- Check stop names for typos (case insensitive matching supported)
- Use full stop names: "Flinders Street" not "Flinders St"
- Try nearby stops or use stop IDs directly for precision
"No departures found":
- Verify the route services the requested stops
- Check service hours - some routes don't operate at all times
- Try broader time windows or different directions
Connection timeouts:
- The PTV API can be slow during peak times
- Server automatically retries with exponential backoff
- Check network connectivity and firewall settings
Tool not found in Claude:
- Verify MCP server configuration in Claude Desktop
- Restart Claude Desktop after configuration changes
- Check server logs for startup errors
Error Codes
Code | Description |
---|---|
STOP_NOT_FOUND | The specified stop name was not found |
ROUTE_NOT_FOUND | Route does not service the specified stop |
DIRECTION_NOT_FOUND | Invalid direction for the route |
NO_DEPARTURES | No upcoming departures found |
NO_APPROACHING_TRAINS | No vehicles detected approaching the stop |
PTV_API_ERROR | Upstream API error or timeout |
Getting Help
- Check the PTV API FAQ
- Review server logs for detailed error information
- Open an issue on GitHub with reproduction steps
- Ensure you're using the latest version
š¦ Current Status
- ā Environment Setup: Complete with Bun + TypeScript strict mode
- ā Core Architecture: Modular design with clean separation of concerns
- ā PTV API Integration: Full HMAC-SHA1 auth + retry logic + error handling
- ā Tool Implementation: All 3 MVP tools fully functional
- ā Testing: Comprehensive test suite (36 tests - 30 passing, 6 failing on mock data)
- ā Real-time Features: GPS vehicle tracking with Haversine distance calculations
- ā Melbourne Timezone: Complete DST-aware timezone handling utilities
- ā Error Handling: Structured errors with actionable user guidance
- ā Documentation: Complete user + developer + AI agent guides
- ā Claude Desktop Integration: Ready with provided mcp.json configuration
- ā Production Ready: Meets all MVP objectives with enhanced features
šļø Development
Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature
) - Make your changes and add tests
- Ensure all tests pass (
bun test
) - Commit your changes (
git commit -m 'Add amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
Architecture Overview
The server follows a clean, layered architecture:
- MCP Layer (
src/mcp/
) - Server initialization and tool registration - Feature Tools (
src/features/
) - High-level tool orchestration and business logic - PTV Client (
src/ptv/
) - API authentication, HTTP client, and response caching - Types (
src/ptv/types.ts
) - TypeScript interfaces for all API responses
Key Components
- Authentication - HMAC-SHA1 signature generation per PTV API requirements
- HTTP Client - Retry logic, timeout handling, and exponential backoff
- Caching - TTL-based in-memory cache for stops, routes, and directions
- Error Handling - Structured error responses with actionable user messages
- Real-time Data - Live vehicle positions and schedule-based fallbacks
š License
MIT License - see LICENSE file for details
š Data Attribution
This software uses data from the Public Transport Victoria (PTV) Timetable API.
- Data Source: Public Transport Victoria (PTV) Timetable API
- Data Provider: Public Transport Victoria, State Government of Victoria, Australia
- Data License: Creative Commons Attribution 3.0 Australia
- Data URL: https://www.ptv.vic.gov.au/footer/data-and-reporting/datasets/ptv-timetable-api/
Users of this software should ensure they comply with the PTV API terms of use and provide appropriate attribution when using PTV timetable data.