@squawk/mcp 0.12.0 → 0.13.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/README.md +35 -18
- package/dist/resolvers.d.ts +88 -27
- package/dist/resolvers.d.ts.map +1 -1
- package/dist/resolvers.js +174 -62
- package/dist/tools/airports.d.ts +6 -4
- package/dist/tools/airports.d.ts.map +1 -1
- package/dist/tools/airports.js +15 -10
- package/dist/tools/airspace.d.ts +5 -3
- package/dist/tools/airspace.d.ts.map +1 -1
- package/dist/tools/airspace.js +19 -9
- package/dist/tools/airways.d.ts +3 -2
- package/dist/tools/airways.d.ts.map +1 -1
- package/dist/tools/airways.js +16 -11
- package/dist/tools/datasets.d.ts +13 -6
- package/dist/tools/datasets.d.ts.map +1 -1
- package/dist/tools/datasets.js +28 -49
- package/dist/tools/fixes.d.ts +3 -2
- package/dist/tools/fixes.d.ts.map +1 -1
- package/dist/tools/fixes.js +16 -11
- package/dist/tools/flightplan.d.ts +5 -3
- package/dist/tools/flightplan.d.ts.map +1 -1
- package/dist/tools/flightplan.js +40 -15
- package/dist/tools/navaids.d.ts +3 -2
- package/dist/tools/navaids.d.ts.map +1 -1
- package/dist/tools/navaids.js +19 -13
- package/dist/tools/procedures.d.ts +3 -2
- package/dist/tools/procedures.d.ts.map +1 -1
- package/dist/tools/procedures.js +28 -19
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -98,7 +98,7 @@ version explicitly in the client config:
|
|
|
98
98
|
"mcpServers": {
|
|
99
99
|
"squawk": {
|
|
100
100
|
"command": "npx",
|
|
101
|
-
"args": ["-y", "@squawk/mcp@0.
|
|
101
|
+
"args": ["-y", "@squawk/mcp@0.13.0"]
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
104
|
}
|
|
@@ -144,14 +144,17 @@ rest of the server keeps working normally. If you do not need aircraft lookups,
|
|
|
144
144
|
is required.
|
|
145
145
|
|
|
146
146
|
To enable lookups, install the data package alongside `@squawk/mcp`. Through `npx` the cleanest
|
|
147
|
-
option is the `-p` flag, which adds extra packages to the temporary install npx builds
|
|
147
|
+
option is the `-p` flag, which adds extra packages to the temporary install npx builds. Once more
|
|
148
|
+
than one package is involved, npx no longer infers which one to run, so give it each package
|
|
149
|
+
behind its own `-p` and name the actual binary (`squawk-mcp`, not the package name) as the
|
|
150
|
+
trailing command:
|
|
148
151
|
|
|
149
152
|
```json
|
|
150
153
|
{
|
|
151
154
|
"mcpServers": {
|
|
152
155
|
"squawk": {
|
|
153
156
|
"command": "npx",
|
|
154
|
-
"args": ["-y", "-p", "@squawk/icao-registry-data", "@squawk/mcp"]
|
|
157
|
+
"args": ["-y", "-p", "@squawk/icao-registry-data", "-p", "@squawk/mcp", "squawk-mcp"]
|
|
155
158
|
}
|
|
156
159
|
}
|
|
157
160
|
}
|
|
@@ -164,7 +167,14 @@ Pinning works the same way:
|
|
|
164
167
|
"mcpServers": {
|
|
165
168
|
"squawk": {
|
|
166
169
|
"command": "npx",
|
|
167
|
-
"args": [
|
|
170
|
+
"args": [
|
|
171
|
+
"-y",
|
|
172
|
+
"-p",
|
|
173
|
+
"@squawk/icao-registry-data@0.8.12",
|
|
174
|
+
"-p",
|
|
175
|
+
"@squawk/mcp@0.13.0",
|
|
176
|
+
"squawk-mcp"
|
|
177
|
+
]
|
|
168
178
|
}
|
|
169
179
|
}
|
|
170
180
|
}
|
|
@@ -395,9 +405,9 @@ left to the model itself.
|
|
|
395
405
|
|
|
396
406
|
### Server diagnostics
|
|
397
407
|
|
|
398
|
-
| Tool | Purpose
|
|
399
|
-
| -------------------- |
|
|
400
|
-
| `get_dataset_status` | Report NASR cycle date, build timestamp, and record counts for every
|
|
408
|
+
| Tool | Purpose |
|
|
409
|
+
| -------------------- | ----------------------------------------------------------------------------------------------------------------------- |
|
|
410
|
+
| `get_dataset_status` | Report NASR/CIFP cycle date, build timestamp, and record counts for every bundled snapshot, plus whether each is loaded |
|
|
401
411
|
|
|
402
412
|
## Configuration
|
|
403
413
|
|
|
@@ -462,13 +472,16 @@ Two things worth knowing before you trim:
|
|
|
462
472
|
- **`datasets` is a group like any other.** It holds `get_dataset_status`, the tool that
|
|
463
473
|
reports which NASR and CIFP cycles the running server is serving. An allowlist that
|
|
464
474
|
leaves it out means you can no longer ask how current the data is, so include it unless
|
|
465
|
-
you are sure you do not want it. It is the cheapest group in the catalog
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
475
|
+
you are sure you do not want it. It is the cheapest group in the catalog, and it stays
|
|
476
|
+
cheap: cycle dates and record counts are read from a small metadata module in each data
|
|
477
|
+
package, so asking for status never loads a snapshot.
|
|
478
|
+
- **Trimming the catalog trims the data too.** Each snapshot is decompressed the first time
|
|
479
|
+
a tool actually reads it, so a group you never register is a group whose data never
|
|
480
|
+
loads. Dropping `procedures` from a session that never asks about approach plates saves
|
|
481
|
+
its load outright, not just its share of the context window. A group you kept still works
|
|
482
|
+
when it reads data belonging to a group you dropped - `flightplan` resolves airports and
|
|
483
|
+
navaids in a route string with `airports` and `navaids` disabled, loading those snapshots
|
|
484
|
+
on its own first call, because you disabled those tools, not that data.
|
|
472
485
|
|
|
473
486
|
## Notes
|
|
474
487
|
|
|
@@ -479,7 +492,11 @@ Two things worth knowing before you trim:
|
|
|
479
492
|
- Live weather tools issue HTTPS requests to `https://aviationweather.gov/api/data/...` (or the
|
|
480
493
|
override above). They are the only tools that touch the network at invocation time; everything
|
|
481
494
|
else operates against bundled snapshots in memory.
|
|
482
|
-
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
the
|
|
495
|
+
- Snapshots are decompressed and indexed on first use rather than at startup, so the server comes
|
|
496
|
+
up immediately and each dataset pays a one-time cost the first time a tool reads it. Every later
|
|
497
|
+
call against a loaded dataset is served from memory. Procedures is the largest of these loads and
|
|
498
|
+
navaids by far the smallest, with airports, fixes, airspace, and airways in between; loading all
|
|
499
|
+
of them is on the order of a second. Parsing a route string triggers the biggest single first
|
|
500
|
+
call, since `flightplan` draws on five snapshots at once. The aircraft registration snapshot (the
|
|
501
|
+
largest overall, and an optional peer dependency) loads on the first `lookup_aircraft_by_icao_hex`
|
|
502
|
+
call, if the package is installed.
|
package/dist/resolvers.d.ts
CHANGED
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @packageDocumentation
|
|
3
|
-
* Shared resolver
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* Shared resolver accessors used across the squawk MCP tool modules. Every
|
|
4
|
+
* bundled FAA snapshot loads on demand: the first accessor call dynamically
|
|
5
|
+
* imports its data package, decompresses and indexes the snapshot, and caches
|
|
6
|
+
* the result for the life of the process. A session that only asks about
|
|
7
|
+
* airports never decompresses the CIFP procedure snapshot, and a session that
|
|
8
|
+
* asks nothing pays nothing beyond process start.
|
|
6
9
|
*
|
|
7
|
-
*
|
|
10
|
+
* Each accessor memoizes the in-flight load rather than the finished
|
|
11
|
+
* resolver, so concurrent tool calls needing the same dataset share one
|
|
12
|
+
* import and one index build instead of racing to build two.
|
|
13
|
+
*
|
|
14
|
+
* The ICAO registry follows the same shape with one extra wrinkle: its data
|
|
8
15
|
* package (`@squawk/icao-registry-data`) is declared as an optional peer
|
|
9
|
-
* dependency rather than a required dep
|
|
10
|
-
*
|
|
11
|
-
* cached for subsequent calls. When the peer is not installed, the import
|
|
16
|
+
* dependency rather than a required dep, so a failed import is an expected
|
|
17
|
+
* outcome rather than a broken install. When the peer is absent the import
|
|
12
18
|
* throws `ERR_MODULE_NOT_FOUND` and {@link getIcaoRegistry} surfaces a
|
|
13
19
|
* {@link MissingDataPackageError} for the tool handler to format.
|
|
14
20
|
*/
|
|
@@ -19,18 +25,75 @@ import { type FixResolver } from '@squawk/fixes';
|
|
|
19
25
|
import { type IcaoRegistry } from '@squawk/icao-registry';
|
|
20
26
|
import { type NavaidResolver } from '@squawk/navaids';
|
|
21
27
|
import { type ProcedureResolver } from '@squawk/procedures';
|
|
22
|
-
/**
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
/**
|
|
29
|
+
* Returns the shared airport resolver, importing and indexing the bundled US
|
|
30
|
+
* NASR airport snapshot on the first call.
|
|
31
|
+
*
|
|
32
|
+
* @returns The shared airport resolver.
|
|
33
|
+
*/
|
|
34
|
+
export declare function getAirportResolver(): Promise<AirportResolver>;
|
|
35
|
+
/**
|
|
36
|
+
* Returns the shared airspace resolver, importing and indexing the bundled US
|
|
37
|
+
* NASR airspace GeoJSON snapshot on the first call.
|
|
38
|
+
*
|
|
39
|
+
* @returns The shared airspace resolver.
|
|
40
|
+
*/
|
|
41
|
+
export declare function getAirspaceResolver(): Promise<AirspaceResolver>;
|
|
42
|
+
/**
|
|
43
|
+
* Returns the shared airway resolver, importing and indexing the bundled US
|
|
44
|
+
* NASR airway snapshot on the first call.
|
|
45
|
+
*
|
|
46
|
+
* @returns The shared airway resolver.
|
|
47
|
+
*/
|
|
48
|
+
export declare function getAirwayResolver(): Promise<AirwayResolver>;
|
|
49
|
+
/**
|
|
50
|
+
* Returns the shared fix resolver, importing and indexing the bundled US NASR
|
|
51
|
+
* fix snapshot on the first call.
|
|
52
|
+
*
|
|
53
|
+
* @returns The shared fix resolver.
|
|
54
|
+
*/
|
|
55
|
+
export declare function getFixResolver(): Promise<FixResolver>;
|
|
56
|
+
/**
|
|
57
|
+
* Returns the shared navaid resolver, importing and indexing the bundled US
|
|
58
|
+
* NASR navaid snapshot on the first call.
|
|
59
|
+
*
|
|
60
|
+
* @returns The shared navaid resolver.
|
|
61
|
+
*/
|
|
62
|
+
export declare function getNavaidResolver(): Promise<NavaidResolver>;
|
|
63
|
+
/**
|
|
64
|
+
* Returns the shared procedure resolver, importing and indexing the bundled
|
|
65
|
+
* FAA CIFP procedure snapshot on the first call.
|
|
66
|
+
*
|
|
67
|
+
* @returns The shared procedure resolver.
|
|
68
|
+
*/
|
|
69
|
+
export declare function getProcedureResolver(): Promise<ProcedureResolver>;
|
|
70
|
+
/**
|
|
71
|
+
* Whether each required bundled snapshot has been loaded into the running
|
|
72
|
+
* process. Build metadata is not part of this shape: it is available from
|
|
73
|
+
* each data package's `/meta` subpath without loading anything, so only the
|
|
74
|
+
* in-memory state has to be read from here.
|
|
75
|
+
*/
|
|
76
|
+
export interface BundledDatasetLoadState {
|
|
77
|
+
/** Whether the airport snapshot is loaded. */
|
|
78
|
+
readonly airports: boolean;
|
|
79
|
+
/** Whether the airspace snapshot is loaded. */
|
|
80
|
+
readonly airspace: boolean;
|
|
81
|
+
/** Whether the airway snapshot is loaded. */
|
|
82
|
+
readonly airways: boolean;
|
|
83
|
+
/** Whether the fix snapshot is loaded. */
|
|
84
|
+
readonly fixes: boolean;
|
|
85
|
+
/** Whether the navaid snapshot is loaded. */
|
|
86
|
+
readonly navaids: boolean;
|
|
87
|
+
/** Whether the procedure snapshot is loaded. */
|
|
88
|
+
readonly procedures: boolean;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Reports which required bundled snapshots are currently in memory, without
|
|
92
|
+
* loading any of them.
|
|
93
|
+
*
|
|
94
|
+
* @returns Per-dataset load state.
|
|
95
|
+
*/
|
|
96
|
+
export declare function getBundledDatasetLoadState(): BundledDatasetLoadState;
|
|
34
97
|
/**
|
|
35
98
|
* Error thrown when a tool tries to load an optional data package peer that
|
|
36
99
|
* has not been installed alongside `@squawk/mcp`. Tool handlers catch this
|
|
@@ -59,12 +122,10 @@ type IcaoRegistryDataLoader = () => Promise<typeof import('@squawk/icao-registry
|
|
|
59
122
|
* the bundled FAA aircraft registration snapshot on the first call. Subsequent
|
|
60
123
|
* calls reuse the cached instance.
|
|
61
124
|
*
|
|
62
|
-
* The registry is
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
* never install the peer see only the structured missing-package error
|
|
67
|
-
* surfaced by the tool handler.
|
|
125
|
+
* The registry's data package is the largest snapshot in the suite (roughly
|
|
126
|
+
* 40 MB raw) and is declared as an optional peer dependency rather than a
|
|
127
|
+
* required dep, so consumers who never install the peer see only the
|
|
128
|
+
* structured missing-package error surfaced by the tool handler.
|
|
68
129
|
*
|
|
69
130
|
* @returns The shared registry instance.
|
|
70
131
|
* @throws {MissingDataPackageError} when `@squawk/icao-registry-data` is not
|
|
@@ -76,8 +137,8 @@ export declare function getIcaoRegistry(): Promise<IcaoRegistry>;
|
|
|
76
137
|
*
|
|
77
138
|
* Test-only seam for swapping the optional data package loader. Production
|
|
78
139
|
* code must not call this. Pass `undefined` to restore the default loader
|
|
79
|
-
* and clear all cached state (instance, metadata, and the
|
|
80
|
-
* sticky flag) so subsequent tests start from a clean slate.
|
|
140
|
+
* and clear all cached state (instance, in-flight load, metadata, and the
|
|
141
|
+
* missing-peer sticky flag) so subsequent tests start from a clean slate.
|
|
81
142
|
*
|
|
82
143
|
* @param loader - Replacement loader, or `undefined` to reset.
|
|
83
144
|
*/
|
package/dist/resolvers.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolvers.d.ts","sourceRoot":"","sources":["../src/resolvers.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"resolvers.d.ts","sourceRoot":"","sources":["../src/resolvers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAyB,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAC/E,OAAO,EAA0B,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACjF,OAAO,EAAwB,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAC5E,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAwB,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAC5E,OAAO,EAA2B,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAmGrF;;;;;GAKG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAAC,eAAe,CAAC,CAE7D;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAE/D;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAAC,cAAc,CAAC,CAE3D;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC,CAErD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAAC,cAAc,CAAC,CAE3D;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAEjE;AAED;;;;;GAKG;AACH,MAAM,WAAW,uBAAuB;IACtC,8CAA8C;IAC9C,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,+CAA+C;IAC/C,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,6CAA6C;IAC7C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,0CAA0C;IAC1C,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,6CAA6C;IAC7C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,gDAAgD;IAChD,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;CAC9B;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,IAAI,uBAAuB,CASpE;AAED;;;;;GAKG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,kEAAkE;IAClE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,oFAAoF;IACpF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,kFAAkF;IAClF,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAEhC;;;;;OAKG;gBACS,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;CAQrD;AA0BD,2EAA2E;AAC3E,KAAK,sBAAsB,GAAG,MAAM,OAAO,CAAC,cAAc,4BAA4B,CAAC,CAAC,CAAC;AAwDzF;;;;;;;;;;;;;GAaG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,YAAY,CAAC,CAS7D;AAED;;;;;;;;;GASG;AACH,wBAAgB,kCAAkC,CAChD,MAAM,EAAE,sBAAsB,GAAG,SAAS,GACzC,IAAI,CAMN;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAE9C;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,IACrC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAEzD"}
|
package/dist/resolvers.js
CHANGED
|
@@ -1,52 +1,146 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @packageDocumentation
|
|
3
|
-
* Shared resolver
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* Shared resolver accessors used across the squawk MCP tool modules. Every
|
|
4
|
+
* bundled FAA snapshot loads on demand: the first accessor call dynamically
|
|
5
|
+
* imports its data package, decompresses and indexes the snapshot, and caches
|
|
6
|
+
* the result for the life of the process. A session that only asks about
|
|
7
|
+
* airports never decompresses the CIFP procedure snapshot, and a session that
|
|
8
|
+
* asks nothing pays nothing beyond process start.
|
|
6
9
|
*
|
|
7
|
-
*
|
|
10
|
+
* Each accessor memoizes the in-flight load rather than the finished
|
|
11
|
+
* resolver, so concurrent tool calls needing the same dataset share one
|
|
12
|
+
* import and one index build instead of racing to build two.
|
|
13
|
+
*
|
|
14
|
+
* The ICAO registry follows the same shape with one extra wrinkle: its data
|
|
8
15
|
* package (`@squawk/icao-registry-data`) is declared as an optional peer
|
|
9
|
-
* dependency rather than a required dep
|
|
10
|
-
*
|
|
11
|
-
* cached for subsequent calls. When the peer is not installed, the import
|
|
16
|
+
* dependency rather than a required dep, so a failed import is an expected
|
|
17
|
+
* outcome rather than a broken install. When the peer is absent the import
|
|
12
18
|
* throws `ERR_MODULE_NOT_FOUND` and {@link getIcaoRegistry} surfaces a
|
|
13
19
|
* {@link MissingDataPackageError} for the tool handler to format.
|
|
14
20
|
*/
|
|
15
|
-
import { usBundledAirports } from '@squawk/airport-data';
|
|
16
21
|
import { createAirportResolver } from '@squawk/airports';
|
|
17
22
|
import { createAirspaceResolver } from '@squawk/airspace';
|
|
18
|
-
import { usBundledAirspace } from '@squawk/airspace-data';
|
|
19
|
-
import { usBundledAirways } from '@squawk/airway-data';
|
|
20
23
|
import { createAirwayResolver } from '@squawk/airways';
|
|
21
|
-
import { usBundledFixes } from '@squawk/fix-data';
|
|
22
24
|
import { createFixResolver } from '@squawk/fixes';
|
|
23
25
|
import { createIcaoRegistry } from '@squawk/icao-registry';
|
|
24
|
-
import { usBundledNavaids } from '@squawk/navaid-data';
|
|
25
26
|
import { createNavaidResolver } from '@squawk/navaids';
|
|
26
|
-
import { usBundledProcedures } from '@squawk/procedure-data';
|
|
27
27
|
import { createProcedureResolver } from '@squawk/procedures';
|
|
28
|
-
/**
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
28
|
+
/**
|
|
29
|
+
* Builds a {@link LazyDataset} around a data package's dynamic import.
|
|
30
|
+
*
|
|
31
|
+
* The in-flight promise is what gets memoized, not the finished resolver, so
|
|
32
|
+
* two tool calls arriving before the first load settles share a single import
|
|
33
|
+
* and a single index build. A rejected load clears the memo so a later call
|
|
34
|
+
* retries rather than inheriting a permanently poisoned cache.
|
|
35
|
+
*
|
|
36
|
+
* @typeParam TDataset - Dataset object exported by the data package.
|
|
37
|
+
* @typeParam TResolver - Resolver type built over the dataset records.
|
|
38
|
+
* @param importDataset - Dynamic import resolving to the bundled dataset.
|
|
39
|
+
* @param buildResolver - Builds the resolver from the imported dataset.
|
|
40
|
+
* @returns Accessors over the lazily-loaded dataset.
|
|
41
|
+
*/
|
|
42
|
+
function createLazyDataset(importDataset, buildResolver) {
|
|
43
|
+
let loaded;
|
|
44
|
+
let pending;
|
|
45
|
+
return {
|
|
46
|
+
getResolver: () => {
|
|
47
|
+
if (loaded !== undefined) {
|
|
48
|
+
return Promise.resolve(loaded);
|
|
49
|
+
}
|
|
50
|
+
pending ??= importDataset().then((dataset) => {
|
|
51
|
+
loaded = buildResolver(dataset);
|
|
52
|
+
return loaded;
|
|
53
|
+
}, (err) => {
|
|
54
|
+
pending = undefined;
|
|
55
|
+
throw err;
|
|
56
|
+
});
|
|
57
|
+
return pending;
|
|
58
|
+
},
|
|
59
|
+
isLoaded: () => loaded !== undefined,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/** Lazily-loaded airport dataset backed by the US NASR snapshot. */
|
|
63
|
+
const airportDataset = createLazyDataset(async () => (await import('@squawk/airport-data')).usBundledAirports, (dataset) => createAirportResolver({ data: dataset.records }));
|
|
64
|
+
/** Lazily-loaded airspace dataset backed by the US NASR airspace GeoJSON snapshot. */
|
|
65
|
+
const airspaceDataset = createLazyDataset(async () => (await import('@squawk/airspace-data')).usBundledAirspace, (dataset) => createAirspaceResolver({ data: dataset }));
|
|
66
|
+
/** Lazily-loaded airway dataset backed by the US NASR snapshot. */
|
|
67
|
+
const airwayDataset = createLazyDataset(async () => (await import('@squawk/airway-data')).usBundledAirways, (dataset) => createAirwayResolver({ data: dataset.records }));
|
|
68
|
+
/** Lazily-loaded fix dataset backed by the US NASR snapshot. */
|
|
69
|
+
const fixDataset = createLazyDataset(async () => (await import('@squawk/fix-data')).usBundledFixes, (dataset) => createFixResolver({ data: dataset.records }));
|
|
70
|
+
/** Lazily-loaded navaid dataset backed by the US NASR snapshot. */
|
|
71
|
+
const navaidDataset = createLazyDataset(async () => (await import('@squawk/navaid-data')).usBundledNavaids, (dataset) => createNavaidResolver({ data: dataset.records }));
|
|
72
|
+
/** Lazily-loaded procedure dataset backed by the FAA CIFP snapshot. */
|
|
73
|
+
const procedureDataset = createLazyDataset(async () => (await import('@squawk/procedure-data')).usBundledProcedures, (dataset) => createProcedureResolver({ data: dataset.records }));
|
|
74
|
+
/**
|
|
75
|
+
* Returns the shared airport resolver, importing and indexing the bundled US
|
|
76
|
+
* NASR airport snapshot on the first call.
|
|
77
|
+
*
|
|
78
|
+
* @returns The shared airport resolver.
|
|
79
|
+
*/
|
|
80
|
+
export function getAirportResolver() {
|
|
81
|
+
return airportDataset.getResolver();
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Returns the shared airspace resolver, importing and indexing the bundled US
|
|
85
|
+
* NASR airspace GeoJSON snapshot on the first call.
|
|
86
|
+
*
|
|
87
|
+
* @returns The shared airspace resolver.
|
|
88
|
+
*/
|
|
89
|
+
export function getAirspaceResolver() {
|
|
90
|
+
return airspaceDataset.getResolver();
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Returns the shared airway resolver, importing and indexing the bundled US
|
|
94
|
+
* NASR airway snapshot on the first call.
|
|
95
|
+
*
|
|
96
|
+
* @returns The shared airway resolver.
|
|
97
|
+
*/
|
|
98
|
+
export function getAirwayResolver() {
|
|
99
|
+
return airwayDataset.getResolver();
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Returns the shared fix resolver, importing and indexing the bundled US NASR
|
|
103
|
+
* fix snapshot on the first call.
|
|
104
|
+
*
|
|
105
|
+
* @returns The shared fix resolver.
|
|
106
|
+
*/
|
|
107
|
+
export function getFixResolver() {
|
|
108
|
+
return fixDataset.getResolver();
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Returns the shared navaid resolver, importing and indexing the bundled US
|
|
112
|
+
* NASR navaid snapshot on the first call.
|
|
113
|
+
*
|
|
114
|
+
* @returns The shared navaid resolver.
|
|
115
|
+
*/
|
|
116
|
+
export function getNavaidResolver() {
|
|
117
|
+
return navaidDataset.getResolver();
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Returns the shared procedure resolver, importing and indexing the bundled
|
|
121
|
+
* FAA CIFP procedure snapshot on the first call.
|
|
122
|
+
*
|
|
123
|
+
* @returns The shared procedure resolver.
|
|
124
|
+
*/
|
|
125
|
+
export function getProcedureResolver() {
|
|
126
|
+
return procedureDataset.getResolver();
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Reports which required bundled snapshots are currently in memory, without
|
|
130
|
+
* loading any of them.
|
|
131
|
+
*
|
|
132
|
+
* @returns Per-dataset load state.
|
|
133
|
+
*/
|
|
134
|
+
export function getBundledDatasetLoadState() {
|
|
135
|
+
return {
|
|
136
|
+
airports: airportDataset.isLoaded(),
|
|
137
|
+
airspace: airspaceDataset.isLoaded(),
|
|
138
|
+
airways: airwayDataset.isLoaded(),
|
|
139
|
+
fixes: fixDataset.isLoaded(),
|
|
140
|
+
navaids: navaidDataset.isLoaded(),
|
|
141
|
+
procedures: procedureDataset.isLoaded(),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
50
144
|
/**
|
|
51
145
|
* Error thrown when a tool tries to load an optional data package peer that
|
|
52
146
|
* has not been installed alongside `@squawk/mcp`. Tool handlers catch this
|
|
@@ -77,6 +171,11 @@ export class MissingDataPackageError extends Error {
|
|
|
77
171
|
}
|
|
78
172
|
/** Cached ICAO registry instance, populated on the first {@link getIcaoRegistry} call. */
|
|
79
173
|
let icaoRegistryInstance;
|
|
174
|
+
/**
|
|
175
|
+
* In-flight registry load, memoized so concurrent lookups share one import
|
|
176
|
+
* and one index build. Cleared when the load rejects so a later call retries.
|
|
177
|
+
*/
|
|
178
|
+
let icaoRegistryPending;
|
|
80
179
|
/**
|
|
81
180
|
* Cached metadata captured the first time the registry is loaded. Held
|
|
82
181
|
* separately from the registry instance so {@link getIcaoRegistryMetadata}
|
|
@@ -111,17 +210,44 @@ let icaoRegistryDataLoader = defaultIcaoRegistryDataLoader;
|
|
|
111
210
|
function isModuleNotFoundError(err) {
|
|
112
211
|
return err instanceof Error && 'code' in err && err.code === 'ERR_MODULE_NOT_FOUND';
|
|
113
212
|
}
|
|
213
|
+
/**
|
|
214
|
+
* Imports the optional registry peer and builds the registry, populating the
|
|
215
|
+
* module-level caches. Split out of {@link getIcaoRegistry} so the memoized
|
|
216
|
+
* in-flight promise has a single body behind it.
|
|
217
|
+
*
|
|
218
|
+
* @returns The newly built registry instance.
|
|
219
|
+
* @throws {MissingDataPackageError} when the peer is not installed.
|
|
220
|
+
*/
|
|
221
|
+
async function loadIcaoRegistry() {
|
|
222
|
+
let registryDataModule;
|
|
223
|
+
try {
|
|
224
|
+
registryDataModule = await icaoRegistryDataLoader();
|
|
225
|
+
}
|
|
226
|
+
catch (err) {
|
|
227
|
+
icaoRegistryPending = undefined;
|
|
228
|
+
if (isModuleNotFoundError(err)) {
|
|
229
|
+
icaoRegistryMissing = true;
|
|
230
|
+
throw new MissingDataPackageError('icao-registry', '@squawk/icao-registry-data');
|
|
231
|
+
}
|
|
232
|
+
throw err;
|
|
233
|
+
}
|
|
234
|
+
const { usBundledRegistry } = registryDataModule;
|
|
235
|
+
icaoRegistryInstance = createIcaoRegistry({ data: usBundledRegistry.records });
|
|
236
|
+
icaoRegistryMetadata = {
|
|
237
|
+
generatedAt: usBundledRegistry.properties.generatedAt,
|
|
238
|
+
recordCount: usBundledRegistry.properties.recordCount,
|
|
239
|
+
};
|
|
240
|
+
return icaoRegistryInstance;
|
|
241
|
+
}
|
|
114
242
|
/**
|
|
115
243
|
* Returns the shared {@link IcaoRegistry} instance, decompressing and indexing
|
|
116
244
|
* the bundled FAA aircraft registration snapshot on the first call. Subsequent
|
|
117
245
|
* calls reuse the cached instance.
|
|
118
246
|
*
|
|
119
|
-
* The registry is
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
* never install the peer see only the structured missing-package error
|
|
124
|
-
* surfaced by the tool handler.
|
|
247
|
+
* The registry's data package is the largest snapshot in the suite (roughly
|
|
248
|
+
* 40 MB raw) and is declared as an optional peer dependency rather than a
|
|
249
|
+
* required dep, so consumers who never install the peer see only the
|
|
250
|
+
* structured missing-package error surfaced by the tool handler.
|
|
125
251
|
*
|
|
126
252
|
* @returns The shared registry instance.
|
|
127
253
|
* @throws {MissingDataPackageError} when `@squawk/icao-registry-data` is not
|
|
@@ -131,40 +257,26 @@ export async function getIcaoRegistry() {
|
|
|
131
257
|
if (icaoRegistryMissing) {
|
|
132
258
|
throw new MissingDataPackageError('icao-registry', '@squawk/icao-registry-data');
|
|
133
259
|
}
|
|
134
|
-
if (icaoRegistryInstance
|
|
135
|
-
|
|
136
|
-
try {
|
|
137
|
-
registryDataModule = await icaoRegistryDataLoader();
|
|
138
|
-
}
|
|
139
|
-
catch (err) {
|
|
140
|
-
if (isModuleNotFoundError(err)) {
|
|
141
|
-
icaoRegistryMissing = true;
|
|
142
|
-
throw new MissingDataPackageError('icao-registry', '@squawk/icao-registry-data');
|
|
143
|
-
}
|
|
144
|
-
throw err;
|
|
145
|
-
}
|
|
146
|
-
const { usBundledRegistry } = registryDataModule;
|
|
147
|
-
icaoRegistryInstance = createIcaoRegistry({ data: usBundledRegistry.records });
|
|
148
|
-
icaoRegistryMetadata = {
|
|
149
|
-
generatedAt: usBundledRegistry.properties.generatedAt,
|
|
150
|
-
recordCount: usBundledRegistry.properties.recordCount,
|
|
151
|
-
};
|
|
260
|
+
if (icaoRegistryInstance !== undefined) {
|
|
261
|
+
return icaoRegistryInstance;
|
|
152
262
|
}
|
|
153
|
-
|
|
263
|
+
icaoRegistryPending ??= loadIcaoRegistry();
|
|
264
|
+
return icaoRegistryPending;
|
|
154
265
|
}
|
|
155
266
|
/**
|
|
156
267
|
* @internal
|
|
157
268
|
*
|
|
158
269
|
* Test-only seam for swapping the optional data package loader. Production
|
|
159
270
|
* code must not call this. Pass `undefined` to restore the default loader
|
|
160
|
-
* and clear all cached state (instance, metadata, and the
|
|
161
|
-
* sticky flag) so subsequent tests start from a clean slate.
|
|
271
|
+
* and clear all cached state (instance, in-flight load, metadata, and the
|
|
272
|
+
* missing-peer sticky flag) so subsequent tests start from a clean slate.
|
|
162
273
|
*
|
|
163
274
|
* @param loader - Replacement loader, or `undefined` to reset.
|
|
164
275
|
*/
|
|
165
276
|
export function __setIcaoRegistryDataLoaderForTest(loader) {
|
|
166
277
|
icaoRegistryDataLoader = loader ?? defaultIcaoRegistryDataLoader;
|
|
167
278
|
icaoRegistryInstance = undefined;
|
|
279
|
+
icaoRegistryPending = undefined;
|
|
168
280
|
icaoRegistryMetadata = undefined;
|
|
169
281
|
icaoRegistryMissing = false;
|
|
170
282
|
}
|
package/dist/tools/airports.d.ts
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @packageDocumentation
|
|
3
3
|
* MCP tool module wrapping `@squawk/airports` airport lookup methods, backed
|
|
4
|
-
* by the US NASR snapshot in `@squawk/airport-data`. The dataset is
|
|
5
|
-
* and indexed
|
|
4
|
+
* by the US NASR snapshot in `@squawk/airport-data`. The dataset is imported
|
|
5
|
+
* and indexed by the first handler to call {@link getAirportResolver}, so a
|
|
6
|
+
* session that never asks about an airport never pays for the snapshot.
|
|
6
7
|
*/
|
|
7
8
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
8
9
|
/**
|
|
9
10
|
* Registers airport lookup tools (by FAA ID, by ICAO code, nearest, text
|
|
10
|
-
* search) on the given MCP server. Tools share the
|
|
11
|
-
*
|
|
11
|
+
* search) on the given MCP server. Tools share the resolver singleton from
|
|
12
|
+
* {@link getAirportResolver}, which builds the bundled US NASR dataset on
|
|
13
|
+
* the first invocation and reuses it thereafter.
|
|
12
14
|
*
|
|
13
15
|
* @param server - The MCP server instance to register tools on.
|
|
14
16
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"airports.d.ts","sourceRoot":"","sources":["../../src/tools/airports.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"airports.d.ts","sourceRoot":"","sources":["../../src/tools/airports.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAkBzE;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA6J5D"}
|