fli
Google Flights MCP, CLI and Python Library
Install / Use
claude mcp add punitarani -- npx -y github:punitarani/fliIf the server publishes to npm under a different name, use that package instead — check the repo README.
MCP Server
Model Context Protocol server
Quality Score
Category
Development & EngineeringSupported Platforms
Our assessment of fli
fli scores 88/100 on our quality scale, 1798th of 4,617 Development & Engineering skills we index (top 39%).
Its MCP Server is 28 KB long, well organised into 66 sections with 17 code examples: a thorough specification that gives an agent plenty to work with.
With 3,478 GitHub stars, it is one of the more widely adopted skills in the catalogue.
Maintenance, license and trust
- The repository was last updated about 2 months ago, so fli is actively maintained.
- Our last check on 2026-10-21 found the source still online.
- It is released under the MIT license, a permissive license that allows use, modification and commercial use with attribution.
- Its trust signals score 95/100, with 1 caution from licensing, adoption, age or documentation. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.
Safety scan
No issues foundOur scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands. An AI review of the same text found nothing harmful.
AI review by kimi-k2.7-code on 2026-09-24. Automated pattern scan on 2026-09-24. It catches known dangerous patterns, not every risk — read a skill before letting an agent act on it.
fli compared with similar skills
All 4 of these similar skills score higher than fli; compare them before choosing.
| Skill | Score | Stars | Updated | Format |
|---|---|---|---|---|
| fli (this skill)by punitarani | 88 | 3.5k | 46d ago | MCP Server |
| taste-skillby Leonxlnx | 100 | 110.6k | today | CLAUDE.md |
| Agent-Reachby Panniantong | 100 | 109.2k | today | CLAUDE.md |
| headroomby headroomlabs-ai | 100 | 78.9k | today | CLAUDE.md |
| ai-job-searchby ai-job-search-dev | 100 | 69.8k | today | CLAUDE.md |
Frequently asked questions
- How do I install fli?
- Run
claude mcp add punitarani -- npx -y github:punitarani/fli. The install tabs above show the steps for each supported agent. - Which AI agents does fli work with?
- It is written for Claude Code and Claude Desktop, as a MCP Server file. Other agents that read the same format can often use it too.
- Is fli safe to use?
- Our scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands. An AI review of the same text found nothing harmful. It is MIT-licensed and scores 95/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
- Is fli still maintained?
- The repository was last updated about 2 months ago, so fli is actively maintained.
Skill content
View source on GitHub🛫 Fli - Flight Search MCP Server and Library
A powerful Python library that provides programmatic access to Google Flights data with an elegant CLI interface. Search flights, find the best deals, and filter results with ease.
🚀 What makes
flispecial? Unlike other flight search libraries that rely on web scraping, Fli directly interacts with Google Flights' API through reverse engineering. This means:
- Fast: Direct API access means faster, more reliable results
- Zero Scraping: No HTML parsing, no browser automation, just pure API interaction
- Reliable: Less prone to breaking from UI changes
- Modular: Extensible architecture for easy customization and integration
MCP Server
pipx install flights
# Run the MCP server on STDIO
fli-mcp
# Run the MCP server over HTTP (streamable)
fli-mcp-http # serves at http://127.0.0.1:8000/mcp/

Connecting to Claude Desktop
{
"mcpServers": {
"fli": {
"command": "/Users/<user>/.local/bin/fli-mcp"
}
}
}
Note: Replace
<user>with your actual username. You can also find the path to the MCP server by runningwhich fli-mcpin your terminal.
MCP Tools Available
The MCP server provides two main tools:
| Tool | Description |
|----------------------|-------------------------------------------------------------|
| search_flights | Search for flights on a specific date with detailed filters |
| search_dates | Find the cheapest travel dates across a flexible date range |
search_flights Parameters
| Parameter | Type | Description |
|---------------------|--------|-------------------------------------------------------------|
| origin | string | Departure airport IATA code(s) — comma-separated for multi |
| destination | string | Arrival airport IATA code(s) — comma-separated for multi |
| departure_date | string | Travel date in YYYY-MM-DD format |
| return_date | string | Return date for round trips (optional) |
| cabin_class | string | ECONOMY, PREMIUM_ECONOMY, BUSINESS, or FIRST |
| max_stops | string | ANY, NON_STOP, ONE_STOP, or TWO_PLUS_STOPS |
| departure_window | string | Time window in 'HH-HH' format (e.g., '6-20') |
| airlines | list | Filter by airline codes (e.g., ['BA', 'AA']) |
| exclude_airlines | list | Airline IATA codes to exclude (e.g., ['DL', 'B6']) |
| alliance | list | Restrict to alliances: ONEWORLD, SKYTEAM, STAR_ALLIANCE |
| exclude_alliance | list | Alliance names to exclude from results |
| min_layover | int | Minimum layover duration in minutes (multi-stop only) |
| max_layover | int | Maximum layover duration in minutes (multi-stop only) |
| top_n | int | Round-trip only: outbound options expanded into return flights (default 5, 1-10) |
| currency | string | ISO 4217 code (e.g. 'EUR', 'JPY') — flows to curr= param |
| language | string | BCP-47 language code (e.g. 'en-GB') — flows to hl= param |
| country | string | ISO 3166-1 alpha-2 country code (e.g. 'GB') for gl= param |
| sort_by | string | CHEAPEST, DURATION, DEPARTURE_TIME, or ARRIVAL_TIME |
| passengers | int | Number of adult passengers |
| children | int | Number of children (ages 2-11) |
| infants_in_seat | int | Number of infants (under 2) occupying their own seat |
| infants_on_lap | int | Number of lap infants (under 2, no seat) |
Total travelers (
passengers + children + infants_in_seat + infants_on_lap) must be between 1 and 9, andinfants_on_lapcannot exceedpassengers.A round trip costs
1 + top_npage fetches (one outbound search, plus one per outbound candidate expanded into return flights), sotop_nis capped at 10. Round-trip results all from one airline? Raisetop_n, or sort differently — the default sort only ever expands the cheapesttop_noutbounds, which are often the same carrier.
search_dates Parameters
| Parameter | Type | Description |
|---------------------|--------|-------------------------------------------------------------|
| origin | string | Departure airport IATA code(s) — comma-separated for multi |
| destination | string | Arrival airport IATA code(s) — comma-separated for multi |
| start_date | string | Start of date range in YYYY-MM-DD format |
| end_date | string | End of date range in YYYY-MM-DD format |
| trip_duration | int | Trip duration in days (for round-trips) |
| is_round_trip | bool | Whether to search for round-trip flights |
| cabin_class | string | ECONOMY, PREMIUM_ECONOMY, BUSINESS, or FIRST |
| max_stops | string | ANY, NON_STOP, ONE_STOP, or TWO_PLUS_STOPS |
| departure_window | string | Time window in 'HH-HH' format (e.g., '6-20') |
| airlines | list | Filter by airline codes (e.g., ['BA', 'AA']) |
| exclude_airlines | list | Airline IATA codes to exclude |
| alliance | list | Restrict to alliances: ONEWORLD, SKYTEAM, STAR_ALLIANCE |
| exclude_alliance | list | Alliance names to exclude |
| min_layover | int | Minimum layover duration in minutes |
| max_layover | int | Maximum layover duration in minutes |
| currency | string | ISO 4217 currency code (e.g. 'EUR', 'JPY') |
| language | string | BCP-47 language code (e.g. 'en-GB') |
| country | string | ISO 3166-1 alpha-2 country code (e.g. 'GB') |
| sort_by_price | bool | Sort results by price (lowest first) |
| passengers | int | Number of adult passengers |
| children | int | Number of children (ages 2-11) |
| infants_in_seat | int | Number of infants (under 2) occupying their own seat |
| infants_on_lap | int | Number of lap infants (under 2, no seat) |
Same passenger limits as
search_flights: total 1-9,infants_on_lap≤passengers.
Quick Start
pip install flights
# Install using pipx (recommended for CLI)
pipx install flights
# Get started with CLI
fli --help

Features
-
🔍 Powerful Search
- One-way flight searches
- Multi-city flight searches
- Flexible departure times
- Multi-airline support
- Cabin class selection
- Stop preferences
- Custom result sorting
-
💺 Cabin Classes
- Economy
- Premium Economy
- Business
- First
-
🎯 Smart Sorting
- Price
- Duration
- Departure Time
- Arrival Time
-
🛡️ Built-in Protection
- Rate limiting
- Automatic retries
- Comprehensive error handling
- Input validation
Search transport
Searches are served by Google's public search page rather than the
FlightsFrontendService RPC. Since 2026-08 GetShoppingResults and
GetCalendarGraph require an x-goog-batchexecute-bgr header that only the
page's own JavaScript can produce, so a plain HTTP client gets HTTP 200 with no
payload. Fli issues GET https://www.google.com/travel/flights?tfs=<protobuf>
instead and reads the results out of the page's inline AF_initDataCallback
blob keyed ds:1.
What that means in practice:
- Three filters are not supported.
emissions,bagsandexclude_basic_economyhave notfsfield and cannot be reconstructed from the decoded rows, so they are dropped with a warning. Stops, cabin, passengers, alliances and layover bounds ride in the request; airline include/exclude, price cap, max duration and departure windows are applied to the results after fetching. - Multi-city raises
SearchUnsupportedError. Google loads those results client-side through the gated RPC, so the page carries no rows to read. Search each leg separately. get_booking_optionsis unavailable. It callsGetBookingResults, which is gated the same way, and currently raisesSearchRejectedError. The per-flighttfsbooking deep links are built offline and still work.- Fewer rows per search. Expect roughly 20-45 itineraries, fewer than the old RPC returned — and a client-side filter cannot back-fill the list the way Google's server-side one did.
- Children and infants thin the results — sometimes to nothing. Google
prices those parties client-side, so the page inlines fewer itineraries for
them, and in premium cabins often none (measured 2026-09: JFK→LHR economy
23 rows for one adult, 16 with an infant; SFO→NRT business 9 rows for one
or two adults, 0 with a child). Extra adults cost nothing. An empty result
for such a search does not mean the route has no flights — and neither
does it mean this is why:
search()only warns when the fetched page itself came back with zero rows, not when the caller's own airline/price/ duration/window filter removed rows Google did return. An adults-only search shows the schedule. - Date searches cost one page fetch per date. The page has no calendar
grid, so a range is priced date by date; one
SearchDates.searchcovers at most 93 dates and a wider range raisesValueError. Budget for it: 93 dates across 10 workers is several hundred MB of pages and parsed JSON at peak. A sweep that never manages to load a single page — the shape a blocked or consent-gated client produces — gives up after a handful of dates rather than paying the retry budget on all of them. Only pages served without results count towards that: a timeout or a dropped connection says nothing about the dates not yet tried, so those never abandon a sweep. Measured with the real backoff: 42 page fetches (bounded at 45, so up to ~135 HTTP requests once the client's own retries multiply in) and about 4 seconds, the same whether the range is 30 days or 93. Unbroken, a 93-date range would have cost 279 fetches and up to 837 requests. The bound is(5 + worker count) x 3, so raisingconfigure_concurrencyraises it proportionally. That breaker disarms for good the moment any page loads, even an empty one, so it cannot catch a sweep that is mostly timeouts around one lucky date —SearchDates.searchraises that case too, whenever nothing priced and at least half the attempted dates never loaded. A minority of failures alongside real results, or alongside a confirmed-empty range (None), still returns normally but logs one warning naming the counts. - A page occasionally arrives without results. Roughly one request in sixty
returns HTTP 200 with no
ds:1blob; the client retries that case up to twice (0.5s then 1.5s) before raisingSearchParseError. A healthy search never pays for it. FLI_SOCS_COOKIE. EU/EEA IPs are redirected to Google's consent interstitial,
Truncated for display — read the full file on GitHub.
Related Skills
taste-skill
110.6kAgent skills that give coding agents taste: art direction, reference images and a browser check instead of generic AI pages
Agent-Reach
109.2kGive your AI agent eyes to see the entire internet. Read & search Twitter, Reddit, YouTube, GitHub, Bilibili, XiaoHongShu — one CLI, zero API fees.
headroom
78.9kCompress tool outputs, logs, files, and RAG chunks before they reach the LLM. 20% fewer tokens for coding agents, 60-95% fewer tokens for JSON, same answers. Library, proxy, MCP server.
ai-job-search
69.8kThe job search that runs on your machine. AI job application framework built on Claude Code: evaluate postings, tailor CVs, write cover letters, prep interviews. Fork it and own it.
Languages
Trust signals
From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.
