@reneturcios/flightdata 0.0.0-stage → 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Rene Turcios
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,152 @@
1
- # Temporary Holding Version
1
+ # flightdata
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ flightdata is a small local bridge to the hosted
4
+ HasData Google Flights MCP server, which returns
5
+ Google Flights search results as JSON. Give it a
6
+ departure, a destination and an outbound date, and
7
+ it fetches matching itineraries: each option's
8
+ price, total duration and stops, its flight legs
9
+ with airline, flight number, aircraft, airports
10
+ and times, and its CO2 emissions, plus the booking
11
+ and departure tokens the upstream issues for
12
+ following up on a chosen itinerary.
13
+
14
+ Searches cover one-way, round-trip and multi-city
15
+ trips. They can be shaped by passenger mix (adults,
16
+ children, infants in a seat or on a lap), travel
17
+ class, carry-on bags, a maximum price, sort order
18
+ (price, duration, emissions, departure or arrival
19
+ time), stop limits, included or excluded airlines
20
+ and connections, departure and return time windows,
21
+ layover duration bounds, a maximum total duration,
22
+ an emissions preference and a deep-search mode.
23
+
24
+ The bridge stores no fares of its own. It serves
25
+ the upstream server's tool list locally, exactly as
26
+ captured from the live endpoint, and forwards each
27
+ tool call upstream, returning the result untouched.
28
+ The captured surface is a single read-only fare
29
+ search: there is no booking, reservation, ticketing
30
+ or payment tool in it.
31
+
32
+ ## Tools
33
+
34
+ - `hasdata_google_travel_flights_getGoogleFlights`
35
+ — search Google Flights. Required: `departureId`
36
+ (IATA code or location kgmid; comma-separated
37
+ multiples allowed), `arrivalId` (same formats),
38
+ and `outboundDate` (`yyyy-MM-dd`). Optional:
39
+ `returnDate`, `type` (`roundTrip` / `oneWay` /
40
+ `multiCity`), `multiCityJson`, `gl`, `hl`,
41
+ `currency`, `travelClass` (`economy` /
42
+ `premiumEconomy` / `business` / `first`),
43
+ `showHidden`, `adults`, `children`,
44
+ `infantsInSeat`, `infantsOnLap`, `sortBy`
45
+ (`topFlights` / `price` / `departureTime` /
46
+ `arrivalTime` / `duration` / `emissions`),
47
+ `stops` (`nonStop` / `oneStopOrFewer` /
48
+ `twoStopsOrFewer`), `excludeAirlines`,
49
+ `includeAirlines`, `bags`, `maxPrice`,
50
+ `outboundTimes`, `returnTimes`, `lessEmissions`,
51
+ `layoverDuration`, `includeConnections`,
52
+ `excludeConnections`, `maxDuration`, `deepSearch`,
53
+ `departureToken` and `bookingToken`. Returns
54
+ per-itinerary price, duration, stops and legs,
55
+ emissions, and booking/departure tokens.
56
+
57
+ ## Configuration
58
+
59
+ - `HASDATA_GOOGLE_FLIGHTS_MCP_URL` (optional) —
60
+ override the upstream endpoint. Defaults to
61
+ `https://mcp.hasdata.com/mcp?apis=google_travel_flights`.
62
+ (The override hook is this rebuild's own labelled
63
+ reconstruction.)
64
+ - `HASDATA_API_KEY` (optional) — when set, every
65
+ upstream request carries an `x-api-key: <key>`
66
+ header, for the caller's own HasData API key. When
67
+ it is not set, no key header is sent. (The header
68
+ name and the env name are pinned by the original's
69
+ registry record; forwarding the key from this env
70
+ var is a labelled reconstruction — the original
71
+ surface was captured keyless.)
72
+
73
+ ### Forwarding mechanics
74
+
75
+ On the first tool call the client opens a streamable
76
+ HTTP session with the upstream: a JSON-RPC
77
+ `initialize` request (protocolVersion `2025-03-26`,
78
+ clientInfo name `flightdata`), then a
79
+ `notifications/initialized` notification, then the
80
+ `tools/call` request carrying the caller's arguments
81
+ unchanged. When the upstream answers `initialize`
82
+ with an `Mcp-Session-Id` header, that value rides on
83
+ every later request of the session, which is reused
84
+ for the life of the process. Replies may arrive as
85
+ plain JSON or as server-sent events; both are read.
86
+
87
+ Successful upstream results pass through verbatim,
88
+ including any `isError` flag the upstream sets.
89
+ Failures — a JSON-RPC error, a non-2xx status, an
90
+ unreadable response, or a request that cannot be
91
+ completed — come back as an `isError` result whose
92
+ text starts with `flightdata error:` (this rendering
93
+ is this rebuild's own labelled reconstruction).
94
+
95
+ ## CLI
96
+
97
+ The tool is also a subcommand taking one JSON
98
+ argument string:
99
+
100
+ ```bash
101
+ npx @reneturcios/flightdata hasdata_google_travel_flights_getGoogleFlights '{"departureId":"SFO","arrivalId":"LHR","outboundDate":"2026-12-01","type":"oneWay","travelClass":"economy","stops":"nonStop"}'
102
+ npx @reneturcios/flightdata --version
103
+ ```
104
+
105
+ Exit codes: `0` on success, `1` on an `isError`
106
+ result, `2` on a usage error.
107
+
108
+ ## MCP server
109
+
110
+ ```bash
111
+ npx -y @reneturcios/flightdata mcp
112
+ ```
113
+
114
+ MCP client config:
115
+
116
+ ```json
117
+ {
118
+ "mcpServers": {
119
+ "flightdata": {
120
+ "command": "npx",
121
+ "args": ["-y", "@reneturcios/flightdata", "mcp"]
122
+ }
123
+ }
124
+ }
125
+ ```
126
+
127
+ ## Docker
128
+
129
+ ```bash
130
+ docker run -i ghcr.io/cloudcorprecords/flightdata
131
+ docker run --rm ghcr.io/cloudcorprecords/flightdata --version
132
+ ```
133
+
134
+ The container's default command is `mcp`, so the first
135
+ form is a stdio MCP server; any other arguments reach
136
+ the CLI normally.
137
+
138
+ ## Development
139
+
140
+ ```bash
141
+ npm install
142
+ npm run build
143
+ npm test
144
+ npm run dev
145
+ ```
146
+
147
+ The test suite runs entirely against a stubbed
148
+ JSON-RPC upstream — no live network calls.
149
+
150
+ ## License
151
+
152
+ MIT — see `LICENSE`.
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,78 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * flightdata CLI.
4
+ *
5
+ * flightdata <tool> '<json-args>'
6
+ * flightdata mcp
7
+ * flightdata --version
8
+ *
9
+ * <tool> is the 1 forwarded tool. Each tool subcommand
10
+ * takes one JSON argument string with the tool's
11
+ * arguments, forwards the call like the MCP path, and
12
+ * prints the forwarded result content. Exit codes:
13
+ * 0 success, 1 on an isError result, 2 usage error.
14
+ */
15
+ import { callTool, TOOL_NAMES, VERSION } from "./forward.js";
16
+ function usage() {
17
+ console.error(`Usage:
18
+ flightdata <tool> '<json-args>' one of: ${TOOL_NAMES.join(", ")}
19
+ flightdata mcp
20
+ flightdata --version`);
21
+ process.exit(2);
22
+ }
23
+ function firstText(result) {
24
+ const content = result.content;
25
+ if (Array.isArray(content)) {
26
+ for (const item of content) {
27
+ if (item !== null &&
28
+ typeof item === "object" &&
29
+ item.type === "text" &&
30
+ typeof item.text === "string") {
31
+ return item.text;
32
+ }
33
+ }
34
+ }
35
+ return typeof content === "string" ? content : JSON.stringify(content);
36
+ }
37
+ async function main() {
38
+ const [cmd, ...rest] = process.argv.slice(2);
39
+ if (cmd === "--version" || cmd === "-v") {
40
+ console.log(VERSION);
41
+ return;
42
+ }
43
+ if (cmd === "mcp") {
44
+ if (rest.length !== 0)
45
+ usage();
46
+ const { startMcpServer } = await import("./mcp.js");
47
+ await startMcpServer();
48
+ return;
49
+ }
50
+ if (!TOOL_NAMES.includes(cmd ?? ""))
51
+ usage();
52
+ if (rest.length > 1)
53
+ usage();
54
+ let args = {};
55
+ if (rest.length === 1) {
56
+ try {
57
+ const parsed = JSON.parse(rest[0]);
58
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
59
+ usage();
60
+ }
61
+ args = parsed;
62
+ }
63
+ catch {
64
+ console.error("error: argument must be a JSON object string");
65
+ process.exit(2);
66
+ }
67
+ }
68
+ const result = await callTool(cmd, args);
69
+ if (result.isError) {
70
+ console.error(`error: ${firstText(result)}`);
71
+ process.exit(1);
72
+ }
73
+ console.log(typeof result.content === "string"
74
+ ? result.content
75
+ : JSON.stringify(result.content, null, 2));
76
+ }
77
+ void main();
78
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * flightdata core: a forwarding client for the hosted
3
+ * HasData Google Flights MCP server.
4
+ *
5
+ * No flight search is run locally. tools/list is answered from
6
+ * the literal tool definition below, taken verbatim from
7
+ * a live capture of the upstream server (name, title,
8
+ * description and inputSchema exactly as captured,
9
+ * including the title key the tool carries). A tools/call
10
+ * is forwarded over a streamable-HTTP JSON-RPC session:
11
+ * an initialize POST, a notifications/initialized POST,
12
+ * then the tools/call POST, honouring the Mcp-Session-Id
13
+ * response header when the upstream issues one. The
14
+ * session is established lazily on the first forwarded
15
+ * call and reused for the lifetime of the client.
16
+ *
17
+ * The upstream endpoint is pinned to
18
+ * https://mcp.hasdata.com/mcp?apis=google_travel_flights — the query
19
+ * string is part of the pinned URL — and can be
20
+ * overridden with the HASDATA_GOOGLE_FLIGHTS_MCP_URL environment
21
+ * variable (that override is a labelled reconstruction).
22
+ * When HASDATA_API_KEY is set in the environment, every
23
+ * upstream request carries an `x-api-key: <key>` header
24
+ * (the header name is pinned by the registry record's
25
+ * remote declaration; forwarding the key from this env
26
+ * var is a labelled reconstruction — the capture itself
27
+ * was taken keyless). When the variable is unset, no key
28
+ * header is sent, and no Authorization header is sent in
29
+ * either case.
30
+ *
31
+ * Upstream results pass through verbatim, including any
32
+ * isError flag and any extra result fields. Failures — a
33
+ * JSON-RPC error from the upstream, a non-2xx status, an
34
+ * unparseable response, or a fetch that throws or times
35
+ * out — surface as an isError result whose text starts
36
+ * with `flightdata error:` (that rendering is a labelled
37
+ * reconstruction). Responses may be plain JSON or SSE
38
+ * (data: lines); the JSON-RPC message with the matching
39
+ * id wins.
40
+ */
41
+ import type { ForwardDeps, ToolArgs, ToolDef, ToolResult } from "./types.js";
42
+ export declare const VERSION = "0.1.0";
43
+ export declare const DEFAULT_ENDPOINT_URL = "https://mcp.hasdata.com/mcp?apis=google_travel_flights";
44
+ export declare const DEFAULT_TIMEOUT_MS = 30000;
45
+ export declare const PROTOCOL_VERSION = "2025-03-26";
46
+ export declare const TOOL_DEFS: ToolDef[];
47
+ export declare const TOOL_NAMES: string[];
48
+ /** Whether `name` is one of the captured tools. */
49
+ export declare function isKnownTool(name: string): boolean;
50
+ /**
51
+ * Parse a JSON-RPC response body, tolerating SSE framing.
52
+ * Returns the message whose id matches `expectedId` when
53
+ * one is present, else the last parseable message, else
54
+ * null when nothing parses.
55
+ */
56
+ export declare function parseRpcBody(text: string, expectedId?: number): Record<string, unknown> | null;
57
+ /**
58
+ * A forwarding client holding one upstream session. The
59
+ * session is established lazily on the first forwarded
60
+ * call and reused for the lifetime of the client (the
61
+ * process lifetime when the client is the MCP server's
62
+ * or a one-shot client for the CLI).
63
+ */
64
+ export declare class FlightdataClient {
65
+ private readonly deps;
66
+ private sessionId;
67
+ private ready;
68
+ private sessionPromise;
69
+ private idCounter;
70
+ constructor(deps?: ForwardDeps);
71
+ private fetchFn;
72
+ private endpointUrl;
73
+ private apiKey;
74
+ private timeoutMs;
75
+ private nextId;
76
+ private post;
77
+ private ensureSession;
78
+ /** Forward one tool call; upstream failures come back as isError results. */
79
+ callTool(name: string, args: ToolArgs): Promise<ToolResult>;
80
+ }
81
+ /** Create a forwarding client; tests inject a fake fetch and env through deps. */
82
+ export declare function createClient(deps?: ForwardDeps): FlightdataClient;
83
+ /** One-shot helper: a fresh client per call (the CLI path). */
84
+ export declare function callTool(name: string, args: ToolArgs, deps?: ForwardDeps): Promise<ToolResult>;
@@ -0,0 +1,409 @@
1
+ export const VERSION = "0.1.0";
2
+ export const DEFAULT_ENDPOINT_URL = "https://mcp.hasdata.com/mcp?apis=google_travel_flights";
3
+ export const DEFAULT_TIMEOUT_MS = 30000;
4
+ export const PROTOCOL_VERSION = "2025-03-26";
5
+ /* ------------------------------------------------------------------ */
6
+ /* Tool definitions (tools/list literals, verbatim from the live */
7
+ /* capture in harness/fixtures/hasdata-google-flights-tools-original.json) */
8
+ /* ------------------------------------------------------------------ */
9
+ export const TOOL_DEFS = [
10
+ {
11
+ "name": "hasdata_google_travel_flights_getGoogleFlights",
12
+ "title": "google_travel_flights: GET /",
13
+ "description": "Get Google Flights Results\n\nSearches Google Flights for one-way, round-trip, or multi-city itineraries with passenger mix (adults, children, infants in-seat/on-lap), travel class, bags, max price, sort order (price, duration, emissions, departure/arrival time), stops, include/exclude airlines and connections, time windows, layover duration, and deep-search mode. Returns per-itinerary price, total duration, stops, flight legs with airline, flight number, aircraft, departure/arrival airports and times, CO2 emissions, plus booking and departure tokens for round-trip returns or booking options. Use for travel-planning agents, fare monitoring, corporate travel dashboards, emission-aware trip optimization, and comparing routes and airlines across markets.",
14
+ "inputSchema": {
15
+ "type": "object",
16
+ "properties": {
17
+ "departureId": {
18
+ "type": "string",
19
+ "description": "Specifies the departure airport code (IATA) or location kgmid.\n\n - **IATA Code**: A 3-letter uppercase code (e.g., SFO for San Francisco, LHR for London Heathrow). Search on [IATA](https://www.iata.org/en/publications/directories/code-search).\n - **Location kgmid**: A string starting with `/m/`, found in Wikidata under \"Freebase ID\" (e.g., `/m/02_286` for New York, NY).\n\nMultiple values can be separated by commas (e.g., `JFK,LGA,/m/0hptm`).\n"
20
+ },
21
+ "arrivalId": {
22
+ "type": "string",
23
+ "description": "Specifies the arrival airport code (IATA) or location kgmid.\n\n - **IATA Code**: A 3-letter uppercase code (e.g., `SFO` for San Francisco, `LHR` for London Heathrow). Search on [IATA](https://www.iata.org/en/publications/directories/code-search).\n - **Location kgmid**: A string starting with `/m/`, found in Wikidata under \"Freebase ID\" (e.g., `/m/02_286` for New York, NY).\n\nMultiple values can be separated by commas (e.g., `JFK,LGA,/m/0hptm`).\n"
24
+ },
25
+ "outboundDate": {
26
+ "type": "string",
27
+ "description": "The outbound travel date in 'yyyy-MM-dd' format.\n"
28
+ },
29
+ "returnDate": {
30
+ "type": "string",
31
+ "description": "The return travel date in 'yyyy-MM-dd' format. Required when **type** is `roundTrip`.\n"
32
+ },
33
+ "type": {
34
+ "type": "string",
35
+ "enum": [
36
+ "roundTrip",
37
+ "oneWay",
38
+ "multiCity"
39
+ ],
40
+ "description": "Specifies the type of flight. Options:\n\n - `roundTrip` (default)\n - `oneWay`\n - `multiCity` (requires `multiCityJson` for flight details)\n\nFor round trips, retrieve return flight details with a separate request using `departureToken`.\n"
41
+ },
42
+ "multiCityJson": {
43
+ "type": "string",
44
+ "description": "This parameter specifies flight details for multi-city trips. It is a JSON string containing multiple flight objects. Each object must include the following fields:\n\n- **departureId** – The departure airport code or location KGMID. Uses the same format as the main `departureId` parameter.\n- **arrivalId** – The arrival airport code or location KGMID. Uses the same format as the main `arrivalId` parameter.\n- **date** – The flight date. Uses the same format as the `outboundDate` parameter.\n- **times** *(optional)* – The time range for the flight. Uses the same format as the `outboundTimes` parameter.\n"
45
+ },
46
+ "gl": {
47
+ "type": "string",
48
+ "description": "The two-letter country code for the country you want to limit the search to. Provide one exact documented value (245 allowed), e.g. `ac`, `af`."
49
+ },
50
+ "hl": {
51
+ "type": "string",
52
+ "description": "The two-letter language code for the language you want to use for the search. Provide one exact documented value (159 allowed), e.g. `af`, `ak`."
53
+ },
54
+ "currency": {
55
+ "type": "string",
56
+ "description": "Parameter defines the currency of the returned prices Provide one exact documented value (71 allowed), e.g. `ALL`, `DZD`."
57
+ },
58
+ "travelClass": {
59
+ "type": "string",
60
+ "enum": [
61
+ "economy",
62
+ "premiumEconomy",
63
+ "business",
64
+ "first"
65
+ ],
66
+ "description": "The travel class for the flight (Economy, Premium Economy, Business, or First).\n"
67
+ },
68
+ "showHidden": {
69
+ "type": "boolean",
70
+ "description": "Indicates whether to include hidden options in the results.\n"
71
+ },
72
+ "adults": {
73
+ "type": "number",
74
+ "description": "Number of adult passengers (>= 1 if specified).\n"
75
+ },
76
+ "children": {
77
+ "type": "number",
78
+ "description": "Number of child passengers.\n"
79
+ },
80
+ "infantsInSeat": {
81
+ "type": "number",
82
+ "description": "Number of infants occupying seats.\n"
83
+ },
84
+ "infantsOnLap": {
85
+ "type": "number",
86
+ "description": "Number of infants sitting on an adult's lap.\n"
87
+ },
88
+ "sortBy": {
89
+ "type": "string",
90
+ "enum": [
91
+ "topFlights",
92
+ "price",
93
+ "departureTime",
94
+ "arrivalTime",
95
+ "duration",
96
+ "emissions"
97
+ ],
98
+ "description": "Sort the flight results based on price, departure time, arrival time, etc.\n"
99
+ },
100
+ "stops": {
101
+ "type": "string",
102
+ "enum": [
103
+ "nonStop",
104
+ "oneStopOrFewer",
105
+ "twoStopsOrFewer"
106
+ ],
107
+ "description": "Restrict the number of stops (layovers) in the flight itinerary.\n"
108
+ },
109
+ "excludeAirlines": {
110
+ "type": "string",
111
+ "description": "A comma separated list of airline codes to exclude from results. You can search for airline codes on [IATA](https://www.iata.org/en/publications/directories/code-search). For example, `UA` is United Airlines.\n"
112
+ },
113
+ "includeAirlines": {
114
+ "type": "string",
115
+ "description": "A comma separated list of airline codes to exclusively include in results. You can search for airline codes on [IATA](https://www.iata.org/en/publications/directories/code-search). For example, `UA` is United Airlines.\n\n`excludeAirlines` and `includeAirlines` parameters can't be used together.\n"
116
+ },
117
+ "bags": {
118
+ "type": "number",
119
+ "description": "Number of carry-on bags per passenger.\n"
120
+ },
121
+ "maxPrice": {
122
+ "type": "number",
123
+ "description": "Maximum price limit for the flight search, in the selected currency.\n"
124
+ },
125
+ "outboundTimes": {
126
+ "type": "string",
127
+ "description": "Set up to 4 time boundaries (2 for departure, 2 for arrival) to filter flights. Each number represents the start of an hour.\n\nExamples:\n - `6,20` → 6:00 AM - 9:00 PM departure\n - `1,15` → 1:00 AM - 4:00 PM departure\n - `7,18,2,21` → 7:00 AM - 9:00 PM departure, 2:00 AM - 10:00 PM arrival\n"
128
+ },
129
+ "returnTimes": {
130
+ "type": "string",
131
+ "description": "Set up to 4 time boundaries (2 for departure, 2 for arrival) to filter return flights. Each number represents the start of an hour.\n\nExamples:\n - `6,20` → 6:00 AM - 9:00 PM departure\n - `1,15` → 1:00 AM - 4:00 PM departure\n - `7,18,2,21` → 7:00 AM - 9:00 PM departure, 2:00 AM - 10:00 PM arrival\n"
132
+ },
133
+ "lessEmissions": {
134
+ "type": "boolean",
135
+ "description": "Prefer flight options with lower carbon emissions.\n"
136
+ },
137
+ "layoverDuration": {
138
+ "type": "string",
139
+ "description": "Set the maximum layover duration in minutes to filter flights. For example, `120, 360` filters layovers between 2 hours and 6 hours, while `45, 180` allows layovers from 45 minutes to 3 hours.\n"
140
+ },
141
+ "includeConnections": {
142
+ "type": "string",
143
+ "description": "A comma separated list of specific airports to allow as connections.\n"
144
+ },
145
+ "excludeConnections": {
146
+ "type": "string",
147
+ "description": "A comma separated list of specific airports to exclude as connections.\n"
148
+ },
149
+ "maxDuration": {
150
+ "type": "number",
151
+ "description": "The maximum total flight duration in minutes.\n"
152
+ },
153
+ "deepSearch": {
154
+ "type": "boolean",
155
+ "description": "Enable deep search. Returns the same results as Google Flights in a browser, but takes longer to respond. Default is `false`.\n"
156
+ },
157
+ "departureToken": {
158
+ "type": "string",
159
+ "description": "Used to select a flight and retrieve return flights for a round trip or the next leg of the itinerary for a multi-city trip.\n"
160
+ },
161
+ "bookingToken": {
162
+ "type": "string",
163
+ "description": "Used to request booking options for selected flights. This token is found in the flight results and cannot be used with `departureToken`.\n"
164
+ }
165
+ },
166
+ "required": [
167
+ "departureId",
168
+ "arrivalId",
169
+ "outboundDate"
170
+ ],
171
+ "additionalProperties": false,
172
+ "$schema": "http://json-schema.org/draft-07/schema#"
173
+ }
174
+ }
175
+ ];
176
+ export const TOOL_NAMES = TOOL_DEFS.map((t) => t.name);
177
+ /** Whether `name` is one of the captured tools. */
178
+ export function isKnownTool(name) {
179
+ return TOOL_NAMES.includes(name);
180
+ }
181
+ /* ------------------------------------------------------------------ */
182
+ /* Forwarding client */
183
+ /* ------------------------------------------------------------------ */
184
+ function errorResult(detail) {
185
+ return {
186
+ content: [{ type: "text", text: `flightdata error: ${detail}` }],
187
+ isError: true,
188
+ };
189
+ }
190
+ function rpcErrorMessage(error) {
191
+ if (error !== null && typeof error === "object") {
192
+ const message = error.message;
193
+ if (typeof message === "string" && message !== "")
194
+ return message;
195
+ return JSON.stringify(error);
196
+ }
197
+ return String(error);
198
+ }
199
+ /**
200
+ * Parse a JSON-RPC response body, tolerating SSE framing.
201
+ * Returns the message whose id matches `expectedId` when
202
+ * one is present, else the last parseable message, else
203
+ * null when nothing parses.
204
+ */
205
+ export function parseRpcBody(text, expectedId) {
206
+ const trimmed = text.trim();
207
+ if (trimmed === "")
208
+ return null;
209
+ const candidates = [];
210
+ const tryPush = (payload) => {
211
+ try {
212
+ const parsed = JSON.parse(payload);
213
+ if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) {
214
+ candidates.push(parsed);
215
+ }
216
+ }
217
+ catch {
218
+ // Not JSON; ignore this candidate.
219
+ }
220
+ };
221
+ if (trimmed.includes("data:")) {
222
+ for (const line of trimmed.split("\n")) {
223
+ const t = line.trim();
224
+ if (!t.startsWith("data:"))
225
+ continue;
226
+ const payload = t.slice("data:".length).trim();
227
+ if (payload !== "" && payload !== "[DONE]")
228
+ tryPush(payload);
229
+ }
230
+ }
231
+ else {
232
+ tryPush(trimmed);
233
+ }
234
+ if (candidates.length === 0)
235
+ return null;
236
+ if (expectedId !== undefined) {
237
+ const match = candidates.find((c) => c.id === expectedId);
238
+ if (match !== undefined)
239
+ return match;
240
+ }
241
+ return candidates[candidates.length - 1];
242
+ }
243
+ async function defaultFetch(url, init) {
244
+ return fetch(url, init);
245
+ }
246
+ /**
247
+ * A forwarding client holding one upstream session. The
248
+ * session is established lazily on the first forwarded
249
+ * call and reused for the lifetime of the client (the
250
+ * process lifetime when the client is the MCP server's
251
+ * or a one-shot client for the CLI).
252
+ */
253
+ export class FlightdataClient {
254
+ deps;
255
+ sessionId = null;
256
+ ready = false;
257
+ sessionPromise = null;
258
+ idCounter = 0;
259
+ constructor(deps = {}) {
260
+ this.deps = deps;
261
+ }
262
+ fetchFn() {
263
+ return this.deps.fetchFn ?? defaultFetch;
264
+ }
265
+ endpointUrl() {
266
+ if (this.deps.url && this.deps.url.trim() !== "")
267
+ return this.deps.url.trim();
268
+ const raw = (this.deps.env ?? process.env).HASDATA_GOOGLE_FLIGHTS_MCP_URL;
269
+ if (raw && raw.trim() !== "")
270
+ return raw.trim();
271
+ return DEFAULT_ENDPOINT_URL;
272
+ }
273
+ apiKey() {
274
+ const raw = (this.deps.env ?? process.env).HASDATA_API_KEY;
275
+ if (raw && raw.trim() !== "")
276
+ return raw.trim();
277
+ return null;
278
+ }
279
+ timeoutMs() {
280
+ if (typeof this.deps.timeoutMs === "number" && this.deps.timeoutMs > 0) {
281
+ return this.deps.timeoutMs;
282
+ }
283
+ return DEFAULT_TIMEOUT_MS;
284
+ }
285
+ nextId() {
286
+ this.idCounter += 1;
287
+ return this.idCounter;
288
+ }
289
+ async post(body, withSession) {
290
+ const headers = {
291
+ "Content-Type": "application/json",
292
+ Accept: "application/json, text/event-stream",
293
+ };
294
+ const key = this.apiKey();
295
+ if (key !== null)
296
+ headers["x-api-key"] = key;
297
+ if (withSession && this.sessionId !== null) {
298
+ headers["Mcp-Session-Id"] = this.sessionId;
299
+ }
300
+ const controller = new AbortController();
301
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs());
302
+ try {
303
+ return await this.fetchFn()(this.endpointUrl(), {
304
+ method: "POST",
305
+ headers,
306
+ body: JSON.stringify(body),
307
+ signal: controller.signal,
308
+ });
309
+ }
310
+ finally {
311
+ clearTimeout(timer);
312
+ }
313
+ }
314
+ async ensureSession() {
315
+ if (this.ready)
316
+ return;
317
+ if (this.sessionPromise === null) {
318
+ this.sessionPromise = (async () => {
319
+ const initId = this.nextId();
320
+ const initRes = await this.post({
321
+ jsonrpc: "2.0",
322
+ id: initId,
323
+ method: "initialize",
324
+ params: {
325
+ protocolVersion: PROTOCOL_VERSION,
326
+ capabilities: {},
327
+ clientInfo: { name: "flightdata", version: VERSION },
328
+ },
329
+ }, false);
330
+ const sessionId = initRes.headers.get("mcp-session-id");
331
+ if (sessionId)
332
+ this.sessionId = sessionId;
333
+ const initText = await initRes.text();
334
+ const initParsed = parseRpcBody(initText, initId);
335
+ if (initParsed !== null && initParsed.error) {
336
+ throw new Error(rpcErrorMessage(initParsed.error));
337
+ }
338
+ if (initRes.status < 200 || initRes.status >= 300) {
339
+ throw new Error(`HTTP ${initRes.status}`);
340
+ }
341
+ if (initParsed === null && initText.trim() !== "") {
342
+ throw new Error("malformed response");
343
+ }
344
+ const initializedRes = await this.post({ jsonrpc: "2.0", method: "notifications/initialized" }, true);
345
+ try {
346
+ await initializedRes.text();
347
+ }
348
+ catch {
349
+ // The notification response body carries nothing we need.
350
+ }
351
+ this.ready = true;
352
+ })();
353
+ }
354
+ try {
355
+ await this.sessionPromise;
356
+ }
357
+ catch (err) {
358
+ this.sessionPromise = null;
359
+ this.sessionId = null;
360
+ throw err;
361
+ }
362
+ }
363
+ /** Forward one tool call; upstream failures come back as isError results. */
364
+ async callTool(name, args) {
365
+ try {
366
+ await this.ensureSession();
367
+ }
368
+ catch (err) {
369
+ return errorResult(err instanceof Error ? err.message : String(err));
370
+ }
371
+ const callId = this.nextId();
372
+ let callRes;
373
+ try {
374
+ callRes = await this.post({
375
+ jsonrpc: "2.0",
376
+ id: callId,
377
+ method: "tools/call",
378
+ params: { name, arguments: args ?? {} },
379
+ }, true);
380
+ }
381
+ catch (err) {
382
+ return errorResult(`request failed: ${err instanceof Error ? err.message : String(err)}`);
383
+ }
384
+ const parsed = parseRpcBody(await callRes.text(), callId);
385
+ if (parsed !== null && parsed.error) {
386
+ return errorResult(rpcErrorMessage(parsed.error));
387
+ }
388
+ if (callRes.status < 200 || callRes.status >= 300) {
389
+ return errorResult(`HTTP ${callRes.status}`);
390
+ }
391
+ if (parsed === null)
392
+ return errorResult("malformed response");
393
+ const result = parsed.result;
394
+ if (result === undefined || result === null || typeof result !== "object") {
395
+ return errorResult("malformed response");
396
+ }
397
+ // Pass the upstream result through verbatim.
398
+ return result;
399
+ }
400
+ }
401
+ /** Create a forwarding client; tests inject a fake fetch and env through deps. */
402
+ export function createClient(deps = {}) {
403
+ return new FlightdataClient(deps);
404
+ }
405
+ /** One-shot helper: a fresh client per call (the CLI path). */
406
+ export async function callTool(name, args, deps = {}) {
407
+ return new FlightdataClient(deps).callTool(name, args);
408
+ }
409
+ //# sourceMappingURL=forward.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forward.js","sourceRoot":"","sources":["../src/forward.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export * from "./types.js";
2
+ export * from "./forward.js";
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export * from "./types.js";
2
+ export * from "./forward.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC"}
package/dist/mcp.d.ts ADDED
@@ -0,0 +1,35 @@
1
+ /**
2
+ * flightdata MCP server. Tools: the 1 captured HasData
3
+ * Google Flights tool (see forward.ts).
4
+ *
5
+ * Why the low-level Server instead of McpServer: the
6
+ * high-level helper converts zod schemas to JSON Schema
7
+ * and rewrites the served schemas, which breaks exact
8
+ * tool-list/schema parity with the live capture. This
9
+ * file serves tools/list locally from the core's explicit
10
+ * literals — the verbatim tool objects from the upstream
11
+ * server's live tools/list — and forwards every
12
+ * tools/call upstream.
13
+ *
14
+ * A forwarded result is returned unchanged (including any
15
+ * upstream isError flag and extra result fields). An
16
+ * upstream failure comes back as an isError result
17
+ * carrying a `flightdata error:` text, synthesised by the
18
+ * forwarding client. An unknown tool name is rejected
19
+ * with McpError MethodNotFound, and arguments that are
20
+ * not a JSON object with McpError InvalidParams, before
21
+ * any network hop.
22
+ */
23
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
24
+ import { type FlightdataClient } from "./forward.js";
25
+ import type { ForwardDeps, ToolResult } from "./types.js";
26
+ /**
27
+ * Validate and forward one tools/call through `client`.
28
+ * Exported so the forwarding behaviour can be tested
29
+ * directly without a stdio transport.
30
+ */
31
+ export declare function handleCallTool(client: FlightdataClient, name: string, args: unknown): Promise<ToolResult>;
32
+ /** Build the stdio MCP server (transport not yet connected). */
33
+ export declare function createServer(deps?: ForwardDeps): Server;
34
+ /** Connect the MCP server over stdio. */
35
+ export declare function startMcpServer(deps?: ForwardDeps): Promise<void>;
package/dist/mcp.js ADDED
@@ -0,0 +1,60 @@
1
+ /**
2
+ * flightdata MCP server. Tools: the 1 captured HasData
3
+ * Google Flights tool (see forward.ts).
4
+ *
5
+ * Why the low-level Server instead of McpServer: the
6
+ * high-level helper converts zod schemas to JSON Schema
7
+ * and rewrites the served schemas, which breaks exact
8
+ * tool-list/schema parity with the live capture. This
9
+ * file serves tools/list locally from the core's explicit
10
+ * literals — the verbatim tool objects from the upstream
11
+ * server's live tools/list — and forwards every
12
+ * tools/call upstream.
13
+ *
14
+ * A forwarded result is returned unchanged (including any
15
+ * upstream isError flag and extra result fields). An
16
+ * upstream failure comes back as an isError result
17
+ * carrying a `flightdata error:` text, synthesised by the
18
+ * forwarding client. An unknown tool name is rejected
19
+ * with McpError MethodNotFound, and arguments that are
20
+ * not a JSON object with McpError InvalidParams, before
21
+ * any network hop.
22
+ */
23
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
24
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
25
+ import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, } from "@modelcontextprotocol/sdk/types.js";
26
+ import { createClient, isKnownTool, TOOL_DEFS, VERSION, } from "./forward.js";
27
+ /**
28
+ * Validate and forward one tools/call through `client`.
29
+ * Exported so the forwarding behaviour can be tested
30
+ * directly without a stdio transport.
31
+ */
32
+ export async function handleCallTool(client, name, args) {
33
+ if (!isKnownTool(name)) {
34
+ throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
35
+ }
36
+ if (args !== undefined &&
37
+ (typeof args !== "object" || args === null || Array.isArray(args))) {
38
+ throw new McpError(ErrorCode.InvalidParams, `Arguments for tool ${name} must be a JSON object`);
39
+ }
40
+ return client.callTool(name, (args ?? {}));
41
+ }
42
+ /** Build the stdio MCP server (transport not yet connected). */
43
+ export function createServer(deps = {}) {
44
+ const client = createClient(deps);
45
+ const server = new Server({ name: "flightdata", version: VERSION }, { capabilities: { tools: {} } });
46
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
47
+ tools: TOOL_DEFS,
48
+ }));
49
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
50
+ const { name, arguments: args } = request.params;
51
+ const result = await handleCallTool(client, name, args);
52
+ return result;
53
+ });
54
+ return server;
55
+ }
56
+ /** Connect the MCP server over stdio. */
57
+ export async function startMcpServer(deps = {}) {
58
+ await createServer(deps).connect(new StdioServerTransport());
59
+ }
60
+ //# sourceMappingURL=mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,qBAAqB,EACrB,SAAS,EACT,sBAAsB,EACtB,QAAQ,GACT,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACL,YAAY,EACZ,WAAW,EACX,SAAS,EACT,OAAO,GAER,MAAM,cAAc,CAAC;AAGtB;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAwB,EACxB,IAAY,EACZ,IAAa;IAEb,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,cAAc,EAAE,iBAAiB,IAAI,EAAE,CAAC,CAAC;IACxE,CAAC;IACD,IACE,IAAI,KAAK,SAAS;QAClB,CAAC,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAClE,CAAC;QACD,MAAM,IAAI,QAAQ,CAChB,SAAS,CAAC,aAAa,EACvB,sBAAsB,IAAI,wBAAwB,CACnD,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,IAAI,EAAE,CAA4B,CAAC,CAAC;AACxE,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,YAAY,CAAC,OAAoB,EAAE;IACjD,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,EACxC,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAChC,CAAC;IAEF,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;QAC5D,KAAK,EAAE,SAAS;KACjB,CAAC,CAAC,CAAC;IAEJ,MAAM,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QAChE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;QACjD,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QACxD,OAAO,MAAe,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,yCAAyC;AACzC,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAoB,EAAE;IACzD,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,oBAAoB,EAAE,CAAC,CAAC;AAC/D,CAAC"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * flightdata types.
3
+ *
4
+ * flightdata holds no flight data of its own. It is a forwarding
5
+ * client: the captured tool surface lives here as data (ToolDef
6
+ * entries served verbatim for tools/list) and every tools/call
7
+ * travels to the hosted HasData Google Flights MCP endpoint through an
8
+ * injectable fetch, so the test suite never touches the live
9
+ * network.
10
+ */
11
+ /** One captured tool definition, served verbatim for tools/list. */
12
+ export interface ToolDef {
13
+ name: string;
14
+ title?: string;
15
+ description: string;
16
+ inputSchema: Record<string, unknown>;
17
+ [key: string]: unknown;
18
+ }
19
+ /** A tool's arguments, as decoded JSON. */
20
+ export type ToolArgs = Record<string, unknown>;
21
+ /** A tools/call result: upstream results pass through verbatim; failures use this shape. */
22
+ export interface ToolResult {
23
+ content?: unknown;
24
+ isError?: boolean;
25
+ [key: string]: unknown;
26
+ }
27
+ /** The minimal slice of a fetch Response this client relies on. */
28
+ export interface FetchResponseLike {
29
+ ok: boolean;
30
+ status: number;
31
+ headers: {
32
+ get(name: string): string | null;
33
+ };
34
+ text(): Promise<string>;
35
+ }
36
+ /** Injectable fetch, so tests never touch the live network. */
37
+ export type FetchFn = (url: string, init?: {
38
+ method?: string;
39
+ headers?: Record<string, string>;
40
+ body?: string;
41
+ signal?: AbortSignal;
42
+ }) => Promise<FetchResponseLike>;
43
+ /** Runtime dependencies for the forwarding client, all injectable in tests. */
44
+ export interface ForwardDeps {
45
+ /** Fetch implementation. Defaults to the global fetch. */
46
+ fetchFn?: FetchFn;
47
+ /** Environment (HASDATA_GOOGLE_FLIGHTS_MCP_URL, HASDATA_API_KEY). Defaults to process.env. */
48
+ env?: Record<string, string | undefined>;
49
+ /** Endpoint URL override. Defaults to env HASDATA_GOOGLE_FLIGHTS_MCP_URL or the pinned default. */
50
+ url?: string;
51
+ /** Per-request timeout in ms. Defaults to 30000. */
52
+ timeoutMs?: number;
53
+ }
package/dist/types.js ADDED
@@ -0,0 +1,12 @@
1
+ /**
2
+ * flightdata types.
3
+ *
4
+ * flightdata holds no flight data of its own. It is a forwarding
5
+ * client: the captured tool surface lives here as data (ToolDef
6
+ * entries served verbatim for tools/list) and every tools/call
7
+ * travels to the hosted HasData Google Flights MCP endpoint through an
8
+ * injectable fetch, so the test suite never touches the live
9
+ * network.
10
+ */
11
+ export {};
12
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
package/package.json CHANGED
@@ -1,6 +1 @@
1
- {
2
- "name": "@reneturcios/flightdata",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
1
+ {"bin":{"flightdata":"dist/cli.js"},"dependencies":{"@modelcontextprotocol/sdk":"^1","zod":"^4"},"description":"Google Flights results as JSON from your agent: a local bridge to the hosted HasData Google Flights MCP service that searches one-way, round-trip and multi-city itineraries with passenger mix, travel class, stops, airline and emissions filters, returning per-itinerary prices, durations, legs and tokens as returned upstream. One bin serves a small CLI and a stdio MCP server.","devDependencies":{"@types/node":"^20","tsx":"^4","typescript":"^5"},"engines":{"node":">=20"},"files":["dist","server.json"],"homepage":"https://github.com/CloudCorpRecords/flightdata#readme","license":"MIT","mcpName":"io.github.CloudCorpRecords/flightdata","name":"@reneturcios/flightdata","private":false,"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/CloudCorpRecords/flightdata.git"},"scripts":{"build":"tsc","dev":"tsx src/cli.ts","test":"tsx --test test/*.test.ts"},"type":"module","version":"0.1.0"}
package/server.json ADDED
@@ -0,0 +1 @@
1
+ {"$schema":"https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json","description":"Google Flights search as JSON: itineraries, prices, times, stops and emissions filters.","name":"io.github.CloudCorpRecords/flightdata","packages":[{"identifier":"@reneturcios/flightdata","packageArguments":[{"type":"positional","value":"mcp"}],"registryBaseUrl":"https://registry.npmjs.org","registryType":"npm","runtimeHint":"npx","transport":{"type":"stdio"},"version":"0.1.0"},{"identifier":"ghcr.io/cloudcorprecords/flightdata:0.1.0","packageArguments":[{"type":"positional","value":"mcp"}],"registryType":"oci","runtimeArguments":[{"name":"--rm","type":"named"},{"name":"-i","type":"named"}],"runtimeHint":"docker","transport":{"type":"stdio"}}],"repository":{"source":"github","url":"https://github.com/CloudCorpRecords/flightdata"},"version":"0.1.0"}