Skip to main content
Glama

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.

Example prompts

Ask in plain language. The server picks the tool.

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

  • What is the cheapest day to fly to Bangkok in September?

  • I am flying Berlin to Lisbon on 12 May and back on the 19th. Would shifting a day either way be cheaper?

  • Where can I fly from St Petersburg for under 30 000 rubles?

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

Related MCP server: @theyahia/travelpayouts-mcp

Common prompts

The same kind of question, with the tools a typical agent reaches for.

Prompt

Tools it reaches for

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

lookup_cities → search_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_airports → search_flights

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

search_flights with depart_after, adults, children, trip_class

Install

Paste this into a terminal. It is the same docker command every client block below runs; the process speaks MCP on stdin and waits there.

AVIASALES_API_TOKEN=your-token-here AVIASALES_MARKET=ru \
  docker run -i --rm \
  -e AVIASALES_API_TOKEN \
  -e AVIASALES_MARKET \
  ghcr.io/stufently/aviasales-mcp:latest

You need Docker, and a free Travelpayouts API token from https://www.travelpayouts.com/programs/100/tools/api. A wrong token still lets the process start (so does no token at all in the Docker image); it surfaces as an error on the first search. AVIASALES_MARKET is optional — see Configuration. Drop that variable and its -e pair if you do not need it.

:latest follows releases; pin a version tag (:0.5.3) if you would rather upgrade by hand.

Without Docker, the same server is on PyPI as aviasales-mcp (Python 3.12+). uvx fetches and runs it in one step:

AVIASALES_API_TOKEN=your-token-here AVIASALES_MARKET=ru uvx aviasales-mcp

pip install aviasales-mcp puts the same aviasales-mcp command on your PATH. In a client config, use "command": "uvx", "args": ["aviasales-mcp"] with the token in env instead of the docker command in the blocks below.

MCP client configs

Every block runs the same docker command as the terminal snippet above. -e AVIASALES_API_TOKEN with no value hands the container the variable the client sets in env, so the token is written in exactly one place.

Keep the token out of anything you commit. A project-level .mcp.json, .cursor/mcp.json or .zed/settings.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.

Claude Code

Project file: .mcp.json in the project root.

{
  "mcpServers": {
    "aviasales": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "AVIASALES_API_TOKEN",
        "-e", "AVIASALES_MARKET",
        "ghcr.io/stufently/aviasales-mcp:latest"
      ],
      "env": {
        "AVIASALES_API_TOKEN": "your-token-here",
        "AVIASALES_MARKET": "ru"
      }
    }
  }
}

Or from the terminal:

claude mcp add --scope user aviasales \
  -e AVIASALES_API_TOKEN=your-token-here -e AVIASALES_MARKET=ru -- \
  docker run -i --rm -e AVIASALES_API_TOKEN -e AVIASALES_MARKET \
  ghcr.io/stufently/aviasales-mcp:latest

--scope user makes it available in every project and keeps the token in ~/.claude.json, out of the repository. Check with claude mcp list.

Claude Desktop

File: claude_desktop_config.json — macOS ~/Library/Application Support/Claude/claude_desktop_config.json, Windows %APPDATA%\Claude\claude_desktop_config.json, Linux ~/.config/Claude/claude_desktop_config.json.

{
  "mcpServers": {
    "aviasales": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "AVIASALES_API_TOKEN",
        "-e", "AVIASALES_MARKET",
        "ghcr.io/stufently/aviasales-mcp:latest"
      ],
      "env": {
        "AVIASALES_API_TOKEN": "your-token-here",
        "AVIASALES_MARKET": "ru"
      }
    }
  }
}

One click, without editing JSON: download the .mcpb from https://github.com/stufently/aviasales-mcp/releases/latest and open it. Claude Desktop installs the extension and asks for the Travelpayouts API token.

The same release includes checksums.txt, the SHA256 of every file attached to it: the .mcpb, and from the first PyPI release on also the sdist and the wheel, byte for byte the files uploaded to PyPI. Download it into the same directory as the bundle and check it before opening the bundle:

sha256sum -c --ignore-missing checksums.txt   # run next to the downloaded files

On macOS, shasum -a 256 -c checks the same file.

Claude Desktop starts with a trimmed PATH and may not find docker by name: if the server fails to start, replace "docker" with its absolute path (which docker).

Cursor

File: ~/.cursor/mcp.json (every project) or .cursor/mcp.json (this project).

{
  "mcpServers": {
    "aviasales": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "AVIASALES_API_TOKEN",
        "-e", "AVIASALES_MARKET",
        "ghcr.io/stufently/aviasales-mcp:latest"
      ],
      "env": {
        "AVIASALES_API_TOKEN": "your-token-here",
        "AVIASALES_MARKET": "ru"
      }
    }
  }
}

Windsurf

File: mcp_config.json — macOS and Linux ~/.config/devin/mcp_config.json (or $XDG_CONFIG_HOME/devin/mcp_config.json), Windows %APPDATA%\devin\mcp_config.json. Older builds read ~/.codeium/windsurf/mcp_config.json.

{
  "mcpServers": {
    "aviasales": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "AVIASALES_API_TOKEN",
        "-e", "AVIASALES_MARKET",
        "ghcr.io/stufently/aviasales-mcp:latest"
      ],
      "env": {
        "AVIASALES_API_TOKEN": "your-token-here",
        "AVIASALES_MARKET": "ru"
      }
    }
  }
}

Zed

File: settings.json at ~/.config/zed/settings.json (or zed: open settings).

{
  "context_servers": {
    "aviasales": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "AVIASALES_API_TOKEN",
        "-e", "AVIASALES_MARKET",
        "ghcr.io/stufently/aviasales-mcp:latest"
      ],
      "env": {
        "AVIASALES_API_TOKEN": "your-token-here",
        "AVIASALES_MARKET": "ru"
      }
    }
  }
}

Codex

codex mcp add aviasales --env AVIASALES_API_TOKEN=your-token-here -- \
  docker run -i --rm -e AVIASALES_API_TOKEN ghcr.io/stufently/aviasales-mcp:latest

Or by hand in ~/.codex/config.toml:

[mcp_servers.aviasales]
command = "docker"
args = ["run", "-i", "--rm", "-e", "AVIASALES_API_TOKEN", "-e", "AVIASALES_MARKET",
        "ghcr.io/stufently/aviasales-mcp:latest"]

[mcp_servers.aviasales.env]
AVIASALES_API_TOKEN = "your-token-here"
AVIASALES_MARKET = "ru"

Any other stdio client

Command docker, arguments run -i --rm -e AVIASALES_API_TOKEN ghcr.io/stufently/aviasales-mcp:latest, and AVIASALES_API_TOKEN in the environment the client gives the process. The server is also listed in the official MCP registry as io.github.stufently/aviasales-mcp, which clients with a registry browser can install from directly.

Verified clients and OS

Only what was actually run is marked verified. Everything else is a config written from the client's documentation and has not been tried.

Client or path

OS

Status

How

Test suite, Python 3.12 / 3.13 / 3.14

Linux (GitHub ubuntu-latest)

Verified on every PR and push to main

ci.yml; HTTP is mocked

Docker runtime image build

Linux (GitHub ubuntu-latest)

Verified on every PR and push to main

ci.yml

Plain MCP over stdio (initialize, tools/list) with the Docker image

Linux x86_64

Verified 2026-10-12

13 tools listed, every one readOnlyHint: true, destructiveHint: false

Claude Code 2.1.296, Docker command from this README

Linux x86_64

Verified 2026-10-12: connects and lists all 13 tools

A placeholder token; no tool call reached the API in this check

uv run launch used by the .mcpb

Linux, ghcr.io/astral-sh/uv image

Verified 2026-10-10: starts and answers tools/list

Without Claude Desktop

Travelpayouts Data API with a real token

Linux

Verified 2026-07-29 (live probe of the Data API endpoints)

See CHANGELOG

Claude Desktop (.mcpb or JSON config)

macOS, Windows, Linux

Not verified

No Claude Desktop on the test host

Cursor, Windsurf, Zed, Codex

any

Not verified

Configs follow each client's docs as of 2026-10-10

Any client on macOS or Windows

macOS, Windows

Not verified

uvx aviasales-mcp@0.5.3 from PyPI over stdio (initialize, tools/list)

Linux, ghcr.io/astral-sh/uv image

Verified 2026-10-14: 13 tools listed

A placeholder token; no tool call reached the API

Tools

All thirteen tools only read: they search cached fares and reference data. None books, buys, writes or changes anything, and none costs money to call beyond the Travelpayouts rate limit, so there is no separate read-only mode to turn on.

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)

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

Building the image yourself from a checkout, instead of pulling it:

  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

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, 3.13 and 3.14 plus a Docker image build — see .github/workflows/ci.yml.

Releasing

Pushing a v* tag runs .github/workflows/release.yml: the CI suite, then an sdist and a wheel checked against the tag version and twine check, an upload to PyPI through Trusted Publishing (no token stored anywhere), and finally the GitHub Release with the sdist, wheel, .mcpb and checksums.txt. registry.yml publishes the image and the MCP registry entry from the same tag. version in pyproject.toml and server.json must match the tag.

License

GPL-3.0-or-later — see LICENSE.

Available Tools

13 tools
find_nearest_airportsA
Read-onlyIdempotent

Find the airports closest to a place name or to a latitude and longitude.

Use when the user asks which airport to fly into for a town, a resort, or a point on the map. lookup_airports only matches a name, and the nearest airport is rarely named after the town, so call this tool for that question. Feed the returned city code, not the airport code, to search_flights for fares.

Pass either near (resolved against the city and airport datasets) or an explicit latitude/longitude pair.

ParametersJSON Schema
NameRequiredDescriptionDefault
nearNoPlace name or IATA code to search around (e.g. "Pattaya", "UTP").
limitNoMax airports to return (1-50, default 5).
localeNo2-letter locale for names. Defaults to the server's locale.
latitudeNoLatitude in degrees, -90 to 90. Overrides `near`.
longitudeNoLongitude in degrees, -180 to 180. Overrides `near`.
flightable_onlyNoSkip airports with no scheduled service (default True).
max_distance_kmNoIgnore airports further away than this. Optional.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, non-destructive, open-world behavior, so the safety profile is covered. The description adds real behavioral context beyond that: `near` is resolved against both city and airport datasets, and the result carries a city code rather than an airport code. It stops short of describing distance ordering or pagination limits, which keeps it from a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short paragraphs, each doing distinct work: what it does, when to use it versus the sibling plus the downstream handoff, and the input-mode selection. The scoping and routing guidance is front-loaded and no sentence is filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present and annotations covering the safety profile, the description only needs to carry purpose, usage routing, and input-mode selection — all of which it does. An agent has everything required to choose and call this tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the schema already documents each parameter, including the override relationship ('latitude ... Overrides `near`'). The description restates the either/or selection of `near` versus a lat/long pair but adds no format, unit, or constraint detail beyond the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource (find airports closest to a place or coordinates) and immediately contrasts with the sibling lookup_airports, which only matches names. An agent can distinguish the two without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit trigger ('when the user asks which airport to fly into for a town, a resort, or a point on the map'), names the alternative tool and why it fails for this question, and routes the downstream step (feed the returned city code, not airport code, to search_flights). Nothing is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_alternative_directionsA
Read-onlyIdempotent

Get prices for nearby airports and cities around a chosen route.

Use when the traveller can fly from or into a different airport and wants those fares. To learn which airports are near a place, use find_nearest_airports first; for the named city pair only, use search_flights.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax results (1-20, default 10).
marketNo2-letter market whose price cache to read. Defaults to the server's configured market.
originYesOrigin IATA code.
currencyNoPrice currency (3 letters). Defaults to the server's currency.
return_atNoReturn date (YYYY-MM-DD or YYYY-MM). Optional.
destinationYesDestination IATA code.
departure_atNoDeparture date (YYYY-MM-DD or YYYY-MM). Optional.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, openWorldHint and non-destructive, so the safety profile is covered. The description adds scope ('nearby airports and cities') but no extra behavioral detail such as caching, pagination, or result freshness. Adequate but not rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences, front-loading the purpose and then the routing guidance. No wasted text, though it is slightly denser than strictly necessary.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values need no explanation, and annotations cover safety. The description supplies the selection logic relative to siblings, making it complete enough for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all seven parameters (origin, destination, dates, currency, market, limit) are already documented. The description adds no meaning beyond the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Get prices for nearby airports and cities around a chosen route') with clear scope. It is immediately distinguishable from search_flights (named city pair) and find_nearest_airports (airport discovery).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says when to use it ('when the traveller can fly from or into a different airport') and routes to alternatives: find_nearest_airports for discovery and search_flights for the exact city pair. Nothing is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_city_directionsA
Read-onlyIdempotent

List the cheapest destinations reachable from a city, with a fare and dates.

Use when the user asks where they can fly from a city, or wants somewhere cheap without naming a destination. For who flies into a city use get_popular_directions; to price one chosen route afterwards use search_flights or get_prices_calendar.

ParametersJSON Schema
NameRequiredDescriptionDefault
originYesOrigin city IATA code (e.g. "MOW"). Use `lookup_cities` to resolve a city name first.
currencyNoPrice currency (3 letters). Defaults to the server's currency.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, openWorldHint and destructiveHint=false, so the safety profile is fully covered by structured data. The description adds useful context that results include fares and dates, but discloses nothing about pagination, result limits, or currency behavior beyond what's in the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences, front-loaded with the core action and immediately followed by routing guidance. No filler or repetition of schema content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-value details need not be spelled out; the description covers action, scope, and sibling routing for a two-parameter read-only tool. Nothing an agent needs to select or call it is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both parameters (origin IATA, currency) are already documented in the schema, including the pointer to lookup_cities. The description's 'from a city' adds no meaning beyond the schema's 'Origin city IATA code'.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List the cheapest destinations reachable from a city') plus scope ('with a fare and dates'), and explicitly distinguishes itself from the similarly-named siblings get_popular_directions and get_alternative_directions.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit when-to-use condition ('user asks where they can fly from a city, or wants somewhere cheap without naming a destination') and routes to named alternatives (get_popular_directions for inbound, search_flights/get_prices_calendar for pricing a chosen route).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_flexible_date_pricesA
Read-onlyIdempotent

Compare prices for the days around a departure and an optional return.

Use when the user already has dates and asks whether shifting a day either way would be cheaper. For one exact date use search_flights; for the cheapest day across a whole month use get_prices_calendar. This covers roughly a week around both the outbound and the return.

ParametersJSON Schema
NameRequiredDescriptionDefault
adultsNoNumber of adult passengers, 1-9 (default 1).
marketNo2-letter market whose price cache to read. Defaults to the server's configured market.
originYesOrigin IATA code.
infantsNoNumber of infants under 2, 0-8 (default 0).
childrenNoNumber of children 2-11 years, 0-8 (default 0).
currencyNoPrice currency (3 letters). Defaults to the server's currency.
trip_classNo"economy", "comfort", "business" or "first" (default "economy").economy
depart_dateYesIntended departure date (YYYY-MM-DD). Required.
destinationYesDestination IATA code.
return_dateNoIntended return date (YYYY-MM-DD). Omit for one-way.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnly, idempotent, non-destructive, openWorld), so the bar is lower. The description adds genuinely useful scope context — roughly a week of dates around both outbound and return — which the annotations do not convey. It stops short of describing caching behavior or result volume, keeping it at a 4.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences, front-loaded with the action, then the usage trigger, then the alternatives. Every sentence earns its place with no redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained, and the annotations carry the safety profile. For a read-only, fully-documented 10-parameter query tool, the description covers what an agent needs to select and call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all ten parameters including the adult/child/infant breakdown and date formats. The description only implicitly touches depart_date/return_date via 'days around', adding little beyond the schema. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Compare prices for the days around a departure and an optional return') and immediately contrasts itself with two named siblings. An agent can distinguish it from search_flights and get_prices_calendar without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit trigger ('user already has dates and asks whether shifting a day either way would be cheaper') and routes the two adjacent cases to the correct alternatives with their selecting conditions. Nothing is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_latest_pricesA
Read-onlyIdempotent

Get the most recently found flight prices from other travellers' searches.

Use when the user wants the latest fares that just appeared, on one route or across the whole cache. For a specific trip on chosen dates use search_flights instead. Prices are per adult (cached); passenger parameters are encoded into each booking_link.

These rows come from the older v2 shape: they name the selling agency rather than an airline, carry no flight number, and their booking_link is reconstructed from the route and dates.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax results (1-100, default 20).
adultsNoNumber of adult passengers, 1-9 (default 1).
marketNo2-letter market whose price cache to read. Defaults to the server's configured market.
originNoOrigin IATA code. Optional.
infantsNoNumber of infants under 2, 0-8 (default 0). Cannot exceed the number of adults; the excess is trimmed.
one_wayNoOne-way tickets only.
childrenNoNumber of children 2-11 years, 0-8 (default 0). Adults plus children cannot exceed 9; the excess is trimmed.
currencyNoPrice currency (3 letters). Defaults to the server's currency.
trip_classNo"economy", "comfort", "business" or "first" (default "economy").economy
destinationNoDestination IATA code. Optional.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover the read-only, idempotent safety profile, so the bar is lower, but the description adds real behavioral context: rows are cached v2-shape data naming an agency rather than an airline, lack flight numbers, and have reconstructed booking_links. The only thing not addressed is pagination/ordering of results, which is minor given the output schema exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight paragraphs: purpose and scope first, the routing alternative second, the data-shape caveat last. Every sentence adds information an agent needs; nothing is redundant.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 10-parameter read tool with full schema coverage, full annotations, and an output schema, the description fills the remaining gaps: routing to the correct sibling and warning about the legacy v2 row shape. Nothing material is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so every parameter is already documented in the schema, and the output schema covers the response. The description adds only incidental parameter-relevant notes (per-adult pricing, passenger details encoded in booking_link), not syntax or format guidance beyond the schema. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names a specific verb (get) and resource (latest flight prices from other travellers' searches), and explicitly contrasts itself with search_flights. An agent can disambiguate it from all twelve siblings without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit trigger ('when the user wants the latest fares that just appeared') plus a named alternative ('For a specific trip on chosen dates use search_flights instead'). Both the use and the when-not-to-use case are stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_prices_calendarA
Read-onlyIdempotent

Get grouped calendar prices for a route, one fare per day or per month.

Use when the user asks which day or month is cheapest to fly a known route. For fares on one specific date use search_flights; for a few days either side of dates already chosen use get_flexible_date_prices. Codes are IATA; use lookup_cities to resolve a name first.

Prices are per adult (cached); passenger parameters are encoded into each booking_link.

ParametersJSON Schema
NameRequiredDescriptionDefault
adultsNoNumber of adult passengers, 1-9 (default 1).
marketNo2-letter market whose price cache to read (e.g. "us", "ru"). Defaults to the server's configured market.
originYesOrigin IATA code.
infantsNoNumber of infants under 2, 0-8 (default 0). Cannot exceed the number of adults; the excess is trimmed.
childrenNoNumber of children 2-11 years, 0-8 (default 0). Adults plus children cannot exceed 9; the excess is trimmed.
currencyNoPrice currency (3 letters). Defaults to the server's currency.
group_byNoGroup results by "departure_at" or "month" (default "departure_at").departure_at
return_atNoReturn month (YYYY-MM). Optional.
trip_classNo"economy", "comfort", "business" or "first" (default "economy").economy
destinationYesDestination IATA code.
departure_atNoDeparture month (YYYY-MM). Optional.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive, so the safety profile is covered. The description adds real behavioral context beyond that: prices are cached, quoted per adult, and passenger counts are encoded into the booking_link rather than affecting the returned fare. It stops short of describing coverage limits or freshness of the cache, so it is not a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short blocks: what it returns, when to use it versus siblings, and pricing/param caveats. The routing rules are front-loaded before the caveats, and no sentence is redundant.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present and rich annotations, the description does not need to explain return values, and it covers usage, code semantics, and pricing basis. The only mild gap is the absence of any note on cache staleness or result scope given the market parameter selects a cache.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description goes one step further by telling the agent that the location fields are IATA codes and that lookup_cities must be used to resolve plain names first, plus clarifying that passenger parameters are baked into booking_link rather than the quoted price — details the schema does not spell out.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource ("Get grouped calendar prices for a route") and immediately clarifies the granularity of the result ("one fare per day or per month"), which maps directly to the group_by enum. It is clearly distinguishable from siblings like search_flights and get_flexible_date_prices without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states the exact scenario for this tool ("which day or month is cheapest to fly a known route") and then names two alternatives with the conditions that select them: search_flights for one specific date, get_flexible_date_prices for a few days either side. It also routes to lookup_cities when codes must be resolved from a name.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

lookup_airlinesA
Read-onlyIdempotent

Look up airlines by name or IATA code.

Use when the user asks which airline a code belongs to, or wants the IATA code for an airline name. For an airport, city, or country code use lookup_airports, lookup_cities, or lookup_countries; for fares use search_flights.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax results to return (1-500, default 50).
localeNo2-letter locale for names (e.g. "en", "ru"). Defaults to the server's locale.
searchNoAirline name substring or exact IATA code (e.g. "aeroflot", "SU"). Omit to list airlines from the start of the dataset.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, openWorldHint, and destructiveHint=false, so the safety profile is fully covered without description help. The description adds only routing context, disclosing nothing about result caps, dataset ordering, or locale-dependent output beyond what the schema states. Adequate but adds little behavioral value.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight paragraphs; the capability statement is front-loaded and the sibling routing follows, with zero filler. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained, and the annotations carry the safety semantics. With all three parameters documented in the schema and clear routing, nothing an agent needs to invoke this correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%: search (name substring or exact IATA), locale, and limit are all documented in the schema with examples and defaults. The description's mention of 'name or IATA code' restates the search parameter rather than adding syntax or edge-case guidance, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Look up airlines') plus the two lookup keys (name or IATA code), immediately telling the agent what entity this resolves. It is clearly distinguished from lookup_airports, lookup_cities, lookup_countries, and search_flights, all of which are named explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives the triggering condition ('user asks which airline a code belongs to, or wants the IATA code for an airline name') and routes the agent away from this tool for airports, cities, countries, and fares by naming the correct alternatives. Nothing about when-not-to-use is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

lookup_airportsA
Read-onlyIdempotent

Look up airports by name, IATA code, or city code.

Use when the user names an airport or a code and needs its city, country, or coordinates. For the closest airport to a town that does not share the airport's name, use find_nearest_airports instead of this tool.

The full dataset is ~10k airports, so always pass search — an unfiltered call just returns the first limit entries in dataset order. Results are ranked: exact code, then exact city code, then name matches, with airports you cannot actually fly to last.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax results to return (1-500, default 50).
localeNo2-letter locale for names (e.g. "en", "ru"). Defaults to the server's locale.
searchNoAirport name substring, exact IATA code, or city code (e.g. "heathrow", "LHR", "MOW").

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare this read-only, idempotent, open-world and non-destructive, so the safety profile is covered. The description goes further, disclosing dataset scale (~10k), the consequence of an unfiltered call (first `limit` in dataset order), and the ranking order with 'can't fly to' airports last. This is rich behavioral context beyond annotations; only return-shape detail is missing, and an output schema exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core verb and keys, then the routing rule, then the operational caveat and ranking order. Four tight clauses, each earning its place with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a three-parameter lookup with annotations and an output schema, everything an agent needs is present: when to call it, when to call the sibling instead, the mandatory search argument, and how results are ranked. Nothing material is omitted.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so parameters are already documented. The description adds meaning beyond the schema by giving examples of each search key (name substring, exact IATA code, city code) and by stating that an unfiltered call behaves differently from a filtered one, which informs how to use `limit`.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a clear verb and resource ('look up airports') and specifies the three lookup keys (name, IATA code, city code). It explicitly distinguishes itself from the sibling find_nearest_airports, so an agent can route correctly without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit when-to-use ('user names an airport or code and needs city/country/coordinates') and when-not (redirects to find_nearest_airports for towns not sharing the airport's name). It even adds an operational constraint: always pass search. Nothing is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

lookup_citiesA
Read-onlyIdempotent

Look up cities by name or IATA code and return the code flight tools expect.

Use when the user names a city and a flight search needs its IATA code. For an airport code use lookup_airports; for the nearest airport to a place that is not itself a city, use find_nearest_airports.

Every flight tool takes IATA codes, so this is usually the first call when the user names a place. The full dataset is ~9.6k cities, so always pass search. Names are only available in the requested locale: searching "Мюнхен" needs locale="ru".

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax results to return (1-500, default 50).
localeNo2-letter locale for names (e.g. "en", "ru"). Defaults to the server's locale.
searchNoCity name substring or exact IATA code (e.g. "bangkok", "BKK").

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, openWorld and non-destructive, so the safety profile is covered. The description adds genuinely new behavioral context: the ~9.6k city dataset means search must always be supplied, and names are locale-bound ('searching "Мюнхен" needs locale="ru"'), which is a real failure mode an agent would otherwise hit.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the purpose, then routes to alternatives, then closes with the two operational constraints. Every sentence carries information; nothing is restated from the schema or annotations.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need no explanation. Combined with full annotation coverage and complete parameter descriptions, the description supplies exactly the missing pieces: sibling routing, dataset scale, and locale-dependent matching.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds meaning beyond the schema: it explains why `search` should always be passed and that `locale` gates which name spellings will match. `limit` is left to the schema, which documents it fully, so no gap remains.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (look up) and resource (cities) plus the output contract: the IATA code flight tools expect. It explicitly distinguishes itself from lookup_airports and find_nearest_airports by name, so an agent can route correctly without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit when-to-use condition ('when the user names a city and a flight search needs its IATA code'), names two sibling alternatives with the conditions that select them ('for an airport code use lookup_airports', 'for the nearest airport to a place that is not itself a city, use find_nearest_airports'), and adds the imperative 'always pass search'.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

lookup_countriesA
Read-onlyIdempotent

Look up countries by name or two-letter country code.

Use when the user asks which country a code belongs to, or wants that country's code or currency. For a city or airport code use lookup_cities or lookup_airports; this tool does not search flight prices.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax results to return (1-500, default 50).
localeNo2-letter locale for names (e.g. "en", "ru"). Defaults to the server's locale.
searchNoCountry name substring or exact code (e.g. "thailand", "TH").

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already carry readOnlyHint, idempotentHint, openWorldHint and destructiveHint=false, so the safety profile is fully covered by structured fields. The description adds only light behavioral value: the scope exclusion about flight prices and the fact that currency is returned. No pagination or locale behavior is disclosed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences with the primary capability front-loaded and the sibling routing in the second. No filler or restatement of the tool name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present and rich annotations, the description only needs to carry purpose, usage context and sibling routing, all of which it does. Nothing required for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so limit, locale and search are already documented in the schema. The description mentions the two accepted lookup forms but adds no format or constraint detail beyond what the schema provides; baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Look up countries') and the two acceptable input forms (name or two-letter country code). It also names the sibling tools it is not (lookup_cities, lookup_airports), so an agent can distinguish it without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit activation conditions are given ('when the user asks which country a code belongs to, or wants that country's code or currency'), plus named alternatives for the confusable cases and an explicit exclusion ('this tool does not search flight prices').

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_by_price_rangeA
Read-onlyIdempotent

Find flights whose cached fare falls inside a minimum and maximum price.

Use when the user has a budget, including anywhere under a price with no destination named. Leave destination unset to let the budget pick the city; prices are per adult in economy. For a named route on a date or a month use search_flights or get_prices_calendar.

There is deliberately no date argument: this endpoint ignores one (verified — passing a December date returns the same July and September fares), and each result carries its own departure_at.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax results (1-100, default 20).
marketNo2-letter market whose price cache to read. Defaults to the server's configured market.
originYesOrigin IATA code.
currencyNoPrice currency (3 letters). Defaults to the server's currency.
value_maxYesHighest acceptable price, in `currency`.
value_minYesLowest acceptable price, in `currency`.
destinationNoDestination IATA code. Optional — omit to search anywhere.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations by disclosing that fares come from a cache, that pricing is per adult in economy, and — importantly — that a date argument is deliberately absent because the endpoint ignores one, verified empirically, with each result carrying its own `departure_at`. It doesn't mention result ordering, staleness windows, or rate limits, so it stops short of a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences with the core behavior front-loaded, followed by the usage router and then the non-obvious date caveat. Every sentence carries distinct information; no preamble or restatement of the title.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return formatting is unnecessary, and the description covers what an agent needs to choose and call the tool: scope, routing to siblings, the intentional absence of a date param, and the interpretation of the price bounds. Nothing material is missing for a 7-param read-only search.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3, but the description adds real meaning: omitting `destination` switches the tool to an anywhere/budget-driven mode, and price bounds are framed as per-adult economy fares in the active currency. These contextualize otherwise mechanical min/max fields.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Find flights whose cached fare falls inside a minimum and maximum price'), naming the exact retrieval mechanism (cached fare) rather than a generic search. It explicitly differentiates itself from `search_flights` and `get_prices_calendar`, so an agent can pick it without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit trigger ('when the user has a budget, including anywhere under a price with no destination named'), an explicit parameter rule ('Leave destination unset to let the budget pick the city'), and names the two sibling alternatives plus the condition that selects them. Nothing is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_flightsA
Read-onlyIdempotent

Search flight prices between two cities on a date or across a month.

Use when the user names both ends of a route and wants fares, a booking link, or only departures inside a time window. For the cheapest day in a month use get_prices_calendar; for the days around dates already chosen use get_flexible_date_prices; for a budget with no destination use search_by_price_range.

Both codes must be IATA — call lookup_cities first if you only have a city name. For nearby airports use get_alternative_directions. A multi-city trip needs one call per leg.

Note on passengers: the price data comes from a cache of recent searches and is always PER ADULT in economy. The adults/children/infants/trip_class parameters are encoded into each ticket's booking_link, so the link opens Aviasales with the full party pre-filled and shows the real total price.

Durations: each ticket reports duration_total (full door-to-door travel time), duration_to/duration_back (pure flight time per direction) and layover_minutes (combined ground time between connecting flights; 0 for direct flights). All values are in minutes.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax number of results (1-100, default 10).
adultsNoNumber of adult passengers, 1-9 (default 1).
directNoIf True, show only non-stop flights.
marketNo2-letter market whose price cache to read (e.g. "us", "ru", "th"). The same route in the same currency is priced differently per market, so set this to the traveller's country. Defaults to the server's configured market.
originYesOrigin city IATA code (e.g. "MOW", "LED").
infantsNoNumber of infants under 2, 0-8 (default 0). Cannot exceed the number of adults; the excess is trimmed.
one_wayNoIf True, search one-way tickets only.
childrenNoNumber of children 2-11 years, 0-8 (default 0). Adults plus children cannot exceed 9; the excess is trimmed.
currencyNoPrice currency code (3 letters, e.g. "rub", "usd"). Defaults to the server's configured currency.
return_atNoReturn date or month (YYYY-MM-DD or YYYY-MM). Optional.
trip_classNo"economy", "comfort", "business" or "first" (default "economy").economy
destinationYesDestination city IATA code (e.g. "IST", "BCN").
depart_afterNoKeep only flights departing at or after this local time ("HH:MM", 24-hour). Optional.
departure_atNoDeparture date or month (YYYY-MM-DD or YYYY-MM). Optional; a month searches every day in it.
depart_beforeNoKeep only flights departing at or before this local time ("HH:MM", 24-hour). Optional. Combined with depart_after and set earlier than it, the window wraps midnight (e.g. 22:00-06:00).

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive, so the bar is lower. The description still adds non-obvious behaviour: prices come from a cache of recent searches, are always PER ADULT in economy, and the party size/trip class are only encoded into the booking_link. That is a genuine gotcha an agent would otherwise mis-handle. It stops short of describing result-paging or no-results behaviour.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded and well-paragraphed: purpose, then sibling routing, then prerequisites, then caveats. Slight redundancy in the closing 'Durations' paragraph, which explains return fields already covered by the output schema, but every other sentence drives a routing or invocation decision.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 15-parameter, open-world search tool this is complete: routing, prerequisites, passenger/pricing semantics, and multi-leg handling are all covered. Safety is carried by annotations, parameter detail by a 100%-covered schema, and return shape by the output schema, so nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3, but the description adds real meaning beyond it: the passengers/trip_class parameters do NOT change the returned price, they only pre-fill the booking link and reveal the true total. The IATA-code constraint on origin/destination is also reinforced in prose. It adds semantics the schema's field descriptions do not convey.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource+scope: 'Search flight prices between two cities on a date or across a month.' It immediately distinguishes itself from four named siblings (get_prices_calendar, get_flexible_date_prices, search_by_price_range), so an agent can route without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit when-to-use ('user names both ends of a route and wants fares, a booking link, or only departures inside a time window') plus named alternatives with the exact condition that selects each. Prerequisites are also stated: both codes must be IATA, call lookup_cities first, one call per leg for multi-city, get_alternative_directions for nearby airports.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 13 tool updatesv0.5.3
    • First observedfind_nearest_airports
    • First observedget_alternative_directions
    • First observedget_city_directions
    • First observedget_flexible_date_prices
    • First observedget_latest_prices
    • First observedget_popular_directions
    • First observedget_prices_calendar
    • First observedlookup_airlines
    • First observedlookup_airports
    • First observedlookup_cities
    • First observedlookup_countries
    • First observedsearch_by_price_range
    • First observedsearch_flights

TDQS

A4.3/5.0

Scored across 13 tools

Disambiguation4/5

The price-search tools (search_flights, get_prices_calendar, get_flexible_date_prices, search_by_price_range, get_latest_prices) overlap conceptually, but each description explicitly states its trigger and points to sibling tools, which largely removes misselection risk. The direction trio (get_popular_directions vs get_city_directions vs get_alternative_directions) is the closest to confusing, yet descriptions clarify inbound vs outbound vs nearby-airport semantics.

Naming Consistency4/5

All names are snake_case verb_noun and highly readable, with consistent get_/lookup_/search_/find_ prefixes. Minor deviation: retrieval verbs vary (lookup_cities vs find_nearest_airports vs get_popular_directions) for lookups that return lists, but the pattern stays predictable.

Tool Count5/5

13 tools is squarely in the well-scoped range and each earns its place: four lookup/resolution tools, one core search, four price-variation tools, and four direction/alternative tools. No redundant or filler tools are present.

Completeness4/5

The read-only flight-price discovery domain is well covered end to end: code resolution, nearest-airport resolution, route search, calendar/flexible/range pricing, latest fares, and directional discovery. Minor gap is absence of a tool to fetch a specific offer's details (e.g. baggage/flight number), though booking links are provided as a workaround.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    Flight search for AI agents: flexible-date cheapest round-trips with a good-price verdict from historical data. Hosted remote MCP, free, no key.
    3
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Enables real-time flight fare searches across date ranges and multiple destinations, with historical price insights and booking links. Provides one-way and round-trip search tools through MCP.
    4
    1
    MIT