A Spring Boot application that provides real-time public transit information by consuming and processing GTFS (General Transit Feed Specification) real-time data feeds. The application periodically fetches trip updates from Kraków's public transportation system and exposes them through a REST API.
This application serves as a middleware service that:
- periodically downloads GTFS real-time Protocol Buffer data from Kraków's transit authority (schedules, routes, stops)
- parses and stores trip updates in memory
- exposes MCP Tools
- exposes REST endpoints for querying real-time transit information
- finds fastest direct connections between stops using both static and real-time data
- validates service availability using GTFS calendar and calendar_dates data
The system is designed to handle real-time transit data, converting complex Protocol Buffer messages into simplified JSON DTOs for easy consumption by client applications.
- Spring Boot 3.5.8 - main application framework providing dependency injection, REST controllers, and scheduling capabilities
- Java 25 - programming language with modern features
- Spring Web
- Spring AI MCP Server
- Protocol Buffers (protobuf) 4.28.2 - binary serialization format for GTFS Realtime data
- Usage: parsing
.pbfiles from transit feeds using generated Java classes - Gradle Plugin:
com.google.protobufversion 0.9.5 for code generation
- Usage: parsing
- Univocity Parsers 2.9.1 - high-performance CSV parser for GTFS static data
- Usage: parsing GTFS CSV files (stops.txt, routes.txt, trips.txt, etc.)
- Spring Data JDBC - simplified data access layer without the complexity of JPA
- H2 Database - in-memory database for storing GTFS static data
- Configuration: automatic schema initialization on startup
- Lombok - code generation library reducing boilerplate
- Spring Boot DevTools - development-time features for faster iteration
- JUnit 5 (Jupiter) - modern testing framework
- Mockito - mocking framework for unit tests
- MockMvc - spring test framework for integration testing
- Usage: testing REST endpoints without starting a full HTTP server
- OkHttp MockWebServer 4.12.0 - mock HTTP server for testing external API calls
- Usage: simulating GTFS feed responses in tests
- JaCoCo - code coverage analysis tool
- Usage: generating test coverage reports in XML and HTML formats
- GitHub Actions - pipeline for automated building, testing, and JaCoCo coverage reporting
- Gradle - build automation and dependency management
- Gradle Wrapper - ensures consistent Gradle version across environments
GET /tripsReturns all current trip updates with stop time information.
Response: 200 OK
[
{
"tripId": "123456",
"routeId": "50",
"tripStartDate": "20260104",
"stopTimeUpdates": [
{
"stopId": "1234",
"arrivalTime": "2026-01-04 14:30:00",
"departureTime": "2026-01-04 14:30:30",
"arrivalDelay": 120,
"departureDelay": 90
}
]
}
]GET /trips/random-stop-timeReturns a randomly selected stop time update from all available trips.
Response: 200 OK
{
"stopId": "1234",
"arrivalTime": "2026-01-04 14:30:00",
"departureTime": "2026-01-04 14:30:30",
"arrivalDelay": 120,
"departureDelay": 90
}GET /fastest-direct-connection?from={stopName}&to={stopName}Finds the fastest direct connection between two stops for current date.
Query Parameters:
from(required) - departure stop nameto(required) - arrival stop name
Response: 200 OK
{
"routeName": "50",
"arrivalTime": "2026-01-08T14:45:00"
}GET /fastest-direct-connection/with-date?from={stopName}&to={stopName}&travelDate={date}Finds the fastest direct connection between two stops for a specific date.
Query Parameters:
from(required) - departure stop nameto(required) - arrival stop nametravelDate(required) - travel date in format YYYY-MM-DD
Response: 200 OK
{
"routeName": "50",
"arrivalTime": "2026-01-15T14:45:00"
}When no data is available:
Response: 500 Internal Server Error
{
"code": "SERVICE_UNAVAILABLE",
"message": "No trip updates available"
}- Download and install Claude Desktop from the official website.
- Add java 25 JDK to your system PATH.
- In repository directory, run:
./gradlew clean bootJar
- Copy absolute path of the JAR generated in
build/libs/. - Go to claude_desktop_config.json
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json - Add the following entry to the main json object:
"mcpServers": { "krakow-transport": { "command": "java", "args": [ "-jar", "your/copied/path/transit-location-api-0.0.1-SNAPSHOT.jar", ] } }
- Launch Claude Desktop and select "krakow-transport" as the MCP server.
- the application uses an in-memory repository pattern rather than persistent database storage for real-time data
- GTFS static data is stored in H2 database for schedule queries and connection finding
- Protocol Buffer code is generated automatically during build from
gtfs-realtime.proto - scheduling uses ISO-8601 duration format (
PT5M= 5 minutes) - all timestamps are converted to system default timezone
- thread-safety is ensured through
volatilekeyword and immutable DTOs - comprehensive exception handling provides clear error messages to API consumers
- HTTP metadata checking (ETag, Last-Modified) optimizes bandwidth by avoiding unnecessary downloads
- service calendar validation ensures connections are only returned for active service dates
- direct connection algorithm prioritizes real-time data but falls back to static schedules
- batch processing (2000 rows) optimizes database imports for large GTFS datasets
- supports stops with identical names by checking all matching stop IDs
The project includes comprehensive test coverage:
- Unit Tests: individual component testing with Mockito
- Integration Tests: end-to-end API testing with MockMvc
- Code Coverage: tracked with JaCoCo, reports generated after each test run
This project is part of academic coursework at AGH University of Science and Technology.
GTFS data is provided by Zarząd Transportu Publicznego w Krakowie (Kraków Public Transport Authority):
- website: https://gtfs.ztp.krakow.pl/
- data format: GTFS Realtime Specification
- update frequency: real-time (application polls every 5 minutes)