@dangahagan/weather-mcp 1.34.0 → 1.34.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 +3 -3
- package/dist/utils/geohash.d.ts +46 -2
- package/dist/utils/geohash.d.ts.map +1 -1
- package/dist/utils/geohash.js +80 -21
- package/dist/utils/geohash.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/@dangahagan/weather-mcp)
|
|
4
4
|
[](https://registry.modelcontextprotocol.io/v0/servers?search=io.github.dgahagan/weather-mcp)
|
|
5
5
|
[](https://opensource.org/licenses/MIT)
|
|
6
|
-
[](./docs/testing/TEST_SUITE_README.md)
|
|
7
7
|
[](https://nodejs.org)
|
|
8
8
|
|
|
9
9
|
**Give your AI assistant real weather data — 17 tools, zero API keys, zero signup, zero cost.**
|
|
@@ -58,7 +58,7 @@ Choose this one if you want:
|
|
|
58
58
|
|
|
59
59
|
- **Genuinely free** — every data source is a free public API. No trial that expires, no credit card, no rate-limited "free tier" bait.
|
|
60
60
|
- **No API keys** — install to first forecast in under a minute. Nothing to configure, nothing to leak into a repo. ([Four optional keys](#optional-api-keys) add extras if you want them; the default configuration needs none.)
|
|
61
|
-
- **Fully open source** — MIT licensed, readable TypeScript, 4,
|
|
61
|
+
- **Fully open source** — MIT licensed, readable TypeScript, 4,420 tests. Audit it, fork it, fix it.
|
|
62
62
|
- **Privacy-respecting** — your queries go directly from your machine to public weather APIs. No middleman server, and no telemetry unless you opt in.
|
|
63
63
|
- **Breadth** — 17 tools covering weather, safety hazards (lightning, floods, wildfires), marine conditions, air quality, and historical data back to 1940. Most weather MCPs stop at forecasts.
|
|
64
64
|
|
|
@@ -391,7 +391,7 @@ Being honest about what free public data can and can't do:
|
|
|
391
391
|
```bash
|
|
392
392
|
npm run build # Compile TypeScript
|
|
393
393
|
npm run dev # Run in development mode
|
|
394
|
-
npm test # Run all 4,
|
|
394
|
+
npm test # Run all 4,420 tests
|
|
395
395
|
npm run test:coverage # Coverage report
|
|
396
396
|
npm run audit # Dependency vulnerability scan
|
|
397
397
|
```
|
package/dist/utils/geohash.d.ts
CHANGED
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
*/
|
|
5
5
|
/**
|
|
6
6
|
* Bounding box for geographic area
|
|
7
|
+
*
|
|
8
|
+
* Latitude is clamped to [-90, 90]. Longitude is an interval on the unwrapped line and is
|
|
9
|
+
* never clamped: `minLon < -180` or `maxLon > 180` means the box crosses the antimeridian.
|
|
10
|
+
* The interval is never wider than 360°.
|
|
7
11
|
*/
|
|
8
12
|
export interface BoundingBox {
|
|
9
13
|
minLat: number;
|
|
@@ -11,8 +15,18 @@ export interface BoundingBox {
|
|
|
11
15
|
maxLat: number;
|
|
12
16
|
maxLon: number;
|
|
13
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* True when `lon` lies in the box's longitude interval, read on the unwrapped line:
|
|
20
|
+
* a box that crosses ±180° admits a longitude that lands inside it after a ±360° shift.
|
|
21
|
+
*/
|
|
22
|
+
export declare function lonInBox(lon: number, box: BoundingBox): boolean;
|
|
14
23
|
/**
|
|
15
24
|
* Calculate bounding box around a point given a radius in kilometers
|
|
25
|
+
*
|
|
26
|
+
* The longitude interval is `lon ± lonDelta` on the unwrapped line, so a box near ±180°
|
|
27
|
+
* extends past it (see `BoundingBox`). The half-width is capped at 180°: toward the poles
|
|
28
|
+
* `cos(lat) → 0` and `lonDelta` grows without bound, and a 360°-wide interval is already the
|
|
29
|
+
* full circle.
|
|
16
30
|
* @param lat Latitude
|
|
17
31
|
* @param lon Longitude
|
|
18
32
|
* @param radiusKm Radius in kilometers
|
|
@@ -25,6 +39,31 @@ export declare function calculateBoundingBox(lat: number, lon: number, radiusKm:
|
|
|
25
39
|
* @returns Array of neighbor geohashes (up to 8 neighbors)
|
|
26
40
|
*/
|
|
27
41
|
export declare function getGeohashNeighbors(hash: string): string[];
|
|
42
|
+
/**
|
|
43
|
+
* Geohash tiles for a search area, with the count the precision budget is charged
|
|
44
|
+
*/
|
|
45
|
+
export interface GeohashTileSet {
|
|
46
|
+
/** Every tile admitted, on both sides of the antimeridian when the box crosses it */
|
|
47
|
+
tiles: Set<string>;
|
|
48
|
+
/** How many of `tiles` the budget counts: the start tile, plus every tile whose centre lies
|
|
49
|
+
* inside the box with its longitude interval clamped to [-180, 180] */
|
|
50
|
+
budgeted: number;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Compute geohash tiles that overlap a search area, and the budgeted count
|
|
54
|
+
* Uses breadth-first search to find all geohashes whose centre lies within the bounding box
|
|
55
|
+
*
|
|
56
|
+
* The budgeted count is the start tile plus every tile whose centre lies inside the box
|
|
57
|
+
* with its longitude interval clamped to [-180, 180]: exactly the tiles this function
|
|
58
|
+
* returned before subscriptions crossed the antimeridian. Tiles that enter only through the
|
|
59
|
+
* wrap or the far-side seed are subscribed but not counted.
|
|
60
|
+
* @param lat Center latitude
|
|
61
|
+
* @param lon Center longitude
|
|
62
|
+
* @param radiusKm Search radius in kilometers
|
|
63
|
+
* @param precision Geohash precision (1-12)
|
|
64
|
+
* @returns The tile set and its budgeted count
|
|
65
|
+
*/
|
|
66
|
+
export declare function computeGeohashTilesBudgeted(lat: number, lon: number, radiusKm: number, precision: number): GeohashTileSet;
|
|
28
67
|
/**
|
|
29
68
|
* Compute geohash tiles that overlap a circular search area
|
|
30
69
|
* Uses breadth-first search to find all geohashes within the bounding box
|
|
@@ -37,13 +76,18 @@ export declare function getGeohashNeighbors(hash: string): string[];
|
|
|
37
76
|
export declare function computeGeohashTiles(lat: number, lon: number, radiusKm: number, precision: number): Set<string>;
|
|
38
77
|
/**
|
|
39
78
|
* Calculate optimal geohash tiles for MQTT subscription
|
|
40
|
-
* Selects the
|
|
79
|
+
* Selects the finest (highest) precision whose budgeted tile count is at or below maxTiles:
|
|
80
|
+
* precisions run from 1 to 12 and the last one that fits is kept. The budgeted count is the
|
|
81
|
+
* tile set as it was before subscriptions crossed the antimeridian (see
|
|
82
|
+
* computeGeohashTilesBudgeted), so the precision chosen is the same as before, on every input. A box that crosses the
|
|
83
|
+
* antimeridian may return more than maxTiles tiles (observed maximum 2 × maxTiles), because
|
|
84
|
+
* tiles that enter only through the wrap or the far-side seed do not count against the budget.
|
|
41
85
|
* This balances spatial granularity against subscription overhead
|
|
42
86
|
*
|
|
43
87
|
* @param lat Center latitude
|
|
44
88
|
* @param lon Center longitude
|
|
45
89
|
* @param radiusKm Search radius in kilometers
|
|
46
|
-
* @param maxTiles Maximum
|
|
90
|
+
* @param maxTiles Maximum budgeted tiles (default 9, as used by homeassistant-blitzortung)
|
|
47
91
|
* @returns Set of geohash strings to subscribe to
|
|
48
92
|
*/
|
|
49
93
|
export declare function calculateGeohashSubscriptions(lat: number, lon: number, radiusKm: number, maxTiles?: number): Set<string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"geohash.d.ts","sourceRoot":"","sources":["../../src/utils/geohash.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH
|
|
1
|
+
{"version":3,"file":"geohash.d.ts","sourceRoot":"","sources":["../../src/utils/geohash.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,GAAG,OAAO,CAI/D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,WAAW,CAY5F;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAmB1D;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,qFAAqF;IACrF,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACnB;4EACwE;IACxE,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,2BAA2B,CACzC,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,cAAc,CAoEhB;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,GAAG,CAAC,MAAM,CAAC,CAEb;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,6BAA6B,CAC3C,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,QAAQ,GAAE,MAAU,GACnB,GAAG,CAAC,MAAM,CAAC,CAsBb;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAgBT"}
|
package/dist/utils/geohash.js
CHANGED
|
@@ -3,8 +3,22 @@
|
|
|
3
3
|
* Based on the homeassistant-blitzortung implementation
|
|
4
4
|
*/
|
|
5
5
|
import * as geohash from '../vendor/ngeohash.js';
|
|
6
|
+
/**
|
|
7
|
+
* True when `lon` lies in the box's longitude interval, read on the unwrapped line:
|
|
8
|
+
* a box that crosses ±180° admits a longitude that lands inside it after a ±360° shift.
|
|
9
|
+
*/
|
|
10
|
+
export function lonInBox(lon, box) {
|
|
11
|
+
return (lon >= box.minLon && lon <= box.maxLon)
|
|
12
|
+
|| (lon + 360 >= box.minLon && lon + 360 <= box.maxLon)
|
|
13
|
+
|| (lon - 360 >= box.minLon && lon - 360 <= box.maxLon);
|
|
14
|
+
}
|
|
6
15
|
/**
|
|
7
16
|
* Calculate bounding box around a point given a radius in kilometers
|
|
17
|
+
*
|
|
18
|
+
* The longitude interval is `lon ± lonDelta` on the unwrapped line, so a box near ±180°
|
|
19
|
+
* extends past it (see `BoundingBox`). The half-width is capped at 180°: toward the poles
|
|
20
|
+
* `cos(lat) → 0` and `lonDelta` grows without bound, and a 360°-wide interval is already the
|
|
21
|
+
* full circle.
|
|
8
22
|
* @param lat Latitude
|
|
9
23
|
* @param lon Longitude
|
|
10
24
|
* @param radiusKm Radius in kilometers
|
|
@@ -14,11 +28,12 @@ export function calculateBoundingBox(lat, lon, radiusKm) {
|
|
|
14
28
|
// Earth's circumference at equator: ~40,000 km
|
|
15
29
|
const latDelta = (radiusKm * 360) / 40000;
|
|
16
30
|
const lonDelta = latDelta / Math.cos((lat * Math.PI) / 180);
|
|
31
|
+
const d = Math.min(180, lonDelta);
|
|
17
32
|
return {
|
|
18
33
|
minLat: Math.max(-90, lat - latDelta),
|
|
19
|
-
minLon:
|
|
34
|
+
minLon: lon - d,
|
|
20
35
|
maxLat: Math.min(90, lat + latDelta),
|
|
21
|
-
maxLon:
|
|
36
|
+
maxLon: lon + d
|
|
22
37
|
};
|
|
23
38
|
}
|
|
24
39
|
/**
|
|
@@ -40,29 +55,58 @@ export function getGeohashNeighbors(hash) {
|
|
|
40
55
|
neighbors.push(geohash.neighbor(hash, [-1, -1])); // SW
|
|
41
56
|
}
|
|
42
57
|
catch (error) {
|
|
43
|
-
//
|
|
44
|
-
//
|
|
58
|
+
// Defensive guard only: the vendored neighbor clamps latitude, wraps longitude
|
|
59
|
+
// across the antimeridian and does not throw
|
|
45
60
|
}
|
|
46
61
|
return neighbors;
|
|
47
62
|
}
|
|
48
63
|
/**
|
|
49
|
-
* Compute geohash tiles that overlap a
|
|
50
|
-
* Uses breadth-first search to find all geohashes within the bounding box
|
|
64
|
+
* Compute geohash tiles that overlap a search area, and the budgeted count
|
|
65
|
+
* Uses breadth-first search to find all geohashes whose centre lies within the bounding box
|
|
66
|
+
*
|
|
67
|
+
* The budgeted count is the start tile plus every tile whose centre lies inside the box
|
|
68
|
+
* with its longitude interval clamped to [-180, 180]: exactly the tiles this function
|
|
69
|
+
* returned before subscriptions crossed the antimeridian. Tiles that enter only through the
|
|
70
|
+
* wrap or the far-side seed are subscribed but not counted.
|
|
51
71
|
* @param lat Center latitude
|
|
52
72
|
* @param lon Center longitude
|
|
53
73
|
* @param radiusKm Search radius in kilometers
|
|
54
74
|
* @param precision Geohash precision (1-12)
|
|
55
|
-
* @returns
|
|
75
|
+
* @returns The tile set and its budgeted count
|
|
56
76
|
*/
|
|
57
|
-
export function
|
|
77
|
+
export function computeGeohashTilesBudgeted(lat, lon, radiusKm, precision) {
|
|
58
78
|
const bbox = calculateBoundingBox(lat, lon, radiusKm);
|
|
79
|
+
const crosses = bbox.minLon < -180 || bbox.maxLon > 180;
|
|
80
|
+
const clampedMinLon = Math.max(-180, bbox.minLon);
|
|
81
|
+
const clampedMaxLon = Math.min(180, bbox.maxLon);
|
|
59
82
|
const tiles = new Set();
|
|
60
83
|
const queue = [];
|
|
61
84
|
const MAX_TILES = 10000; // Safety limit to prevent memory exhaustion
|
|
62
|
-
|
|
85
|
+
let budgeted = 0;
|
|
86
|
+
const inClampedBox = (centre) => centre.latitude >= bbox.minLat &&
|
|
87
|
+
centre.latitude <= bbox.maxLat &&
|
|
88
|
+
centre.longitude >= clampedMinLon &&
|
|
89
|
+
centre.longitude <= clampedMaxLon;
|
|
90
|
+
const admit = (hash, counted) => {
|
|
91
|
+
tiles.add(hash);
|
|
92
|
+
queue.push(hash);
|
|
93
|
+
if (counted) {
|
|
94
|
+
budgeted++;
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
// Start with the center point's geohash. It is always counted, as it always was
|
|
63
98
|
const centerHash = geohash.encode(lat, lon, precision);
|
|
64
|
-
|
|
65
|
-
|
|
99
|
+
admit(centerHash, true);
|
|
100
|
+
// A box that crosses the antimeridian also starts from the far side's edge cell at the
|
|
101
|
+
// point's latitude. Like the start cell, that cell always overlaps the box, and the
|
|
102
|
+
// centre test below can reject both for the same reason. encode places 180 in the
|
|
103
|
+
// easternmost cell and -180 in the westernmost, so this is the far edge by construction.
|
|
104
|
+
if (crosses) {
|
|
105
|
+
const farHash = geohash.encode(lat, lon >= 0 ? -180 : 180, precision);
|
|
106
|
+
if (!tiles.has(farHash)) {
|
|
107
|
+
admit(farHash, inClampedBox(geohash.decode(farHash)));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
66
110
|
// Breadth-first search to find all tiles within bounding box
|
|
67
111
|
while (queue.length > 0) {
|
|
68
112
|
const currentHash = queue.shift();
|
|
@@ -73,30 +117,45 @@ export function computeGeohashTiles(lat, lon, radiusKm, precision) {
|
|
|
73
117
|
}
|
|
74
118
|
// Safety check: prevent unbounded growth
|
|
75
119
|
if (tiles.size >= MAX_TILES) {
|
|
76
|
-
return tiles;
|
|
120
|
+
return { tiles, budgeted };
|
|
77
121
|
}
|
|
78
122
|
// Decode neighbor to check if it's within bounding box
|
|
79
123
|
const decoded = geohash.decode(neighbor);
|
|
80
124
|
if (decoded.latitude >= bbox.minLat &&
|
|
81
125
|
decoded.latitude <= bbox.maxLat &&
|
|
82
|
-
decoded.longitude
|
|
83
|
-
decoded
|
|
84
|
-
tiles.add(neighbor);
|
|
85
|
-
queue.push(neighbor);
|
|
126
|
+
lonInBox(decoded.longitude, bbox)) {
|
|
127
|
+
admit(neighbor, inClampedBox(decoded));
|
|
86
128
|
}
|
|
87
129
|
}
|
|
88
130
|
}
|
|
89
|
-
return tiles;
|
|
131
|
+
return { tiles, budgeted };
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Compute geohash tiles that overlap a circular search area
|
|
135
|
+
* Uses breadth-first search to find all geohashes within the bounding box
|
|
136
|
+
* @param lat Center latitude
|
|
137
|
+
* @param lon Center longitude
|
|
138
|
+
* @param radiusKm Search radius in kilometers
|
|
139
|
+
* @param precision Geohash precision (1-12)
|
|
140
|
+
* @returns Set of geohash strings that overlap the search area
|
|
141
|
+
*/
|
|
142
|
+
export function computeGeohashTiles(lat, lon, radiusKm, precision) {
|
|
143
|
+
return computeGeohashTilesBudgeted(lat, lon, radiusKm, precision).tiles;
|
|
90
144
|
}
|
|
91
145
|
/**
|
|
92
146
|
* Calculate optimal geohash tiles for MQTT subscription
|
|
93
|
-
* Selects the
|
|
147
|
+
* Selects the finest (highest) precision whose budgeted tile count is at or below maxTiles:
|
|
148
|
+
* precisions run from 1 to 12 and the last one that fits is kept. The budgeted count is the
|
|
149
|
+
* tile set as it was before subscriptions crossed the antimeridian (see
|
|
150
|
+
* computeGeohashTilesBudgeted), so the precision chosen is the same as before, on every input. A box that crosses the
|
|
151
|
+
* antimeridian may return more than maxTiles tiles (observed maximum 2 × maxTiles), because
|
|
152
|
+
* tiles that enter only through the wrap or the far-side seed do not count against the budget.
|
|
94
153
|
* This balances spatial granularity against subscription overhead
|
|
95
154
|
*
|
|
96
155
|
* @param lat Center latitude
|
|
97
156
|
* @param lon Center longitude
|
|
98
157
|
* @param radiusKm Search radius in kilometers
|
|
99
|
-
* @param maxTiles Maximum
|
|
158
|
+
* @param maxTiles Maximum budgeted tiles (default 9, as used by homeassistant-blitzortung)
|
|
100
159
|
* @returns Set of geohash strings to subscribe to
|
|
101
160
|
*/
|
|
102
161
|
export function calculateGeohashSubscriptions(lat, lon, radiusKm, maxTiles = 9) {
|
|
@@ -104,8 +163,8 @@ export function calculateGeohashSubscriptions(lat, lon, radiusKm, maxTiles = 9)
|
|
|
104
163
|
// Iterate through precision levels 1-12
|
|
105
164
|
// Start with coarse precision and increase until we exceed maxTiles
|
|
106
165
|
for (let precision = 1; precision <= 12; precision++) {
|
|
107
|
-
const tiles =
|
|
108
|
-
if (
|
|
166
|
+
const { tiles, budgeted } = computeGeohashTilesBudgeted(lat, lon, radiusKm, precision);
|
|
167
|
+
if (budgeted <= maxTiles) {
|
|
109
168
|
result = tiles;
|
|
110
169
|
}
|
|
111
170
|
else {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"geohash.js","sourceRoot":"","sources":["../../src/utils/geohash.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"geohash.js","sourceRoot":"","sources":["../../src/utils/geohash.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dangahagan/weather-mcp",
|
|
3
|
-
"version": "1.34.
|
|
3
|
+
"version": "1.34.1",
|
|
4
4
|
"description": "MCP server giving AI assistants 17 weather tools with zero API keys: global forecasts, current conditions, alerts, air quality, marine conditions, lightning detection, radar imagery, river levels, wildfire tracking, and historical weather back to 1940. Built entirely on free public APIs (NOAA, Open-Meteo, USGS, NIFC).",
|
|
5
5
|
"mcpName": "io.github.dgahagan/weather-mcp",
|
|
6
6
|
"main": "dist/index.js",
|