google-flights-mcp-server 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -204,6 +204,46 @@ function parseSegment(leg) {
|
|
|
204
204
|
};
|
|
205
205
|
}
|
|
206
206
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
207
|
+
function parseExtensions(raw) {
|
|
208
|
+
// offer[4][6] contains baggage amenity flags: [carry_on_flag, checked_bag_flag]
|
|
209
|
+
// carry_on_flag: 0 = included
|
|
210
|
+
// checked_bag_flag: 0 = not included, 1 = one bag included, 2 = two bags included
|
|
211
|
+
const amenityFlags = raw?.[4]?.[6];
|
|
212
|
+
const carryOnIncluded = Array.isArray(amenityFlags) ? amenityFlags[0] === 0 : true;
|
|
213
|
+
const checkedBagsIncluded = Array.isArray(amenityFlags) ? amenityFlags[1] || 0 : 0;
|
|
214
|
+
return {
|
|
215
|
+
carry_on_included: carryOnIncluded,
|
|
216
|
+
checked_bags_included: checkedBagsIncluded,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
220
|
+
function parseFareBrand(raw) {
|
|
221
|
+
// Google Flights does not include fare brand names (e.g. "Basic Economy", "Main Cabin")
|
|
222
|
+
// in the initial search results HTML. However, details[22][2] contains a numeric fare tier
|
|
223
|
+
// indicator that correlates with fare restrictions and amenity levels.
|
|
224
|
+
//
|
|
225
|
+
// Observed mapping from cross-referencing with amenity data and pricing patterns:
|
|
226
|
+
// 1 = Economy (lowest tier for the airline — often "Basic Economy" for US carriers)
|
|
227
|
+
// 2 = Economy+ / Standard (mid-tier with some extras like seat selection)
|
|
228
|
+
// 3 = Economy Flex / Full (higher tier with more flexibility, carry-on, etc.)
|
|
229
|
+
//
|
|
230
|
+
// This is a best-effort interpretation of undocumented numeric codes.
|
|
231
|
+
// Use the `extensions` field for concrete amenity details (carry-on, checked bags).
|
|
232
|
+
const fareTier = raw?.[0]?.[22]?.[2];
|
|
233
|
+
if (fareTier === undefined || fareTier === null)
|
|
234
|
+
return null;
|
|
235
|
+
switch (fareTier) {
|
|
236
|
+
case 1:
|
|
237
|
+
return 'Economy';
|
|
238
|
+
case 2:
|
|
239
|
+
return 'Economy+';
|
|
240
|
+
case 3:
|
|
241
|
+
return 'Economy Flex';
|
|
242
|
+
default:
|
|
243
|
+
return null;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
207
247
|
function parseFlightOffers(ds1, currency) {
|
|
208
248
|
const offers = [];
|
|
209
249
|
if (!ds1?.[3]?.[0] || !Array.isArray(ds1[3][0]))
|
|
@@ -235,6 +275,7 @@ function parseFlightOffers(ds1, currency) {
|
|
|
235
275
|
airline: details[1]?.[0] || '',
|
|
236
276
|
airline_code: details[0] || '',
|
|
237
277
|
is_best: rankData?.[0] === 1,
|
|
278
|
+
fare_brand: parseFareBrand(raw),
|
|
238
279
|
departure: formatTime(details[5]),
|
|
239
280
|
arrival: formatTime(details[8]),
|
|
240
281
|
departure_date: formatDate(details[4]),
|
|
@@ -242,6 +283,7 @@ function parseFlightOffers(ds1, currency) {
|
|
|
242
283
|
duration_minutes: details[9] || 0,
|
|
243
284
|
stops: segments.length > 0 ? segments.length - 1 : 0,
|
|
244
285
|
segments,
|
|
286
|
+
extensions: parseExtensions(raw),
|
|
245
287
|
booking_token: priceData[1] || '',
|
|
246
288
|
});
|
|
247
289
|
}
|
|
@@ -319,6 +361,10 @@ export async function searchFlights(options) {
|
|
|
319
361
|
let allOffers = parseFlightOffers(ds1, options.currency);
|
|
320
362
|
// Apply client-side stop filter (supplements the protobuf filter)
|
|
321
363
|
allOffers = filterByStops(allOffers, options.max_stops);
|
|
364
|
+
// Filter out basic economy fares (fare_brand "Economy" = tier 1, the lowest/basic tier)
|
|
365
|
+
if (options.exclude_basic_economy) {
|
|
366
|
+
allOffers = allOffers.filter((o) => o.fare_brand !== 'Economy');
|
|
367
|
+
}
|
|
322
368
|
// Sort
|
|
323
369
|
allOffers = sortOffers(allOffers, options.sort_by);
|
|
324
370
|
const totalResults = allOffers.length;
|
|
@@ -15,12 +15,17 @@ export interface FlightSegment {
|
|
|
15
15
|
duration_minutes: number;
|
|
16
16
|
legroom: string | null;
|
|
17
17
|
}
|
|
18
|
+
export interface FlightExtensions {
|
|
19
|
+
carry_on_included: boolean;
|
|
20
|
+
checked_bags_included: number;
|
|
21
|
+
}
|
|
18
22
|
export interface FlightOffer {
|
|
19
23
|
price: number;
|
|
20
24
|
currency: string;
|
|
21
25
|
airline: string;
|
|
22
26
|
airline_code: string;
|
|
23
27
|
is_best: boolean;
|
|
28
|
+
fare_brand: string | null;
|
|
24
29
|
departure: string;
|
|
25
30
|
arrival: string;
|
|
26
31
|
departure_date: string;
|
|
@@ -28,6 +33,7 @@ export interface FlightOffer {
|
|
|
28
33
|
duration_minutes: number;
|
|
29
34
|
stops: number;
|
|
30
35
|
segments: FlightSegment[];
|
|
36
|
+
extensions: FlightExtensions;
|
|
31
37
|
booking_token: string;
|
|
32
38
|
}
|
|
33
39
|
export interface DateGridEntry {
|
|
@@ -61,6 +67,7 @@ export interface SearchFlightsOptions {
|
|
|
61
67
|
max_results: number;
|
|
62
68
|
offset: number;
|
|
63
69
|
currency: string;
|
|
70
|
+
exclude_basic_economy: boolean;
|
|
64
71
|
}
|
|
65
72
|
export interface SearchFlightsResult {
|
|
66
73
|
query: {
|
package/shared/index.d.ts
CHANGED
|
@@ -2,6 +2,6 @@ export { registerResources } from './resources.js';
|
|
|
2
2
|
export { createRegisterTools, getAllToolNames } from './tools.js';
|
|
3
3
|
export { createMCPServer, GoogleFlightsClient, type CreateMCPServerOptions, type FlightsClientFactory, type IFlightsClient, } from './server.js';
|
|
4
4
|
export { searchFlights, getDateGrid, findAirportCode, buildTfsParam, } from './flights-client/flights-client.js';
|
|
5
|
-
export type { FlightOffer, FlightSegment, DateGridEntry, DateGridResult, AirportResult, SearchFlightsOptions, SearchFlightsResult, GetDateGridOptions, SeatClass, TripType, } from './flights-client/types.js';
|
|
5
|
+
export type { FlightOffer, FlightSegment, FlightExtensions, DateGridEntry, DateGridResult, AirportResult, SearchFlightsOptions, SearchFlightsResult, GetDateGridOptions, SeatClass, TripType, } from './flights-client/types.js';
|
|
6
6
|
export { logServerStart, logError, logWarning, logInfo, logDebug } from './logging.js';
|
|
7
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -17,6 +17,7 @@ export declare const SearchFlightsSchema: z.ZodObject<{
|
|
|
17
17
|
max_results: z.ZodDefault<z.ZodNumber>;
|
|
18
18
|
offset: z.ZodDefault<z.ZodNumber>;
|
|
19
19
|
currency: z.ZodDefault<z.ZodString>;
|
|
20
|
+
exclude_basic_economy: z.ZodDefault<z.ZodBoolean>;
|
|
20
21
|
}, "strip", z.ZodTypeAny, {
|
|
21
22
|
sort_by: "best" | "price" | "duration" | "departure" | "arrival";
|
|
22
23
|
max_stops: "any" | "nonstop" | "1" | "2";
|
|
@@ -32,6 +33,7 @@ export declare const SearchFlightsSchema: z.ZodObject<{
|
|
|
32
33
|
infants_on_lap: number;
|
|
33
34
|
max_results: number;
|
|
34
35
|
offset: number;
|
|
36
|
+
exclude_basic_economy: boolean;
|
|
35
37
|
return_date?: string | undefined;
|
|
36
38
|
}, {
|
|
37
39
|
origin: string;
|
|
@@ -49,6 +51,7 @@ export declare const SearchFlightsSchema: z.ZodObject<{
|
|
|
49
51
|
infants_on_lap?: number | undefined;
|
|
50
52
|
max_results?: number | undefined;
|
|
51
53
|
offset?: number | undefined;
|
|
54
|
+
exclude_basic_economy?: boolean | undefined;
|
|
52
55
|
}>;
|
|
53
56
|
export declare function searchFlightsTool(_server: Server, clientFactory: FlightsClientFactory): {
|
|
54
57
|
name: string;
|
|
@@ -120,6 +123,10 @@ export declare function searchFlightsTool(_server: Server, clientFactory: Flight
|
|
|
120
123
|
type: string;
|
|
121
124
|
description: string;
|
|
122
125
|
};
|
|
126
|
+
exclude_basic_economy: {
|
|
127
|
+
type: string;
|
|
128
|
+
description: string;
|
|
129
|
+
};
|
|
123
130
|
};
|
|
124
131
|
required: string[];
|
|
125
132
|
};
|
|
@@ -57,13 +57,21 @@ export const SearchFlightsSchema = z.object({
|
|
|
57
57
|
.max(3)
|
|
58
58
|
.default('USD')
|
|
59
59
|
.describe('Currency code for prices (e.g., "USD", "EUR", "GBP")'),
|
|
60
|
+
exclude_basic_economy: z
|
|
61
|
+
.boolean()
|
|
62
|
+
.default(true)
|
|
63
|
+
.describe('Exclude basic economy fares from results (default: true). Basic economy fares typically have restrictions like no carry-on, no seat selection, and no changes. Set to false to include all fare tiers.'),
|
|
60
64
|
});
|
|
61
65
|
export function searchFlightsTool(_server, clientFactory) {
|
|
62
66
|
return {
|
|
63
67
|
name: 'search_flights',
|
|
64
68
|
description: `Search for flights on Google Flights with full filtering and pagination.
|
|
65
69
|
|
|
66
|
-
Returns structured flight data including prices, airlines, times, durations, stops,
|
|
70
|
+
Returns structured flight data including prices, airlines, times, durations, stops, individual flight segments with aircraft type and legroom, fare brand (e.g. "Economy", "Economy+", "Economy Flex"), and fare extensions (carry-on and checked bag inclusion).
|
|
71
|
+
|
|
72
|
+
The fare_brand field indicates the fare tier: "Economy" (basic/lowest tier), "Economy+" (mid-tier with extras), or "Economy Flex" (higher tier with more flexibility). This is derived from Google's numeric fare tier data and may be null if unavailable. Use the extensions field (carry_on_included, checked_bags_included) for concrete amenity details.
|
|
73
|
+
|
|
74
|
+
By default, basic economy fares (fare_brand "Economy") are excluded from results since they typically have significant restrictions (no carry-on, no seat selection, non-refundable). Set exclude_basic_economy to false to include all fare tiers.
|
|
67
75
|
|
|
68
76
|
IMPORTANT — Handling large result sets: Popular routes often return 50-150+ flights. If total_results is high, recommend narrowing with filters (max_stops, sort_by, seat_class) rather than paginating through everything. For example, set max_stops to "nonstop" or sort_by to "price" to surface the most relevant options quickly.
|
|
69
77
|
|
|
@@ -135,6 +143,10 @@ Use get_date_grid to find the cheapest dates before searching.`,
|
|
|
135
143
|
type: 'string',
|
|
136
144
|
description: 'Currency code for prices (default: USD)',
|
|
137
145
|
},
|
|
146
|
+
exclude_basic_economy: {
|
|
147
|
+
type: 'boolean',
|
|
148
|
+
description: 'Exclude basic economy fares (default: true). Set to false to include all fare tiers.',
|
|
149
|
+
},
|
|
138
150
|
},
|
|
139
151
|
required: ['origin', 'destination', 'departure_date'],
|
|
140
152
|
},
|