A REST API server for searching flights using Google Flights data, powered by fast-flights and FastAPI.
# Install Python 3.11
pyenv install 3.11.9
pyenv local 3.11.9
# Create virtual environment
$(pyenv which python) -m venv venv
source venv/bin/activate
# Install dependencies
pip install -r requirements.txt# Option 1: Run directly
python main.py
# Option 2: Run with uvicorn (with hot reload)
uvicorn main:app --reload --host 0.0.0.0 --port 8000The server will start at http://localhost:8000
A single-page HTML UI is included for testing the API. Simply open test_ui.html in your browser:
# Open the HTML file in your default browser
open test_ui.html # macOS
# or
xdg-open test_ui.html # Linux
# or just double-click test_ui.htmlThe UI includes:
- Flight Search: Search for flights with an intuitive form
- Airport Search: Find airports by name or city
- Results Display: Beautiful, easy-to-read flight results
Note: Make sure the API server is running on http://localhost:8000 for the UI to work.
FastAPI provides built-in interactive documentation:
| UI | URL | Description |
|---|---|---|
| Swagger UI | http://localhost:8000/docs | Interactive API explorer - test endpoints directly |
| ReDoc | http://localhost:8000/redoc | Clean API reference documentation |
Check if the service is running.
Request:
GET /api/healthResponse:
{
"status": "ok"
}Example:
curl http://localhost:8000/api/healthSearch for airports by name or city.
Request:
GET /api/airports/search?q={query}Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
q |
string | Yes | Search query (city or airport name) |
Response:
{
"airports": [
{
"code": "TPE",
"name": "TAIWAN_TAOYUAN_INTERNATIONAL_AIRPORT"
},
{
"code": "TSA",
"name": "TAIPEI_SONGSHAN_AIRPORT"
}
]
}Examples:
# Search for airports in Taipei
curl "http://localhost:8000/api/airports/search?q=taipei"
# Search for airports in Los Angeles
curl "http://localhost:8000/api/airports/search?q=angeles"
# Search for airports in Kayseri
curl "http://localhost:8000/api/airports/search?q=kayseri"Search for available flights based on criteria.
Request:
POST /api/flights/search
Content-Type: application/jsonRequest Body:
{
"from_airport": "TPE",
"to_airport": "LAX",
"date": "2025-02-01",
"return_date": null,
"trip": "one-way",
"airlines": ["DL", "AA"],
"max_stops": 2,
"seat": "economy",
"passengers": {
"adults": 1,
"children": 0,
"infants_in_seat": 0,
"infants_on_lap": 0
}
}Request Body Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
from_airport |
string | Yes | Departure airport (3-letter IATA code) |
to_airport |
string | Yes | Arrival airport (3-letter IATA code) |
date |
string | Yes | Outbound departure date (YYYY-MM-DD) |
return_date |
string | Conditional | Return departure date (YYYY-MM-DD). Required for round-trip, must be null for one-way |
trip |
string | Yes | Trip type: one-way or round-trip |
airlines |
array | No | Note: Airline filtering is not currently supported by the underlying fast_flights library. This parameter is accepted but ignored. |
max_stops |
integer | No | Maximum number of stops. Applies to both outbound and return legs. |
seat |
string | No | Seat class: economy, premium-economy, business, first (default: economy) |
passengers |
object | No | Passenger counts |
passengers.adults |
integer | No | Number of adults (default: 1, min: 1, max: 9) |
passengers.children |
integer | No | Number of children (default: 0) |
passengers.infants_in_seat |
integer | No | Number of infants in seat (default: 0) |
passengers.infants_on_lap |
integer | No | Number of infants on lap (default: 0) |
fetch_mode |
string | No | Fetch mode: common (default, standard scraping) or local (uses Playwright) |
Constraints:
- Total passengers cannot exceed 9
- Number of infants on lap cannot exceed number of adults
- One-way trips:
return_datemust benullor omitted - Round-trip:
return_dateis required - Single-leg searches only (AβB for one-way, AβBβA for round-trip)
Fetch Modes:
common(default) - Standard web scraping using HTTP requests, fast and lightweightlocal- Uses local Playwright browser to render JavaScript (requires additional setup)
Valid Airlines Values:
- Any 2-letter IATA airline code (e.g.,
DL,AA,UA,BA) - Alliance names:
SKYTEAM,STAR_ALLIANCE,ONEWORLD
Response:
{
"current_price": "low",
"flights": [
{
"is_best": true,
"name": "Delta",
"departure": "2025-02-01 10:30 AM",
"arrival": "2025-02-01 6:45 PM",
"arrival_time_ahead": "+0",
"duration": "12h 15m",
"stops": 1,
"delay": null,
"price": "$542"
}
]
}Examples:
# One-way flight search
curl -X POST "http://localhost:8000/api/flights/search" \
-H "Content-Type: application/json" \
-d '{
"from_airport": "JFK",
"to_airport": "LAX",
"date": "2026-02-06",
"trip": "one-way",
"seat": "economy",
"passengers": {
"adults": 1
}
}'
# Round-trip flight search
curl -X POST "http://localhost:8000/api/flights/search" \
-H "Content-Type: application/json" \
-d '{
"from_airport": "JFK",
"to_airport": "LAX",
"date": "2026-02-06",
"return_date": "2026-02-13",
"trip": "round-trip",
"seat": "economy",
"passengers": {
"adults": 2,
"children": 1
}
}'
# Business class with max stops filter
curl -X POST "http://localhost:8000/api/flights/search" \
-H "Content-Type: application/json" \
-d '{
"from_airport": "SFO",
"to_airport": "NRT",
"date": "2026-02-06",
"trip": "one-way",
"max_stops": 1,
"seat": "business",
"passengers": {
"adults": 1
}
}'
# Family trip with multiple passengers
curl -X POST "http://localhost:8000/api/flights/search" \
-H "Content-Type: application/json" \
-d '{
"from_airport": "JFK",
"to_airport": "LAX",
"date": "2026-02-06",
"trip": "one-way",
"seat": "economy",
"passengers": {
"adults": 2,
"children": 2,
"infants_in_seat": 0,
"infants_on_lap": 0
}
}'| Code | Airport |
|---|---|
| JFK | New York John F. Kennedy |
| LAX | Los Angeles International |
| SFO | San Francisco International |
| ORD | Chicago O'Hare |
| LHR | London Heathrow |
| CDG | Paris Charles de Gaulle |
| NRT | Tokyo Narita |
| HND | Tokyo Haneda |
| TPE | Taiwan Taoyuan International |
| ICN | Seoul Incheon |
All endpoints return errors in this format:
{
"detail": "Error message describing what went wrong"
}HTTP Status Codes:
| Code | Description |
|---|---|
| 200 | Success |
| 422 | Validation Error (invalid request body) |
| 500 | Internal Server Error |
This API can be exposed via the Model Context Protocol (MCP) using gen-mcp, allowing AI assistants to interact with the flight search API directly.
-
Download gen-mcp:
# Latest release version make download-genmcp-release # Or nightly snapshot make download-genmcp-nightly
-
Start the API server:
python main.py
-
Fetch OpenAPI spec:
make fetch-openapi # Or manually: curl http://localhost:8000/openapi.json > openapi.json -
Generate MCP configuration:
make generate-mcpfile
This creates
mcpfile.yamlfrom the OpenAPI spec withinvocationBasesconfigured.Configure API URL (optional, defaults to
http://localhost:8000):API_URL=http://localhost:8000 make generate-mcpfile
-
Start MCP server:
make start-mcp-server
-
Stop MCP server:
make stop-mcp-server
| Target | Description |
|---|---|
download-genmcp-release |
Download latest release version of gen-mcp |
download-genmcp-nightly |
Download nightly snapshot version of gen-mcp |
fetch-openapi |
Fetch OpenAPI spec from running API server |
generate-mcpfile |
Generate mcpfile.yaml from OpenAPI spec |
start-mcp-server |
Start the MCP server |
stop-mcp-server |
Stop the MCP server |
view-logs |
View recent logs from API and MCP servers |
clean-genmcp |
Remove downloaded gen-mcp binary and generated files |
The API server logs all requests, responses, and fast-flights library calls:
- API Server Logs:
api-server.log(also output to stdout) - MCP Server Logs:
.genmcp/mcp-server.log
View logs:
# View recent logs
make view-logs
# Follow API server logs in real-time
tail -f api-server.logWhat gets logged:
- All HTTP requests and responses (method, path, status, timing)
- Request/response bodies (for debugging)
- Fast-flights library calls (function calls, parameters)
- Google Flights HTTP requests (via httpx/httpcore logging)
- Errors with full stack traces
.genmcp/- Directory containing the gen-mcp binary (not checked in)mcpfile.yaml- MCP tool definitions generated from OpenAPI spec (not checked in)openapi.json- OpenAPI specification (not checked in)
MIT