@squawk/mcp 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/README.md +301 -0
  2. package/dist/bin.d.ts +11 -0
  3. package/dist/bin.d.ts.map +1 -0
  4. package/dist/bin.js +41 -0
  5. package/dist/index.d.ts +24 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +23 -0
  8. package/dist/resolvers.d.ts +60 -0
  9. package/dist/resolvers.d.ts.map +1 -0
  10. package/dist/resolvers.js +94 -0
  11. package/dist/server.d.ts +45 -0
  12. package/dist/server.d.ts.map +1 -0
  13. package/dist/server.js +92 -0
  14. package/dist/tools/airports.d.ts +16 -0
  15. package/dist/tools/airports.d.ts.map +1 -0
  16. package/dist/tools/airports.js +142 -0
  17. package/dist/tools/airspace.d.ts +15 -0
  18. package/dist/tools/airspace.d.ts.map +1 -0
  19. package/dist/tools/airspace.js +81 -0
  20. package/dist/tools/airways.d.ts +14 -0
  21. package/dist/tools/airways.d.ts.map +1 -0
  22. package/dist/tools/airways.js +115 -0
  23. package/dist/tools/datasets.d.ts +18 -0
  24. package/dist/tools/datasets.d.ts.map +1 -0
  25. package/dist/tools/datasets.js +78 -0
  26. package/dist/tools/fixes.d.ts +14 -0
  27. package/dist/tools/fixes.d.ts.map +1 -0
  28. package/dist/tools/fixes.js +108 -0
  29. package/dist/tools/flight-math.d.ts +23 -0
  30. package/dist/tools/flight-math.d.ts.map +1 -0
  31. package/dist/tools/flight-math.js +643 -0
  32. package/dist/tools/flightplan.d.ts +17 -0
  33. package/dist/tools/flightplan.d.ts.map +1 -0
  34. package/dist/tools/flightplan.js +64 -0
  35. package/dist/tools/geo.d.ts +15 -0
  36. package/dist/tools/geo.d.ts.map +1 -0
  37. package/dist/tools/geo.js +127 -0
  38. package/dist/tools/icao-registry.d.ts +19 -0
  39. package/dist/tools/icao-registry.d.ts.map +1 -0
  40. package/dist/tools/icao-registry.js +45 -0
  41. package/dist/tools/navaids.d.ts +14 -0
  42. package/dist/tools/navaids.d.ts.map +1 -0
  43. package/dist/tools/navaids.js +143 -0
  44. package/dist/tools/notams.d.ts +13 -0
  45. package/dist/tools/notams.d.ts.map +1 -0
  46. package/dist/tools/notams.js +29 -0
  47. package/dist/tools/procedures.d.ts +15 -0
  48. package/dist/tools/procedures.d.ts.map +1 -0
  49. package/dist/tools/procedures.js +120 -0
  50. package/dist/tools/tool-helpers.d.ts +66 -0
  51. package/dist/tools/tool-helpers.d.ts.map +1 -0
  52. package/dist/tools/tool-helpers.js +55 -0
  53. package/dist/tools/weather.d.ts +18 -0
  54. package/dist/tools/weather.d.ts.map +1 -0
  55. package/dist/tools/weather.js +215 -0
  56. package/package.json +77 -0
package/dist/server.js ADDED
@@ -0,0 +1,92 @@
1
+ /**
2
+ * @packageDocumentation
3
+ * Server factory for @squawk/mcp. Assembles an {@link McpServer} preloaded
4
+ * with every squawk aviation tool module.
5
+ */
6
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
7
+ import { readFileSync } from 'node:fs';
8
+ import { dirname, resolve } from 'node:path';
9
+ import { fileURLToPath } from 'node:url';
10
+ import { registerAirportTools } from './tools/airports.js';
11
+ import { registerAirspaceTools } from './tools/airspace.js';
12
+ import { registerAirwayTools } from './tools/airways.js';
13
+ import { registerDatasetTools } from './tools/datasets.js';
14
+ import { registerFixTools } from './tools/fixes.js';
15
+ import { registerFlightMathTools } from './tools/flight-math.js';
16
+ import { registerFlightplanTools } from './tools/flightplan.js';
17
+ import { registerGeoTools } from './tools/geo.js';
18
+ import { registerIcaoRegistryTools } from './tools/icao-registry.js';
19
+ import { registerNavaidTools } from './tools/navaids.js';
20
+ import { registerNotamTools } from './tools/notams.js';
21
+ import { registerProcedureTools } from './tools/procedures.js';
22
+ import { registerWeatherTools } from './tools/weather.js';
23
+ const packageJsonPath = resolve(dirname(fileURLToPath(import.meta.url)), '../package.json');
24
+ const packageMeta = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
25
+ /**
26
+ * Ordered list of tool-module registrars invoked during server construction.
27
+ * Holding them in a single array keeps {@link createSquawkMcpServer} symmetric
28
+ * across modules and lets {@link TOOL_MODULE_COUNT} stay accurate without
29
+ * manual bookkeeping.
30
+ */
31
+ const TOOL_MODULE_REGISTRARS = [
32
+ registerGeoTools,
33
+ registerFlightMathTools,
34
+ registerAirportTools,
35
+ registerAirspaceTools,
36
+ registerNavaidTools,
37
+ registerFixTools,
38
+ registerAirwayTools,
39
+ registerProcedureTools,
40
+ registerIcaoRegistryTools,
41
+ registerWeatherTools,
42
+ registerNotamTools,
43
+ registerFlightplanTools,
44
+ registerDatasetTools,
45
+ ];
46
+ /**
47
+ * Number of tool modules registered by {@link createSquawkMcpServer}. Exposed
48
+ * so the stdio entrypoint can include the count in its startup diagnostic
49
+ * without re-counting at runtime.
50
+ */
51
+ export const TOOL_MODULE_COUNT = TOOL_MODULE_REGISTRARS.length;
52
+ /**
53
+ * Package name as published to npm. Convenient for diagnostic logs that want
54
+ * to identify the running server without re-reading `package.json`.
55
+ */
56
+ export const PACKAGE_NAME = packageMeta.name;
57
+ /**
58
+ * Package version pulled from `package.json` at module load. Mirrored as the
59
+ * server's `version` field and reused by the stdio entrypoint diagnostic.
60
+ */
61
+ export const PACKAGE_VERSION = packageMeta.version;
62
+ /**
63
+ * Creates an MCP server preloaded with every squawk aviation tool module.
64
+ *
65
+ * Tool registration triggers eager construction of the shared resolver
66
+ * singletons in `./resolvers.js` for every domain except the ICAO aircraft
67
+ * registry, which loads on first lookup. Live weather fetch tools issue
68
+ * outbound HTTPS requests to the Aviation Weather Center text API only when
69
+ * invoked.
70
+ *
71
+ * ```typescript
72
+ * import { createSquawkMcpServer } from '@squawk/mcp';
73
+ * import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
74
+ *
75
+ * const server = createSquawkMcpServer();
76
+ * await server.connect(new StdioServerTransport());
77
+ * ```
78
+ *
79
+ * @returns A fully configured MCP server instance. Connect it to a transport
80
+ * (typically `StdioServerTransport` for CLI use) via
81
+ * `server.connect(transport)` to begin handling protocol messages.
82
+ */
83
+ export function createSquawkMcpServer() {
84
+ const server = new McpServer({
85
+ name: PACKAGE_NAME,
86
+ version: PACKAGE_VERSION,
87
+ });
88
+ for (const register of TOOL_MODULE_REGISTRARS) {
89
+ register(server);
90
+ }
91
+ return server;
92
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @packageDocumentation
3
+ * MCP tool module wrapping `@squawk/airports` airport lookup methods, backed
4
+ * by the US NASR snapshot in `@squawk/airport-data`. The dataset is loaded
5
+ * and indexed eagerly when the shared {@link airportResolver} is imported.
6
+ */
7
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
8
+ /**
9
+ * Registers airport lookup tools (by FAA ID, by ICAO code, nearest, text
10
+ * search) on the given MCP server. Tools share the {@link airportResolver}
11
+ * singleton built at module load time from the bundled US NASR dataset.
12
+ *
13
+ * @param server - The MCP server instance to register tools on.
14
+ */
15
+ export declare function registerAirportTools(server: McpServer): void;
16
+ //# sourceMappingURL=airports.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"airports.d.ts","sourceRoot":"","sources":["../../src/tools/airports.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAgBzE;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA6I5D"}
@@ -0,0 +1,142 @@
1
+ /**
2
+ * @packageDocumentation
3
+ * MCP tool module wrapping `@squawk/airports` airport lookup methods, backed
4
+ * by the US NASR snapshot in `@squawk/airport-data`. The dataset is loaded
5
+ * and indexed eagerly when the shared {@link airportResolver} is imported.
6
+ */
7
+ import { z } from 'zod';
8
+ import { airportResolver } from '../resolvers.js';
9
+ /** All {@link FacilityType} values, used for input validation. */
10
+ const FACILITY_TYPE_VALUES = [
11
+ 'AIRPORT',
12
+ 'HELIPORT',
13
+ 'SEAPLANE_BASE',
14
+ 'GLIDERPORT',
15
+ 'ULTRALIGHT',
16
+ 'BALLOONPORT',
17
+ ];
18
+ /**
19
+ * Registers airport lookup tools (by FAA ID, by ICAO code, nearest, text
20
+ * search) on the given MCP server. Tools share the {@link airportResolver}
21
+ * singleton built at module load time from the bundled US NASR dataset.
22
+ *
23
+ * @param server - The MCP server instance to register tools on.
24
+ */
25
+ export function registerAirportTools(server) {
26
+ const resolver = airportResolver;
27
+ server.registerTool('get_airport_by_faa_id', {
28
+ title: 'Get airport by FAA identifier',
29
+ description: 'Looks up a US airport by its FAA location identifier (e.g. "JFK", "LAX", "3N6"). Returns the full airport record including runways, frequencies, and ILS data, or null if no match is found.',
30
+ inputSchema: {
31
+ faaId: z.string().min(1).describe('FAA location identifier (case-insensitive).'),
32
+ },
33
+ }, ({ faaId }) => {
34
+ const airport = resolver.byFaaId(faaId);
35
+ if (airport === undefined) {
36
+ return {
37
+ content: [{ type: 'text', text: `No airport found with FAA ID "${faaId}".` }],
38
+ structuredContent: { airport: null },
39
+ };
40
+ }
41
+ return {
42
+ content: [{ type: 'text', text: JSON.stringify(airport, null, 2) }],
43
+ structuredContent: { airport },
44
+ };
45
+ });
46
+ server.registerTool('get_airport_by_icao', {
47
+ title: 'Get airport by ICAO code',
48
+ description: 'Looks up a US airport by its ICAO code (e.g. "KJFK", "KLAX"). Returns the full airport record including runways, frequencies, and ILS data, or null if no match is found.',
49
+ inputSchema: {
50
+ icao: z.string().min(1).describe('ICAO airport code (case-insensitive).'),
51
+ },
52
+ }, ({ icao }) => {
53
+ const airport = resolver.byIcao(icao);
54
+ if (airport === undefined) {
55
+ return {
56
+ content: [{ type: 'text', text: `No airport found with ICAO code "${icao}".` }],
57
+ structuredContent: { airport: null },
58
+ };
59
+ }
60
+ return {
61
+ content: [{ type: 'text', text: JSON.stringify(airport, null, 2) }],
62
+ structuredContent: { airport },
63
+ };
64
+ });
65
+ server.registerTool('find_nearest_airports', {
66
+ title: 'Find nearest airports',
67
+ description: 'Finds US airports near a geographic position, sorted by great-circle distance in nautical miles. Supports filtering by facility type and minimum runway length.',
68
+ inputSchema: {
69
+ lat: z.number().min(-90).max(90).describe('Latitude in decimal degrees (WGS84).'),
70
+ lon: z.number().min(-180).max(180).describe('Longitude in decimal degrees (WGS84).'),
71
+ maxDistanceNm: z
72
+ .number()
73
+ .positive()
74
+ .optional()
75
+ .describe('Maximum search radius in nautical miles. Defaults to 30.'),
76
+ limit: z
77
+ .number()
78
+ .int()
79
+ .positive()
80
+ .optional()
81
+ .describe('Maximum number of results to return. Defaults to 10.'),
82
+ facilityTypes: z
83
+ .array(z.enum(FACILITY_TYPE_VALUES))
84
+ .optional()
85
+ .describe('Restrict results to these facility types. Omit to include all types.'),
86
+ minRunwayLengthFt: z
87
+ .number()
88
+ .positive()
89
+ .optional()
90
+ .describe('Only include airports with at least one runway meeting this length in feet.'),
91
+ },
92
+ }, ({ lat, lon, maxDistanceNm, limit, facilityTypes, minRunwayLengthFt }) => {
93
+ const query = { lat, lon };
94
+ if (maxDistanceNm !== undefined) {
95
+ query.maxDistanceNm = maxDistanceNm;
96
+ }
97
+ if (limit !== undefined) {
98
+ query.limit = limit;
99
+ }
100
+ if (facilityTypes !== undefined) {
101
+ query.types = new Set(facilityTypes);
102
+ }
103
+ if (minRunwayLengthFt !== undefined) {
104
+ query.minRunwayLengthFt = minRunwayLengthFt;
105
+ }
106
+ const results = resolver.nearest(query);
107
+ return {
108
+ content: [{ type: 'text', text: JSON.stringify(results, null, 2) }],
109
+ structuredContent: { results },
110
+ };
111
+ });
112
+ server.registerTool('search_airports', {
113
+ title: 'Search airports by name or city',
114
+ description: 'Searches US airports using case-insensitive substring matching on airport name and city. Returns airports in alphabetical order by name. Use this when the user knows a partial name but not the identifier.',
115
+ inputSchema: {
116
+ text: z.string().min(1).describe('Substring to match against airport name or city.'),
117
+ limit: z
118
+ .number()
119
+ .int()
120
+ .positive()
121
+ .optional()
122
+ .describe('Maximum number of results to return. Defaults to 20.'),
123
+ facilityTypes: z
124
+ .array(z.enum(FACILITY_TYPE_VALUES))
125
+ .optional()
126
+ .describe('Restrict results to these facility types. Omit to include all types.'),
127
+ },
128
+ }, ({ text, limit, facilityTypes }) => {
129
+ const query = { text };
130
+ if (limit !== undefined) {
131
+ query.limit = limit;
132
+ }
133
+ if (facilityTypes !== undefined) {
134
+ query.types = new Set(facilityTypes);
135
+ }
136
+ const results = resolver.search(query);
137
+ return {
138
+ content: [{ type: 'text', text: JSON.stringify(results, null, 2) }],
139
+ structuredContent: { results },
140
+ };
141
+ });
142
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @packageDocumentation
3
+ * MCP tool module wrapping `@squawk/airspace` point-in-airspace queries,
4
+ * backed by the US NASR airspace GeoJSON snapshot in `@squawk/airspace-data`.
5
+ */
6
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
7
+ /**
8
+ * Registers airspace query tools on the given MCP server. The bundled US
9
+ * airspace GeoJSON snapshot is decoded and indexed eagerly via the shared
10
+ * {@link airspaceResolver}.
11
+ *
12
+ * @param server - The MCP server instance to register tools on.
13
+ */
14
+ export declare function registerAirspaceTools(server: McpServer): void;
15
+ //# sourceMappingURL=airspace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"airspace.d.ts","sourceRoot":"","sources":["../../src/tools/airspace.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAmEzE;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA+B7D"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * @packageDocumentation
3
+ * MCP tool module wrapping `@squawk/airspace` point-in-airspace queries,
4
+ * backed by the US NASR airspace GeoJSON snapshot in `@squawk/airspace-data`.
5
+ */
6
+ import { z } from 'zod';
7
+ import { airspaceResolver } from '../resolvers.js';
8
+ /** All {@link AirspaceType} values, used for input validation. */
9
+ const AIRSPACE_TYPE_VALUES = [
10
+ 'CLASS_B',
11
+ 'CLASS_C',
12
+ 'CLASS_D',
13
+ 'CLASS_E2',
14
+ 'CLASS_E3',
15
+ 'CLASS_E4',
16
+ 'CLASS_E5',
17
+ 'CLASS_E6',
18
+ 'CLASS_E7',
19
+ 'MOA',
20
+ 'RESTRICTED',
21
+ 'PROHIBITED',
22
+ 'WARNING',
23
+ 'ALERT',
24
+ 'NSA',
25
+ ];
26
+ /**
27
+ * Strips the polygon boundary from a feature for tool output. The boundary
28
+ * coordinates are dropped because a single Class B feature can carry hundreds
29
+ * of vertices, and the MCP client almost always wants the descriptive metadata
30
+ * (type, identifier, vertical bounds, controlling facility) rather than the
31
+ * raw geometry. The structured-content schema preserves a `vertexCount` so
32
+ * callers can tell how detailed the original boundary was.
33
+ */
34
+ function summarizeFeature(feature) {
35
+ const ring = feature.boundary.coordinates[0] ?? [];
36
+ return {
37
+ type: feature.type,
38
+ name: feature.name,
39
+ identifier: feature.identifier,
40
+ floor: feature.floor,
41
+ ceiling: feature.ceiling,
42
+ state: feature.state,
43
+ controllingFacility: feature.controllingFacility,
44
+ scheduleDescription: feature.scheduleDescription,
45
+ vertexCount: ring.length,
46
+ };
47
+ }
48
+ /**
49
+ * Registers airspace query tools on the given MCP server. The bundled US
50
+ * airspace GeoJSON snapshot is decoded and indexed eagerly via the shared
51
+ * {@link airspaceResolver}.
52
+ *
53
+ * @param server - The MCP server instance to register tools on.
54
+ */
55
+ export function registerAirspaceTools(server) {
56
+ server.registerTool('query_airspace_at_position', {
57
+ title: 'Query airspace at a position and altitude',
58
+ description: 'Returns every US airspace feature whose lateral polygon contains the given position and whose vertical bounds contain the given altitude (feet MSL). Covers Class B/C/D/E controlled airspace and Special Use Airspace (MOA, restricted, prohibited, warning, alert, NSA). The boundary polygon is summarized as a vertex count to keep responses compact - call this tool with multiple altitudes to walk a vertical profile.',
59
+ inputSchema: {
60
+ lat: z.number().min(-90).max(90).describe('Latitude in decimal degrees (WGS84).'),
61
+ lon: z.number().min(-180).max(180).describe('Longitude in decimal degrees (WGS84).'),
62
+ altitudeFt: z
63
+ .number()
64
+ .describe('Altitude in feet MSL to compare against airspace vertical bounds.'),
65
+ airspaceTypes: z
66
+ .array(z.enum(AIRSPACE_TYPE_VALUES))
67
+ .optional()
68
+ .describe('Restrict results to these airspace types. Omit to include all types.'),
69
+ },
70
+ }, ({ lat, lon, altitudeFt, airspaceTypes }) => {
71
+ const query = { lat, lon, altitudeFt };
72
+ if (airspaceTypes !== undefined) {
73
+ query.types = new Set(airspaceTypes);
74
+ }
75
+ const features = airspaceResolver(query).map(summarizeFeature);
76
+ return {
77
+ content: [{ type: 'text', text: JSON.stringify(features, null, 2) }],
78
+ structuredContent: { features },
79
+ };
80
+ });
81
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @packageDocumentation
3
+ * MCP tool module wrapping `@squawk/airways` airway lookup, traversal, and
4
+ * expansion methods, backed by the US NASR snapshot in `@squawk/airway-data`.
5
+ */
6
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
7
+ /**
8
+ * Registers airway lookup tools on the given MCP server. Uses the shared
9
+ * {@link airwayResolver} built at module load time.
10
+ *
11
+ * @param server - The MCP server instance to register tools on.
12
+ */
13
+ export declare function registerAirwayTools(server: McpServer): void;
14
+ //# sourceMappingURL=airways.d.ts.map
@@ -0,0 +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;AAsBzE;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA6G3D"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * @packageDocumentation
3
+ * MCP tool module wrapping `@squawk/airways` airway lookup, traversal, and
4
+ * expansion methods, backed by the US NASR snapshot in `@squawk/airway-data`.
5
+ */
6
+ import { z } from 'zod';
7
+ import { airwayResolver } from '../resolvers.js';
8
+ /** All {@link AirwayType} values, used for input validation. */
9
+ const AIRWAY_TYPE_VALUES = [
10
+ 'VICTOR',
11
+ 'JET',
12
+ 'RNAV_Q',
13
+ 'RNAV_T',
14
+ 'GREEN',
15
+ 'RED',
16
+ 'AMBER',
17
+ 'BLUE',
18
+ 'ATLANTIC',
19
+ 'BAHAMA',
20
+ 'PACIFIC',
21
+ 'PUERTO_RICO',
22
+ ];
23
+ /**
24
+ * Registers airway lookup tools on the given MCP server. Uses the shared
25
+ * {@link airwayResolver} built at module load time.
26
+ *
27
+ * @param server - The MCP server instance to register tools on.
28
+ */
29
+ export function registerAirwayTools(server) {
30
+ server.registerTool('get_airway_by_designation', {
31
+ title: 'Get airways by designation',
32
+ description: 'Looks up US airways by designation (e.g. "V16", "J60", "Q1"). Multiple airways can share the same designation across regions (for example V16 exists in both the contiguous US and Hawaii), so the result is always an array. Returns an empty array when no match is found.',
33
+ inputSchema: {
34
+ designation: z.string().min(1).describe('Airway designation (case-insensitive).'),
35
+ },
36
+ }, ({ designation }) => {
37
+ const airways = airwayResolver.byDesignation(designation);
38
+ return {
39
+ content: [{ type: 'text', text: JSON.stringify(airways, null, 2) }],
40
+ structuredContent: { airways },
41
+ };
42
+ });
43
+ server.registerTool('expand_airway_segment', {
44
+ title: 'Expand an airway between two fixes',
45
+ description: 'Expands an airway between two fixes, returning the ordered sequence of waypoints from the entry fix to the exit fix (inclusive). Airways can be traversed in either direction. Returns null if the entry/exit fixes are not found on the airway.',
46
+ inputSchema: {
47
+ designation: z.string().min(1).describe('Airway designation (case-insensitive).'),
48
+ entryFix: z.string().min(1).describe('Identifier of the entry fix (case-insensitive).'),
49
+ exitFix: z.string().min(1).describe('Identifier of the exit fix (case-insensitive).'),
50
+ },
51
+ }, ({ designation, entryFix, exitFix }) => {
52
+ const expansion = airwayResolver.expand(designation, entryFix, exitFix);
53
+ if (expansion === undefined) {
54
+ return {
55
+ content: [
56
+ {
57
+ type: 'text',
58
+ text: `Could not expand airway "${designation}" from "${entryFix}" to "${exitFix}".`,
59
+ },
60
+ ],
61
+ structuredContent: { expansion: null },
62
+ };
63
+ }
64
+ return {
65
+ content: [{ type: 'text', text: JSON.stringify(expansion, null, 2) }],
66
+ structuredContent: { expansion },
67
+ };
68
+ });
69
+ server.registerTool('find_airways_by_fix', {
70
+ title: 'Find airways through a fix',
71
+ description: 'Finds all US airways that pass through a given fix, navaid, or waypoint identifier. Each result includes the airway record and the waypoint index where the identifier appears in the airway sequence.',
72
+ inputSchema: {
73
+ ident: z
74
+ .string()
75
+ .min(1)
76
+ .describe('Fix, navaid, or waypoint identifier (case-insensitive).'),
77
+ },
78
+ }, ({ ident }) => {
79
+ const results = airwayResolver.byFix(ident);
80
+ return {
81
+ content: [{ type: 'text', text: JSON.stringify(results, null, 2) }],
82
+ structuredContent: { results },
83
+ };
84
+ });
85
+ server.registerTool('search_airways', {
86
+ title: 'Search airways by designation',
87
+ description: 'Searches US airways by case-insensitive substring matching against the airway designation. Results are returned in alphabetical order by designation.',
88
+ inputSchema: {
89
+ text: z.string().min(1).describe('Substring to match against the airway designation.'),
90
+ airwayTypes: z
91
+ .array(z.enum(AIRWAY_TYPE_VALUES))
92
+ .optional()
93
+ .describe('Restrict results to these airway types. Omit to include all types.'),
94
+ limit: z
95
+ .number()
96
+ .int()
97
+ .positive()
98
+ .optional()
99
+ .describe('Maximum number of results to return. Defaults to 20.'),
100
+ },
101
+ }, ({ text, airwayTypes, limit }) => {
102
+ const query = { text };
103
+ if (airwayTypes !== undefined) {
104
+ query.types = new Set(airwayTypes);
105
+ }
106
+ if (limit !== undefined) {
107
+ query.limit = limit;
108
+ }
109
+ const airways = airwayResolver.search(query);
110
+ return {
111
+ content: [{ type: 'text', text: JSON.stringify(airways, null, 2) }],
112
+ structuredContent: { airways },
113
+ };
114
+ });
115
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @packageDocumentation
3
+ * MCP tool module exposing build provenance and record counts for every
4
+ * bundled FAA snapshot the server loads. Lets an LLM client report exactly
5
+ * which NASR cycle and registry vintage answered a query - critical context
6
+ * for aviation use, where stale data is a real safety concern.
7
+ */
8
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
9
+ /**
10
+ * Registers the `get_dataset_status` tool on the given MCP server. The tool
11
+ * takes no input and reports the NASR cycle date, generation timestamp, and
12
+ * record counts for each loaded snapshot. The lazily-loaded ICAO registry
13
+ * reports its load state without being initialized as a side effect.
14
+ *
15
+ * @param server - The MCP server instance to register tools on.
16
+ */
17
+ export declare function registerDatasetTools(server: McpServer): void;
18
+ //# sourceMappingURL=datasets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"datasets.d.ts","sourceRoot":"","sources":["../../src/tools/datasets.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AASzE;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA6D5D"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * @packageDocumentation
3
+ * MCP tool module exposing build provenance and record counts for every
4
+ * bundled FAA snapshot the server loads. Lets an LLM client report exactly
5
+ * which NASR cycle and registry vintage answered a query - critical context
6
+ * for aviation use, where stale data is a real safety concern.
7
+ */
8
+ import { usBundledAirports } from '@squawk/airport-data';
9
+ import { usBundledAirspace } from '@squawk/airspace-data';
10
+ import { usBundledAirways } from '@squawk/airway-data';
11
+ import { usBundledFixes } from '@squawk/fix-data';
12
+ import { usBundledNavaids } from '@squawk/navaid-data';
13
+ import { usBundledProcedures } from '@squawk/procedure-data';
14
+ import { getIcaoRegistryMetadata, isIcaoRegistryLoaded } from '../resolvers.js';
15
+ /**
16
+ * Registers the `get_dataset_status` tool on the given MCP server. The tool
17
+ * takes no input and reports the NASR cycle date, generation timestamp, and
18
+ * record counts for each loaded snapshot. The lazily-loaded ICAO registry
19
+ * reports its load state without being initialized as a side effect.
20
+ *
21
+ * @param server - The MCP server instance to register tools on.
22
+ */
23
+ export function registerDatasetTools(server) {
24
+ server.registerTool('get_dataset_status', {
25
+ title: 'Report status of every bundled dataset',
26
+ description: 'Returns the FAA NASR cycle effective date, build timestamp, and record counts for each dataset the server loads (airports, airspace, navaids, fixes, airways, procedures, ICAO aircraft registry). Use this when a user asks "how current is the data?" or before answering a question that depends on procedure/navaid currency. The aircraft registry is lazily loaded and reports its load state without forcing initialization.',
27
+ inputSchema: {},
28
+ }, () => {
29
+ const registryMetadata = getIcaoRegistryMetadata();
30
+ const datasets = {
31
+ airports: {
32
+ nasrCycleDate: usBundledAirports.properties.nasrCycleDate,
33
+ generatedAt: usBundledAirports.properties.generatedAt,
34
+ recordCount: usBundledAirports.properties.recordCount,
35
+ },
36
+ airspace: {
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
+ nasrCycleDate: usBundledProcedures.properties.nasrCycleDate,
59
+ generatedAt: usBundledProcedures.properties.generatedAt,
60
+ recordCount: usBundledProcedures.properties.recordCount,
61
+ sidCount: usBundledProcedures.properties.sidCount,
62
+ starCount: usBundledProcedures.properties.starCount,
63
+ waypointCount: usBundledProcedures.properties.waypointCount,
64
+ },
65
+ icaoRegistry: registryMetadata !== undefined
66
+ ? {
67
+ loaded: true,
68
+ generatedAt: registryMetadata.generatedAt,
69
+ recordCount: registryMetadata.recordCount,
70
+ }
71
+ : { loaded: isIcaoRegistryLoaded() },
72
+ };
73
+ return {
74
+ content: [{ type: 'text', text: JSON.stringify(datasets, null, 2) }],
75
+ structuredContent: { datasets },
76
+ };
77
+ });
78
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @packageDocumentation
3
+ * MCP tool module wrapping `@squawk/fixes` fix/waypoint lookup methods,
4
+ * backed by the US NASR snapshot in `@squawk/fix-data`.
5
+ */
6
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
7
+ /**
8
+ * Registers fix/waypoint lookup tools on the given MCP server. Uses the
9
+ * shared {@link fixResolver} built at module load time.
10
+ *
11
+ * @param server - The MCP server instance to register tools on.
12
+ */
13
+ export declare function registerFixTools(server: McpServer): void;
14
+ //# sourceMappingURL=fixes.d.ts.map
@@ -0,0 +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;AAkBzE;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAsGxD"}