@squawk/mcp 0.12.1 → 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 +23 -16
- 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 +7 -7
package/dist/tools/airspace.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* `@squawk/airspace-data`.
|
|
6
6
|
*/
|
|
7
7
|
import { z } from 'zod';
|
|
8
|
-
import {
|
|
8
|
+
import { getAirportResolver, getAirspaceResolver } from '../resolvers.js';
|
|
9
9
|
/** All {@link AirspaceType} values, used for input validation. */
|
|
10
10
|
const AIRSPACE_TYPE_VALUES = [
|
|
11
11
|
'CLASS_B',
|
|
@@ -58,9 +58,11 @@ function summarizeFeature(feature) {
|
|
|
58
58
|
};
|
|
59
59
|
}
|
|
60
60
|
/**
|
|
61
|
-
* Registers airspace query tools on the given MCP server.
|
|
62
|
-
*
|
|
63
|
-
*
|
|
61
|
+
* Registers airspace query tools on the given MCP server. Each handler pulls
|
|
62
|
+
* the shared resolver from {@link getAirspaceResolver}, which decodes and
|
|
63
|
+
* indexes the bundled US airspace GeoJSON snapshot on the first invocation.
|
|
64
|
+
* `get_airspace_for_airport` additionally resolves the airport identifier,
|
|
65
|
+
* so it loads the airport snapshot alongside the airspace one.
|
|
64
66
|
*
|
|
65
67
|
* @param server - The MCP server instance to register tools on.
|
|
66
68
|
*/
|
|
@@ -79,7 +81,8 @@ export function registerAirspaceTools(server) {
|
|
|
79
81
|
.optional()
|
|
80
82
|
.describe('Restrict results to these airspace types. Omit to include all types.'),
|
|
81
83
|
},
|
|
82
|
-
}, ({ lat, lon, altitudeFt, airspaceTypes }) => {
|
|
84
|
+
}, async ({ lat, lon, altitudeFt, airspaceTypes }) => {
|
|
85
|
+
const airspaceResolver = await getAirspaceResolver();
|
|
83
86
|
const query = { lat, lon, altitudeFt };
|
|
84
87
|
if (airspaceTypes !== undefined) {
|
|
85
88
|
query.types = new Set(airspaceTypes);
|
|
@@ -103,7 +106,11 @@ export function registerAirspaceTools(server) {
|
|
|
103
106
|
.optional()
|
|
104
107
|
.describe('Restrict results to these airspace types. Defaults to surface-area classes (CLASS_B, CLASS_C, CLASS_D, CLASS_E2).'),
|
|
105
108
|
},
|
|
106
|
-
}, ({ airportId, airspaceTypes }) => {
|
|
109
|
+
}, async ({ airportId, airspaceTypes }) => {
|
|
110
|
+
const [airportResolver, airspaceResolver] = await Promise.all([
|
|
111
|
+
getAirportResolver(),
|
|
112
|
+
getAirspaceResolver(),
|
|
113
|
+
]);
|
|
107
114
|
const airport = airportResolver.byFaaId(airportId) ?? airportResolver.byIcao(airportId);
|
|
108
115
|
if (airport === undefined) {
|
|
109
116
|
return {
|
|
@@ -131,7 +138,8 @@ export function registerAirspaceTools(server) {
|
|
|
131
138
|
.optional()
|
|
132
139
|
.describe('Altitude in feet MSL. Defaults to 0 (surface), which selects the LOW stratum where applicable. Pass FL180+ to target HIGH or FL600+ to target UTA.'),
|
|
133
140
|
},
|
|
134
|
-
}, ({ lat, lon, altitudeFt }) => {
|
|
141
|
+
}, async ({ lat, lon, altitudeFt }) => {
|
|
142
|
+
const airspaceResolver = await getAirspaceResolver();
|
|
135
143
|
const query = {
|
|
136
144
|
lat,
|
|
137
145
|
lon,
|
|
@@ -158,7 +166,8 @@ export function registerAirspaceTools(server) {
|
|
|
158
166
|
.optional()
|
|
159
167
|
.describe('Restrict to a single stratum (LOW, HIGH, UTA, CTA, FIR, or CTA/FIR). Omit to return every published stratum for the center.'),
|
|
160
168
|
},
|
|
161
|
-
}, ({ artccId, stratum }) => {
|
|
169
|
+
}, async ({ artccId, stratum }) => {
|
|
170
|
+
const airspaceResolver = await getAirspaceResolver();
|
|
162
171
|
const features = airspaceResolver.byArtcc(artccId, stratum);
|
|
163
172
|
return {
|
|
164
173
|
content: [{ type: 'text', text: JSON.stringify({ features }, null, 2) }],
|
|
@@ -190,7 +199,8 @@ export function registerAirspaceTools(server) {
|
|
|
190
199
|
.optional()
|
|
191
200
|
.describe('Minimum match score (exclusive) in [0, 1] a result must reach. Defaults to 0. Raise it to drop weak fuzzy matches.'),
|
|
192
201
|
},
|
|
193
|
-
}, ({ text, airspaceTypes, limit, minScore }) => {
|
|
202
|
+
}, async ({ text, airspaceTypes, limit, minScore }) => {
|
|
203
|
+
const airspaceResolver = await getAirspaceResolver();
|
|
194
204
|
const query = { text };
|
|
195
205
|
if (airspaceTypes !== undefined) {
|
|
196
206
|
query.types = new Set(airspaceTypes);
|
package/dist/tools/airways.d.ts
CHANGED
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
7
7
|
/**
|
|
8
|
-
* Registers airway lookup tools on the given MCP server.
|
|
9
|
-
* {@link
|
|
8
|
+
* Registers airway lookup tools on the given MCP server. Each handler pulls
|
|
9
|
+
* the shared resolver from {@link getAirwayResolver}, which imports and
|
|
10
|
+
* indexes the bundled US NASR snapshot on the first invocation.
|
|
10
11
|
*
|
|
11
12
|
* @param server - The MCP server instance to register tools on.
|
|
12
13
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"airways.d.ts","sourceRoot":"","sources":["../../src/tools/airways.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAwBzE
|
|
1
|
+
{"version":3,"file":"airways.d.ts","sourceRoot":"","sources":["../../src/tools/airways.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAwBzE;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA+H3D"}
|
package/dist/tools/airways.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* expansion methods, backed by the US NASR snapshot in `@squawk/airway-data`.
|
|
5
5
|
*/
|
|
6
6
|
import { z } from 'zod';
|
|
7
|
-
import {
|
|
7
|
+
import { getAirwayResolver } from '../resolvers.js';
|
|
8
8
|
/** All {@link AirwayType} values, used for input validation. */
|
|
9
9
|
const AIRWAY_TYPE_VALUES = [
|
|
10
10
|
'VICTOR',
|
|
@@ -21,8 +21,9 @@ const AIRWAY_TYPE_VALUES = [
|
|
|
21
21
|
'PUERTO_RICO',
|
|
22
22
|
];
|
|
23
23
|
/**
|
|
24
|
-
* Registers airway lookup tools on the given MCP server.
|
|
25
|
-
* {@link
|
|
24
|
+
* Registers airway lookup tools on the given MCP server. Each handler pulls
|
|
25
|
+
* the shared resolver from {@link getAirwayResolver}, which imports and
|
|
26
|
+
* indexes the bundled US NASR snapshot on the first invocation.
|
|
26
27
|
*
|
|
27
28
|
* @param server - The MCP server instance to register tools on.
|
|
28
29
|
*/
|
|
@@ -33,8 +34,9 @@ export function registerAirwayTools(server) {
|
|
|
33
34
|
inputSchema: {
|
|
34
35
|
designation: z.string().min(1).describe('Airway designation (case-insensitive).'),
|
|
35
36
|
},
|
|
36
|
-
}, ({ designation }) => {
|
|
37
|
-
const
|
|
37
|
+
}, async ({ designation }) => {
|
|
38
|
+
const resolver = await getAirwayResolver();
|
|
39
|
+
const airways = resolver.byDesignation(designation);
|
|
38
40
|
return {
|
|
39
41
|
content: [{ type: 'text', text: JSON.stringify(airways, null, 2) }],
|
|
40
42
|
structuredContent: { airways },
|
|
@@ -48,8 +50,9 @@ export function registerAirwayTools(server) {
|
|
|
48
50
|
entryFix: z.string().min(1).describe('Identifier of the entry fix (case-insensitive).'),
|
|
49
51
|
exitFix: z.string().min(1).describe('Identifier of the exit fix (case-insensitive).'),
|
|
50
52
|
},
|
|
51
|
-
}, ({ designation, entryFix, exitFix }) => {
|
|
52
|
-
const
|
|
53
|
+
}, async ({ designation, entryFix, exitFix }) => {
|
|
54
|
+
const resolver = await getAirwayResolver();
|
|
55
|
+
const expansion = resolver.expand(designation, entryFix, exitFix);
|
|
53
56
|
if (expansion === undefined) {
|
|
54
57
|
return {
|
|
55
58
|
content: [
|
|
@@ -75,8 +78,9 @@ export function registerAirwayTools(server) {
|
|
|
75
78
|
.min(1)
|
|
76
79
|
.describe('Fix, navaid, or waypoint identifier (case-insensitive).'),
|
|
77
80
|
},
|
|
78
|
-
}, ({ ident }) => {
|
|
79
|
-
const
|
|
81
|
+
}, async ({ ident }) => {
|
|
82
|
+
const resolver = await getAirwayResolver();
|
|
83
|
+
const results = resolver.byFix(ident);
|
|
80
84
|
return {
|
|
81
85
|
content: [{ type: 'text', text: JSON.stringify(results, null, 2) }],
|
|
82
86
|
structuredContent: { results },
|
|
@@ -107,7 +111,8 @@ export function registerAirwayTools(server) {
|
|
|
107
111
|
.optional()
|
|
108
112
|
.describe('Minimum match score (exclusive) in [0, 1] a result must reach. Defaults to 0. Raise it to drop weak fuzzy matches.'),
|
|
109
113
|
},
|
|
110
|
-
}, ({ text, airwayTypes, limit, minScore }) => {
|
|
114
|
+
}, async ({ text, airwayTypes, limit, minScore }) => {
|
|
115
|
+
const resolver = await getAirwayResolver();
|
|
111
116
|
const query = { text };
|
|
112
117
|
if (airwayTypes !== undefined) {
|
|
113
118
|
query.types = new Set(airwayTypes);
|
|
@@ -118,7 +123,7 @@ export function registerAirwayTools(server) {
|
|
|
118
123
|
if (minScore !== undefined) {
|
|
119
124
|
query.minScore = minScore;
|
|
120
125
|
}
|
|
121
|
-
const airways =
|
|
126
|
+
const airways = resolver.search(query);
|
|
122
127
|
return {
|
|
123
128
|
content: [{ type: 'text', text: JSON.stringify(airways, null, 2) }],
|
|
124
129
|
structuredContent: { airways },
|
package/dist/tools/datasets.d.ts
CHANGED
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @packageDocumentation
|
|
3
3
|
* MCP tool module exposing build provenance and record counts for every
|
|
4
|
-
* bundled FAA snapshot the server
|
|
5
|
-
* which NASR cycle and registry vintage answered a query - critical
|
|
6
|
-
* for aviation use, where stale data is a real safety concern.
|
|
4
|
+
* bundled FAA snapshot the server can serve. Lets an LLM client report
|
|
5
|
+
* exactly which NASR cycle and registry vintage answered a query - critical
|
|
6
|
+
* context for aviation use, where stale data is a real safety concern.
|
|
7
|
+
*
|
|
8
|
+
* Every dataset's metadata comes from its data package's `/meta` subpath, a
|
|
9
|
+
* generated constant carrying the cycle date, build timestamp, and record
|
|
10
|
+
* counts. Reading it costs nothing, so reporting status never pulls a
|
|
11
|
+
* snapshot into memory that a session did not otherwise need. Each entry also
|
|
12
|
+
* carries whether its records are currently loaded, which is the one fact
|
|
13
|
+
* that has to be read from the resolver layer.
|
|
7
14
|
*/
|
|
8
15
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
9
16
|
/**
|
|
10
17
|
* Registers the `get_dataset_status` tool on the given MCP server. The tool
|
|
11
|
-
* takes no input and reports the
|
|
12
|
-
* record counts for
|
|
13
|
-
*
|
|
18
|
+
* takes no input and reports the cycle effective date, generation timestamp,
|
|
19
|
+
* and record counts for every bundled snapshot, along with whether each one
|
|
20
|
+
* is currently loaded. Answering does not load anything.
|
|
14
21
|
*
|
|
15
22
|
* @param server - The MCP server instance to register tools on.
|
|
16
23
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"datasets.d.ts","sourceRoot":"","sources":["../../src/tools/datasets.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"datasets.d.ts","sourceRoot":"","sources":["../../src/tools/datasets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAezE;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAkC5D"}
|
package/dist/tools/datasets.js
CHANGED
|
@@ -1,68 +1,47 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @packageDocumentation
|
|
3
3
|
* MCP tool module exposing build provenance and record counts for every
|
|
4
|
-
* bundled FAA snapshot the server
|
|
5
|
-
* which NASR cycle and registry vintage answered a query - critical
|
|
6
|
-
* for aviation use, where stale data is a real safety concern.
|
|
4
|
+
* bundled FAA snapshot the server can serve. Lets an LLM client report
|
|
5
|
+
* exactly which NASR cycle and registry vintage answered a query - critical
|
|
6
|
+
* context for aviation use, where stale data is a real safety concern.
|
|
7
|
+
*
|
|
8
|
+
* Every dataset's metadata comes from its data package's `/meta` subpath, a
|
|
9
|
+
* generated constant carrying the cycle date, build timestamp, and record
|
|
10
|
+
* counts. Reading it costs nothing, so reporting status never pulls a
|
|
11
|
+
* snapshot into memory that a session did not otherwise need. Each entry also
|
|
12
|
+
* carries whether its records are currently loaded, which is the one fact
|
|
13
|
+
* that has to be read from the resolver layer.
|
|
7
14
|
*/
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import { getIcaoRegistryMetadata, isIcaoRegistryLoaded } from '../resolvers.js';
|
|
15
|
+
import { usBundledAirportsProperties } from '@squawk/airport-data/meta';
|
|
16
|
+
import { usBundledAirspaceProperties } from '@squawk/airspace-data/meta';
|
|
17
|
+
import { usBundledAirwaysProperties } from '@squawk/airway-data/meta';
|
|
18
|
+
import { usBundledFixesProperties } from '@squawk/fix-data/meta';
|
|
19
|
+
import { usBundledNavaidsProperties } from '@squawk/navaid-data/meta';
|
|
20
|
+
import { usBundledProceduresProperties } from '@squawk/procedure-data/meta';
|
|
21
|
+
import { getBundledDatasetLoadState, getIcaoRegistryMetadata, isIcaoRegistryLoaded, } from '../resolvers.js';
|
|
15
22
|
/**
|
|
16
23
|
* Registers the `get_dataset_status` tool on the given MCP server. The tool
|
|
17
|
-
* takes no input and reports the
|
|
18
|
-
* record counts for
|
|
19
|
-
*
|
|
24
|
+
* takes no input and reports the cycle effective date, generation timestamp,
|
|
25
|
+
* and record counts for every bundled snapshot, along with whether each one
|
|
26
|
+
* is currently loaded. Answering does not load anything.
|
|
20
27
|
*
|
|
21
28
|
* @param server - The MCP server instance to register tools on.
|
|
22
29
|
*/
|
|
23
30
|
export function registerDatasetTools(server) {
|
|
24
31
|
server.registerTool('get_dataset_status', {
|
|
25
32
|
title: 'Report status of every bundled dataset',
|
|
26
|
-
description: 'Returns the cycle effective date (FAA NASR for airports/airspace/navaids/fixes/airways; FAA CIFP for procedures), build timestamp, and record counts for
|
|
33
|
+
description: 'Returns the cycle effective date (FAA NASR for airports/airspace/navaids/fixes/airways; FAA CIFP for procedures), build timestamp, and record counts for every dataset the server can serve, plus a `loaded` flag saying whether that dataset is currently in memory. Use this when a user asks "how current is the data?" or before answering a question that depends on procedure/navaid currency. Calling it is cheap and never forces a dataset to load, so `loaded: false` means only that nothing has needed that snapshot yet - the cycle dates it reports are accurate either way. The aircraft registry is an optional peer package, so it reports its vintage only once a lookup has loaded it.',
|
|
27
34
|
inputSchema: {},
|
|
28
35
|
}, () => {
|
|
36
|
+
const loadState = getBundledDatasetLoadState();
|
|
29
37
|
const registryMetadata = getIcaoRegistryMetadata();
|
|
30
38
|
const datasets = {
|
|
31
|
-
airports: {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
},
|
|
36
|
-
|
|
37
|
-
nasrCycleDate: usBundledAirspace.properties.nasrCycleDate,
|
|
38
|
-
generatedAt: usBundledAirspace.properties.generatedAt,
|
|
39
|
-
featureCount: usBundledAirspace.properties.featureCount,
|
|
40
|
-
},
|
|
41
|
-
navaids: {
|
|
42
|
-
nasrCycleDate: usBundledNavaids.properties.nasrCycleDate,
|
|
43
|
-
generatedAt: usBundledNavaids.properties.generatedAt,
|
|
44
|
-
recordCount: usBundledNavaids.properties.recordCount,
|
|
45
|
-
},
|
|
46
|
-
fixes: {
|
|
47
|
-
nasrCycleDate: usBundledFixes.properties.nasrCycleDate,
|
|
48
|
-
generatedAt: usBundledFixes.properties.generatedAt,
|
|
49
|
-
recordCount: usBundledFixes.properties.recordCount,
|
|
50
|
-
},
|
|
51
|
-
airways: {
|
|
52
|
-
nasrCycleDate: usBundledAirways.properties.nasrCycleDate,
|
|
53
|
-
generatedAt: usBundledAirways.properties.generatedAt,
|
|
54
|
-
recordCount: usBundledAirways.properties.recordCount,
|
|
55
|
-
waypointCount: usBundledAirways.properties.waypointCount,
|
|
56
|
-
},
|
|
57
|
-
procedures: {
|
|
58
|
-
cifpCycleDate: usBundledProcedures.properties.cifpCycleDate,
|
|
59
|
-
generatedAt: usBundledProcedures.properties.generatedAt,
|
|
60
|
-
recordCount: usBundledProcedures.properties.recordCount,
|
|
61
|
-
sidCount: usBundledProcedures.properties.sidCount,
|
|
62
|
-
starCount: usBundledProcedures.properties.starCount,
|
|
63
|
-
iapCount: usBundledProcedures.properties.iapCount,
|
|
64
|
-
legCount: usBundledProcedures.properties.legCount,
|
|
65
|
-
},
|
|
39
|
+
airports: { loaded: loadState.airports, ...usBundledAirportsProperties },
|
|
40
|
+
airspace: { loaded: loadState.airspace, ...usBundledAirspaceProperties },
|
|
41
|
+
navaids: { loaded: loadState.navaids, ...usBundledNavaidsProperties },
|
|
42
|
+
fixes: { loaded: loadState.fixes, ...usBundledFixesProperties },
|
|
43
|
+
airways: { loaded: loadState.airways, ...usBundledAirwaysProperties },
|
|
44
|
+
procedures: { loaded: loadState.procedures, ...usBundledProceduresProperties },
|
|
66
45
|
icaoRegistry: registryMetadata !== undefined
|
|
67
46
|
? {
|
|
68
47
|
loaded: true,
|
package/dist/tools/fixes.d.ts
CHANGED
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
7
7
|
/**
|
|
8
|
-
* Registers fix/waypoint lookup tools on the given MCP server.
|
|
9
|
-
* shared {@link
|
|
8
|
+
* Registers fix/waypoint lookup tools on the given MCP server. Each handler
|
|
9
|
+
* pulls the shared resolver from {@link getFixResolver}, which imports and
|
|
10
|
+
* indexes the bundled US NASR snapshot on the first invocation.
|
|
10
11
|
*
|
|
11
12
|
* @param server - The MCP server instance to register tools on.
|
|
12
13
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fixes.d.ts","sourceRoot":"","sources":["../../src/tools/fixes.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAoBzE
|
|
1
|
+
{"version":3,"file":"fixes.d.ts","sourceRoot":"","sources":["../../src/tools/fixes.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAoBzE;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA4JxD"}
|
package/dist/tools/fixes.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* backed by the US NASR snapshot in `@squawk/fix-data`.
|
|
5
5
|
*/
|
|
6
6
|
import { z } from 'zod';
|
|
7
|
-
import {
|
|
7
|
+
import { getFixResolver } from '../resolvers.js';
|
|
8
8
|
/** All {@link FixUseCode} values, used for input validation. */
|
|
9
9
|
const FIX_USE_CODE_VALUES = [
|
|
10
10
|
'WP',
|
|
@@ -17,8 +17,9 @@ const FIX_USE_CODE_VALUES = [
|
|
|
17
17
|
'RADAR',
|
|
18
18
|
];
|
|
19
19
|
/**
|
|
20
|
-
* Registers fix/waypoint lookup tools on the given MCP server.
|
|
21
|
-
* shared {@link
|
|
20
|
+
* Registers fix/waypoint lookup tools on the given MCP server. Each handler
|
|
21
|
+
* pulls the shared resolver from {@link getFixResolver}, which imports and
|
|
22
|
+
* indexes the bundled US NASR snapshot on the first invocation.
|
|
22
23
|
*
|
|
23
24
|
* @param server - The MCP server instance to register tools on.
|
|
24
25
|
*/
|
|
@@ -29,8 +30,9 @@ export function registerFixTools(server) {
|
|
|
29
30
|
inputSchema: {
|
|
30
31
|
ident: z.string().min(1).describe('Fix identifier (case-insensitive).'),
|
|
31
32
|
},
|
|
32
|
-
}, ({ ident }) => {
|
|
33
|
-
const
|
|
33
|
+
}, async ({ ident }) => {
|
|
34
|
+
const resolver = await getFixResolver();
|
|
35
|
+
const fixes = resolver.byIdent(ident);
|
|
34
36
|
return {
|
|
35
37
|
content: [{ type: 'text', text: JSON.stringify(fixes, null, 2) }],
|
|
36
38
|
structuredContent: { fixes },
|
|
@@ -57,8 +59,9 @@ export function registerFixTools(server) {
|
|
|
57
59
|
.optional()
|
|
58
60
|
.describe('Maximum great-circle distance in nautical miles. Omit to let the nearest match win regardless of distance.'),
|
|
59
61
|
},
|
|
60
|
-
}, ({ ident, lat, lon, toleranceNm }) => {
|
|
61
|
-
const
|
|
62
|
+
}, async ({ ident, lat, lon, toleranceNm }) => {
|
|
63
|
+
const resolver = await getFixResolver();
|
|
64
|
+
const fix = resolver.byIdentAtPosition(ident, lat, lon, toleranceNm) ?? null;
|
|
62
65
|
return {
|
|
63
66
|
content: [{ type: 'text', text: JSON.stringify(fix, null, 2) }],
|
|
64
67
|
structuredContent: { fix },
|
|
@@ -86,7 +89,8 @@ export function registerFixTools(server) {
|
|
|
86
89
|
.optional()
|
|
87
90
|
.describe('Restrict results to these FAA fix-use codes (e.g. WP=waypoint, RP=reporting point, VFR=VFR waypoint). Omit to include all use codes.'),
|
|
88
91
|
},
|
|
89
|
-
}, ({ lat, lon, maxDistanceNm, limit, useCodes }) => {
|
|
92
|
+
}, async ({ lat, lon, maxDistanceNm, limit, useCodes }) => {
|
|
93
|
+
const resolver = await getFixResolver();
|
|
90
94
|
const query = { lat, lon };
|
|
91
95
|
if (maxDistanceNm !== undefined) {
|
|
92
96
|
query.maxDistanceNm = maxDistanceNm;
|
|
@@ -97,7 +101,7 @@ export function registerFixTools(server) {
|
|
|
97
101
|
if (useCodes !== undefined) {
|
|
98
102
|
query.useCodes = new Set(useCodes);
|
|
99
103
|
}
|
|
100
|
-
const results =
|
|
104
|
+
const results = resolver.nearest(query);
|
|
101
105
|
return {
|
|
102
106
|
content: [{ type: 'text', text: JSON.stringify(results, null, 2) }],
|
|
103
107
|
structuredContent: { results },
|
|
@@ -128,7 +132,8 @@ export function registerFixTools(server) {
|
|
|
128
132
|
.optional()
|
|
129
133
|
.describe('Minimum match score (exclusive) in [0, 1] a result must reach. Defaults to 0. Raise it to drop weak fuzzy matches.'),
|
|
130
134
|
},
|
|
131
|
-
}, ({ text, useCodes, limit, minScore }) => {
|
|
135
|
+
}, async ({ text, useCodes, limit, minScore }) => {
|
|
136
|
+
const resolver = await getFixResolver();
|
|
132
137
|
const query = { text };
|
|
133
138
|
if (useCodes !== undefined) {
|
|
134
139
|
query.useCodes = new Set(useCodes);
|
|
@@ -139,7 +144,7 @@ export function registerFixTools(server) {
|
|
|
139
144
|
if (minScore !== undefined) {
|
|
140
145
|
query.minScore = minScore;
|
|
141
146
|
}
|
|
142
|
-
const fixes =
|
|
147
|
+
const fixes = resolver.search(query);
|
|
143
148
|
return {
|
|
144
149
|
content: [{ type: 'text', text: JSON.stringify(fixes, null, 2) }],
|
|
145
150
|
structuredContent: { fixes },
|
|
@@ -3,13 +3,15 @@
|
|
|
3
3
|
* MCP tool module wrapping `@squawk/flightplan` route-string parsing and
|
|
4
4
|
* great-circle distance computation. The flightplan resolver composes the
|
|
5
5
|
* shared airport, navaid, fix, airway, and procedure resolvers from the
|
|
6
|
-
* package's `resolvers` module
|
|
6
|
+
* package's `resolvers` module, so the first route parsed in a session loads
|
|
7
|
+
* all five of those snapshots.
|
|
7
8
|
*/
|
|
8
9
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
9
10
|
/**
|
|
10
11
|
* Registers flight plan parsing and route distance tools on the given MCP
|
|
11
|
-
* server.
|
|
12
|
-
*
|
|
12
|
+
* server. Each handler pulls the composed resolver from
|
|
13
|
+
* {@link getFlightplanResolver}, which builds it from the bundled NASR and
|
|
14
|
+
* CIFP snapshots on the first invocation.
|
|
13
15
|
*
|
|
14
16
|
* @param server - The MCP server instance to register tools on.
|
|
15
17
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flightplan.d.ts","sourceRoot":"","sources":["../../src/tools/flightplan.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"flightplan.d.ts","sourceRoot":"","sources":["../../src/tools/flightplan.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAoDzE;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA4I/D"}
|
package/dist/tools/flightplan.js
CHANGED
|
@@ -3,26 +3,47 @@
|
|
|
3
3
|
* MCP tool module wrapping `@squawk/flightplan` route-string parsing and
|
|
4
4
|
* great-circle distance computation. The flightplan resolver composes the
|
|
5
5
|
* shared airport, navaid, fix, airway, and procedure resolvers from the
|
|
6
|
-
* package's `resolvers` module
|
|
6
|
+
* package's `resolvers` module, so the first route parsed in a session loads
|
|
7
|
+
* all five of those snapshots.
|
|
7
8
|
*/
|
|
8
9
|
import { z } from 'zod';
|
|
9
10
|
import { computeRouteDistance, computeRouteTiming, createFlightplanResolver, extractRoutePoints, routeToLineString, } from '@squawk/flightplan';
|
|
10
|
-
import {
|
|
11
|
+
import { getAirportResolver, getAirwayResolver, getFixResolver, getNavaidResolver, getProcedureResolver, } from '../resolvers.js';
|
|
12
|
+
/**
|
|
13
|
+
* Memoized composed resolver. Holding the promise rather than the finished
|
|
14
|
+
* resolver means concurrent route parses share one load of the five
|
|
15
|
+
* underlying snapshots instead of each building their own composition.
|
|
16
|
+
*/
|
|
17
|
+
let flightplanResolver;
|
|
18
|
+
/**
|
|
19
|
+
* Returns the composed flightplan resolver, loading the five snapshots it
|
|
20
|
+
* draws on (airports, navaids, fixes, airways, procedures) in parallel on the
|
|
21
|
+
* first call. A rejected load clears the memo so a later call can retry.
|
|
22
|
+
*
|
|
23
|
+
* @returns The shared flightplan resolver.
|
|
24
|
+
*/
|
|
25
|
+
function getFlightplanResolver() {
|
|
26
|
+
flightplanResolver ??= Promise.all([
|
|
27
|
+
getAirportResolver(),
|
|
28
|
+
getNavaidResolver(),
|
|
29
|
+
getFixResolver(),
|
|
30
|
+
getAirwayResolver(),
|
|
31
|
+
getProcedureResolver(),
|
|
32
|
+
]).then(([airports, navaids, fixes, airways, procedures]) => createFlightplanResolver({ airports, navaids, fixes, airways, procedures }), (err) => {
|
|
33
|
+
flightplanResolver = undefined;
|
|
34
|
+
throw err;
|
|
35
|
+
});
|
|
36
|
+
return flightplanResolver;
|
|
37
|
+
}
|
|
11
38
|
/**
|
|
12
39
|
* Registers flight plan parsing and route distance tools on the given MCP
|
|
13
|
-
* server.
|
|
14
|
-
*
|
|
40
|
+
* server. Each handler pulls the composed resolver from
|
|
41
|
+
* {@link getFlightplanResolver}, which builds it from the bundled NASR and
|
|
42
|
+
* CIFP snapshots on the first invocation.
|
|
15
43
|
*
|
|
16
44
|
* @param server - The MCP server instance to register tools on.
|
|
17
45
|
*/
|
|
18
46
|
export function registerFlightplanTools(server) {
|
|
19
|
-
const resolver = createFlightplanResolver({
|
|
20
|
-
airports: airportResolver,
|
|
21
|
-
navaids: navaidResolver,
|
|
22
|
-
fixes: fixResolver,
|
|
23
|
-
airways: airwayResolver,
|
|
24
|
-
procedures: procedureResolver,
|
|
25
|
-
});
|
|
26
47
|
server.registerTool('parse_flightplan_route', {
|
|
27
48
|
title: 'Parse a flight plan route string',
|
|
28
49
|
description: 'Parses a whitespace-separated flight plan route string (e.g. "KJFK DCT MERIT J60 MARTN DCT KLAX") into structured route elements. Each token is classified as an airport, SID, STAR, airway, direct (DCT), waypoint, lat/lon coordinate, speed/altitude group, or unresolved. Airway tokens are expanded into waypoint sequences between the entry and exit fixes. SID/STAR tokens are expanded into their first common route, and the dotted PROCCODE.TRANSITION form (e.g. "NUBLE4.JJIMY") additionally merges the named transition\'s waypoints into the expansion.',
|
|
@@ -32,7 +53,8 @@ export function registerFlightplanTools(server) {
|
|
|
32
53
|
.min(1)
|
|
33
54
|
.describe('Whitespace-separated route string in ICAO Item 15 conventions.'),
|
|
34
55
|
},
|
|
35
|
-
}, ({ routeString }) => {
|
|
56
|
+
}, async ({ routeString }) => {
|
|
57
|
+
const resolver = await getFlightplanResolver();
|
|
36
58
|
const route = resolver.parse(routeString);
|
|
37
59
|
return {
|
|
38
60
|
content: [{ type: 'text', text: JSON.stringify(route, null, 2) }],
|
|
@@ -53,7 +75,8 @@ export function registerFlightplanTools(server) {
|
|
|
53
75
|
.optional()
|
|
54
76
|
.describe('Optional ground speed in knots used to compute estimated time enroute. Omit to skip ETE.'),
|
|
55
77
|
},
|
|
56
|
-
}, ({ routeString, groundSpeedKt }) => {
|
|
78
|
+
}, async ({ routeString, groundSpeedKt }) => {
|
|
79
|
+
const resolver = await getFlightplanResolver();
|
|
57
80
|
const route = resolver.parse(routeString);
|
|
58
81
|
const result = computeRouteDistance(route, groundSpeedKt);
|
|
59
82
|
return {
|
|
@@ -70,7 +93,8 @@ export function registerFlightplanTools(server) {
|
|
|
70
93
|
.min(1)
|
|
71
94
|
.describe('Whitespace-separated route string in ICAO Item 15 conventions.'),
|
|
72
95
|
},
|
|
73
|
-
}, ({ routeString }) => {
|
|
96
|
+
}, async ({ routeString }) => {
|
|
97
|
+
const resolver = await getFlightplanResolver();
|
|
74
98
|
const route = resolver.parse(routeString);
|
|
75
99
|
const points = extractRoutePoints(route);
|
|
76
100
|
const lineString = routeToLineString(route);
|
|
@@ -114,7 +138,8 @@ export function registerFlightplanTools(server) {
|
|
|
114
138
|
.optional()
|
|
115
139
|
.describe('Optional fuel on board in the same unit as fuelBurnPerHr. With the burn rate, enables endurance and fuel-sufficiency reporting.'),
|
|
116
140
|
},
|
|
117
|
-
}, ({ routeString, trueAirspeedKt, wind, fuelBurnPerHr, fuelAvailable }) => {
|
|
141
|
+
}, async ({ routeString, trueAirspeedKt, wind, fuelBurnPerHr, fuelAvailable }) => {
|
|
142
|
+
const resolver = await getFlightplanResolver();
|
|
118
143
|
const route = resolver.parse(routeString);
|
|
119
144
|
const result = computeRouteTiming(route, {
|
|
120
145
|
trueAirspeedKt,
|
package/dist/tools/navaids.d.ts
CHANGED
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
7
7
|
/**
|
|
8
|
-
* Registers navaid lookup tools on the given MCP server.
|
|
9
|
-
* {@link
|
|
8
|
+
* Registers navaid lookup tools on the given MCP server. Each handler pulls
|
|
9
|
+
* the shared resolver from {@link getNavaidResolver}, which imports and
|
|
10
|
+
* indexes the bundled US NASR snapshot on the first invocation.
|
|
10
11
|
*
|
|
11
12
|
* @param server - The MCP server instance to register tools on.
|
|
12
13
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navaids.d.ts","sourceRoot":"","sources":["../../src/tools/navaids.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAsBzE
|
|
1
|
+
{"version":3,"file":"navaids.d.ts","sourceRoot":"","sources":["../../src/tools/navaids.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAsBzE;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAkM3D"}
|