"""Aviationstack MCP server tools.
Note: Ensure 'requests' and 'mcp' packages are installed and importable in your environment.
"""
import os
import json
import random
import requests
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("Aviationstack MCP")
# Fetch flight data from the AviationStack API.
def fetch_flight_data(url: str, params: dict) -> dict:
"""Fetch flight data from the AviationStack API."""
api_key = os.getenv('AVIATION_STACK_API_KEY')
if not api_key:
raise ValueError("AVIATION_STACK_API_KEY not set in environment.")
params = {'access_key': api_key, **params}
response = requests.get(url, params=params, timeout=10)
response.raise_for_status()
return response.json()
# MCP tool to get flights with a specific airline.
@mcp.tool()
def flights_with_airline(airline_name: str, number_of_flights: int) -> str:
"""MCP tool to get flights with a specific airline."""
try:
data = fetch_flight_data(
'http://api.aviationstack.com/v1/flights',
{'airline_name': airline_name, 'limit': number_of_flights}
)
filtered_flights = []
data_list = data.get('data', [])
number_of_flights_to_fetch = min(number_of_flights, len(data_list))
# Sample random flights from the data list
sampled_flights = random.sample(data_list, number_of_flights_to_fetch)
for flight in sampled_flights:
filtered_flights.append({
'flight_number': flight.get('flight').get('iata'),
'airline': flight.get('airline').get('name'),
'departure_airport': flight.get('departure').get('airport'),
'departure_timezone': flight.get('departure').get('timezone'),
'departure_time': flight.get('departure').get('scheduled'),
'arrival_airport': flight.get('arrival').get('airport'),
'arrival_timezone': flight.get('arrival').get('timezone'),
'flight_status': flight.get('flight_status'),
'departure_delay': flight.get('departure').get('delay'),
'departure_terminal': flight.get('departure').get('terminal'),
'departure_gate': flight.get('departure').get('gate'),
})
return json.dumps(filtered_flights) if filtered_flights else (
f"No flights found for airline '{airline_name}'."
)
except requests.RequestException as e:
return f"Request error: {str(e)}"
except (KeyError, ValueError, TypeError) as e:
return f"Error fetching flights: {str(e)}"
@mcp.tool()
def flight_arrival_departure_schedule(
airport_iata_code: str,
schedule_type: str,
airline_name: str,
number_of_flights: int
) -> str:
"""MCP tool to get flight arrival and departure schedule."""
try:
data = fetch_flight_data(
'http://api.aviationstack.com/v1/timetable',
{'iataCode': airport_iata_code, 'type': schedule_type, 'airline_name': airline_name}
)
data_list = data.get('data', [])
number_of_flights = min(number_of_flights, len(data_list))
# Sample random flights from the data list
sampled_flights = random.sample(data_list, number_of_flights)
filtered_flights = []
for flight in sampled_flights:
filtered_flights.append({
'airline': flight.get('airline').get('name'),
'flight_number': flight.get('flight').get('iataNumber'),
'departure_estimated_time': flight.get('departure').get('estimatedTime'),
'departure_scheduled_time': flight.get('departure').get('scheduledTime'),
'departure_actual_time': flight.get('departure').get('actualTime'),
'departure_terminal': flight.get('departure').get('terminal'),
'departure_gate': flight.get('departure').get('gate'),
'arrival_estimated_time': flight.get('arrival').get('estimatedTime'),
'arrival_scheduled_time': flight.get('arrival').get('scheduledTime'),
'arrival_airport_code': flight.get('arrival').get('iataCode'),
'arrival_terminal': flight.get('arrival').get('terminal'),
'arrival_gate': flight.get('arrival').get('gate'),
'departure_delay': flight.get('departure').get('delay'),
})
return json.dumps(filtered_flights) if filtered_flights else (
f"No flights found for iata code '{airport_iata_code}'."
)
except requests.RequestException as e:
return f"Request error: {str(e)}"
except (KeyError, ValueError, TypeError) as e:
return f"Error fetching flight schedule: {str(e)}"
# MCP tool to get future flight arrival and departure schedule.
@mcp.tool()
def future_flights_arrival_departure_schedule(
airport_iata_code: str,
schedule_type: str,
airline_iata: str,
date: str,
number_of_flights: int
) -> str:
"""MCP tool to get flight future arrival and departure schedule."""
try:
data = fetch_flight_data(
'http://api.aviationstack.com/v1/flightsFuture',
{
'iataCode': airport_iata_code,
'type': schedule_type,
'airline_iata': airline_iata,
'date': date,
}
) # date is in format YYYY-MM-DD
data_list = data.get('data', [])
number_of_flights = min(number_of_flights, len(data_list))
# Sample random flights from the data list
sampled_flights = random.sample(data_list, number_of_flights)
filtered_flights = []
for flight in sampled_flights:
filtered_flights.append({
'airline': flight.get('airline').get('name'),
'flight_number': flight.get('flight').get('iataNumber'),
'departure_scheduled_time': flight.get('departure').get('scheduledTime'),
'arrival_scheduled_time': flight.get('arrival').get('scheduledTime'),
'arrival_airport_code': flight.get('arrival').get('iataCode'),
'arrival_terminal': flight.get('arrival').get('terminal'),
'arrival_gate': flight.get('arrival').get('gate'),
'aircraft': flight.get('aircraft').get('modelText')
})
return json.dumps(filtered_flights) if filtered_flights else (
f"No flights found for iata code '{airport_iata_code}'."
)
except requests.RequestException as e:
return f"Request error: {str(e)}"
except (KeyError, ValueError, TypeError) as e:
return f"Error fetching flight future schedule: {str(e)}"
# MCP tool to get random aircraft type.
@mcp.tool()
def random_aircraft_type(number_of_aircraft: int) -> str:
"""MCP tool to get random aircraft type."""
try:
data = fetch_flight_data('http://api.aviationstack.com/v1/aircraft_types', {
'limit': number_of_aircraft
})
data_list = data.get('data', [])
number_of_aircraft_to_fetch = min(number_of_aircraft, len(data_list))
# Sample random aircraft types from the data list
sampled_aircraft_types = random.sample(data_list, number_of_aircraft_to_fetch)
aircraft_types = []
for aircraft_type in sampled_aircraft_types:
aircraft_types.append({
'aircraft_name': aircraft_type.get('aircraft_name'),
'icao_code': aircraft_type.get('iata_code'),
})
return json.dumps(aircraft_types)
except requests.RequestException as e:
return f"Request error: {str(e)}"
except (KeyError, ValueError, TypeError) as e:
return f"Error fetching aircraft type: {str(e)}"
# MCP tool to get random airplanes detailed info.
@mcp.tool()
def random_airplanes_detailed_info(number_of_airplanes: int) -> str:
"""MCP tool to get random airplanes."""
try:
data = fetch_flight_data('http://api.aviationstack.com/v1/airplanes', {
'limit': number_of_airplanes
})
data_list = data.get('data', [])
number_of_airplanes_to_fetch = min(number_of_airplanes, len(data_list))
# Sample random airplanes from the data list
sampled_airplanes = random.sample(data_list, number_of_airplanes_to_fetch)
airplanes = []
for airplane in sampled_airplanes:
airplanes.append({
'production_line': airplane.get('production_line'),
'plane_owner': airplane.get('plane_owner'),
'plane_age': airplane.get('plane_age'),
'model_name': airplane.get('model_name'),
'model_code': airplane.get('model_code'),
'plane_series': airplane.get('plane_series'),
'registration_number': airplane.get('registration_number'),
'engines_type': airplane.get('engines_type'),
'engines_count': airplane.get('engines_count'),
'delivery_date': airplane.get('delivery_date'),
'first_flight_date': airplane.get('first_flight_date'),
})
return json.dumps(airplanes)
except requests.RequestException as e:
return f"Request error: {str(e)}"
except (KeyError, ValueError, TypeError) as e:
return f"Error fetching airplanes: {str(e)}"
# MCP tool to get random countries detailed info.
@mcp.tool()
def random_countries_detailed_info(number_of_countries: int) -> str:
"""MCP tool to get random countries detailed info."""
try:
data = fetch_flight_data('http://api.aviationstack.com/v1/countries', {
'limit': number_of_countries
})
data_list = data.get('data', [])
number_of_countries_to_fetch = min(number_of_countries, len(data_list))
# Sample random countries from the data list
sampled_countries = random.sample(data_list, number_of_countries_to_fetch)
countries = []
for country in sampled_countries:
countries.append({
'country_name': country.get('name'),
'capital': country.get('capital'),
'currency_code': country.get('currency_code'),
'fips_code': country.get('fips_code'),
'country_iso2': country.get('country_iso2'),
'country_iso3': country.get('country_iso3'),
'continent': country.get('continent'),
'country_id': country.get('country_id'),
'currency_name': country.get('currency_name'),
'country_iso_numeric': country.get('country_iso_numeric'),
'phone_prefix': country.get('phone_prefix'),
'population': country.get('population'),
})
return json.dumps(countries)
except requests.RequestException as e:
return f"Request error: {str(e)}"
except (KeyError, ValueError, TypeError) as e:
return f"Error fetching countries: {str(e)}"
# MCP tool to get random cities detailed info.
@mcp.tool()
def random_cities_detailed_info(number_of_cities: int) -> str:
"""MCP tool to get random cities detailed info."""
try:
data = fetch_flight_data('http://api.aviationstack.com/v1/cities', {
'limit': number_of_cities
})
data_list = data.get('data', [])
number_of_cities_to_fetch = min(number_of_cities, len(data_list))
# Sample random cities from the data list
sampled_cities = random.sample(data_list, number_of_cities_to_fetch)
cities = []
for city in sampled_cities:
cities.append({
'gmt': city.get('gmt'),
'city_id': city.get('city_id'),
'iata_code': city.get('iata_code'),
'country_iso2': city.get('country_iso2'),
'geoname_id': city.get('geoname_id'),
'latitude': city.get('latitude'),
'longitude': city.get('longitude'),
'timezone': city.get('timezone'),
'city_name': city.get('city_name'),
})
return json.dumps(cities)
except requests.RequestException as e:
return f"Request error: {str(e)}"
except (KeyError, ValueError, TypeError) as e:
return f"Error fetching cities: {str(e)}"