@dangahagan/weather-mcp 1.6.1 → 1.7.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 +249 -30
- package/dist/analytics/anonymizer.d.ts +37 -0
- package/dist/analytics/anonymizer.d.ts.map +1 -0
- package/dist/analytics/anonymizer.js +112 -0
- package/dist/analytics/anonymizer.js.map +1 -0
- package/dist/analytics/collector.d.ts +72 -0
- package/dist/analytics/collector.d.ts.map +1 -0
- package/dist/analytics/collector.js +282 -0
- package/dist/analytics/collector.js.map +1 -0
- package/dist/analytics/config.d.ts +15 -0
- package/dist/analytics/config.d.ts.map +1 -0
- package/dist/analytics/config.js +172 -0
- package/dist/analytics/config.js.map +1 -0
- package/dist/analytics/index.d.ts +8 -0
- package/dist/analytics/index.d.ts.map +1 -0
- package/dist/analytics/index.js +7 -0
- package/dist/analytics/index.js.map +1 -0
- package/dist/analytics/middleware.d.ts +33 -0
- package/dist/analytics/middleware.d.ts.map +1 -0
- package/dist/analytics/middleware.js +99 -0
- package/dist/analytics/middleware.js.map +1 -0
- package/dist/analytics/transport.d.ts +11 -0
- package/dist/analytics/transport.d.ts.map +1 -0
- package/dist/analytics/transport.js +92 -0
- package/dist/analytics/transport.js.map +1 -0
- package/dist/analytics/types.d.ts +74 -0
- package/dist/analytics/types.d.ts.map +1 -0
- package/dist/analytics/types.js +6 -0
- package/dist/analytics/types.js.map +1 -0
- package/dist/config/tools.d.ts +1 -1
- package/dist/config/tools.d.ts.map +1 -1
- package/dist/config/tools.js +25 -5
- package/dist/config/tools.js.map +1 -1
- package/dist/errors/ApiError.d.ts +6 -6
- package/dist/errors/ApiError.d.ts.map +1 -1
- package/dist/errors/ApiError.js.map +1 -1
- package/dist/handlers/forecastHandler.d.ts +2 -1
- package/dist/handlers/forecastHandler.d.ts.map +1 -1
- package/dist/handlers/forecastHandler.js +5 -4
- package/dist/handlers/forecastHandler.js.map +1 -1
- package/dist/handlers/locationHandler.d.ts +3 -2
- package/dist/handlers/locationHandler.d.ts.map +1 -1
- package/dist/handlers/locationHandler.js +27 -17
- package/dist/handlers/locationHandler.js.map +1 -1
- package/dist/handlers/riverConditionsHandler.js +13 -9
- package/dist/handlers/riverConditionsHandler.js.map +1 -1
- package/dist/handlers/savedLocationsHandler.d.ts +50 -0
- package/dist/handlers/savedLocationsHandler.d.ts.map +1 -0
- package/dist/handlers/savedLocationsHandler.js +399 -0
- package/dist/handlers/savedLocationsHandler.js.map +1 -0
- package/dist/handlers/statusHandler.js +2 -2
- package/dist/handlers/statusHandler.js.map +1 -1
- package/dist/index.js +210 -46
- package/dist/index.js.map +1 -1
- package/dist/services/geocoding.d.ts +57 -0
- package/dist/services/geocoding.d.ts.map +1 -0
- package/dist/services/geocoding.js +393 -0
- package/dist/services/geocoding.js.map +1 -0
- package/dist/services/locationStore.d.ts +62 -0
- package/dist/services/locationStore.d.ts.map +1 -0
- package/dist/services/locationStore.js +201 -0
- package/dist/services/locationStore.js.map +1 -0
- package/dist/services/nifc.d.ts.map +1 -1
- package/dist/services/nifc.js +11 -3
- package/dist/services/nifc.js.map +1 -1
- package/dist/services/noaa.d.ts.map +1 -1
- package/dist/services/noaa.js +11 -8
- package/dist/services/noaa.js.map +1 -1
- package/dist/services/nominatim.d.ts +62 -0
- package/dist/services/nominatim.d.ts.map +1 -0
- package/dist/services/nominatim.js +254 -0
- package/dist/services/nominatim.js.map +1 -0
- package/dist/services/openmeteo.d.ts.map +1 -1
- package/dist/services/openmeteo.js +16 -11
- package/dist/services/openmeteo.js.map +1 -1
- package/dist/types/noaa.d.ts +22 -7
- package/dist/types/noaa.d.ts.map +1 -1
- package/dist/types/nominatim.d.ts +72 -0
- package/dist/types/nominatim.d.ts.map +1 -0
- package/dist/types/nominatim.js +6 -0
- package/dist/types/nominatim.js.map +1 -0
- package/dist/types/savedLocations.d.ts +58 -0
- package/dist/types/savedLocations.d.ts.map +1 -0
- package/dist/types/savedLocations.js +5 -0
- package/dist/types/savedLocations.js.map +1 -0
- package/dist/utils/geography.d.ts +17 -0
- package/dist/utils/geography.d.ts.map +1 -1
- package/dist/utils/geography.js +56 -0
- package/dist/utils/geography.js.map +1 -1
- package/dist/utils/locationResolver.d.ts +25 -0
- package/dist/utils/locationResolver.d.ts.map +1 -0
- package/dist/utils/locationResolver.js +70 -0
- package/dist/utils/locationResolver.js.map +1 -0
- package/package.json +6 -7
package/README.md
CHANGED
|
@@ -30,6 +30,14 @@ An MCP (Model Context Protocol) server that provides **global weather data** to
|
|
|
30
30
|
- Support for cities, airports, landmarks, and regions globally
|
|
31
31
|
- Detailed metadata: timezone, elevation, population, country
|
|
32
32
|
- Enables natural language queries: "What's the weather in Tokyo?"
|
|
33
|
+
- **Saved Locations**: Save and reuse favorite locations (NEW in v1.7.0)
|
|
34
|
+
- Save frequently used locations with simple aliases ("home", "work", "cabin")
|
|
35
|
+
- Use saved locations by name instead of coordinates in all weather tools
|
|
36
|
+
- Tag locations with activities ("boating", "hiking", "skiing") for contextual weather info
|
|
37
|
+
- Automatic geocoding when saving (just provide location name)
|
|
38
|
+
- Persistent storage in `~/.weather-mcp/locations.json`
|
|
39
|
+
- Manage locations: save, list, view details, remove
|
|
40
|
+
- Makes queries natural: "What's the weather at home?" instead of providing coordinates
|
|
33
41
|
- **Climate Normals - Historical Context**: Compare weather to 30-year averages (NEW in v1.2.0)
|
|
34
42
|
- **Optional enhancement** for current conditions and forecasts (`include_normals=true`)
|
|
35
43
|
- Shows normal high/low temperatures and precipitation for comparison
|
|
@@ -161,6 +169,28 @@ The cache automatically stores and retrieves weather data with intelligent expir
|
|
|
161
169
|
|
|
162
170
|
### Configuration
|
|
163
171
|
|
|
172
|
+
**For most users: No configuration needed!** The server works out of the box with sensible defaults and requires no API keys.
|
|
173
|
+
|
|
174
|
+
#### Optional: Environment Variables
|
|
175
|
+
|
|
176
|
+
To customize server behavior, copy the example configuration file:
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
cp .env.example .env
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Then edit `.env` to adjust settings as needed. See [`.env.example`](./.env.example) for comprehensive documentation on all available options.
|
|
183
|
+
|
|
184
|
+
**What you can configure:**
|
|
185
|
+
- **Tool Selection** - Choose which MCP tools to expose (basic/standard/full/all presets)
|
|
186
|
+
- **Cache Settings** - Adjust cache size and enable/disable caching
|
|
187
|
+
- **API Configuration** - Set request timeouts
|
|
188
|
+
- **Logging** - Control log verbosity levels
|
|
189
|
+
- **Optional API Tokens** - Add NCEI token for official US climate normals (falls back to free Open-Meteo data)
|
|
190
|
+
- **Lightning Detection** - Configure alternative MQTT broker (optional)
|
|
191
|
+
|
|
192
|
+
All settings have sensible defaults and can be omitted entirely.
|
|
193
|
+
|
|
164
194
|
#### Tool Selection (NEW in v1.4.0)
|
|
165
195
|
|
|
166
196
|
Control which MCP tools are exposed to reduce context overhead and customize functionality. By default, only **basic** tools are enabled.
|
|
@@ -169,25 +199,16 @@ Control which MCP tools are exposed to reduce context overhead and customize fun
|
|
|
169
199
|
- `basic` (default): Essential weather tools (5 tools) - forecast, current_conditions, alerts, search_location, check_service_status
|
|
170
200
|
- `standard`: Basic + historical_weather (6 tools)
|
|
171
201
|
- `full`: Standard + air_quality (7 tools)
|
|
172
|
-
- `all`: All available tools (
|
|
202
|
+
- `all`: All available tools (16 tools) - includes marine_conditions, weather_imagery, lightning_activity, river_conditions, wildfire_info, save_location, list_saved_locations, get_saved_location, remove_saved_location
|
|
173
203
|
|
|
174
204
|
**Configuration Examples:**
|
|
175
205
|
|
|
176
206
|
```bash
|
|
177
|
-
#
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
#
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
# Add tools to a preset
|
|
184
|
-
export ENABLED_TOOLS=basic,+historical,+air_quality
|
|
185
|
-
|
|
186
|
-
# Remove tools from a preset
|
|
187
|
-
export ENABLED_TOOLS=all,-marine
|
|
188
|
-
|
|
189
|
-
# Complex combinations
|
|
190
|
-
export ENABLED_TOOLS=standard,+air_quality,-alerts
|
|
207
|
+
# In .env file or MCP client config
|
|
208
|
+
ENABLED_TOOLS=full # Use a preset
|
|
209
|
+
ENABLED_TOOLS=forecast,current,alerts,air_quality # Specific tools only
|
|
210
|
+
ENABLED_TOOLS=basic,+historical,+air_quality # Add to preset
|
|
211
|
+
ENABLED_TOOLS=all,-marine # Remove from preset
|
|
191
212
|
```
|
|
192
213
|
|
|
193
214
|
**Tool Aliases:**
|
|
@@ -198,20 +219,24 @@ Short names are supported: `forecast`, `current`, `conditions`, `alerts`, `warni
|
|
|
198
219
|
- **Better Security**: Only expose necessary functionality
|
|
199
220
|
- **Customization**: Tailor the server to your specific use case
|
|
200
221
|
|
|
201
|
-
####
|
|
222
|
+
#### MCP Client Configuration
|
|
202
223
|
|
|
203
|
-
|
|
224
|
+
You can also set environment variables directly in your MCP client configuration file instead of using a `.env` file:
|
|
204
225
|
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
226
|
+
```json
|
|
227
|
+
{
|
|
228
|
+
"mcpServers": {
|
|
229
|
+
"weather": {
|
|
230
|
+
"command": "npx",
|
|
231
|
+
"args": ["-y", "@dangahagan/weather-mcp@latest"],
|
|
232
|
+
"env": {
|
|
233
|
+
"ENABLED_TOOLS": "full",
|
|
234
|
+
"CACHE_MAX_SIZE": "2000",
|
|
235
|
+
"LOG_LEVEL": "1"
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
215
240
|
```
|
|
216
241
|
|
|
217
242
|
**Note on Climate Normals (v1.2.0):**
|
|
@@ -220,6 +245,25 @@ export NCEI_API_TOKEN=your_token_here
|
|
|
220
245
|
- Get a free token at: https://www.ncdc.noaa.gov/cdo-web/token
|
|
221
246
|
- If NCEI token is configured but unavailable, the system automatically falls back to Open-Meteo
|
|
222
247
|
|
|
248
|
+
#### Saved Locations (NEW in v1.7.0)
|
|
249
|
+
|
|
250
|
+
The saved locations feature stores your favorite places (like "home", "work", "cabin") for easy reuse in weather queries. No configuration needed - it works automatically!
|
|
251
|
+
|
|
252
|
+
**Storage Location:**
|
|
253
|
+
- Data stored in: `~/.weather-mcp/locations.json`
|
|
254
|
+
- Directory created automatically on first save
|
|
255
|
+
- File is human-readable JSON (can be backed up or edited manually)
|
|
256
|
+
|
|
257
|
+
**Features:**
|
|
258
|
+
- No limit on number of saved locations
|
|
259
|
+
- Tag locations with activities (e.g., "boating", "hiking") to help AI provide relevant weather info
|
|
260
|
+
- Persistent across MCP server restarts
|
|
261
|
+
- Portable - copy the file to migrate locations to another machine
|
|
262
|
+
|
|
263
|
+
**Learn More:**
|
|
264
|
+
- See [save_location](#13-save_location-new-in-v170) for usage instructions
|
|
265
|
+
- See [Using Saved Locations](#using-saved-locations-with-weather-tools) for examples
|
|
266
|
+
|
|
223
267
|
### Monitoring
|
|
224
268
|
|
|
225
269
|
Use the `check_service_status` tool to view cache statistics including:
|
|
@@ -268,7 +312,7 @@ If you prefer to build from source:
|
|
|
268
312
|
|
|
269
313
|
1. Clone the repository:
|
|
270
314
|
```bash
|
|
271
|
-
git clone https://github.com/
|
|
315
|
+
git clone https://github.com/weather-mcp/weather-mcp.git
|
|
272
316
|
cd weather-mcp
|
|
273
317
|
```
|
|
274
318
|
|
|
@@ -282,6 +326,14 @@ npm install
|
|
|
282
326
|
npm run build
|
|
283
327
|
```
|
|
284
328
|
|
|
329
|
+
4. (Optional) Configure environment variables:
|
|
330
|
+
```bash
|
|
331
|
+
cp .env.example .env
|
|
332
|
+
# Edit .env to customize settings (all optional)
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
See the [Configuration](#configuration) section for details.
|
|
336
|
+
|
|
285
337
|
## Upgrading to Latest Version
|
|
286
338
|
|
|
287
339
|
### Upgrading npm Installation
|
|
@@ -333,7 +385,7 @@ npm run build
|
|
|
333
385
|
You can verify your installed version by checking:
|
|
334
386
|
- npm: `npm list -g @dangahagan/weather-mcp`
|
|
335
387
|
- Source: `git describe --tags` or check `package.json`
|
|
336
|
-
- Latest release: https://github.com/
|
|
388
|
+
- Latest release: https://github.com/weather-mcp/weather-mcp/releases
|
|
337
389
|
|
|
338
390
|
## Usage with AI Assistants
|
|
339
391
|
|
|
@@ -795,6 +847,136 @@ Provides critical wildfire monitoring and safety information using NIFC (Nationa
|
|
|
795
847
|
|
|
796
848
|
**Note:** Data from NIFC WFIGS (Wildland Fire Interagency Geospatial Services). Always consult official sources for evacuation orders at https://inciweb.nwcg.gov/
|
|
797
849
|
|
|
850
|
+
### 13. save_location (NEW in v1.7.0)
|
|
851
|
+
Save a location with an alias for easy reuse in weather queries.
|
|
852
|
+
|
|
853
|
+
**Parameters:**
|
|
854
|
+
- `alias` (required): Short name for the location (e.g., "home", "work", "cabin"). Max 50 characters.
|
|
855
|
+
- `location_query` (optional): Location to geocode and save (e.g., "Seattle, WA", "Paris, France"). Not required if latitude/longitude provided.
|
|
856
|
+
- `latitude` (optional): Latitude if providing coordinates directly. Not required if location_query provided.
|
|
857
|
+
- `longitude` (optional): Longitude if providing coordinates directly. Not required if location_query provided.
|
|
858
|
+
- `name` (optional): Display name (required when using latitude/longitude directly)
|
|
859
|
+
- `activities` (optional): Activities you do at this location (e.g., ["boating", "fishing"]). Helps AI provide relevant weather information. Each activity max 50 characters.
|
|
860
|
+
|
|
861
|
+
**Description:**
|
|
862
|
+
Saves a location to persistent storage (`~/.weather-mcp/locations.json`) for easy reuse. Accepts either a location query (which will be automatically geocoded using Nominatim/OpenStreetMap) or direct coordinates. Once saved, the location can be used in any weather tool by providing `location_name` instead of coordinates.
|
|
863
|
+
|
|
864
|
+
**Smart Updates:** If the alias already exists and you only provide `name` and/or `activities` (without location details), it will update just those fields while preserving all coordinates and metadata. This makes it easy to add activities or rename locations without re-specifying the full address.
|
|
865
|
+
|
|
866
|
+
**Examples:**
|
|
867
|
+
```
|
|
868
|
+
"Save my home location in Seattle, WA"
|
|
869
|
+
→ save_location(alias="home", location_query="Seattle, WA")
|
|
870
|
+
|
|
871
|
+
"Save the cabin at Lake Tahoe"
|
|
872
|
+
→ save_location(alias="cabin", location_query="Lake Tahoe, CA")
|
|
873
|
+
|
|
874
|
+
"Save coordinates 47.6062, -122.3321 as my office"
|
|
875
|
+
→ save_location(alias="office", latitude=47.6062, longitude=-122.3321, name="Seattle Office")
|
|
876
|
+
|
|
877
|
+
"Save the lake house where we go boating and fishing"
|
|
878
|
+
→ save_location(alias="lake_house", location_query="Lake Tahoe, CA", activities=["boating", "fishing"])
|
|
879
|
+
|
|
880
|
+
"Save my favorite hiking spot"
|
|
881
|
+
→ save_location(alias="trail", location_query="Mt. Rainier, WA", activities=["hiking", "camping", "photography"])
|
|
882
|
+
|
|
883
|
+
"Add more activities to the cabin" (smart update - no location needed)
|
|
884
|
+
→ save_location(alias="cabin", activities=["boating", "fishing", "hiking", "swimming"])
|
|
885
|
+
|
|
886
|
+
"Rename my campsite" (smart update - no location needed)
|
|
887
|
+
→ save_location(alias="campsite", name="Yosemite Valley Campground")
|
|
888
|
+
```
|
|
889
|
+
|
|
890
|
+
**Returns:**
|
|
891
|
+
- Confirmation of save with location details
|
|
892
|
+
- Coordinates, timezone, and administrative region
|
|
893
|
+
- Usage examples showing how to use with weather tools
|
|
894
|
+
|
|
895
|
+
### 14. list_saved_locations (NEW in v1.7.0)
|
|
896
|
+
View all saved locations.
|
|
897
|
+
|
|
898
|
+
**Parameters:** None
|
|
899
|
+
|
|
900
|
+
**Description:**
|
|
901
|
+
Lists all locations saved in your persistent storage with their aliases, names, coordinates, and save dates. Helpful for seeing what location names are available for use with weather tools.
|
|
902
|
+
|
|
903
|
+
**Examples:**
|
|
904
|
+
```
|
|
905
|
+
"Show my saved locations"
|
|
906
|
+
"What locations do I have saved?"
|
|
907
|
+
"List all my saved places"
|
|
908
|
+
```
|
|
909
|
+
|
|
910
|
+
**Returns:**
|
|
911
|
+
- List of all saved locations with full details
|
|
912
|
+
- Usage examples for each location
|
|
913
|
+
- Total count of saved locations
|
|
914
|
+
|
|
915
|
+
### 15. get_saved_location (NEW in v1.7.0)
|
|
916
|
+
Get details for a specific saved location.
|
|
917
|
+
|
|
918
|
+
**Parameters:**
|
|
919
|
+
- `alias` (required): The name of the saved location to retrieve (e.g., "home", "work")
|
|
920
|
+
|
|
921
|
+
**Description:**
|
|
922
|
+
Retrieves detailed information about a specific saved location, including coordinates, timezone, region information, and save/update timestamps.
|
|
923
|
+
|
|
924
|
+
**Examples:**
|
|
925
|
+
```
|
|
926
|
+
"Show details for my home location"
|
|
927
|
+
"What are the coordinates for my cabin?"
|
|
928
|
+
"Get info about my work location"
|
|
929
|
+
```
|
|
930
|
+
|
|
931
|
+
**Returns:**
|
|
932
|
+
- Location name and coordinates
|
|
933
|
+
- Timezone and administrative regions
|
|
934
|
+
- Save and update timestamps
|
|
935
|
+
- Usage examples
|
|
936
|
+
|
|
937
|
+
### 16. remove_saved_location (NEW in v1.7.0)
|
|
938
|
+
Remove a saved location.
|
|
939
|
+
|
|
940
|
+
**Parameters:**
|
|
941
|
+
- `alias` (required): The name of the saved location to remove (e.g., "home", "work")
|
|
942
|
+
|
|
943
|
+
**Description:**
|
|
944
|
+
Permanently removes a saved location from storage. The location data is deleted and can no longer be used with weather tools unless saved again.
|
|
945
|
+
|
|
946
|
+
**Examples:**
|
|
947
|
+
```
|
|
948
|
+
"Remove my work location"
|
|
949
|
+
"Delete the cabin from saved locations"
|
|
950
|
+
"Remove home"
|
|
951
|
+
```
|
|
952
|
+
|
|
953
|
+
**Returns:**
|
|
954
|
+
- Confirmation of removal
|
|
955
|
+
- Count of remaining saved locations
|
|
956
|
+
|
|
957
|
+
## Using Saved Locations with Weather Tools
|
|
958
|
+
|
|
959
|
+
Once you've saved locations, you can use them with any weather tool by providing `location_name` instead of coordinates:
|
|
960
|
+
|
|
961
|
+
**Examples:**
|
|
962
|
+
```
|
|
963
|
+
# Instead of:
|
|
964
|
+
get_forecast(latitude=47.6062, longitude=-122.3321)
|
|
965
|
+
|
|
966
|
+
# You can use:
|
|
967
|
+
get_forecast(location_name="home")
|
|
968
|
+
|
|
969
|
+
# Natural language queries work too:
|
|
970
|
+
"What's the weather forecast at home?"
|
|
971
|
+
"How's the air quality at my cabin?"
|
|
972
|
+
"Are there any weather alerts for my work location?"
|
|
973
|
+
```
|
|
974
|
+
|
|
975
|
+
**Currently Supported Tools:**
|
|
976
|
+
- `get_forecast` - Weather forecasts using saved locations
|
|
977
|
+
|
|
978
|
+
**Coming Soon:** Support for saved locations in all weather tools (current conditions, alerts, air quality, marine conditions, etc.)
|
|
979
|
+
|
|
798
980
|
## Error Handling & Service Status
|
|
799
981
|
|
|
800
982
|
### Enhanced Error Messages
|
|
@@ -904,7 +1086,7 @@ npx tsx tests/test_noaa_api.ts
|
|
|
904
1086
|
|
|
905
1087
|
### Manual Testing with Claude Code
|
|
906
1088
|
|
|
907
|
-
See [TESTING_GUIDE.md](./docs/TESTING_GUIDE.md) for comprehensive manual testing instructions including:
|
|
1089
|
+
See [TESTING_GUIDE.md](./docs/testing/TESTING_GUIDE.md) for comprehensive manual testing instructions including:
|
|
908
1090
|
- Setup steps for MCP clients
|
|
909
1091
|
- Test cases for all tools
|
|
910
1092
|
- Error handling verification
|
|
@@ -1107,6 +1289,43 @@ To report a security vulnerability, please see our [Security Policy](./SECURITY.
|
|
|
1107
1289
|
- Response timeline commitments (48hr acknowledgment, 7-day assessment)
|
|
1108
1290
|
- Security best practices for users and developers
|
|
1109
1291
|
|
|
1292
|
+
## Documentation
|
|
1293
|
+
|
|
1294
|
+
📚 **[Complete Documentation Index](./docs/README.md)** - Comprehensive navigation guide to all project documentation
|
|
1295
|
+
|
|
1296
|
+
### Quick Links
|
|
1297
|
+
|
|
1298
|
+
**For Users:**
|
|
1299
|
+
- [Client Setup Guide](./docs/CLIENT_SETUP.md) - Setup instructions for 8 different MCP clients
|
|
1300
|
+
- [Testing Guide](./docs/testing/TESTING_GUIDE.md) - Manual testing procedures
|
|
1301
|
+
- [Error Handling](./docs/ERROR_HANDLING.md) - Enhanced error handling features
|
|
1302
|
+
|
|
1303
|
+
**For Developers:**
|
|
1304
|
+
- [Contributing Guidelines](./CONTRIBUTING.md) - How to contribute
|
|
1305
|
+
- [Development Guide](./CLAUDE.md) - AI assistant development guide
|
|
1306
|
+
- [Code Review](./docs/development/CODE_REVIEW.md) - Code quality analysis
|
|
1307
|
+
- [Security Audit](./docs/development/SECURITY_AUDIT_V1.6.md) - Security assessment
|
|
1308
|
+
|
|
1309
|
+
**Planning & Roadmap:**
|
|
1310
|
+
- [Implementation Plan](./docs/planning/IMPLEMENTATION_PLAN.md) - Project roadmap
|
|
1311
|
+
- [Future Enhancements](./docs/planning/FUTURE_ENHANCEMENTS.md) - Planned features
|
|
1312
|
+
- [Roadmap](./docs/planning/ROADMAP.md) - Long-term plans
|
|
1313
|
+
|
|
1314
|
+
**Testing & Quality:**
|
|
1315
|
+
- [Test Suite](./docs/testing/TEST_SUITE_README.md) - Test overview
|
|
1316
|
+
- [Test Coverage](./docs/testing/TEST_COVERAGE_ANALYSIS_2025.md) - Latest coverage analysis
|
|
1317
|
+
- [Test Recommendations](./docs/testing/TEST_RECOMMENDATIONS.md) - Improvement suggestions
|
|
1318
|
+
|
|
1319
|
+
**Analytics (Optional):**
|
|
1320
|
+
- [Analytics Plan](./docs/analytics/ANALYTICS_MCP_PLAN.md) - Privacy-first analytics
|
|
1321
|
+
- [Analytics Security](./docs/analytics/MCP_ANALYTICS_SECURITY_GUIDE.md) - Security implementation guide
|
|
1322
|
+
- [Local Analytics](./docs/analytics/LOCAL_ANALYTICS_GUIDE.md) - Setup guide
|
|
1323
|
+
|
|
1324
|
+
**Technical Documentation:**
|
|
1325
|
+
- [NOAA API Research](./docs/NOAA_API_RESEARCH.md) - NOAA API integration details
|
|
1326
|
+
- [Historical Data Plan](./docs/HISTORICAL_DATA_PLAN.md) - Historical weather implementation
|
|
1327
|
+
- [MCP Best Practices](./docs/MCP_BEST_PRACTICES.md) - MCP protocol guidelines
|
|
1328
|
+
|
|
1110
1329
|
## License
|
|
1111
1330
|
|
|
1112
1331
|
MIT
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data anonymization utilities for privacy-first analytics
|
|
3
|
+
* Ensures no PII is collected as per docs/ANALYTICS_MCP_PLAN.md
|
|
4
|
+
*/
|
|
5
|
+
import { AnalyticsEvent, AnalyticsLevel } from './types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Raw event data before anonymization
|
|
8
|
+
* Includes all possible fields that might be collected
|
|
9
|
+
*/
|
|
10
|
+
interface RawEventData {
|
|
11
|
+
version: string;
|
|
12
|
+
tool: string;
|
|
13
|
+
status: 'success' | 'error';
|
|
14
|
+
timestamp_hour: string;
|
|
15
|
+
analytics_level?: AnalyticsLevel;
|
|
16
|
+
error_type?: string;
|
|
17
|
+
response_time_ms?: number;
|
|
18
|
+
service?: string;
|
|
19
|
+
cache_hit?: boolean;
|
|
20
|
+
retry_count?: number;
|
|
21
|
+
country?: string;
|
|
22
|
+
parameters?: Record<string, unknown>;
|
|
23
|
+
session_id?: string;
|
|
24
|
+
sequence_number?: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Anonymize event data based on analytics level
|
|
28
|
+
* Strips sensitive information and ensures privacy compliance
|
|
29
|
+
*/
|
|
30
|
+
export declare function anonymizeEvent(rawData: RawEventData, level: AnalyticsLevel, salt?: string): AnalyticsEvent;
|
|
31
|
+
/**
|
|
32
|
+
* Round timestamp to nearest hour for privacy
|
|
33
|
+
* Prevents precise user tracking
|
|
34
|
+
*/
|
|
35
|
+
export declare function roundToHour(date: Date): string;
|
|
36
|
+
export {};
|
|
37
|
+
//# sourceMappingURL=anonymizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anonymizer.d.ts","sourceRoot":"","sources":["../../src/analytics/anonymizer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5D;;;GAGG;AACH,UAAU,YAAY;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC;IAC5B,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,cAAc,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,YAAY,EACrB,KAAK,EAAE,cAAc,EACrB,IAAI,CAAC,EAAE,MAAM,GACZ,cAAc,CA0ChB;AAiED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAI9C"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data anonymization utilities for privacy-first analytics
|
|
3
|
+
* Ensures no PII is collected as per docs/ANALYTICS_MCP_PLAN.md
|
|
4
|
+
*/
|
|
5
|
+
import crypto from 'crypto';
|
|
6
|
+
/**
|
|
7
|
+
* Anonymize event data based on analytics level
|
|
8
|
+
* Strips sensitive information and ensures privacy compliance
|
|
9
|
+
*/
|
|
10
|
+
export function anonymizeEvent(rawData, level, salt) {
|
|
11
|
+
// Base event (minimal level) - always included
|
|
12
|
+
const baseEvent = {
|
|
13
|
+
version: rawData.version,
|
|
14
|
+
tool: rawData.tool,
|
|
15
|
+
status: rawData.status,
|
|
16
|
+
timestamp_hour: rawData.timestamp_hour,
|
|
17
|
+
analytics_level: 'minimal',
|
|
18
|
+
...(rawData.status === 'error' && rawData.error_type ? { error_type: rawData.error_type } : {}),
|
|
19
|
+
};
|
|
20
|
+
// Return minimal level (no additional data)
|
|
21
|
+
if (level === 'minimal') {
|
|
22
|
+
return baseEvent;
|
|
23
|
+
}
|
|
24
|
+
// Standard level - add performance metrics
|
|
25
|
+
const standardEvent = {
|
|
26
|
+
...baseEvent,
|
|
27
|
+
analytics_level: 'standard',
|
|
28
|
+
...(rawData.response_time_ms !== undefined && { response_time_ms: rawData.response_time_ms }),
|
|
29
|
+
...(rawData.service && { service: rawData.service }),
|
|
30
|
+
...(rawData.cache_hit !== undefined && { cache_hit: rawData.cache_hit }),
|
|
31
|
+
...(rawData.retry_count !== undefined && { retry_count: rawData.retry_count }),
|
|
32
|
+
...(rawData.country && { country: rawData.country }),
|
|
33
|
+
};
|
|
34
|
+
// Return standard level
|
|
35
|
+
if (level === 'standard') {
|
|
36
|
+
return standardEvent;
|
|
37
|
+
}
|
|
38
|
+
// Detailed level - add anonymized workflow data
|
|
39
|
+
const detailedEvent = {
|
|
40
|
+
...standardEvent,
|
|
41
|
+
analytics_level: 'detailed',
|
|
42
|
+
...(rawData.parameters && { parameters: sanitizeParameters(rawData.parameters) }),
|
|
43
|
+
...(rawData.session_id && { session_id: hashSessionId(rawData.session_id, salt) }),
|
|
44
|
+
...(rawData.sequence_number !== undefined && { sequence_number: rawData.sequence_number }),
|
|
45
|
+
};
|
|
46
|
+
return detailedEvent;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Sanitize tool parameters - ONLY keep safe, non-identifying values
|
|
50
|
+
* NEVER include: coordinates, location names, user input
|
|
51
|
+
*/
|
|
52
|
+
function sanitizeParameters(params) {
|
|
53
|
+
const safe = {};
|
|
54
|
+
// Allowlist of safe parameters that don't contain PII
|
|
55
|
+
const allowedParams = [
|
|
56
|
+
'days',
|
|
57
|
+
'granularity',
|
|
58
|
+
'source',
|
|
59
|
+
'forecast_type',
|
|
60
|
+
'include_normals',
|
|
61
|
+
'include_fire_weather',
|
|
62
|
+
'include_severe_weather',
|
|
63
|
+
'active_only',
|
|
64
|
+
'limit',
|
|
65
|
+
'radius',
|
|
66
|
+
'units',
|
|
67
|
+
'hourly',
|
|
68
|
+
'daily',
|
|
69
|
+
];
|
|
70
|
+
for (const key of allowedParams) {
|
|
71
|
+
if (params[key] !== undefined) {
|
|
72
|
+
// Only include primitive values (no objects/arrays that might contain PII)
|
|
73
|
+
const value = params[key];
|
|
74
|
+
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
|
|
75
|
+
safe[key] = value;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// NEVER include these (blocklist for extra safety):
|
|
80
|
+
// - latitude, longitude, lat, lon
|
|
81
|
+
// - location, address, city, state, zip, postal_code
|
|
82
|
+
// - user, name, email, phone
|
|
83
|
+
// - any user-provided strings
|
|
84
|
+
return safe;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Create one-way hash of session ID
|
|
88
|
+
* Cannot be reversed to identify users
|
|
89
|
+
*/
|
|
90
|
+
function hashSessionId(sessionId, salt) {
|
|
91
|
+
// Salt should always be provided by config (auto-generated)
|
|
92
|
+
// Fallback to environment variable if somehow not provided
|
|
93
|
+
const sessionSalt = salt || process.env.ANALYTICS_SALT || '';
|
|
94
|
+
if (!sessionSalt) {
|
|
95
|
+
throw new Error('Analytics salt must be provided for session ID hashing');
|
|
96
|
+
}
|
|
97
|
+
return crypto
|
|
98
|
+
.createHash('sha256')
|
|
99
|
+
.update(sessionId + sessionSalt)
|
|
100
|
+
.digest('hex')
|
|
101
|
+
.substring(0, 16); // Shortened for storage efficiency
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Round timestamp to nearest hour for privacy
|
|
105
|
+
* Prevents precise user tracking
|
|
106
|
+
*/
|
|
107
|
+
export function roundToHour(date) {
|
|
108
|
+
const rounded = new Date(date);
|
|
109
|
+
rounded.setMinutes(0, 0, 0);
|
|
110
|
+
return rounded.toISOString();
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=anonymizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anonymizer.js","sourceRoot":"","sources":["../../src/analytics/anonymizer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analytics event collector and batch manager
|
|
3
|
+
* Buffers events in memory and periodically flushes to analytics server
|
|
4
|
+
*/
|
|
5
|
+
import { AnalyticsConfig, ToolExecutionMetadata } from './types.js';
|
|
6
|
+
/**
|
|
7
|
+
* AnalyticsCollector - Manages event buffering and batch sending
|
|
8
|
+
* Implements privacy-first analytics with automatic flushing
|
|
9
|
+
*/
|
|
10
|
+
export declare class AnalyticsCollector {
|
|
11
|
+
private buffer;
|
|
12
|
+
private config;
|
|
13
|
+
private flushTimer;
|
|
14
|
+
private sessionId;
|
|
15
|
+
private sequenceNumber;
|
|
16
|
+
private isShuttingDown;
|
|
17
|
+
private consecutiveFailures;
|
|
18
|
+
private circuitOpen;
|
|
19
|
+
private circuitOpenUntil;
|
|
20
|
+
private readonly MAX_CONSECUTIVE_FAILURES;
|
|
21
|
+
private readonly CIRCUIT_BREAKER_RESET_MS;
|
|
22
|
+
private errorCount;
|
|
23
|
+
private successCount;
|
|
24
|
+
private readonly ERROR_THRESHOLD;
|
|
25
|
+
private lastFlushTime;
|
|
26
|
+
private flushCount;
|
|
27
|
+
private readonly MIN_FLUSH_INTERVAL_MS;
|
|
28
|
+
private readonly MAX_FLUSHES_PER_HOUR;
|
|
29
|
+
private readonly MAX_EVENTS_PER_MINUTE;
|
|
30
|
+
private recentEventTimestamps;
|
|
31
|
+
private readonly MAX_BUFFER_SIZE;
|
|
32
|
+
private readonly FLUSH_INTERVAL_MS;
|
|
33
|
+
constructor(config: AnalyticsConfig);
|
|
34
|
+
/**
|
|
35
|
+
* Track a tool execution event
|
|
36
|
+
* Fails silently - analytics should never break the application
|
|
37
|
+
*/
|
|
38
|
+
trackToolCall(tool: string, status: 'success' | 'error', metadata?: ToolExecutionMetadata): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* Flush buffered events to analytics server
|
|
41
|
+
* Called automatically on timer or when buffer is full
|
|
42
|
+
* Implements circuit breaker pattern (3.7)
|
|
43
|
+
*/
|
|
44
|
+
flush(): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Start periodic flush timer
|
|
47
|
+
*/
|
|
48
|
+
private startFlushTimer;
|
|
49
|
+
/**
|
|
50
|
+
* Stop flush timer
|
|
51
|
+
*/
|
|
52
|
+
private stopFlushTimer;
|
|
53
|
+
/**
|
|
54
|
+
* Generate unique session ID
|
|
55
|
+
* Used for tracking tool call sequences in detailed mode
|
|
56
|
+
*/
|
|
57
|
+
private generateSessionId;
|
|
58
|
+
/**
|
|
59
|
+
* Public shutdown method called by main shutdown handler
|
|
60
|
+
* Ensures buffered events are sent before process exits
|
|
61
|
+
*/
|
|
62
|
+
shutdown(): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Get current buffer size (for testing)
|
|
65
|
+
*/
|
|
66
|
+
getBufferSize(): number;
|
|
67
|
+
/**
|
|
68
|
+
* Get session ID (for testing)
|
|
69
|
+
*/
|
|
70
|
+
getSessionId(): string;
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=collector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collector.d.ts","sourceRoot":"","sources":["../../src/analytics/collector.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EAAE,eAAe,EAAkB,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEpF;;;GAGG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,cAAc,CAAS;IAG/B,OAAO,CAAC,mBAAmB,CAAK;IAChC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,gBAAgB,CAAqB;IAC7C,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAK;IAC9C,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAiB;IAG1D,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAM;IAGtC,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAS;IAC/C,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAM;IAC3C,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAM;IAC5C,OAAO,CAAC,qBAAqB,CAAgB;IAE7C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAO;IACvC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAiB;gBAEvC,MAAM,EAAE,eAAe;IAanC;;;OAGG;IACU,aAAa,CACxB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,SAAS,GAAG,OAAO,EAC3B,QAAQ,GAAE,qBAA0B,GACnC,OAAO,CAAC,IAAI,CAAC;IA+GhB;;;;OAIG;IACU,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA6EnC;;OAEG;IACH,OAAO,CAAC,eAAe;IAavB;;OAEG;IACH,OAAO,CAAC,cAAc;IAOtB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAIzB;;;OAGG;IACU,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAmBtC;;OAEG;IACI,aAAa,IAAI,MAAM;IAI9B;;OAEG;IACI,YAAY,IAAI,MAAM;CAG9B"}
|