An MCP server that exposes Ryanair's anonymous flight APIs as tools an LLM can call.
Fare search · price calendars · timetables · the airport/route network — over stdio or streamable HTTP.
Warning
Unofficial. This project consumes Ryanair's public, unauthenticated endpoints and is not affiliated with or endorsed by Ryanair. The APIs are undocumented and may change or rate-limit without notice.
- Features
- Install
- Usage
- Tools
- Agent skill
- How it works
- Development
- Project layout
- Limitations
- Roadmap
- Contributing
- License
- 12 read tools covering Ryanair's full anonymous API surface — one-way and return fares, price calendars, cheapest-weekend search, timetables, and the airport/route network.
- Price history — fares carry
previous_price/price_updated/new_routewhen Ryanair reports them, so callers can spot price drops and newly-added routes. - Resilient client — session priming, User-Agent rotation, capped retries, and a cached network bundle (see How it works).
- Two transports — stdio (default) for clients that spawn a subprocess, or streamable HTTP.
- No keys, no accounts — everything runs against public endpoints.
Requires Go 1.26+.
go build -o ryanair-mcp ./cmd/ryanair-mcp# stdio (default) — for MCP clients that spawn the server as a subprocess
./ryanair-mcp
# streamable HTTP
./ryanair-mcp --transport http --addr :8080| Flag | Default | Description |
|---|---|---|
--transport |
stdio |
stdio or http |
--addr |
:8080 |
listen address (HTTP transport only) |
For a stdio client (e.g. Claude Desktop), point it at the built binary:
{
"mcpServers": {
"ryanair": {
"command": "/absolute/path/to/ryanair-mcp"
}
}
}Multi-arch images (linux/amd64, linux/arm64) are published to
GHCR
on every release, tagged with the version (e.g. 0.2.0), MAJOR.MINOR, and
latest.
# stdio (attach via -i so the client can speak over stdin/stdout)
docker run -i --rm ghcr.io/adambenhassen/ryanair-mcp:latest
# streamable HTTP
docker run --rm -p 8080:8080 ghcr.io/adambenhassen/ryanair-mcp:latest \
--transport http --addr :8080| Tool | What it does | Key inputs |
|---|---|---|
search_one_way |
Cheapest one-way fares from an origin in a date window. Omit destination/country to search anywhere. | origin, date_from, date_to, (opt) destination, country, max_price, currency |
search_return |
Cheapest return fares across outbound and inbound windows, with optional trip-length bounds. | origin, date_from, date_to, return_from, return_to, (opt) min_trip_days, max_trip_days, … |
cheapest_per_day |
Cheapest one-way fare per day of a month on a route (price calendar). | origin, destination, month (YYYY-MM-01), (opt) currency |
cheapest_return_per_day |
Cheapest return fare per day on a route, outbound and inbound calendars side by side. | origin, destination, outbound_month (YYYY-MM-01), (opt) inbound_month, min_trip_days, max_trip_days, currency |
cheapest_weekend |
Cheapest Fri→Sun (or Fri→Mon) return weekend on a route over the next few months. | origin, destination, (opt) months_ahead (default 3), weekend_length (2|3, default 2) |
get_active_dates |
Dates a route is currently bookable (ISO dates, no prices). | origin, destination |
get_schedules |
Published timetable (days/times a route runs, no prices) for a month. | origin, destination, year, month |
list_airports |
List Ryanair airports filtered by country, or look up one airport's full metadata (city, region, timezone, coordinates) by IATA code. | (opt) country (ISO-3166 alpha-2), code (IATA) |
explore_destinations |
Airports reachable from an origin (each flagged seasonal and carrying region/country metadata), optionally annotated with cheapest fares (with_fares) or per-route operator/recent/tags details (with_route_details), filtered, and grouped. |
origin, (opt) with_fares, with_route_details, date_from, date_to, currency, country, region, city, group_by (country|region) |
Airport inputs are IATA codes (e.g. DUB, STN). Dates are ISO YYYY-MM-DD.
Currencies are ISO 4217 (e.g. EUR).
A SKILL.md ships under
skills/ryanair-flights/, following the Agent Skills
open standard (compatible with Claude, Hermes, Cursor, and Codex). It tells an
agent when to reach for this server and how to drive its tools. Point your
agent's skills directory at that folder, or copy it in.
- Session priming. Cold calls to the services API sometimes return
403, so the client warms a cookie jar againstwww.ryanair.comonce before the first request. - Network caching. The airport/route bundle backing
list_airportsandexplore_destinationsis cached for 6 hours. - Retries. Requests retry up to 3 times with capped exponential backoff,
only on
429,5xx, and network errors. Other failures surface immediately as anAPIErrorcarrying the endpoint, status, and a body snippet. - User-Agent rotation. Each request picks a realistic desktop browser UA; Ryanair blocks obvious non-browser clients.
go test ./... # unit tests (parsing, quirks, retry classification, validation)
golangci-lint run # lint (strict config in .golangci.yml)Tests run against recorded fixtures in internal/ryanair/testdata/ — no network
access required.
A build-tagged live smoke test hits the real Ryanair endpoints to catch
wire-format or endpoint drift. It is excluded from build/PR CI (so pull requests
never depend on Ryanair's availability) and instead runs on a daily schedule via
.github/workflows/live.yml. Run it locally too:
go test -tags live ./internal/ryanair/ -vcmd/ryanair-mcp entry point, flag parsing, transport selection
internal/server builds the MCP server, runs stdio / streamable HTTP
internal/tools MCP tool definitions; clean domain types only
internal/ryanair typed client; all Ryanair wire-format quirks live here
- Read-only. No booking or seat-availability endpoints.
- Session-based (authenticated) endpoints. Today we cover only Ryanair's
public, unauthenticated read surface. Booking flows, seat availability/seat
maps, and live pricing sessions (bags, fare classes) sit behind Ryanair's
session/login flow and return
409without one. Bringing these in means reverse-engineering and maintaining that auth flow — a larger, more fragile effort tracked here as future scope, not yet started.
Contributions are welcome — see CONTRIBUTING.md for the dev workflow and conventions, and SECURITY.md to report a vulnerability. Notable changes are tracked in CHANGELOG.md.
MIT © Adam Benhassen