@pipeworx/mcp-aviation-weather 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,19 +2,19 @@
2
2
 
3
3
  Aviation Weather MCP — METAR, TAF, PIREPs, AIRMET/SIGMET, station info
4
4
 
5
- Part of [Pipeworx](https://pipeworx.io) — an MCP gateway connecting AI agents to 250+ live data sources.
5
+ Part of [Pipeworx](https://pipeworx.io) — an MCP gateway connecting AI agents to 1160+ live data sources.
6
6
 
7
7
  ## Tools
8
8
 
9
9
  | Tool | Description |
10
10
  |------|-------------|
11
11
  | `metar` | METAR observations. ids = comma-sep ICAO codes (KSFO,EGLL,LFPG). |
12
- | `taf` | Terminal Aerodrome Forecasts. |
13
- | `pirep` | Pilot reports. Optional id (station), age (hours), distance (NM), level (flight level). |
14
- | `sigmet` | Currently active SIGMETs. |
15
- | `airmet` | Currently active AIRMETs. |
16
- | `gairmet` | Graphical AIRMETs. |
17
- | `windsaloft` | Winds aloft forecast. |
12
+ | `taf` | Terminal Aerodrome Forecast (TAF) for one or more ICAO airport codes (e.g. KSFO,EGLL); returns forecast periods covering wind, visibility, and cloud ceilings for the next 24–30 h. |
13
+ | `pirep` | Pilot reports (PIREPs). Call with no args for recent US-wide reports (default CONUS box), or pass a station `id` for reports within `distance_nm` of it, or a custom `bbox`. |
14
+ | `sigmet` | Fetch all currently active SIGMETs (significant en-route weather hazards: convection, turbulence, icing, volcanic ash) from the US Aviation Weather Center; no inputs required. |
15
+ | `airmet` | Fetch all currently active AIRMETs (moderate turbulence, icing, IFR/mountain-obscuration advisories for general aviation) from the US Aviation Weather Center; no inputs required. |
16
+ | `gairmet` | Fetch Graphical AIRMETs from the US Aviation Weather Center; optionally filter by type (turb, ice, sfc_winds, lifr, ifr); returns GeoJSON-style hazard polygons. |
17
+ | `windsaloft` | Winds and temperatures aloft forecast from the US Aviation Weather Center; specify US region (us/bos/mia/chi/dfw/slc/sfo/alaska) and level (low/high); returns an ASCII table or JSON. |
18
18
  | `stationinfo` | Aerodrome metadata — lat/lon, elevation, country. |
19
19
 
20
20
  ## Quick Start
@@ -31,7 +31,7 @@ Add to your MCP client (Claude Desktop, Cursor, Windsurf, etc.):
31
31
  }
32
32
  ```
33
33
 
34
- Or connect to the full Pipeworx gateway for access to all 250+ data sources:
34
+ Or connect to the full Pipeworx gateway for access to all 1160+ data sources:
35
35
 
36
36
  ```json
37
37
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pipeworx/mcp-aviation-weather",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Aviation Weather MCP — METAR, TAF, PIREPs, AIRMET/SIGMET, station info",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
package/server.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "name": "io.github.pipeworx-io/aviation-weather",
4
4
  "title": "Aviation Weather",
5
5
  "description": "Aviation Weather MCP — METAR, TAF, PIREPs, AIRMET/SIGMET, station info",
6
- "version": "0.1.0",
6
+ "version": "0.1.1",
7
7
  "websiteUrl": "https://pipeworx.io/packs/aviation-weather",
8
8
  "repository": {
9
9
  "url": "https://github.com/pipeworx-io/mcp-aviation-weather",
package/src/index.ts CHANGED
@@ -45,7 +45,7 @@ const tools: McpToolExport['tools'] = [
45
45
  },
46
46
  {
47
47
  name: 'taf',
48
- description: 'Terminal Aerodrome Forecasts.',
48
+ description: 'Terminal Aerodrome Forecast (TAF) for one or more ICAO airport codes (e.g. KSFO,EGLL); returns forecast periods covering wind, visibility, and cloud ceilings for the next 24–30 h.',
49
49
  inputSchema: {
50
50
  type: 'object',
51
51
  properties: {
@@ -58,13 +58,14 @@ const tools: McpToolExport['tools'] = [
58
58
  },
59
59
  {
60
60
  name: 'pirep',
61
- description: 'Pilot reports. Optional id (station), age (hours), distance (NM), level (flight level).',
61
+ description: 'Pilot reports (PIREPs). Call with no args for recent US-wide reports (default CONUS box), or pass a station `id` for reports within `distance_nm` of it, or a custom `bbox`.',
62
62
  inputSchema: {
63
63
  type: 'object',
64
64
  properties: {
65
- id: { type: 'string', description: 'Center station for proximity filter' },
65
+ id: { type: 'string', description: 'Center station for a proximity filter (e.g. "KORD"); reports within distance_nm of it.' },
66
+ distance_nm: { type: 'number', description: 'Radius from `id` in nautical miles (default 200). Only used with `id`.' },
67
+ bbox: { type: 'string', description: 'Bounding box "minLat,minLon,maxLat,maxLon" (default CONUS "20,-130,55,-60" when no id).' },
66
68
  age: { type: 'number', description: 'Lookback hours, default 1.5' },
67
- distance_nm: { type: 'number', description: 'Distance from id in nautical miles, default 200' },
68
69
  level: { type: 'number', description: 'Flight level filter (FL310 = 310)' },
69
70
  format: { type: 'string', description: 'json (default) | raw' },
70
71
  },
@@ -72,7 +73,7 @@ const tools: McpToolExport['tools'] = [
72
73
  },
73
74
  {
74
75
  name: 'sigmet',
75
- description: 'Currently active SIGMETs.',
76
+ description: 'Fetch all currently active SIGMETs (significant en-route weather hazards: convection, turbulence, icing, volcanic ash) from the US Aviation Weather Center; no inputs required.',
76
77
  inputSchema: {
77
78
  type: 'object',
78
79
  properties: { format: { type: 'string', description: 'json (default) | raw' } },
@@ -80,7 +81,7 @@ const tools: McpToolExport['tools'] = [
80
81
  },
81
82
  {
82
83
  name: 'airmet',
83
- description: 'Currently active AIRMETs.',
84
+ description: 'Fetch all currently active AIRMETs (moderate turbulence, icing, IFR/mountain-obscuration advisories for general aviation) from the US Aviation Weather Center; no inputs required.',
84
85
  inputSchema: {
85
86
  type: 'object',
86
87
  properties: { format: { type: 'string' } },
@@ -88,7 +89,7 @@ const tools: McpToolExport['tools'] = [
88
89
  },
89
90
  {
90
91
  name: 'gairmet',
91
- description: 'Graphical AIRMETs.',
92
+ description: 'Fetch Graphical AIRMETs from the US Aviation Weather Center; optionally filter by type (turb, ice, sfc_winds, lifr, ifr); returns GeoJSON-style hazard polygons.',
92
93
  inputSchema: {
93
94
  type: 'object',
94
95
  properties: {
@@ -99,7 +100,7 @@ const tools: McpToolExport['tools'] = [
99
100
  },
100
101
  {
101
102
  name: 'windsaloft',
102
- description: 'Winds aloft forecast.',
103
+ description: 'Winds and temperatures aloft forecast from the US Aviation Weather Center; specify US region (us/bos/mia/chi/dfw/slc/sfo/alaska) and level (low/high); returns an ASCII table or JSON.',
103
104
  inputSchema: {
104
105
  type: 'object',
105
106
  properties: {
@@ -134,11 +135,20 @@ async function callTool(name: string, args: Record<string, unknown>): Promise<un
134
135
  format: String(args.format ?? 'json'),
135
136
  });
136
137
  case 'pirep': {
138
+ // The API REQUIRES either a station id + radial distance OR a bounding
139
+ // box — a bare /pirep 400s ("Must specify bounding box or stations ID and
140
+ // radial distance"). So: with `id`, always send a distance (default 200);
141
+ // without `id`, default to a CONUS bbox so a bare pirep() returns US-wide
142
+ // reports instead of an error.
137
143
  const params: Record<string, string> = { format: String(args.format ?? 'json') };
138
- if (args.id) params.id = String(args.id);
139
144
  if (args.age !== undefined) params.age = String(args.age);
140
- if (args.distance_nm !== undefined) params.distance = String(args.distance_nm);
141
145
  if (args.level !== undefined) params.level = String(args.level);
146
+ if (args.id) {
147
+ params.id = String(args.id);
148
+ params.distance = String(args.distance_nm ?? 200);
149
+ } else {
150
+ params.bbox = typeof args.bbox === 'string' && args.bbox.trim() ? String(args.bbox) : '20,-130,55,-60';
151
+ }
142
152
  return fetchAW('/pirep', params);
143
153
  }
144
154
  case 'sigmet':
@@ -179,10 +189,16 @@ async function fetchAW(path: string, paramsObj: Record<string, string>) {
179
189
  }
180
190
  const format = paramsObj.format ?? 'json';
181
191
  if (format === 'json') {
192
+ // Read once as text, then attempt JSON parse on the string. The earlier
193
+ // version called res.json() then fell through to res.text() on parse
194
+ // failure — but res.json() consumes the body, so the fallback hit
195
+ // "Body has already been used". Reading text first avoids that and
196
+ // also lets us return the raw payload when the upstream returns plain
197
+ // text (e.g. /windtemp ignores ?format=json and ships an ASCII table).
198
+ const text = await res.text();
182
199
  try {
183
- return await res.json();
200
+ return JSON.parse(text);
184
201
  } catch {
185
- const text = await res.text();
186
202
  return { format: 'raw', body: text };
187
203
  }
188
204
  }