Skip to main content
Glama
mtnrabi

Google Flights MCP

by mtnrabi

Google Flights MCP — 무료, 광고 지원

모든 MCP 클라이언트를 위한 실시간 편도 및 왕복 항공편 검색. API 키도, 계정도, 청구도 없습니다. 이 서비스는 사용자에게 관련 요금을 부과하지 않고, 각 결과에 첨부된 하나의 공개된 스폰서 카드로 운영됩니다.

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

이것이 전체 설정입니다. 붙여넣을 키가 없고, 구성할 것도 없습니다.


두 도구

도구

기능

search_oneway_flights

날짜 범위와 목적지 목록을 기준으로 편도 검색

search_roundtrip_flights

왕복을 쌍을 이루는 구간으로 가격을 산정하여, 날짜 범위와 nights 값 기준으로 검색

둘 모두 날짜 범위(departure_date_from / departure_date_to)와 목적지 목록을 받아 서버 측에서 확장합니다. 하나의 사용자 의도는 하나의 도구 호출입니다 — *"10월에 스리랑카 가는 가장 저렴한 표"*는 여러 번의 호출이 아니라 한 번의 호출로 처리됩니다.

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_flights는 고정된 return_date 대신 nights — 숫자 또는 [5, 6, 7] 같은 목록 — 을 추가로 받아서, *"5월에 로마에서 5–7박"*도 역시 한 번의 호출로 처리할 수 있습니다.

반환되는 것

각 결과에는 가격, 소요 시간, 항공사, 직항/경유 여부, 경유 공항과 경유 시간, 그리고 예약 가능한 buy_link가 포함됩니다. 또한 해당 항로와 기간에 대한 Google 자체의 역사적 가격 범위인 price_insights_low, price_insights_high, 그리고 price_range_in_relation_to_other_periodslow / typical / high 판정도 포함됩니다.

마지막 부분이 일반적인 가격 스크래핑보다 이 방식을 선호하는 이유입니다. 어시스턴트가 단순히 숫자를 인용하는 대신, *"이 항로는 $209가 일반적이니 서둘지 않아도 됩니다"*라고 말할 수 있게 해줍니다.

빈 결과 목록은 "해당 항로와 날짜에 항공편이 없다"를 의미합니다 — 이는 오류가 아니라 유효한 대답입니다.

요금은 실시간이며, 실시간뿐입니다

모든 호출은 새 검색입니다. 요금은 몇 분 안에 만료되므로, 결과를 캐시하거나 저장하거나 나중에 현재 시점으로 다시 인용해서는 안 됩니다. 답변이 요금을 언급한다면, 가져온 시점을 밝히고 재사용하는 대신 다시 검색해야 합니다.


어떻게 무료인가

각 성공 결과에는 명확하게 공개된 스폰서 카드 하나가 함께 표시됩니다. 그 카드가 개발자의 전체 수익 모델입니다 — 사용자가 API 키나 신용카드를 가져올 필요가 없도록 백엔드 검색 요청 비용을 충당해 줍니다.

이 부분은 명확히 해야 합니다. 사용자에게 어떤 선택인지 알고 있어야 하기 때문입니다:

  • 결과마다 스폰서 카드 하나, 항상 스폰서로 표시됩니다.

    • ** 오류에 절대 붙지 않습니다. ** 또한 결과가 없는 답변에도 절대 붙지 않습니다. 장황한 것뿐 아니라, 데이터가 없는 광고는 프롬프트 인젝션 시도처럼 보일 수 있습니다 — Lulu의 실제 테스트에서 모델이 이를 정확히 3회 중 3회 지적했습니다.

  • 광고는 검색 서비스를 중단시키지 못합니다. 광고 SDK는 자격 증명이 없으면 무력화되어 있으며, 모든 네트워크 오류는 다시 열립니다.

  • 광고는 Lulu를 통해 제공됩니다. 이 서버는 광고에 사용자의 신원을 보내지 않으며, 슬롯 요청을 보내고 결과를 렌더링할 뿐입니다.

광고가 포함되기 때문에 이 서버는 공식 MCP 레지스트리나 Anthropic 및 OpenAI 디렉터리에는 등록되지 않습니다. 세 곳 모두 광고가 있는 서버를 금지합니다. 이 때문에 무료 모델의의도된 결과치이며, 잘못해서 빠진 것이 아닙니다.

한 가지 미리 언급할 것은

스폰서 카드는 MCP 위젯 프레임을 표시하는 어시스턴트 내부에서만 렌더링될 수 있습니다. 발신자는 소스 IP로 분류되며, 강제 모드에서는 카드를 렌더링할 수 없는 클라이언트는 팬아웃 상한이 줄어들거나 거부될 수 있습니다. 기본 배포 모드는 monitor — 분류하고 로그하며, 모두 대해 서빙합니다. 하지만 헤드리스 스크립트에 연결하는 경우가 아니라면 어시스턴트에 연결하는 것이 아니라면, 아래의 유료 서버가 더 적합하며, 이 방식으로 제한되지 않습니다.


무료 버전이 부족해질 때

동일한 두 도구와 동일한 검색 기능을 가진 유료이며 광고 없는 버전이 있습니다: https://google-flights-mcp.flightpowers.com/mcp

이때느 무료 서버의 기능에 대한 어떤 것이 부차적인 것은 아닙니다. 유료 서버는 단지 광고, 15회 검색 상한, 또는 클라이언트 제한이 시작해서 방해가 될 때 선택하는 것입니다.

| 항목 | 무료 — 이 서버 | 유료 — google-flights-mcp | | --------------------------- | ------------------------------------------------------------ ------------------------------------------------- | | 목적지의 광고 | 결과당 하나의 공개된 스폰서 카드 | 없음 | | API 키 | 필요 없음 | 사용자만 Rd의 RapidAPI 키 | | 호출당 팬아웃 상한 | 15개 검색 | 30개 검색 (최대 한도 60, 호출당 max_searches 로 대체 가능) | | 지출 보고 | 해당 없음 | 모든 응답에 api_usage | | 클라이언트 제한 | 발신자 인 특성에 따라 계층별로 분류; 카드를 렌더링하지 못하는 클라이언트는 감한/거부될 수 있음 | 없음 — 모든 클라이언트, 모든 전송 | | MCP 레지스트리 목록 | 아님 (광고가 금지됨) | 예 — com.flightpowers/google-flights-mcp | | 비용 | 무료 | 사용자의 RapidAPI 사용량 |

절충은 단순합니다. 유료 서버에는 광고와 제한이 없는데, 이는 후원사가 비용을 지불하는 대신 사용자가 직접 자신의 RapidAPI 키로 검색 비용을 지불하기 때문입니다.

키 만료는 1분이면 충분합니다. RapidAPI에서 Google Flights Live API를 구독하고 — 무료 티어가 있습니다 — 사용자의 i.e.x-rapidapi-key를 복사하세요:

https://rapidapi.com/mtnrabi/api/google-flights-live-api

그런 다음 클라이언트를 유료 서버에 연결합니다:

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

키는 ?rapidapi_key= 쿼리 매개변수로 전달하거나, 클라이언트가 제공하는 API 키 필드에 전달될 수도 있습니다. 모든 유료 응답에는 requests_used_by_this_call, plan_requests_remaining, plan_requests_limit를 포함한 api_usage가 포함되어, 지출이 다음 호출 전에 보이기 월말이 아니어도 됩니다.


잘림이 항상 보고됩니다

요청이 한도를 초과하면 날짜는 처음 N개로 잘려저 오는 대신 범위 전체에서 균등하게 샘플링됩니다. 10월에 걸쳐 있는 15개의 날짜가 "월 중에서 가장 저렴한" 답변을 제공합니다. 처음 15일으로는안 됩니다. 모든 응답에는 search_coverage가 포함됩니다:

{"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..."}

조용히 잘려진 검색은 완전한 검색처럼 보이기 때문에, 사용자의 사용자가 "반얼"의 절반에조차도 보지 못한 "최저가" 답변을 신뢰하게 될 수 있습니다.

sort_type이 노출되지 않음

백엔드에서 sort_type은 결과를 다시 정렬하는 것이 아니라 어떤 검색을 실행할지를 선택합니다. upstream APImax_price라는 이유로 이 변수를 무시하고, app.py:255 로 이 항목을 무효화합니다. 어차피 최대 15개 검색 결과를 여기서 병합하고 다시 정렬해야 하므로, 서버는 항상 백엔드 기본값을 사용하며, 병합된 목록 자체를 sort_by(best / price / duration)로 직렬화합니다. 이는 컨트롤할 수 있는 동작입니다. sort_type을 전달하는 것은 예측할 수 없습니다.


비연계

이것은 독립 서비스이며 공개적으로 이용 가능한 항공과가격을 제공합니다. Google과는 제휴하지 않았고, 승인받지 않았으며, 스폰서가 아닙니다. "Google Flights"는 가격 데이터의 출처를 설명하기 위해서만 쓰입니다.


직접 자체 인스턴스 실행

다음 내용은 이 서버를 직접 운영하는 사람을 위한 것입니다. 이 서비스를 사용 하기 원한다면 위의 안내에 나온 설치 줄만 있으면 객체, 구성자 그대로.

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

그것은 업스트림 여행 API를 직접 호출하며, 호출당 paid 채널과는 별도로 자체적으로 그대로 계속 유지됩니다.

빠른 시작

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 에서 상태 확인, /metrics 에서 실시간 카운터를 볼 수 있습니다.

구성

BASE_LAMBDA_URLRAPID_AUTH는 사용자의 공유 여행 API를 가리키며, 서버에 대한 인증을 수행합니다. 값을 인용부호가 포함된 env 파일에서 복사하는 경우, 로더가 인용부호를 한 겹 벗겨낸다는 점에 유의하세요 — 인용부호가 그대로 들어있는 값을 붙여 넣으면 복시 오류 원인처럼 보이는 잘못된 비밀번호가 아니라 403 응답이 발생합니다.

example.env에 모든 변수 설명이 나와 있습니다. 가장 중요한 세 가지:

변수

중요한 이유

MCP_PUBLIC_URL

클라이언트가 연결하는 URL과 MCP_ 정확히 일치해야 합니다. 아래 참조.

MAX_BACKEND_CALLS_PER_TOOL_CALL

비용 상한. 기본값 15.

ENFORCEMENT_MODE

off / monitor / enforce. 기본값 monitor.

MCP_PUBLIC_URL 는 조용한 실패 모드입니다.

Lulu 는 Claude의 _meta.ui.domain 값을 이 값에서 해싱하여 파생합니다. Claude는 동일한 해시를 독립적으로 계산하며, 도메인이 일치하지 않는 프레임을 거부합니다. 잘못된 URL은 항상, 및 카드가 렌더링되지 않고, 어디에서도 뽑히지 않으며, CPM은 계속 0$입니다.

서버는 시작 시 파생된 도메인을 기록하면서 값을 확인할 수 있습니다:

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

팬아웃이 내부인 이유

백엔드는 호출당 정확히 하나의 (origin, destination, date) tuple만 받으므로, "10월의 Sri Lanka행 가장 싼 항공편"은 백엔드 호출 31개입니다. 유료 API에서는 이 점이 문제가 없습니다 — 모든 호출이 수익입니다. 하지만 이 서버에서 수익은 툴 호출당 개별 렌더링된 광고이며, 백엔드 호출은 그 비용이며, 호출 발생하는 비용입니다. 따라서 모델이 31개의 툴 함수를 실행하게 하면 1 배의 수익에 대해 31 배의 비용이 드는 것입니다.

그래서 모델만 하나의 툴 호출하고 서버는 하드 상한 아래에서 백엔드 호출을 확장합니다.

비용 제어

두 가지 독립적인 가드를 사용합니다:

  1. 툴 호출당MAX_BACKEND_CALLS_PER_TOOL_CALL (기본값 15).

  2. 24시간 이동DAILY_BACKEND_CALL_BUDGET (0으로 비활성화). BUDGET_DEGRADE_AT 지점에서부터 MAX_BACKEND_CALLS_PER_TOOL_CALL 제한도 1/3 로 줄고, 100%가 되면 1로 줄어듭니다.

단계적으로 낮추는 것이 거부보다 낫습니다. 80%에서 서비스가 갑자기 중단되친 하루 종일 모든 사용자에게가 장애처럼 보일 것입니다.

24시간 창은 재시작이 되더라도 유지됩니다. — 크래시 루프가 다시 재부팅될 때 재정리라는 새 예산이 아니라 동일한 예산을 사용해야 합니다. 이 유지 방식은 스토어에 따라 다릅니다. Upstash를 사용하는 경우 이 창은 Redis에 저장되고 인스턴스 사이에서 공유됩니다. 프로세스 내 스토어이면 시작 시 LOG_PATH 파일에서 다시 구축됩니다. 둘 다 없을 경우 — Upstash도 쓰기 가능한 로그 파일도 없을 때 — 예산 재설정이 취소될 때마다 발생하므로 감시할 수 없습니다. 이것이 Vercel의 기본이므로, Vercel에서는 Upstash를 구성해야 합니다. /metrics에는 budget.enforceable이 있기 때문에 추측할 필요가 없습니다.

적용 가능한 강제가 무엇인지를 살펴보겠습니다

목표는 "스폰서 카드가 실제로 렌더링되는 환경에서만 작동 가능"하도록 하는 것입니다. 제약 접근 방식은 동작하지 않기 때문에 정확하게 구분할 필요가 있습니다.

clientInfo.name으로는 어떤 것도 차단할 수 없습니다. MCP 사양 Rev 2026-07-28은 이를 규범적으로 말합니다. "일반적으로 클라이언트 본인이 스스로 보고하므로 프로토콜에서 이를 검증하지 않습니다. … 보안 결정을 이에 협의해서는 안 됩니다. 스크립트가 "claude-ai"라는 값을 쉽게 넣을 수 있습니다. 기록은 보고 목적으로만 기록됩니다.

원본 IP는 차단할 수 있습니다. 완료된 TLS handshake를 위조할 수 없고, 두 호스트 모두 원격 MCP는 사용자 컴퓨터가 아니라 자체 클라우드에서 중계합니다:

등급

결정 방식

위젯 렌더링 여부

llm_host

Anthropic 160.79.104.0/21 또는 OpenAI가 공개한 chatgpt-connectors.json 접두어

예 — 비콘을 발송할 수 있는 유일한 등급

local_client

클라이언트 이름 힌트(Claude Code, Cursor, …)

아니요 — CLI 텍스트 카드만, 구조적으로 $0 CPM

unknown

그 외 모든 것

아니요

enforce 모드에서는 llm_host에 전체 상한이 적용되고, 나머지 등급은 1/3만 받으며, BLOCKED_TIERS에 있는 항목은 거부됩니다. 여기에는 의도된 안전 규칙이 두 가지 있습니다.

  • monitor가 기본값입니다. 첫 주에 차단하면 POC가 수집하려고 존재하는 트래픽 표본이 파괴됩니다.

  • OpenAI의 범위 피드(range feed)가 불러와지지 않은 동안 unknown은 절대 차단되지 않습니다. 피드가 없으면 실제 ChatGPT 호출자마저 unknown으로 보이기 때문입니다.

이 서버가 측정할 수 없는 것

렌더링 노출 비콘은 Lulu 위젯 프레임 내부에서 ads.getlulu.dev로 곧장 발송됩니다. 이 프로세스를 거치지 않으므로, 이 서버는 자체적으로 실제 렌더링 비율을 계산할 수 없습니다.

이 서버가 하는 일은 등급별로 제공된(served) 슬롯 수를 세는 것입니다. 그 값을 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 줄에서 이를 합산하면 총 백엔드 요청 수가 됩니다. stdout이 기록인 이유는 모든 환경에서 작동하는 유일한 목적지이기 때문입니다. Vercel은 이를 자동으로 수집하며, 그쪽 파일 시스템은 읽기 전용입니다.

줄은 도구 호출당 하나이며, 백엔드 호출당이 아닙니다. Vercel은 런타임 로그를 요청당 256줄와 1MB로 제한하기 때문입니다.

LOG_PATH는 컨테이너 배포용 두 번째 파일 목적지를 추가합니다. 이 값이 있는 경로를 쓰기 오류가 나면 가짜 대상에 추가하지 않고 로그 자체를 비활성화합니다.

메트릭

GET /metrics (METRICS_TOKEN을 설정하면 x-metrics-token 헤더를 요구). 아랟은 응답 형태이며, 예시 값입니다 — use가 아닙니다.

{"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를 넘어 생존할지를 정하는 숫자입니다. 모든 백엔드 호출은 비용이고, 모든 도구 호출은 기껏해야 렌더링 광고 하나로 이어집니다. 이 값에 실제 호출당 Lambda + 프록시 비용을 곱하고, 광고 네트워크가 실제 보고하는 CPM과 비교하세요.

durable_counters: falsebudget.enforceable: false는 합계가 단일 프로세스만 대상이라는 뜻입니다. 컨테이너에서는 괜찮습니다. Vercel에서는 실제 숫자가 표시보다 높고, 지출 보호 장치가 실제로 장전되어 있지 않다는 뜻입니다 — 아래 참조.

카운터 저장소

카운터는 작은 인터페이스 뒤에 있습니다. 배포 대상에 따라 올바른 구현이 달라지기 때문입니다.

저장소

사용 시점

지속성

프로세스 내 dict

컨테이너, 로컬

아니요

Upstash Redis (REST)

Vercel, 모든 서버리스

Vercel에서는 Fluid compute가 동시 호출 사이 하나의 인스턴스를 공유하고 인스턴스를 자유자제로 늘리므로, 인프로세스 카운터는 나뉘고 계속꺼짐으로 초기화됩니다. 오류를 내는 대신 실제보다 작은 숫자를 반환하게 되는데, 예산 보호 장치가 실패하는 가장 나쁜 방식입니다. 그래서 DAILY_BACKEND_CALL_BUDGET은 공유 저장소가 있어야만 실제로 강제가 가능하며, 서버는 그렇지 않은 척하지 않고 시작 시점과 /metrics에서 이 사실을 명시합니다.

vercel install upstash   # injects UPSTASH_REDIS_REST_URL / _TOKEN

Upstash는 Redis 와이어 프로토콜이 아니라 REST API를 통해 접근합니다. 짧은 수명의 호기은 풀링 클라이언트에 맞는 형태가 아니며, 덕분에 redis 의존성도 없습니다. 모든 저장소 실패는 로그에 남기고 넘어가는데, 카운터 장애가 항공편 검색 장애로 번져서는 안 되기 때문입니다.

광고 연결

enable_lulu_ads 한 줄 방식 대신 위젯 + 미들웨어로 별도 연결했습니다. is_error_result를 받는 경로는 미들웨어뿐이며, 그 덕분에 빈 결과에는 이 광고가 붙지 않고 유지됩니다.

결과는 Lulu의 result 위젯을 통해 렌더링되며, 스폰서 카드로는 랜더링되지 않습니다. 스폰스는 카드에도 광고를 그리지만 렌더링 노출 비콘이 포함되어 있지 않고, 비콘은 오직 result 위젯의 고정 SPONSORED 스트립에만 있습니다. 스폰서 카드만 제공하면 클릭 수익은 나오지만 CPM은 정확히 $0이며, 어디에서도 문제가 보고되지 않습니다. 스폰서 카드는 result 위젯 등록에 실패했을 때 폴백으로 남아 있으며, 그 폴백이 발생하면 자세하게 로그로 기록됩니다.

비콘은 ads.getdadget.dev로 보내는 1×1 <img>입니다. MCP Apps 호스트는 기본 CSP(img-src 'self' data:)를 적용하므로, 해당 도메인을 위젯 리소스에 선언해야 합니다. this은 MCP Apps에서는 app=, ChatGPT에서는 openai/widgetCSP로 합니다. 선언하지 않으면 외관상 정상적 통합과 차이가 없습니다. 카드는 화면에 그려지고, 스트립도 보이고, 노출도 없고, 오류도 없습니다.

한 번 등록한 다음 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 키는 정확히 한 번만 반환됩니다.

청구할 수 있는 필드는 /slot 응답스키인 imp_url입니다 (snake_case). TypeScript 타입은 이를 impUrl로 부르지만, Python SDK는 응답 키를 허용 목록으로 관리하며 imp_url만 읽습니다 (lulu_ads/client.py:210). 실사용 인증 정보를 얻으면 실제 /slot 응답에 이 필드가 들어있는지 꼭 확인하세요. 이 필가 없으면 위젯이 발 soil 비콘이 없고, 그 밖의 내용이 모두 정상이어도 청구 가능한 노출은 생기지 않습니다.

테스트

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

백엔드와 광고 서버를 모두 스텁으로 대체폐 코드기 때문에 스위트에는 네트워크도 인증 정보도 필요하지 않습니다. tests/test_ads.pytests/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함수로 전체 app을 서빙합니다. 따라서 /mcp, /health, /metrics가 모두 같은 프로세스로 인가되므로 rewrite가 필요 없습니다.

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만의 네 가지를 처리하는데, 한 번 잘못 바꾸면 모두 문제는 조용히 사라집니다.

Lifecycle.C. FastMCP는 ASGI lifespan는 시작 이벤트에서 스트리밍이 가능한 HTTP 세션 관리자를 초기화합니다. Without it, every /mcp 이벤트 요청은 Task group is not initialized 오류로 실패합니다 — 즉 /mcp 엔드포인트 전체가 죽게 됩니다. Vercel 의 lifespan support(2025-12)가 구매된 이 2025-12-09는 "FastAPI 응용"에 대해 발표된 것입니다. 베대야 Starlette 앱이 포함되는지는 명시하지 않았습니다. 따라서 api/index.py는 FastMCP 앱을 FastAPI로 감싸고 lifespan=_mcp_app.lifespan을 전달하는데, 이것은 FastMCP가 문서화하는 방식입니다. 이를 "단순화"해서 지워지 마세요.

무상태. stateless_http=True. 호 수명이 짧은 호출은 동일 인스턴스로 전달될 보장이 없으므로, 그 사이 세션을 저장할 곳이 없습니다.

파일과 시스템. 임시 범위/tmp 밖에서는 읽기 전용입니다. LOG_PATH를 비워 두세요. stdout으로 출력하는 MCP_CALL들이 기록입니다.

카운터. Upstash를 구성하시지 않으면 비용 가드는 장식입니다 — 위 참고.

여기서 더 중요한 제한: 평상시 maxDuration은 Fluid의 모든 요금제에서 300초가 기본입니다(백엔드 호출이 최대 약 90초라서 문제없습니다). 응답은 버퍼링하지 않고 스트리밍을 사용하는데, json_response=True로 하면 15개 펜아빗트가 접근할 수 있는 4.5 MB 본문 제한을 다시 끌어들이기 때문입니다. 그리고 1,024개의 파일 디스크립터를 공유를 넘은 MAX_HTTP_CONNECTIONS가 필요한 이유입니다.

로그 보존 기간은 Hobby에서 1시간, Pro에서 1일입니다. MCP_CALL 줄이 POC 결제 증빙이라면, 지속성 로그 배출(drain)과 함께 Pro를 쓰거나, 카운터를 Upstash로 전송하고 /metrics를 읽는 것이 낫습니다.

컨테이너로 배포

Dockerfile은 항상 실행되는 HTTP 서비스 말구니를 만듭니다. render에 배포하는 backend/Dockerfile과 동일한 모양입니다. LOG_PATH를 설정하고 /app/logs에 볼륨을 마운트하면, 지출 가드의 순증 창이 배포와 무관하게 유지됩니다.

어느 방식으로 배포든: 배포 후 MCP_PUBLIC_URL를 실제 URL로 설정하고 (끝에 슬ratch 없이) 시작 로그에 표시된 위젯 도메인을 확인하세요.

-
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