Skip to main content
Glama

title: Aviasales MCP emoji: "✈️" colorFrom: blue colorTo: indigo sdk: docker app_port: 7860 pinned: false short_description: Flight price search over MCP

aviasales-mcp

MCP server for flight price search via Aviasales / Travelpayouts Data API. Thirteen read-only tools that let Claude Code, Claude Desktop, Cursor or any other MCP client answer flight-price questions: fares by route and month, the cheapest day to fly, flexible dates, budget and inspiration search, plus airport/city/airline lookup.

Unlike Google-Flights-scraping MCP servers, place names do not have to be guessed into IATA codes by the model: lookup_cities and find_nearest_airports resolve them.

Related MCP server: Find Flights MCP Server

Common prompts

Ask your agent in plain language — it picks the tool.

Prompt

Tools it reaches for

"How much is a flight from Moscow to Istanbul in March?"

lookup_citiessearch_flights

"What's the cheapest day to fly to Bangkok in September?"

get_prices_calendar

"I'm flying Berlin→Lisbon on 12 May, back on the 19th — would shifting a day either way be cheaper?"

get_flexible_date_prices

"Where can I fly from St Petersburg for under 30 000 ₽?"

get_city_directions, search_by_price_range

"Which airport should I fly into for Pattaya, and what does it cost from Dubai?"

find_nearest_airportssearch_flights

"Novosibirsk to Rome in November — is it cheaper with a few days in Istanbul on the way?"

plan_stopover_trip

"Two weeks in Rome in November, and I would stop somewhere on the way out."

plan_stopover_trip with trip_nights_min/trip_nights_max

"Evening departures only, two adults and a child, business class."

search_flights with depart_after, adults, children, trip_class

Install

You need a free Travelpayouts API token: https://www.travelpayouts.com/programs/100/tools/api

# Run without installing (what MCP client configs below use)
uvx aviasales-mcp

# Or install into the current environment
pip install aviasales-mcp

The PyPI release is still pending. Until it lands, use the Docker invocation in Setup or run from a source checkout with pip install . in the repository root.

MCP client configs

Take the block for your client and put your own token in. AVIASALES_MARKET is optional but worth setting — see Configuration.

Keep the token out of anything you commit. A project-level .mcp.json or .cursor/mcp.json is a normal thing to check into git, and a token pasted there goes with it. Prefer the user-level config file, or .gitignore the project one. On PyPI-less setups the Docker form reads --env-file, which keeps the secret in an ignored .env.

Claude Code

One command, and the token lands in your user config rather than the repo:

claude mcp add aviasales --env AVIASALES_API_TOKEN=your-token-here -- uvx aviasales-mcp

Or add it to ~/.claude.json (every project), or to .mcp.json in the project root if you are happy to gitignore that file:

{
  "mcpServers": {
    "aviasales": {
      "command": "uvx",
      "args": ["aviasales-mcp"],
      "env": {
        "AVIASALES_API_TOKEN": "your-token-here",
        "AVIASALES_MARKET": "ru"
      }
    }
  }
}

Claude Desktop

~/Library/Application Support/Claude/claude_desktop_config.json on macOS, %APPDATA%\Claude\claude_desktop_config.json on Windows. A GUI app starts with a trimmed PATH and often cannot find uvx by name — if the server fails to start, replace "uvx" with its absolute path (which uvx):

{
  "mcpServers": {
    "aviasales": {
      "command": "uvx",
      "args": ["aviasales-mcp"],
      "env": {
        "AVIASALES_API_TOKEN": "your-token-here",
        "AVIASALES_MARKET": "ru"
      }
    }
  }
}

Cursor

~/.cursor/mcp.json (global) or .cursor/mcp.json (per project):

{
  "mcpServers": {
    "aviasales": {
      "command": "uvx",
      "args": ["aviasales-mcp"],
      "env": {
        "AVIASALES_API_TOKEN": "your-token-here",
        "AVIASALES_MARKET": "ru"
      }
    }
  }
}

Docker instead of uvx

Works in all three clients — swap the command/args for:

{
  "command": "docker",
  "args": ["run", "-i", "--rm", "--env-file", "/path/to/.env", "aviasales-mcp"]
}

Tools

Flight prices

Tool

Description

search_flights

Prices between two cities on a date or across a month (v3/prices_for_dates)

get_prices_calendar

Prices grouped by day or month — the cheapest day to fly

get_flexible_date_prices

Prices for the days around your dates — "would shifting a day be cheaper?"

get_latest_prices

Most recently found fares, optionally filtered by route

get_popular_directions

Where travellers reach a destination from

get_city_directions

Cheapest destinations reachable from a city — inspiration search

get_alternative_directions

Prices for nearby airports/cities

search_by_price_range

Flights inside a budget; omit the destination to search anywhere (no date filter — the endpoint ignores one)

plan_stopover_trip

Breaking the journey for a few days in a hub — one-way, or the whole round trip with trip_nights_min/max

search_flights, get_prices_calendar, get_flexible_date_prices and get_latest_prices accept adults (1–9), children (0–8), infants (0–8) and trip_class (economy/comfort/business/first).

The Data API serves a cache of recent searches and takes no passenger parameters, so the party is encoded into each ticket's booking_link instead — the link opens Aviasales with the full party and class pre-filled and shows the real total. The prices themselves are always per adult in economy, which is what the price_note field on every price response spells out for the model.

search_flights also takes depart_after / depart_before (HH:MM, 24-hour) to keep only departures in a time window; set depart_after later than depart_before for a window that wraps midnight (red-eyes).

Tickets carry duration_total (door-to-door minutes), duration_to / duration_back (flight time per direction) and layover_minutes (combined ground time between connections). Every price response also carries a price_summary (min/median/max) so the model can tell a good fare from a bad one without a second search.

Reference data

Tool

Description

lookup_airlines

Airlines by name or IATA code

lookup_airports

Airports by name, IATA code, or city code

lookup_cities

Cities by name or IATA code — turn a city name into a code

lookup_countries

Countries by name or code

find_nearest_airports

Airports closest to a place or to lat/lon, by distance

The lookup_* tools take search, limit (default 50, max 500) and locale, and return {status, total, returned, truncated, data}. Always pass search: the underlying datasets are ~10k airports and ~9.6k cities, which is far more than any model can hold in context. Matches are ranked (exact code, then exact city code, then name), and airports with no scheduled service sort last. Each dataset is downloaded once per process and cached for 24 hours.

find_nearest_airports answers the question lookup_airports cannot: the closest airport is rarely named after the town. It resolves near="Pattaya" against the cached city and airport datasets and ranks by great-circle distance — no third-party geocoder involved.

Errors and empty results

Every response carries status ("ok" or "error"), so an empty data list is never confused with a failure. Bad input is refused before the API call, with the expected format spelled out ("departure_at must be \"YYYY-MM-DD\" or \"YYYY-MM\"…"), and both error and empty responses carry a hint naming what to try next. On a rejected argument the hint says what to substitute and which tool resolves it — enough for the model to fix the call itself on the second attempt.

Setup

Running it yourself, without uvx:

  1. Get an API token at https://www.travelpayouts.com/programs/100/tools/api

  2. Copy .env.example to .env and fill in your token

  3. Build and run with Docker:

docker build -t aviasales-mcp .
docker run --env-file .env aviasales-mcp

Remote connector (Hugging Face Spaces)

Claude's custom connectors reach the server from Anthropic's cloud, not from the viewer's device, so it needs a public HTTPS URL. On individual plans the connector UI takes OAuth credentials and offers no field for a static header, which is why MCP_AUTH_TOKEN is not enough there and Google OAuth is.

The allowlist is the security boundary, not the login. Everyone has a Google account, so MCP_ALLOWED_EMAILS is what separates "signed in" from "allowed to spend the owner's Travelpayouts quota". The server refuses to start with OAuth configured and the list empty.

  1. Create a Google OAuth client (Google Cloud Console → APIs & Services → Credentials → OAuth client ID → Web application). Authorized redirect URI: https://<user>-<space>.hf.space/auth/callback.

  2. Create a Docker Space and push this repository to it. The YAML block at the top of this file is the Space's config; app_port: 7860 matches the Dockerfile.

  3. In Space → Settings → Secrets, set AVIASALES_API_TOKEN, GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, MCP_PUBLIC_URL (https://<user>-<space>.hf.space) and MCP_ALLOWED_EMAILS.

  4. In Claude → Settings → Connectors → Add custom connector, give it https://<user>-<space>.hf.space/mcp and sign in.

Two things to expect. The Space must be public: a private one demands a Hugging Face token on every request, which Claude will not send — the OAuth allowlist is what protects it, not the Space's visibility. And a free Space sleeps when idle; the first request after that wakes it and may time out, so ping it on a schedule if that becomes annoying.

Configuration

Variable

Required

Description

AVIASALES_API_TOKEN

Yes

Travelpayouts API token

AVIASALES_PARTNER_ID

No

Partner ID for booking links

AVIASALES_DEFAULT_CURRENCY

No

Default price currency (default: rub)

AVIASALES_MARKET

No

2-letter market whose price cache to read (unset → ru)

AVIASALES_LOCALE

No

Language of reference data names (default: en)

LOG_LEVEL

No

Logging level (default: INFO)

MCP_PORT

No

Serve streamable-HTTP on this port instead of stdio (PORT also accepted)

MCP_HOST

No

Bind address for HTTP mode (default: 127.0.0.1; use 0.0.0.0 in Docker)

MCP_AUTH_TOKEN

No

Shared secret required on every HTTP request

MCP_AUTH_ALLOW_QUERY_TOKEN

No

Also accept the token as ?token= (default: false)

MCP_ALLOW_INSECURE_HTTP

No

Permit a non-loopback bind with no token (default: false)

AVIASALES_MARKET is worth setting: the price cache is per market, and the same route in the same currency comes back at a different price for ru and us.

HTTP transport

By default the server speaks stdio, which is what local MCP clients expect. Setting MCP_PORT switches it to streamable-HTTP so it can be reached remotely:

docker run --env-file .env \
  -e MCP_PORT=8080 -e MCP_HOST=0.0.0.0 -e MCP_AUTH_TOKEN=<your-secret> \
  -p 8080:8080 aviasales-mcp

The endpoint is then http://<host>:8080/mcp, and every request must present the token as Authorization: Bearer <token>; anything else gets a 401.

Some MCP clients cannot set headers. MCP_AUTH_ALLOW_QUERY_TOKEN=true also accepts ?token=<token>, but note that uvicorn — and any proxy in front of it — writes the full URL to its access log, so the secret ends up in logs. Prefer the header.

There is no TLS here: terminate it at a reverse proxy if the port is reachable from anywhere untrusted.

Without MCP_AUTH_TOKEN the port is unauthenticated and anyone who reaches it can spend your Travelpayouts quota. Loopback binds are allowed (with a warning); binding anything else refuses to start unless you also set MCP_ALLOW_INSECURE_HTTP=true.

Limitations

  • Prices are a cache of recent searches, not live availability. A fare can be gone by the time the link opens; expires_at says when the quote lapses.

  • Prices are always per adult in economy. Passenger count and cabin change the booking link, never the quoted number.

  • No booking. This server searches and links out; it never holds or buys.

  • Cache coverage is uneven. An empty result means nobody searched that route recently, not that the route does not exist.

  • get_latest_prices, the matrices and nearby airports come from the older v2 response shape: they name the selling agency rather than the airline and carry no flight number.

  • Rate limits are per endpoint (600/min for most, 60/min for the week and nearby matrices). The server retries 429s and warns when the published quota runs low.

Development

docker build --target dev -t aviasales-mcp-dev .
docker run --rm aviasales-mcp-dev pytest -q
docker run --rm -v "$(pwd)":/app -w /app aviasales-mcp-dev ruff check src/ tests/

CI runs the suite on Python 3.12 and 3.13 plus a Docker image build — see .github/workflows/ci.yml.

License

GPL-3.0-or-later — see LICENSE.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

  • Flight search, airfare analytics, flexible destinations

  • Google Flights search data: fares, routes, stops, and price insights via a hosted MCP server.

  • Search award flights and cash fares, optimize points, and predict fares inside ChatGPT and Claude.

  • Real-time Google Flights fares for agents. Three things people do with this server. Scan for deals: one call takes a date range and a list of destination airports, expands every combination server side, and returns each fare with Google's own low, typical or high verdict. Put live search in your app: flat JSON with a bookable link on every result, and round trips priced as paired legs. Run a 24/7 AI travel agent: add the server, sign in with Google, and schedule it. No ads, no sponsored content. You bring your own RapidAPI key, so every search is billed to your plan and never to anyone else's. Add https://flights.flightpowers.com/mcp , click Sign in, sign in with Google, and paste your RapidAPI key once on the page that opens. Scripts and clients without a sign-in button send the key as x-rapidapi-key on the same URL.

Related MCP Servers

  • A
    license
    C
    quality
    F
    maintenance
    Enables searching and retrieving detailed flight information using the Duffel API, supporting various flight types and flexible search parameters for efficient travel planning.
    3
    222
    MIT
  • -
    license
    Not graded
    quality
    Not graded
    maintenance
    Enables searching and retrieving flight information using Duffel API, supporting one-way, round-trip, and multi-city queries with flexible search parameters.
    -
  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables tracking flights and grouping them into trips, with tools to create, list, and manage trips and flight bookings.
    -