Skip to main content
Glama
mtnrabi

Google Flights MCP

by mtnrabi

Google Flights MCP — free, ad-supported

Real-time one-...

claude mcp add --transport http google-flights-free https://google-flights-lulu.flightpowers.com/mcp

That is the whole setup. There is no key to paste and nothing to configure.


The two tools

| Tool ... | ...

search_oneway_flights(from_airport="TLV", to_airport="CMB",
                      departure_date_from="2026-10-01",
                      departure_date_to="2026-10-31")

  → 31 combinations requested, 15 searched, results merged and re-sorted

search_roundtrip...

What comes back

...

Fares are live, and only live

...


How it is free

...

One caveat worth stating up front

...


When you outgrow the free one

...

| ... |

...

claude mcp add --transport http google-flights https://google-flights-mcp.flightpowers.com/mcp --header "x-rapidapi-key: YOUR_RAPIDAPI_KEY"

...


Truncation is always reported

...

{"requested_combinations": 31, "searched_combinations": 15, "truncated": true,
 "departure_dates_searched": ["2026-10-01", "2026-10-03", "..."],
 "note": "This request expanded to 31 searches, above the 15-search limit..."}

A silently truncated search...

sort_type is not exposed

...


Non-affiliation

...


Running your own instance

...

MCP client ──HTTP──▶ this server ──POST──▶ upstream travel API ──▶ Google Flights
                          │
                          └──POST /slot──▶ ads.getlulu.dev

It calls the upstream...

Quick start

cd mcp_server
python3 -m venv .venv && .venv/bin/pip install -r requirements.txt
cp example.env .env          # fill it in
set -a && . .env && set +a
.venv/bin/python -m src      # serves on :8000/mcp

Health check at /health, live counters at /metrics.

Configuration

...

MCP_PUBLIC_URL is a silent failure mode

...

sponsored widget domain for https://.../mcp -> <hash>.claudemcpcontent.com

Why fan-out is internal

...

Cost control

...

Enforcement: what does not and can not be possible

...

Уровень

Как определяется

Рендерит виджет?

llm_host

Префиксы Anthropic 160.79.104.0/21 или опубликованные OpenAI chatgpt-connectors.json

Да — единственный уровень, который может отправить beacon

local_client

Подсказка имени клиента (Claude Code, Cursor, …)

Нет — только CLI-карточка, структурно $0 CPM

unknown

Всё остальное

Нет

В режиме enforce уровень llm_host получает полный лимит, остальные уровни — треть, а всё, что в BLOCKED_TIERS, отклоняется. Два намеренных правила безопасности:

  • monitor — это режим по умолчанию. Блокировка на первой неделе уничтожила бы выборку трафика, ради сбора которой существует POC.

  • unknown никогда не блокируется, пока не загружен фид диапазонов OpenAI, потому что без него любой реальный вызывающий ChatGPT выглядит как unknown.

Что этот сервер не может измерить

Beacon отрисованного показа запускается изнутри фрейма виджета Lulu напрямую на ads.getlulu.dev. Он никогда не касается этого процесса, поэтому этот сервер не может сам вычислить настоящий рендер-рейт.

Он подсчитывает слоты, обслуженные по каждому уровню. Сопоставьте это с указанными Lulu отрисованными показами, чтобы получить реальный коэффициент, а затем поместите уровень, который ничего не рендерит, в BLOCKED_TIERS. Механизм уже построен; входное значение — реление выработанное на основе реальных цифр.

Подсчёт запросов Lambda

Каждый вызов инструмента отправляет ровно одну строку в stdout, с префиксом MCP_CALL . Имена полей ниже реальны; значения являются иллюстративными — ничто здесь не является опубликованные характеристики задержки или объёма:

MCP_CALL {"iso":"2026-08-06T09:39:37Z","tool":"search_roundtrip_flights",
 "tier":"unknown","requested_combinations":3,"backend_calls":3,
 "results_returned":4,"ad_eligible":true,"duration_ms":0}

backend_calls — это количество запросов Lambda для этого вызова. Просуммируйте его по строкам MCP_CALL за любой период и получите общее количество backend-запросов. stdout — источник учёта, потому что это единственный приёмник, который работает везде: Vercel захватывает его автоматически, а файловая система там доступна только для чтения.

Одна строка на вызов инструмента, никогда на backend-вызов: Vercel ограничивает логи выполнения 256 строками и 1 МБ на запрос.

LOG_PATH добавляет второй, файловый приёмник для контейнерных развёртываний. Он отключается сам, если путь не поддерживает запись, а не пишет в пустоту.

Метрики

GET /metrics (установите METRICS_TOKEN, чтобы требовать заголовок x-metrics-token). Формат показан ниже, значения иллюстрационные — это не показатели использования:

{"totals": {"tool_calls": 2, "backend_calls": 4, "ad_eligible_calls": 2},
 "backend_calls_per_tool_call": 2.0,
 "by_tier": {"llm_host": {"tool_calls": 2, "backend_calls": 4}},
 "budget": {"used_24h": 4, "budget": 1000, "remaining": 996,
            "enforceable": false},
 "durable_counters": false,
 "notes": ["..."]}

GET /metrics/calls?hours=24 возвращает количество вызовов по часам UTC.

backend_calls_per_tool_call — это число, которое решает, переживёт ли этот канал POC. Каждый backend-вызов — это стоимость; каждый вызов инструмента — это максимум одно показанное объявление. Умножьте его на реальную стоимость Lambda + прокси за вызов и сравните с CPM, о котором фактически отчитывается рекламная сеть.

durable_counters: false и budget.enforceable: false означают, что итоги охватывают только один процесс. Для контейнере это нормально. На Vercel это означает, что реальные цифры выше показанных и spend guard на самом деле не взведён — см. ниже.

Хранение счётчиков

Счётчики спрятаны за маленьким интерфейсом, потому что целевая платформа развёртывания определяет, какая реализация правильная:

Ждём

Когда

Долговременный

In-process dict

Контейнер, локально

Нет

Upstash Redis (REST)

Vercel, любой serverless

Да

На Vercel Fluid compute разделяет один инстанс между параллельными вызовами и свободно их масштабирует, поэтому внутрипроцессные счётчики фрагментируются и сбрасываются. Они не дают ошибку — они просто возвращают число, меньшее реального, а это худший способ отказа защитного механизма бюджета. Поэтому DAILY_BACKEND_CALL_BUDGET может быть обеспечен только общим хранилищем, и сервер сообщает об этом при запуске и в /metrics, а не делает вид, что это не так.

vercel install upstash   # injects UPSTASH_REDIS_REST_URL / _TOKEN

Upstash используется через REST API, а не через wire-протокол Redis: короткоживущие вызовы не подходят для клиента с пулом соединений, и это оставляет redis в стороне от списка зависимостей. Любой сбой хранилища логируется и проглатывается — сбоёй счётчика никогда не должен стать сбоем поиска авиабилетов.

Подключение рекламы

Реклама подключена отдельно через виджет и middleware, а не через однострочный enable_lulu_ads, потому что только путь middleware принимает is_error_result — это и не даёт рекламе попадать в пустые результаты.

Результаты рендерится через виджет Lulu result, а не через его фирменную карточку. Фирменная карточка рисует объявление, но не содержитбикон отрисованного показа; beacon живёт только в фиксированной полосе SPONSORED widget result. Показ только спонсорской карточки приносит клик-выручку и ровно $0 CPM, и нигде ничего не сообщает об ошибке. Спонсорская карточка остаётся как запасной вариант на случай сбоя регистрации виджета result, и этот сбой логируется громко.

Beacon — это элемент <img> размером 1×1, указывающий на ads.getlulu.dev. Приложения MCP Apps применяют стандартный CSP img-src 'self' data:, поэтому домен нужно объявить на ресурсе виджета — через app= для MCP Apps и openai/widgetCSP для ChatGPT. Без объявления это выглядит идентично рабочей интеграции: карточка рендерится, полоса появляется, никакого импадопрошлого нет и нет ошибки.

Зарегистрируйтесь один раз, затем настройте LULU_ADS_PUBLISHER_ID / LULU_ADS_API_KEY:

curl -X POST https://ads.getlulu.dev/publishers \
  -H 'content-type: application/json' \
  -d '{"name":"...","contact_email":"...","server_url":"..."}'

API-ключ возвращается ровно один раз.

Расчётным полем является imp_url (snake_case) в ответе /slot. Типизации TypeScript называют его impUrl, но в Python SDK разрешённые ключи ответа читают только imp_url (lulu_ads/client.py:210). Когда появятся настоящие учётные данные, проверьте, что реальные ответы /slot действительно несут это поле — без него виджету нечем отправить beacon, и расчётного показа нет, как бы хорошо ни работало всё остальное.

Тесты

.venv/bin/python -m pytest tests -q     # 141 tests

И backend, и рекламный сервер — стабы, поэтому тестам не нужны ни сеть, ни учётные данные. tests/test_ads.py и tests/test_stores.py запускают настоящие стаб-серверы, а не мокают SDK, поэтому они проверяют реальный формат провода.

Развёртывание на Vercel

api/index.py      entrypoint, exports `app`
vercel.json       maxDuration + no-store on /mcp
.python-version   3.13
requirements.txt

Vercel автоматически находит api/index.py и обслуживает всё приложение как одну Fluid function, принимающую все маршруты, так что /mcp, /health и /metrics выполняются в одном процессе. Никакие переписывания не нужны.

vercel link          # new project
vercel install upstash

# `vercel env add` takes ONE variable per invocation --
# `vercel env add <NAME> [environment]`. Each prompts for the value.
vercel env add BASE_LAMBDA_URL production
vercel env add RAPID_AUTH production
vercel env add MCP_PUBLIC_URL production
vercel env add LULU_ADS_PUBLISHER_ID production
vercel env add LULU_ADS_API_KEY production

vercel deploy --prod

Четыре специфические для Vercel вещи, которые этот код уже обрабатывает, и каждая превращается в тихий сбой, если не настроить правильно:

Lifespan. FastMCP инициализирует свой менеджер сессий streamable-HTTP в событие запуска lifespan в ASGI. Без него каждый запрос /mcp падает с Task group is not initialized — это полная недоступность MCP-эндпоинта. Поддержка lifespan на Vercel (выпущена 2025-12-09) заявлена для «FastAPI-приложений»; была ли она покрывает отдельное Starlette-приложение, не выставлено. Поэтому api/index.py оборачивает приложение FastMCP и передавлаёт lifespan=_mcp_app.lifespan, что также является интеграцией, документированной FastMCP. Не «упрощайте» этоу.

Stateless. stateless_http=True. Инвокации короткоживущи и не обязаны попадать на тот же инстанс, поэтому сеанс негде хранить.

Filesystem. Вне эфемерного /tmp файловая система только для чтения. Оставьте LOG_PATH пустым; строки MCP_CALL в stdout — и есть запись.

Counters. Настройте Upstash, иначе защита бюджета чисто декоративная — см. выше.

Другие важные ограничения: maxDuration по умолчанию 300 c на всех тарифах под Fluid (backend-вызовы достигают пика ~90 c, поэтому подходит); ответы передаются стримингом, а не буферизуются, потому что возврат json_response=True снова дал бы лимит 4.5 МБ на тело, к которому может приблизяться разветвление на 15 направлений; а общий пул 1,024 файловых дескрипторов — это причина существования MAX_HTTP_CONNECTIONS.

Удержка логов — 1 час на Hobby, 1 день на Pro. Если строки MCP_CALL — это доказательства нагрузки для POC, это аргументы за Pro и прогрузку логов, либо за перенос счётчиков в Upstash и чтение /metrics.

Развёртывание контейнерта

Dockerfile собирает постоянно работающий HTTP-сервис, такой же формы, как backend/Dockerfile (и который разворачивается на Render). Установите LOG_PATH и смонтируйте том на /app/logs, чтобы скользящее окно бюджета пережило развёртывание.

В любом случае: после развёртывания установите MCP_PUBLIC_URL на реальный URL — без завершающего слеша — и проверьте домен виджета в стартовом логе.

-
license - not tested
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

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

  • AI marketplace — flights, tours, activities, transport & more via MCP. No auth required.

  • Free, no-login flight search with real-time pricing from multiple airlines.

  • Duffel MCP — live flight search + pricing via the Duffel Flights API (duffel.com)

View all MCP Connectors

Latest Blog Posts

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-free'

If you have feedback or need assistance with the MCP directory API, please join our Discord server