google-flights-mcp-server 0.1.1
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/README.md +129 -0
- package/build/index.js +31 -0
- package/package.json +49 -0
- package/shared/flights-client/flights-client.d.ts +23 -0
- package/shared/flights-client/flights-client.js +522 -0
- package/shared/flights-client/types.d.ts +100 -0
- package/shared/flights-client/types.js +1 -0
- package/shared/index.d.ts +7 -0
- package/shared/index.js +8 -0
- package/shared/logging.d.ts +9 -0
- package/shared/logging.js +24 -0
- package/shared/resources.d.ts +3 -0
- package/shared/resources.js +43 -0
- package/shared/server.d.ts +54 -0
- package/shared/server.js +33 -0
- package/shared/tools/find-airport-code.d.ts +38 -0
- package/shared/tools/find-airport-code.js +63 -0
- package/shared/tools/get-date-grid.d.ts +82 -0
- package/shared/tools/get-date-grid.js +106 -0
- package/shared/tools/search-flights.d.ts +140 -0
- package/shared/tools/search-flights.js +171 -0
- package/shared/tools.d.ts +5 -0
- package/shared/tools.js +32 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const SearchFlightsSchema = z.object({
|
|
3
|
+
origin: z.string().min(3).max(3).describe('Origin airport IATA code (e.g., "SFO", "JFK", "LHR")'),
|
|
4
|
+
destination: z
|
|
5
|
+
.string()
|
|
6
|
+
.min(3)
|
|
7
|
+
.max(3)
|
|
8
|
+
.describe('Destination airport IATA code (e.g., "LAX", "LHR", "NRT")'),
|
|
9
|
+
departure_date: z
|
|
10
|
+
.string()
|
|
11
|
+
.regex(/^\d{4}-\d{2}-\d{2}$/)
|
|
12
|
+
.describe('Departure date in YYYY-MM-DD format'),
|
|
13
|
+
return_date: z
|
|
14
|
+
.string()
|
|
15
|
+
.regex(/^\d{4}-\d{2}-\d{2}$/)
|
|
16
|
+
.optional()
|
|
17
|
+
.describe('Return date in YYYY-MM-DD format (required for round_trip)'),
|
|
18
|
+
trip_type: z.enum(['one_way', 'round_trip']).default('one_way').describe('Trip type'),
|
|
19
|
+
seat_class: z
|
|
20
|
+
.enum(['economy', 'premium_economy', 'business', 'first'])
|
|
21
|
+
.default('economy')
|
|
22
|
+
.describe('Cabin class'),
|
|
23
|
+
adults: z.number().int().min(1).max(9).default(1).describe('Number of adult passengers'),
|
|
24
|
+
children: z.number().int().min(0).max(9).default(0).describe('Number of child passengers'),
|
|
25
|
+
infants_in_seat: z
|
|
26
|
+
.number()
|
|
27
|
+
.int()
|
|
28
|
+
.min(0)
|
|
29
|
+
.max(9)
|
|
30
|
+
.default(0)
|
|
31
|
+
.describe('Number of infants with their own seat'),
|
|
32
|
+
infants_on_lap: z.number().int().min(0).max(9).default(0).describe('Number of infants on lap'),
|
|
33
|
+
max_stops: z
|
|
34
|
+
.enum(['any', 'nonstop', '1', '2'])
|
|
35
|
+
.default('any')
|
|
36
|
+
.describe('Maximum number of stops. "any" for no filter, "nonstop" for direct flights only'),
|
|
37
|
+
sort_by: z
|
|
38
|
+
.enum(['best', 'price', 'duration', 'departure', 'arrival'])
|
|
39
|
+
.default('best')
|
|
40
|
+
.describe('Sort order for results'),
|
|
41
|
+
max_results: z
|
|
42
|
+
.number()
|
|
43
|
+
.int()
|
|
44
|
+
.min(1)
|
|
45
|
+
.max(50)
|
|
46
|
+
.default(20)
|
|
47
|
+
.describe('Maximum number of results to return (for pagination)'),
|
|
48
|
+
offset: z
|
|
49
|
+
.number()
|
|
50
|
+
.int()
|
|
51
|
+
.min(0)
|
|
52
|
+
.default(0)
|
|
53
|
+
.describe('Offset for pagination (skip this many results)'),
|
|
54
|
+
currency: z
|
|
55
|
+
.string()
|
|
56
|
+
.min(3)
|
|
57
|
+
.max(3)
|
|
58
|
+
.default('USD')
|
|
59
|
+
.describe('Currency code for prices (e.g., "USD", "EUR", "GBP")'),
|
|
60
|
+
});
|
|
61
|
+
export function searchFlightsTool(_server, clientFactory) {
|
|
62
|
+
return {
|
|
63
|
+
name: 'search_flights',
|
|
64
|
+
description: `Search for flights on Google Flights with full filtering and pagination.
|
|
65
|
+
|
|
66
|
+
Returns structured flight data including prices, airlines, times, durations, stops, and individual flight segments with aircraft type and legroom.
|
|
67
|
+
|
|
68
|
+
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
|
+
|
|
70
|
+
Pagination: The response includes has_more (boolean) and next_offset (number or null). To get the next page, call search_flights again with the same parameters but set offset to next_offset. Keep paginating while has_more is true. Each page returns up to max_results flights.
|
|
71
|
+
|
|
72
|
+
Use find_airport_code first if you need to look up IATA airport codes.
|
|
73
|
+
Use get_date_grid to find the cheapest dates before searching.`,
|
|
74
|
+
inputSchema: {
|
|
75
|
+
type: 'object',
|
|
76
|
+
properties: {
|
|
77
|
+
origin: { type: 'string', description: 'Origin airport IATA code (e.g., "SFO")' },
|
|
78
|
+
destination: {
|
|
79
|
+
type: 'string',
|
|
80
|
+
description: 'Destination airport IATA code (e.g., "LAX")',
|
|
81
|
+
},
|
|
82
|
+
departure_date: {
|
|
83
|
+
type: 'string',
|
|
84
|
+
description: 'Departure date in YYYY-MM-DD format',
|
|
85
|
+
},
|
|
86
|
+
return_date: {
|
|
87
|
+
type: 'string',
|
|
88
|
+
description: 'Return date in YYYY-MM-DD (required for round_trip)',
|
|
89
|
+
},
|
|
90
|
+
trip_type: {
|
|
91
|
+
type: 'string',
|
|
92
|
+
enum: ['one_way', 'round_trip'],
|
|
93
|
+
description: 'Trip type (default: one_way)',
|
|
94
|
+
},
|
|
95
|
+
seat_class: {
|
|
96
|
+
type: 'string',
|
|
97
|
+
enum: ['economy', 'premium_economy', 'business', 'first'],
|
|
98
|
+
description: 'Cabin class (default: economy)',
|
|
99
|
+
},
|
|
100
|
+
adults: {
|
|
101
|
+
type: 'number',
|
|
102
|
+
description: 'Number of adult passengers (default: 1)',
|
|
103
|
+
},
|
|
104
|
+
children: {
|
|
105
|
+
type: 'number',
|
|
106
|
+
description: 'Number of child passengers (default: 0)',
|
|
107
|
+
},
|
|
108
|
+
infants_in_seat: {
|
|
109
|
+
type: 'number',
|
|
110
|
+
description: 'Number of infants with own seat (default: 0)',
|
|
111
|
+
},
|
|
112
|
+
infants_on_lap: {
|
|
113
|
+
type: 'number',
|
|
114
|
+
description: 'Number of infants on lap (default: 0)',
|
|
115
|
+
},
|
|
116
|
+
max_stops: {
|
|
117
|
+
type: 'string',
|
|
118
|
+
enum: ['any', 'nonstop', '1', '2'],
|
|
119
|
+
description: 'Max stops filter (default: any)',
|
|
120
|
+
},
|
|
121
|
+
sort_by: {
|
|
122
|
+
type: 'string',
|
|
123
|
+
enum: ['best', 'price', 'duration', 'departure', 'arrival'],
|
|
124
|
+
description: 'Sort order (default: best)',
|
|
125
|
+
},
|
|
126
|
+
max_results: {
|
|
127
|
+
type: 'number',
|
|
128
|
+
description: 'Max results per page, 1-50 (default: 20)',
|
|
129
|
+
},
|
|
130
|
+
offset: {
|
|
131
|
+
type: 'number',
|
|
132
|
+
description: 'Pagination offset (default: 0)',
|
|
133
|
+
},
|
|
134
|
+
currency: {
|
|
135
|
+
type: 'string',
|
|
136
|
+
description: 'Currency code for prices (default: USD)',
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
required: ['origin', 'destination', 'departure_date'],
|
|
140
|
+
},
|
|
141
|
+
handler: async (args) => {
|
|
142
|
+
try {
|
|
143
|
+
const parsed = SearchFlightsSchema.parse(args);
|
|
144
|
+
// Validate round trip has return date
|
|
145
|
+
if (parsed.trip_type === 'round_trip' && !parsed.return_date) {
|
|
146
|
+
return {
|
|
147
|
+
content: [
|
|
148
|
+
{
|
|
149
|
+
type: 'text',
|
|
150
|
+
text: 'Error: return_date is required when trip_type is "round_trip"',
|
|
151
|
+
},
|
|
152
|
+
],
|
|
153
|
+
isError: true,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
const client = clientFactory();
|
|
157
|
+
const result = await client.searchFlights(parsed);
|
|
158
|
+
return {
|
|
159
|
+
content: [{ type: 'text', text: JSON.stringify(result) }],
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
164
|
+
return {
|
|
165
|
+
content: [{ type: 'text', text: `Error searching flights: ${message}` }],
|
|
166
|
+
isError: true,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
+
import type { FlightsClientFactory } from './server.js';
|
|
3
|
+
export declare function getAllToolNames(): string[];
|
|
4
|
+
export declare function createRegisterTools(clientFactory: FlightsClientFactory): (server: Server) => void;
|
|
5
|
+
//# sourceMappingURL=tools.d.ts.map
|
package/shared/tools.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
import { searchFlightsTool } from './tools/search-flights.js';
|
|
3
|
+
import { getDateGridTool } from './tools/get-date-grid.js';
|
|
4
|
+
import { findAirportCodeTool } from './tools/find-airport-code.js';
|
|
5
|
+
const ALL_TOOLS = [searchFlightsTool, getDateGridTool, findAirportCodeTool];
|
|
6
|
+
export function getAllToolNames() {
|
|
7
|
+
const mockServer = { setRequestHandler: () => { } };
|
|
8
|
+
const mockFactory = (() => { });
|
|
9
|
+
return ALL_TOOLS.map((factory) => factory(mockServer, mockFactory).name);
|
|
10
|
+
}
|
|
11
|
+
export function createRegisterTools(clientFactory) {
|
|
12
|
+
return (server) => {
|
|
13
|
+
const tools = ALL_TOOLS.map((factory) => factory(server, clientFactory));
|
|
14
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
15
|
+
return {
|
|
16
|
+
tools: tools.map((tool) => ({
|
|
17
|
+
name: tool.name,
|
|
18
|
+
description: tool.description,
|
|
19
|
+
inputSchema: tool.inputSchema,
|
|
20
|
+
})),
|
|
21
|
+
};
|
|
22
|
+
});
|
|
23
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
24
|
+
const { name, arguments: args } = request.params;
|
|
25
|
+
const tool = tools.find((t) => t.name === name);
|
|
26
|
+
if (!tool) {
|
|
27
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
28
|
+
}
|
|
29
|
+
return await tool.handler(args);
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
}
|