google-flights-mcp
Provides real-time flight search and fare comparison using Google Flights, including one-way and round-trip searches, price insights, and booking links.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@google-flights-mcpFind the cheapest round-trip flights from New York to Paris for 5-7 nights in May"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Google Flights MCP — real-time fares your agent can search across a whole date range, ad-free
claude mcp add --transport http google-flights https://google-flights-mcp.flightpowers.com/mcp --header "x-rapidapi-key: YOUR_RAPIDAPI_KEY"Hosted. Nothing to clone, nothing to build. Listed in the official MCP Registry as
com.flightpowers/google-flights-mcp. Health check:
/health.
Need a key? Subscribe to the Google Flights Live API on RapidAPI — free tier available —
and copy your x-rapidapi-key: https://rapidapi.com/mtnrabi/api/google-flights-live-api
No key yet? Start with the free server — same search, no signup:
claude mcp add --transport http google-flights-free https://google-flights-lulu.flightpowers.com/mcp
(ad-supported: one disclosed sponsored card per result, fan-out capped at 15, and clients that
cannot render the sponsored card may be capped further.) Come back here when the ads, the
15-search cap, or those client restrictions get in your way.
What your agent gets
Two tools that answer a fare question, not a date lookup.
Ask open-ended questions. "Cheapest one-way to Sri Lanka anywhere in October", "5 to 7 nights in Rome sometime in May, from Tel Aviv or Larnaca" — each is one tool call. Both tools take a departure date range, a list of destination airports, and (round-trip) a
nightsvalue instead of a fixed return date, and expand them internally.Say whether a price is actually good. Every result carries Google's own historical range for that route and period —
price_insights_low,price_insights_high, and aprice_range_in_relation_to_other_periodsverdict oflow/typical/high. That is what lets an agent answer "$209 is typical here, don't rush" instead of just quoting a number.Book, not just browse. Every result includes a
buy_linkto Google Flights.Know what it spent. Every response carries
api_usage— requests used by this call, and what is left on the caller's plan. See Spend reporting.Know what it searched. Every response carries
search_coverage, so the model can say honestly which dates and destinations the answer is based on.
Results are live fares. They go stale within minutes — never cache a fare or reuse an earlier result; search again and state when the data was fetched.
Get a key (free tier available)
The server holds no upstream credential of its own. Every search is billed to your RapidAPI subscription, which is why the key travels with the request.
Subscribe to the Google Flights Live API: https://rapidapi.com/mtnrabi/api/google-flights-live-api
Copy your
x-rapidapi-key.Pass it to the server in any one of the three ways below.
If a key is missing, the tools do not fail silently and do not spend anything — they return
needs_api_key: true with the signup URL and these instructions, phrased for the model to read
back to you.
Three ways to pass your key
Way | How | When to use it |
Header (preferred) |
| Anything that lets you set headers. Keys stay out of URLs, and therefore out of proxy and access logs. |
Query parameter |
| Hosts that only let you paste a URL — claude.ai's custom-connector dialog is the case that matters. |
Client API-key field | Paste the key into the client's own "API key" box | Hosts that send |
First non-empty source wins, in that order. The key is never logged, never echoed into an error message, and never returned in a tool response.
Tools
Tool | What it does |
| Real-time one-way fares. Input: origin IATA, destination IATA or a list, and either one departure date or a date range. Returns price, airline, duration, stops, |
| Real-time round-trip fares priced as paired legs, not two one-ways. Input: origin, destination(s), a departure date or range, and either a |
search_oneway_flights
search_oneway_flights(
from_airport: str, # origin IATA, e.g. "TLV"
to_airport: str | list[str], # destination IATA, or a list to compare
departure_date: str | None = None, # "YYYY-MM-DD"
departure_date_from: str | None = None,# first date of a range
departure_date_to: str | None = None, # last date of a range
max_stops: int | None = None, # 0 = non-stop only
airline_codes: list[str] | None = None,
exclude_airline_codes: list[str] | None = None,
departure_time_min: int | None = None, # hour, 0-23
departure_time_max: int | None = None,
arrival_time_min: int | None = None,
arrival_time_max: int | None = None,
currency: str = "usd",
max_price: int | None = None,
seat_type: int | None = None, # 1 economy, 2 premium economy, 3 business, 4 first
passengers: list[int] | None = None, # [adults, children, infants]
sort_by: str = "best", # "best" | "price" | "duration"
limit: int = 10, # results returned after merge + sort
max_searches: int | None = None, # cap the billed requests this call may make
use_fallback: bool = False, # slower, fewer empty results on hard routes
)search_roundtrip_flights
search_roundtrip_flights(
from_airport: str,
to_airport: str | list[str],
departure_date: str | None = None,
departure_date_from: str | None = None,
departure_date_to: str | None = None,
return_date: str | None = None, # use this OR nights, not both
nights: int | list[int] | None = None, # e.g. 7, or [5, 6, 7]
max_departure_stops: int | None = None,
max_return_stops: int | None = None,
departure_airline_codes: list[str] | None = None,
return_airline_codes: list[str] | None = None,
currency: str = "usd",
max_price: int | None = None,
seat_type: int | None = None,
passengers: list[int] | None = None,
sort_by: str = "best",
limit: int = 10,
max_searches: int | None = None,
use_fallback: bool = False,
)sort_by is applied by this server across the merged result set from every search it ran, so it
is predictable regardless of how many combinations were expanded.
A worked example
User: "I'm in Tel Aviv. Cheapest week-long trip to Rome or Athens, leaving any day in the first half of May."
One call:
{
"name": "search_roundtrip_flights",
"arguments": {
"from_airport": "TLV",
"to_airport": ["FCO", "ATH"],
"departure_date_from": "2026-05-01",
"departure_date_to": "2026-05-15",
"nights": 7,
"sort_by": "price",
"limit": 5
}
}That expands to 15 dates × 2 destinations = 30 combinations, which is exactly the per-call cap. The response shape (field names are real; the values below are illustrative, not a quote — run the call to get live fares):
{
"results": [
{
"from_airport": "Tel Aviv (TLV)",
"to_airport": "Rome (FCO)",
"departure_date": "2026-05-05",
"return_date": "2026-05-12",
"total_price": "$XXX",
"total_price_as_number": 0,
"total_duration_seconds": 0,
"total_stops": 0,
"price_range_in_relation_to_other_periods": "low",
"price_insights_low": 0,
"price_insights_high": 0,
"departure_flight_airline": "...",
"departure_flight_departure_description": "...",
"departure_flight_arrival_description": "...",
"departure_flight_duration": "...",
"departure_flight_stops": 0,
"departure_stops_info": [],
"return_flight_airline": "...",
"return_flight_departure_description": "...",
"return_flight_arrival_description": "...",
"return_flight_duration": "...",
"return_flight_stops": 0,
"return_stops_info": [],
"buy_link": "https://www.google.com/travel/flights?tfs=..."
}
],
"result_count": 5,
"search_coverage": {
"requested_combinations": 30,
"searched_combinations": 30,
"truncated": false,
"max_searches_per_request": 30,
"departure_dates_searched": ["2026-05-01", "..."],
"destinations_searched": ["ATH", "FCO"]
},
"api_usage": {
"requests_used_by_this_call": 30,
"plan_requests_remaining": 0,
"plan_requests_limit": 0,
"note": "This search used 30 of your RapidAPI plan's requests; ... remain in the current period. Each date and destination combination is one billed request."
}
}Other response shapes to expect, all of them normal:
No flights on those dates.
results: []with amessage— Google Flights genuinely returns nothing for some route/date combinations. Not an error. Try nearby dates, a nearby airport, oruse_fallback: true.Some searches failed. A
partialfield says how many of the executed searches failed, and the results cover the rest.Range too wide.
search_coverage.truncated: trueplus anote. The range is sampled evenly across the whole window (first and last kept), not cut short — so the sample is representative, not the first N days. Raisemax_searchesor narrow the range for fuller coverage.No key / rejected key.
needs_api_key: true, zero spend, with the fix. A valid RapidAPI key that is not subscribed to this API is the most common cause.Plan exhausted.
quota_exhausted: truewithapi_usage, plus a reminder that narrowing the range makes remaining quota go further.
Spend reporting (api_usage)
The money is yours, so the meter is visible. Every successful response carries:
Field | Meaning |
| Billed upstream requests this one tool call consumed. |
| What is left on your RapidAPI plan this period. |
| Your plan's limit for the period. |
| The same thing in a sentence, so the model can relay it to you before you ask. |
plan_requests_remaining and plan_requests_limit come from the upstream response and are
omitted when upstream does not report them; the note adapts. The rule the model should state
out loud: one date × one destination = one billed request.
Cost control knobs, in order of bluntness: max_searches per call (lower it to spend less on a
wide question), a narrower date range, a shorter destination list.
One call vs thirty
The underlying REST API takes exactly one (origin, destination, date) tuple per call. Against a
one-date-per-call passthrough, "cheapest to Sri Lanka anywhere in October" is 31 separate tool
calls — 31 round trips through the model, 31 chances to lose the thread, and a bill the user only
discovers afterwards.
Here it is one tool call. The fan-out happens server-side, concurrently, capped, evenly
sampled, deduplicated on buy_link, merged, sorted by your sort_by, and reported honestly in
search_coverage and api_usage.
This server (paid) | Free server | |
Fan-out per call | 30 (hard max 60; raise or lower per call with | 15 |
Ads | none | one disclosed sponsored card per result |
Key | your own RapidAPI key | none needed |
Spend reporting |
| n/a |
Directory-listable | yes | no |
This server carries no ads at all — not by taste but by constraint: Anthropic's connector directory policy and OpenAI's app guidelines both prohibit advertising and sponsored content in tool results, so an ad-carrying server can never be listed there and this one can.
Local development
git clone <this repo> && cd mcp_server_paid
python3 -m venv .venv && .venv/bin/pip install -r requirements.txt
cp example.env .env # fill it in; leave RAPIDAPI_KEY empty
set -a && . .env && set +a
.venv/bin/python -m src # streamable HTTP on http://localhost:8000/mcpPoint a client at the local process the same way:
claude mcp add --transport http google-flights-local http://localhost:8000/mcp --header "x-rapidapi-key: YOUR_RAPIDAPI_KEY"Tests (124 passing, verified):
.venv/bin/python -m pytest -qConfiguration lives in example.env; every variable is documented there. The ones that matter:
Variable | Default | Why it matters |
|
| Per-call fan-out cap. Clamped to a hard maximum of 60. |
|
| Concurrency of the fan-out. |
|
| Connection-pool ceiling; serverless instances share a file-descriptor pool. |
|
| Matches the upstream ceiling, so this side never times out first. |
|
| Results requested per individual upstream search. |
| RapidAPI listing | Quoted back to users who arrive without a key. |
|
| Reported by |
| (empty) | Leave empty in production. If set, every keyless caller is served on — and billed to — that subscription. The server logs a warning at startup and |
| (empty) | When set, |
| (empty) | Empty disables the file sink; stdout |
Operational routes: GET /health (public, unauthenticated — registries poll it),
GET /metrics, GET /metrics/calls?hours=24.
Deployment target is Vercel via api/index.py (FastAPI wrapper handing FastMCP its lifespan,
stateless_http=True). The canonical MCP path is /mcp, no trailing slash.
Never commit a real key. example.env ships with placeholders; keep it that way.
Non-affiliation
This is an independent API that returns publicly available flight pricing. It is not affiliated with, endorsed by, or sponsored by Google. "Google Flights" is used only to describe the public data source. Fares are supplied by the upstream provider, change constantly, and are not guaranteed — always confirm the price on the airline or booking site before purchase.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Flight Intelligence MCP — search, cheapest dates, multi-city, airline compare via Google Flights
Live flight prices and working booking links for AI agents and travel apps.
Free, no-login flight search with real-time pricing from multiple airlines.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/mtnrabi/google-flights-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server