Skip to main content
Glama
by ricleedo

airports-search

Search for flight information and pricing between airports using Google Flights data. Find available flights, compare prices, and get travel options for one-way, round-trip, or multi-city journeys.

Instructions

Search for airport and flight information using Google Flights

Input Schema

NameRequiredDescriptionDefault
arrival_idYesArrival airport code (e.g., 'NRT', 'LAX', 'JFK', 'LHR'). Use 3-letter IATA codes.
departure_idYesDeparture airport code (e.g., 'CDG', 'AUS', 'LAX', 'SFO'). Use 3-letter IATA codes.
include_airportsNoInclude airport information
include_linksNoInclude booking links for each flight (off by default)
include_price_insightsNoInclude price insights and history
max_best_flightsNoMaximum number of best flights to return
max_other_flightsNoMaximum number of other flights to return
multi_city_jsonNoJSON string for multi-city trips with multiple legs (required when type=3)
outbound_dateNoOutbound date in YYYY-MM-DD format
return_dateNoReturn date in YYYY-MM-DD format for round-trip (REQUIRED when type=1)
summary_onlyNoReturn only essential flight information
typeNoTrip type: 1=Round-trip (requires return_date), 2=One-way (default), 3=Multi-city (requires multi_city_json). Use type=2 for one-way trips to avoid errors.

Input Schema (JSON Schema)

{ "properties": { "arrival_id": { "description": "Arrival airport code (e.g., 'NRT', 'LAX', 'JFK', 'LHR'). Use 3-letter IATA codes.", "type": "string" }, "departure_id": { "description": "Departure airport code (e.g., 'CDG', 'AUS', 'LAX', 'SFO'). Use 3-letter IATA codes.", "type": "string" }, "include_airports": { "default": false, "description": "Include airport information", "type": "boolean" }, "include_links": { "default": false, "description": "Include booking links for each flight (off by default)", "type": "boolean" }, "include_price_insights": { "default": true, "description": "Include price insights and history", "type": "boolean" }, "max_best_flights": { "default": 3, "description": "Maximum number of best flights to return", "type": "number" }, "max_other_flights": { "default": 5, "description": "Maximum number of other flights to return", "type": "number" }, "multi_city_json": { "description": "JSON string for multi-city trips with multiple legs (required when type=3)", "type": "string" }, "outbound_date": { "description": "Outbound date in YYYY-MM-DD format", "type": "string" }, "return_date": { "description": "Return date in YYYY-MM-DD format for round-trip (REQUIRED when type=1)", "type": "string" }, "summary_only": { "default": true, "description": "Return only essential flight information", "type": "boolean" }, "type": { "default": 2, "description": "Trip type: 1=Round-trip (requires return_date), 2=One-way (default), 3=Multi-city (requires multi_city_json). Use type=2 for one-way trips to avoid errors.", "type": "number" } }, "required": [ "departure_id", "arrival_id" ], "type": "object" }

Implementation Reference

  • src/index.ts:151-179 (registration)
    Registers the 'airports-search' tool using McpServer.tool(), providing name, description, schema from airportsSearchSchema.shape, and a wrapper async handler that calls searchAirports and formats response.
    server.tool( "airports-search", "Search for airport and flight information using Google Flights", airportsSearchSchema.shape, async (params) => { try { const result = await searchAirports(params); return { content: [ { type: "text", text: result, }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error searching airports data: ${ error instanceof Error ? error.message : String(error) }`, }, ], }; } } );
  • Zod schema defining input parameters for the airports-search tool, including airports, dates, trip type, and formatting options.
    const airportsSearchSchema = z.object({ departure_id: z .string() .describe("Departure airport code (e.g., 'CDG', 'AUS', 'LAX', 'SFO'). Use 3-letter IATA codes."), arrival_id: z.string().describe("Arrival airport code (e.g., 'NRT', 'LAX', 'JFK', 'LHR'). Use 3-letter IATA codes."), outbound_date: z .string() .optional() .describe("Outbound date in YYYY-MM-DD format"), return_date: z .string() .optional() .describe("Return date in YYYY-MM-DD format for round-trip (REQUIRED when type=1)"), multi_city_json: z .string() .optional() .describe("JSON string for multi-city trips with multiple legs (required when type=3)"), type: z .number() .optional() .default(2) .describe("Trip type: 1=Round-trip (requires return_date), 2=One-way (default), 3=Multi-city (requires multi_city_json). Use type=2 for one-way trips to avoid errors."), max_best_flights: z .number() .optional() .default(3) .describe("Maximum number of best flights to return"), max_other_flights: z .number() .optional() .default(5) .describe("Maximum number of other flights to return"), include_price_insights: z .boolean() .optional() .default(true) .describe("Include price insights and history"), include_airports: z .boolean() .optional() .default(false) .describe("Include airport information"), summary_only: z .boolean() .optional() .default(true) .describe("Return only essential flight information"), include_links: z .boolean() .optional() .default(false) .describe("Include booking links for each flight (off by default)"), });
  • The core handler function searchAirports that constructs SerpAPI query for Google Flights, fetches data using axios, and formats the response using formatFlightToMarkdown.
    export async function searchAirports( params: z.infer<typeof airportsSearchSchema> ): Promise<string> { const apiKey = process.env.SERP_API_KEY; if (!apiKey) { throw new Error("SERP_API_KEY environment variable is required"); } const { max_best_flights, max_other_flights, include_price_insights, include_airports, summary_only, include_links, ...apiParams } = params; const searchParams = new URLSearchParams({ engine: "google_flights", api_key: apiKey, departure_id: apiParams.departure_id, arrival_id: apiParams.arrival_id, hl: "en", currency: "USD", ...(apiParams.outbound_date && { outbound_date: apiParams.outbound_date }), ...(apiParams.return_date && { return_date: apiParams.return_date }), ...(apiParams.multi_city_json && { multi_city_json: apiParams.multi_city_json, }), ...(apiParams.type !== undefined && { type: apiParams.type.toString() }), }); try { const response = await axios.get( `${SERPAPI_BASE_URL}?${searchParams.toString()}` ); return formatFlightToMarkdown(response.data, params); } catch (error) { if (axios.isAxiosError(error)) { throw new Error( `Airports API request failed: ${ error.response?.data?.error || error.message }` ); } throw error; } }
  • Helper function to format raw API flight data into a structured Markdown response, handling summary and detailed views.
    function formatFlightToMarkdown(data: any, params: z.infer<typeof airportsSearchSchema>): string { if (!data) return "No flight data available."; let markdown = `# ${params.departure_id} β†’ ${params.arrival_id}\n\n`; // Get the Google Flights URL for booking const googleFlightsUrl = data.search_metadata?.google_flights_url; // Add route summary if (params.summary_only) { const bestFlight = data.best_flights?.[0]; const bestPrice = bestFlight?.price || data.price_insights?.lowest_price; const flightCount = (data.best_flights?.length || 0) + (data.other_flights?.length || 0); markdown += `**Best Price**: $${bestPrice}\n`; if (bestFlight?.flights?.[0]?.airline) { markdown += `**Airline**: ${bestFlight.flights[0].airline}\n`; } markdown += `**Flights Found**: ${flightCount}\n\n`; if (params.include_price_insights !== false && data.price_insights) { markdown += `**Price Level**: ${data.price_insights.price_level}\n`; if (data.price_insights.typical_price_range) { markdown += `**Typical Range**: $${data.price_insights.typical_price_range.join('-$')}\n`; } } return markdown; } // Add best flights if (data.best_flights && params.max_best_flights && params.max_best_flights > 0) { markdown += `## Best Options\n\n`; const bestFlights = data.best_flights.slice(0, params.max_best_flights); bestFlights.forEach((flight: any) => { const stops = flight.flights && flight.flights.length > 1 ? `${flight.flights.length - 1} stop${flight.flights.length > 2 ? 's' : ''}` : 'Direct'; const totalDuration = formatDuration(flight.total_duration); markdown += `### $${flight.price} β€’ ${totalDuration} β€’ ${stops}\n`; if (params.include_links && googleFlightsUrl) { markdown += `**URL**: ${googleFlightsUrl}\n`; } if (flight.flights && flight.flights.length > 0) { flight.flights.forEach((segment: any, index: number) => { const depAirport = segment.departure_airport?.code || segment.departure_airport?.name || segment.departure_airport || 'Unknown'; const arrAirport = segment.arrival_airport?.code || segment.arrival_airport?.name || segment.arrival_airport || 'Unknown'; const depTime = segment.departure_airport?.time || 'Unknown'; const arrTime = segment.arrival_airport?.time || 'Unknown'; markdown += `${segment.airline} ${segment.flight_number}: ${depAirport} ${depTime} β†’ ${arrAirport} ${arrTime}\n`; // Add layover information if this is not the last segment if (index < flight.flights.length - 1 && flight.layovers?.[index]) { const layover = flight.layovers[index]; const layoverDuration = formatDuration(layover.duration); markdown += ` Layover: ${layoverDuration}\n`; } }); } markdown += `\n`; }); } // Add other flights if (data.other_flights && params.max_other_flights && params.max_other_flights > 0) { markdown += `## Other Options\n\n`; const otherFlights = data.other_flights.slice(0, params.max_other_flights); otherFlights.forEach((flight: any) => { const stops = flight.flights && flight.flights.length > 1 ? `${flight.flights.length - 1} stop${flight.flights.length > 2 ? 's' : ''}` : 'Direct'; const totalDuration = formatDuration(flight.total_duration); markdown += `### $${flight.price} β€’ ${totalDuration} β€’ ${stops}\n`; if (params.include_links && googleFlightsUrl) { markdown += `**URL**: ${googleFlightsUrl}\n`; } if (flight.flights && flight.flights.length > 0) { flight.flights.forEach((segment: any, index: number) => { const depAirport = segment.departure_airport?.code || segment.departure_airport?.name || segment.departure_airport || 'Unknown'; const arrAirport = segment.arrival_airport?.code || segment.arrival_airport?.name || segment.arrival_airport || 'Unknown'; const depTime = segment.departure_airport?.time || 'Unknown'; const arrTime = segment.arrival_airport?.time || 'Unknown'; markdown += `${segment.airline} ${segment.flight_number}: ${depAirport} ${depTime} β†’ ${arrAirport} ${arrTime}\n`; // Add layover information if this is not the last segment if (index < flight.flights.length - 1 && flight.layovers?.[index]) { const layover = flight.layovers[index]; const layoverDuration = formatDuration(layover.duration); markdown += ` Layover: ${layoverDuration}\n`; } }); } markdown += `\n`; }); } // Add price insights for detailed view if (params.include_price_insights !== false && data.price_insights && !params.summary_only) { markdown += `**Price Level**: ${data.price_insights.price_level} β€’ Lowest: $${data.price_insights.lowest_price}\n`; } return markdown; }

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/ricleedo/Google-Service-MCP'

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