@dangahagan/weather-mcp 0.1.2 → 0.4.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 (68) hide show
  1. package/README.md +295 -52
  2. package/dist/config/cache.d.ts +30 -0
  3. package/dist/config/cache.d.ts.map +1 -0
  4. package/dist/config/cache.js +105 -0
  5. package/dist/config/cache.js.map +1 -0
  6. package/dist/config/displayThresholds.d.ts +83 -0
  7. package/dist/config/displayThresholds.d.ts.map +1 -0
  8. package/dist/config/displayThresholds.js +83 -0
  9. package/dist/config/displayThresholds.js.map +1 -0
  10. package/dist/errors/ApiError.d.ts +62 -0
  11. package/dist/errors/ApiError.d.ts.map +1 -0
  12. package/dist/errors/ApiError.js +147 -0
  13. package/dist/errors/ApiError.js.map +1 -0
  14. package/dist/handlers/alertsHandler.d.ts +11 -0
  15. package/dist/handlers/alertsHandler.d.ts.map +1 -0
  16. package/dist/handlers/alertsHandler.js +79 -0
  17. package/dist/handlers/alertsHandler.js.map +1 -0
  18. package/dist/handlers/currentConditionsHandler.d.ts +11 -0
  19. package/dist/handlers/currentConditionsHandler.d.ts.map +1 -0
  20. package/dist/handlers/currentConditionsHandler.js +168 -0
  21. package/dist/handlers/currentConditionsHandler.js.map +1 -0
  22. package/dist/handlers/forecastHandler.d.ts +13 -0
  23. package/dist/handlers/forecastHandler.d.ts.map +1 -0
  24. package/dist/handlers/forecastHandler.js +226 -0
  25. package/dist/handlers/forecastHandler.js.map +1 -0
  26. package/dist/handlers/historicalWeatherHandler.d.ts +12 -0
  27. package/dist/handlers/historicalWeatherHandler.d.ts.map +1 -0
  28. package/dist/handlers/historicalWeatherHandler.js +188 -0
  29. package/dist/handlers/historicalWeatherHandler.js.map +1 -0
  30. package/dist/handlers/locationHandler.d.ts +11 -0
  31. package/dist/handlers/locationHandler.d.ts.map +1 -0
  32. package/dist/handlers/locationHandler.js +113 -0
  33. package/dist/handlers/locationHandler.js.map +1 -0
  34. package/dist/handlers/statusHandler.d.ts +12 -0
  35. package/dist/handlers/statusHandler.d.ts.map +1 -0
  36. package/dist/handlers/statusHandler.js +106 -0
  37. package/dist/handlers/statusHandler.js.map +1 -0
  38. package/dist/index.js +149 -343
  39. package/dist/index.js.map +1 -1
  40. package/dist/services/noaa.d.ts +23 -1
  41. package/dist/services/noaa.d.ts.map +1 -1
  42. package/dist/services/noaa.js +154 -41
  43. package/dist/services/noaa.js.map +1 -1
  44. package/dist/services/openmeteo.d.ts +63 -3
  45. package/dist/services/openmeteo.d.ts.map +1 -1
  46. package/dist/services/openmeteo.js +284 -50
  47. package/dist/services/openmeteo.js.map +1 -1
  48. package/dist/types/noaa.d.ts +64 -12
  49. package/dist/types/noaa.d.ts.map +1 -1
  50. package/dist/types/openmeteo.d.ts +156 -0
  51. package/dist/types/openmeteo.d.ts.map +1 -1
  52. package/dist/utils/cache.d.ts +69 -0
  53. package/dist/utils/cache.d.ts.map +1 -0
  54. package/dist/utils/cache.js +164 -0
  55. package/dist/utils/cache.js.map +1 -0
  56. package/dist/utils/logger.d.ts +59 -0
  57. package/dist/utils/logger.d.ts.map +1 -0
  58. package/dist/utils/logger.js +128 -0
  59. package/dist/utils/logger.js.map +1 -0
  60. package/dist/utils/temperatureConversion.d.ts +12 -0
  61. package/dist/utils/temperatureConversion.d.ts.map +1 -0
  62. package/dist/utils/temperatureConversion.js +17 -0
  63. package/dist/utils/temperatureConversion.js.map +1 -0
  64. package/dist/utils/validation.d.ts +89 -0
  65. package/dist/utils/validation.d.ts.map +1 -0
  66. package/dist/utils/validation.js +177 -0
  67. package/dist/utils/validation.js.map +1 -0
  68. package/package.json +10 -3
package/README.md CHANGED
@@ -4,21 +4,86 @@
4
4
  [![MCP Registry](https://img.shields.io/badge/MCP-Registry-blue)](https://registry.modelcontextprotocol.io/v0/servers?search=io.github.dgahagan/weather-mcp)
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
6
 
7
- An MCP (Model Context Protocol) server that provides weather data to AI systems like Claude Code. Uses NOAA's API for US weather forecasts and current conditions, plus Open-Meteo for global historical weather data.
7
+ An MCP (Model Context Protocol) server that provides **global weather data** to AI systems like Claude Code. Uses NOAA's API for detailed US weather, plus Open-Meteo for international forecasts and historical weather data worldwide.
8
8
 
9
9
  **📦 Available in the [Official MCP Registry](https://registry.modelcontextprotocol.io/v0/servers?search=io.github.dgahagan/weather-mcp)** as `io.github.dgahagan/weather-mcp`
10
10
 
11
- **No API keys required!** Both NOAA and Open-Meteo APIs are free to use with no authentication needed.
11
+ **No API keys required!** All APIs (NOAA, Open-Meteo) are free to use with no authentication needed.
12
12
 
13
13
  ## Features
14
14
 
15
- - **Get Forecast**: Retrieve weather forecasts for any US location (7-day forecast)
16
- - **Current Conditions**: Get real-time weather observations for US locations
15
+ - **Location Search**: Find coordinates for any location worldwide (NEW in v0.4.0)
16
+ - Convert location names to coordinates ("Paris" 48.8534°, 2.3488°)
17
+ - Support for cities, airports, landmarks, and regions globally
18
+ - Detailed metadata: timezone, elevation, population, country
19
+ - Enables natural language queries: "What's the weather in Tokyo?"
20
+ - **Global Weather Forecasts**: Get forecasts for any location worldwide (ENHANCED in v0.4.0)
21
+ - Automatic source selection: NOAA (US, more detailed) or Open-Meteo (international)
22
+ - Extended forecasts up to 16 days (was 7)
23
+ - Sunrise/sunset times with daylight duration
24
+ - Daily or hourly granularity
25
+ - Precipitation probability display
26
+ - Temperature trends, humidity, wind, and UV index
27
+ - **Weather Alerts**: Get active weather watches, warnings, and advisories for US locations
28
+ - Severity levels (Extreme, Severe, Moderate, Minor)
29
+ - Urgency and certainty indicators
30
+ - Effective and expiration times
31
+ - Instructions and recommended responses
32
+ - **Current Conditions**: Get enhanced real-time weather observations for US locations
33
+ - Heat index and wind chill when relevant
34
+ - 24-hour temperature range
35
+ - Wind gusts and detailed cloud cover
36
+ - Recent precipitation history
17
37
  - **Historical Data**: Access historical weather observations for any location worldwide
18
38
  - Recent data (last 7 days): Detailed hourly observations from NOAA real-time API (US only)
19
39
  - Archival data (>7 days old): Hourly/daily weather data from 1940-present via Open-Meteo (global coverage)
20
40
  - **Service Status Checking**: Proactively verify API availability with health checks
21
41
  - **Enhanced Error Handling**: Detailed, actionable error messages with status page links
42
+ - **Intelligent Caching**: Built-in in-memory cache reduces API calls and improves performance
43
+
44
+ ## Caching
45
+
46
+ The Weather MCP server includes an intelligent in-memory caching system that significantly improves performance for AI-driven weather queries.
47
+
48
+ ### Benefits
49
+
50
+ - **Faster Responses**: Cached queries return in <10ms vs 200-1000ms for API calls
51
+ - **Reduced API Load**: 50-80% fewer API calls for typical AI conversation patterns
52
+ - **Rate Limit Protection**: Prevents hitting API rate limits during heavy usage
53
+ - **Automatic Management**: Smart TTL-based expiration with LRU eviction
54
+
55
+ ### How It Works
56
+
57
+ The cache automatically stores and retrieves weather data with intelligent expiration:
58
+
59
+ - **Location Searches**: Cached for 30 days (locations don't move) - NEW in v0.4.0
60
+ - **Weather Alerts**: Cached for 5 minutes (alerts can change rapidly)
61
+ - **Forecasts**: Cached for 2 hours (updated approximately hourly)
62
+ - **Current Conditions**: Cached for 15 minutes (observations update every 20-60 minutes)
63
+ - **Historical Data (>1 day old)**: Cached indefinitely (finalized data never changes)
64
+ - **Recent Historical (<1 day)**: Cached for 1 hour (may still be updated)
65
+ - **Grid Coordinates**: Cached indefinitely (geographic mappings are static)
66
+
67
+ ### Configuration
68
+
69
+ Caching is **enabled by default** with sensible settings. To customize:
70
+
71
+ ```bash
72
+ # Disable caching (not recommended)
73
+ export CACHE_ENABLED=false
74
+
75
+ # Adjust maximum cache size (default: 1000 entries)
76
+ export CACHE_MAX_SIZE=1500
77
+ ```
78
+
79
+ ### Monitoring
80
+
81
+ Use the `check_service_status` tool to view cache statistics including:
82
+ - Hit rate percentage
83
+ - Cache size and utilization
84
+ - API call reduction metrics
85
+
86
+ For detailed information about caching architecture and configuration, see [.github/CACHING.md](./.github/CACHING.md).
22
87
 
23
88
  ## Installation
24
89
 
@@ -107,59 +172,109 @@ Restart Claude Code and the weather tools will be available.
107
172
 
108
173
  ## Finding Coordinates
109
174
 
110
- All tools require latitude and longitude coordinates. You can find coordinates for any location by:
111
- - Asking Claude Code: "What are the coordinates for [city name]?"
175
+ **NEW in v0.4.0**: Use the built-in `search_location` tool to find coordinates automatically!
176
+
177
+ ```
178
+ "What's the weather in Paris?"
179
+ → Uses search_location to find Paris coordinates (48.8534°, 2.3488°)
180
+ → Then gets the forecast for those coordinates
181
+ ```
182
+
183
+ You can also find coordinates manually:
112
184
  - Using Google Maps: Right-click a location and select the coordinates
113
185
  - Using a geocoding service like geocode.maps.co or nominatim.org
114
186
 
115
- ### Common US City Coordinates
187
+ ### Common City Coordinates (For Reference)
116
188
 
117
189
  | City | Latitude | Longitude |
118
190
  |------|----------|-----------|
119
- | San Francisco, CA | 37.7749 | -122.4194 |
191
+ | Paris, France | 48.8534 | 2.3488 |
192
+ | Tokyo, Japan | 35.6895 | 139.6917 |
193
+ | London, UK | 51.5085 | -0.1257 |
120
194
  | New York, NY | 40.7128 | -74.0060 |
121
- | Chicago, IL | 41.8781 | -87.6298 |
122
- | Los Angeles, CA | 34.0522 | -118.2437 |
123
- | Denver, CO | 39.7392 | -104.9903 |
124
- | Miami, FL | 25.7617 | -80.1918 |
125
- | Seattle, WA | 47.6062 | -122.3321 |
126
- | Austin, TX | 30.2672 | -97.7431 |
195
+ | San Francisco, CA | 37.7749 | -122.4194 |
196
+ | Sydney, Australia | -33.8688 | 151.2093 |
197
+ | Berlin, Germany | 52.5200 | 13.4050 |
198
+ | Dubai, UAE | 25.2048 | 55.2708 |
127
199
 
128
200
  ## Available Tools
129
201
 
130
- ### 1. check_service_status
131
- Check the operational status of weather APIs.
202
+ ### 1. search_location (NEW in v0.4.0)
203
+ Find coordinates for any location worldwide by name.
132
204
 
133
- **Parameters:** None
205
+ **Parameters:**
206
+ - `query` (required): Location name to search for (e.g., "Paris", "New York, NY", "Tokyo")
207
+ - `limit` (optional): Maximum number of results to return (1-100, default: 5)
134
208
 
135
209
  **Description:**
136
- Performs health checks on both NOAA and Open-Meteo APIs to verify they are operational. Use this tool when experiencing errors or to proactively verify service availability before making weather data requests. Returns current status, helpful messages, and links to official status pages.
210
+ Converts location names to coordinates using the Open-Meteo Geocoding API. Returns multiple matches with detailed metadata including coordinates, timezone, elevation, population, and administrative regions. Enables natural language weather queries by finding coordinates automatically.
137
211
 
138
- **Example:**
212
+ **Examples:**
139
213
  ```
140
- Check if the weather services are operational
214
+ "Find coordinates for Paris"
215
+ "Search for Tokyo, Japan"
216
+ "Where is San Francisco, CA?"
141
217
  ```
142
218
 
143
219
  **Returns:**
144
- - Operational status for NOAA API (forecasts & current conditions)
145
- - Operational status for Open-Meteo API (historical data)
146
- - Status page links and recommended actions if issues are detected
147
- - Overall service availability summary
220
+ - Location name and full administrative hierarchy
221
+ - Latitude and longitude coordinates
222
+ - Timezone and elevation
223
+ - Population (when available)
224
+ - Country and region information
225
+ - Feature type (capital, city, airport, etc.)
148
226
 
149
- ### 2. get_forecast
150
- Get weather forecast for a location.
227
+ ### 2. get_forecast (ENHANCED in v0.4.0)
228
+ Get weather forecast for any location worldwide.
151
229
 
152
230
  **Parameters:**
153
231
  - `latitude` (required): Latitude coordinate (-90 to 90)
154
232
  - `longitude` (required): Longitude coordinate (-180 to 180)
155
- - `days` (optional): Number of days in forecast (1-7, default: 7)
233
+ - `days` (optional): Number of days in forecast (1-16, default: 7)
234
+ - `granularity` (optional): "daily" or "hourly" (default: "daily")
235
+ - `include_precipitation_probability` (optional): Include rain chances (default: true)
236
+ - `source` (optional): "auto" (default), "noaa" (US only), or "openmeteo" (global)
237
+
238
+ **Description:**
239
+ Automatically selects the best data source: NOAA for US locations (more detailed) or Open-Meteo for international locations. Supports extended forecasts up to 16 days. Includes sunrise/sunset times, daylight duration, temperature, precipitation, wind, and UV index.
240
+
241
+ **Examples:**
242
+ ```
243
+ "Get a 7-day forecast for Paris (48.8534, 2.3488)"
244
+ "Hourly forecast for Tokyo for the next 3 days"
245
+ "16-day extended forecast for Sydney, Australia"
246
+ ```
247
+
248
+ **Returns:**
249
+ - Temperature (high/low, feels like)
250
+ - Sunrise and sunset times with daylight duration (NEW in v0.4.0)
251
+ - Precipitation chances and amounts
252
+ - Wind speed, direction, and gusts
253
+ - Weather conditions and descriptions
254
+ - UV index (for international locations)
255
+ - Humidity and atmospheric conditions
256
+
257
+ ### 3. check_service_status
258
+ Check the operational status of weather APIs and cache performance.
259
+
260
+ **Parameters:** None
261
+
262
+ **Description:**
263
+ Performs health checks on both NOAA and Open-Meteo APIs to verify they are operational. Use this tool when experiencing errors or to proactively verify service availability before making weather data requests. Returns current status, helpful messages, links to official status pages, and cache statistics.
156
264
 
157
265
  **Example:**
158
266
  ```
159
- Get the weather forecast for San Francisco (latitude: 37.7749, longitude: -122.4194)
267
+ Check if the weather services are operational
160
268
  ```
161
269
 
162
- ### 3. get_current_conditions
270
+ **Returns:**
271
+ - Operational status for NOAA API (forecasts & current conditions)
272
+ - Operational status for Open-Meteo API (historical data & forecasts)
273
+ - Cache statistics (hit rate, size, API call reduction)
274
+ - Status page links and recommended actions if issues are detected
275
+ - Overall service availability summary
276
+
277
+ ### 4. get_current_conditions
163
278
  Get current weather conditions for a location.
164
279
 
165
280
  **Parameters:**
@@ -171,7 +286,7 @@ Get current weather conditions for a location.
171
286
  What are the current weather conditions in New York? (latitude: 40.7128, longitude: -74.0060)
172
287
  ```
173
288
 
174
- ### 4. get_historical_weather
289
+ ### 5. get_historical_weather
175
290
  Get historical weather observations for a location.
176
291
 
177
292
  **Parameters:**
@@ -302,19 +417,45 @@ Use the `check_service_status` tool to proactively verify API availability:
302
417
 
303
418
  ## Testing
304
419
 
305
- ### Quick Test
420
+ ### Automated Test Suite
421
+
422
+ This project includes a comprehensive test suite with 247 automated tests:
306
423
 
307
- Verify NOAA API connectivity:
308
424
  ```bash
309
- npx tsx tests/test_noaa_api.ts
425
+ # Run all tests
426
+ npm test
427
+
428
+ # Run tests with coverage report
429
+ npm run test:coverage
430
+
431
+ # Run tests in watch mode (during development)
432
+ npm run test:watch
433
+
434
+ # Run tests with interactive UI
435
+ npm run test:ui
310
436
  ```
311
437
 
312
- This runs 5 tests covering all major functionality with real NOAA API calls.
438
+ **Test Coverage:**
439
+ - **247 tests** across unit and integration test suites
440
+ - **100% coverage** on critical utilities (cache, validation, units, errors)
441
+ - **54% overall coverage** with focus on reliability and security
442
+ - All tests execute in ~1 second
443
+
444
+ **Test Categories:**
445
+ - **Unit Tests** (228 tests) - Cache, validation, units, errors, config, retry logic
446
+ - **Integration Tests** (19 tests) - Error recovery scenarios, service status checks
447
+
448
+ ### Quick API Connectivity Test
449
+
450
+ Verify NOAA API connectivity with a quick integration test:
451
+ ```bash
452
+ npx tsx tests/test_noaa_api.ts
453
+ ```
313
454
 
314
455
  ### Manual Testing with Claude Code
315
456
 
316
- See [TESTING_GUIDE.md](./docs/TESTING_GUIDE.md) for comprehensive testing instructions including:
317
- - Setup steps
457
+ See [TESTING_GUIDE.md](./docs/TESTING_GUIDE.md) for comprehensive manual testing instructions including:
458
+ - Setup steps for MCP clients
318
459
  - Test cases for all tools
319
460
  - Error handling verification
320
461
  - Performance testing
@@ -324,43 +465,89 @@ See [TESTING_GUIDE.md](./docs/TESTING_GUIDE.md) for comprehensive testing instru
324
465
 
325
466
  ### Available Scripts
326
467
 
468
+ **Build & Run:**
327
469
  - `npm run build` - Compile TypeScript to JavaScript
328
470
  - `npm run dev` - Run the server in development mode with tsx
329
471
  - `npm start` - Run the compiled server
330
- - `npx tsx tests/test_noaa_api.ts` - Run API connectivity tests
472
+
473
+ **Testing:**
474
+ - `npm test` - Run all automated tests
475
+ - `npm run test:coverage` - Run tests with coverage report
476
+ - `npm run test:watch` - Run tests in watch mode
477
+ - `npm run test:ui` - Run tests with interactive UI
478
+ - `npx tsx tests/test_noaa_api.ts` - Quick API connectivity test
479
+
480
+ **Security & Maintenance:**
481
+ - `npm run audit` - Check for dependency vulnerabilities
482
+ - `npm run audit:fix` - Automatically fix dependency vulnerabilities
331
483
 
332
484
  ### Project Structure
333
485
 
334
486
  ```
335
487
  weather-mcp/
336
488
  ├── src/
337
- │ ├── index.ts # Main MCP server
489
+ │ ├── index.ts # Main MCP server
490
+ │ ├── config/
491
+ │ │ ├── cache.ts # Cache configuration and TTL strategies
492
+ │ │ └── displayThresholds.ts # Display thresholds for weather conditions
493
+ │ ├── errors/
494
+ │ │ └── ApiError.ts # Custom error class hierarchy
495
+ │ ├── handlers/
496
+ │ │ ├── alertsHandler.ts # Weather alerts tool handler
497
+ │ │ ├── currentConditionsHandler.ts # Current conditions handler
498
+ │ │ ├── forecastHandler.ts # Forecast tool handler
499
+ │ │ ├── historicalWeatherHandler.ts # Historical weather handler
500
+ │ │ └── statusHandler.ts # Service status handler
338
501
  │ ├── services/
339
- │ │ ├── noaa.ts # NOAA real-time API service
340
- │ │ └── openmeteo.ts # Open-Meteo historical weather API service
502
+ │ │ ├── noaa.ts # NOAA API service
503
+ │ │ └── openmeteo.ts # Open-Meteo API service
341
504
  │ ├── types/
342
- │ │ ├── noaa.ts # NOAA TypeScript type definitions
343
- │ │ └── openmeteo.ts # Open-Meteo TypeScript type definitions
505
+ │ │ ├── noaa.ts # NOAA TypeScript type definitions
506
+ │ │ └── openmeteo.ts # Open-Meteo TypeScript type definitions
344
507
  │ └── utils/
345
- └── units.ts # Unit conversion utilities
346
- ├── dist/ # Compiled JavaScript (generated)
347
- ├── tests/ # Test files
508
+ ├── cache.ts # LRU cache implementation
509
+ ├── logger.ts # Structured logging utilities
510
+ ├── temperatureConversion.ts # Temperature conversion helpers
511
+ │ ├── units.ts # Unit conversion utilities
512
+ │ └── validation.ts # Input validation functions
513
+ ├── tests/
514
+ │ ├── unit/ # Unit tests (228 tests)
515
+ │ └── integration/ # Integration tests (19 tests)
516
+ ├── dist/ # Compiled JavaScript (generated)
517
+ ├── docs/ # Documentation
348
518
  └── package.json
349
519
  ```
350
520
 
351
521
  ## API Information
352
522
 
353
- This server uses two weather APIs:
523
+ This server uses three weather APIs:
354
524
 
355
- ### NOAA Weather API (Real-time)
525
+ ### NOAA Weather API (Real-time, US)
356
526
  - **Base URL**: https://api.weather.gov
357
527
  - **Authentication**: None required (User-Agent header only)
358
528
  - **Rate Limits**: Enforced with 5-second retry window
359
529
  - **Coverage**: United States locations only
360
- - **Use cases**: Forecasts, current conditions, recent observations (last 7 days)
530
+ - **Use cases**: US forecasts (detailed), current conditions, recent observations (last 7 days)
361
531
  - **Data**: Detailed hourly observations from weather stations
362
532
 
363
- ### Open-Meteo Historical Weather API (Archival)
533
+ ### Open-Meteo Forecast API (Global) - NEW in v0.4.0
534
+ - **Base URL**: https://api.open-meteo.com/v1
535
+ - **Authentication**: None required (no API token needed)
536
+ - **Rate Limits**: 10,000 requests/day for non-commercial use
537
+ - **Coverage**: Global (worldwide locations)
538
+ - **Use cases**: International forecasts, extended forecasts (up to 16 days)
539
+ - **Data**: Temperature, precipitation, wind, humidity, UV index, sunrise/sunset
540
+ - **Resolution**: 11km global grid resolution
541
+
542
+ ### Open-Meteo Geocoding API (Global) - NEW in v0.4.0
543
+ - **Base URL**: https://geocoding-api.open-meteo.com/v1
544
+ - **Authentication**: None required (no API token needed)
545
+ - **Coverage**: Global (worldwide locations)
546
+ - **Use cases**: Location name to coordinates conversion
547
+ - **Data**: Coordinates, timezone, elevation, population, administrative regions
548
+ - **Cache**: 30-day TTL (locations don't move)
549
+
550
+ ### Open-Meteo Historical Weather API (Global, Archival)
364
551
  - **Base URL**: https://archive-api.open-meteo.com/v1
365
552
  - **Authentication**: None required (no API token needed)
366
553
  - **Rate Limits**: 10,000 requests/day for non-commercial use
@@ -376,9 +563,15 @@ For more details on NOAA APIs, see [NOAA_API_RESEARCH.md](./docs/NOAA_API_RESEAR
376
563
 
377
564
  ### Geographic Coverage
378
565
 
379
- **Forecasts and Current Conditions:**
380
- - NOAA APIs only cover **United States locations**
381
- - International locations are not supported for forecasts and current conditions
566
+ **Forecasts:** (UPDATED in v0.4.0)
567
+ - **Global coverage** via automatic source selection
568
+ - US locations: Uses NOAA API (more detailed, includes narratives)
569
+ - International locations: Uses Open-Meteo API (reliable global forecasts)
570
+ - Extended forecasts (>7 days, up to 16 days): Open-Meteo only
571
+
572
+ **Current Conditions:**
573
+ - **US locations only** (NOAA API)
574
+ - International real-time conditions not yet supported
382
575
 
383
576
  **Historical Data:**
384
577
  - Recent data (last 7 days): **US locations only** (NOAA API)
@@ -411,6 +604,51 @@ For more details on NOAA APIs, see [NOAA_API_RESEARCH.md](./docs/NOAA_API_RESEAR
411
604
  - **For historical analysis**: Open-Meteo provides reliable global coverage back to 1940
412
605
  - **For international locations**: Only historical data (>7 days old) is supported
413
606
 
607
+ ## Security
608
+
609
+ This project takes security seriously and implements multiple layers of protection:
610
+
611
+ ### Security Features
612
+
613
+ **Input Validation:**
614
+ - Comprehensive runtime validation for all user inputs
615
+ - NaN and Infinity checks for numeric coordinates
616
+ - Range validation for latitude (-90 to 90) and longitude (-180 to 180)
617
+ - Type checking with TypeScript strict mode
618
+
619
+ **Error Handling:**
620
+ - Custom error class hierarchy with typed errors
621
+ - Error message sanitization to prevent information leakage
622
+ - Retryable errors clearly identified for graceful recovery
623
+ - Network errors sanitized before display
624
+
625
+ **Dependency Security:**
626
+ - Automated dependency scanning via `npm audit`
627
+ - GitHub Dependabot configured for weekly security updates
628
+ - Minimal dependency footprint (3 runtime dependencies)
629
+ - Zero known vulnerabilities in current dependencies
630
+
631
+ **Reliability:**
632
+ - Exponential backoff with jitter prevents thundering herd problems
633
+ - Comprehensive test suite (247 tests) with 100% coverage on critical utilities
634
+ - Memory-safe cache with automatic cleanup
635
+ - Graceful shutdown handling
636
+
637
+ ### Security Audit
638
+
639
+ The project has undergone a comprehensive security audit:
640
+ - **Overall Security Posture:** B+ (Good)
641
+ - **Risk Level:** LOW
642
+ - **Vulnerabilities:** Zero critical or high-severity issues
643
+ - See [SECURITY_AUDIT.md](./docs/development/SECURITY_AUDIT.md) for full audit report
644
+
645
+ ### Reporting Security Issues
646
+
647
+ To report a security vulnerability, please see our [Security Policy](./SECURITY.md) which includes:
648
+ - Vulnerability reporting procedures
649
+ - Response timeline commitments (48hr acknowledgment, 7-day assessment)
650
+ - Security best practices for users and developers
651
+
414
652
  ## License
415
653
 
416
654
  MIT
@@ -418,3 +656,8 @@ MIT
418
656
  ## Contributing
419
657
 
420
658
  Contributions are welcome! Please feel free to submit a Pull Request.
659
+
660
+ For information about code quality, security considerations, and development best practices, see:
661
+ - [CODE_REVIEW.md](./docs/development/CODE_REVIEW.md) - Comprehensive code quality analysis
662
+ - [CONTRIBUTING.md](./CONTRIBUTING.md) - Contribution guidelines
663
+ - [SECURITY.md](./SECURITY.md) - Security policy and vulnerability reporting
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Cache configuration for weather data
3
+ *
4
+ * TTL (Time To Live) values are set based on data volatility:
5
+ * - Historical data: Never changes once recorded
6
+ * - Geographic data: Static (grid coordinates, station locations)
7
+ * - Forecasts: Updated approximately hourly
8
+ * - Current conditions: Observations typically update every 20-60 minutes
9
+ */
10
+ export declare const CacheConfig: {
11
+ readonly enabled: boolean;
12
+ readonly maxSize: number;
13
+ readonly ttl: {
14
+ readonly gridCoordinates: number;
15
+ readonly stations: number;
16
+ readonly forecast: number;
17
+ readonly currentConditions: number;
18
+ readonly alerts: number;
19
+ readonly recentHistorical: number;
20
+ readonly historicalData: number;
21
+ readonly serviceStatus: number;
22
+ };
23
+ };
24
+ /**
25
+ * Determine appropriate TTL for historical weather data based on date
26
+ * @param startDate Start date of the historical query
27
+ * @returns TTL in milliseconds
28
+ */
29
+ export declare function getHistoricalDataTTL(startDate: string | Date): number;
30
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/config/cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAkDH,eAAO,MAAM,WAAW;;;;;;;;;;;;;CA0Cd,CAAC;AAEX;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAYrE"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Cache configuration for weather data
3
+ *
4
+ * TTL (Time To Live) values are set based on data volatility:
5
+ * - Historical data: Never changes once recorded
6
+ * - Geographic data: Static (grid coordinates, station locations)
7
+ * - Forecasts: Updated approximately hourly
8
+ * - Current conditions: Observations typically update every 20-60 minutes
9
+ */
10
+ // Time constants in milliseconds
11
+ const MINUTE = 60 * 1000;
12
+ const HOUR = 60 * MINUTE;
13
+ const DAY = 24 * HOUR;
14
+ /**
15
+ * Parse a boolean environment variable
16
+ * @param key Environment variable key
17
+ * @param defaultValue Default value if not set
18
+ * @returns Boolean value
19
+ */
20
+ function getEnvBoolean(key, defaultValue) {
21
+ const value = process.env[key];
22
+ if (value === undefined)
23
+ return defaultValue;
24
+ return value !== 'false' && value !== '0';
25
+ }
26
+ /**
27
+ * Parse a number environment variable with validation
28
+ * @param key Environment variable key
29
+ * @param defaultValue Default value if not set or invalid
30
+ * @param min Minimum allowed value (optional)
31
+ * @param max Maximum allowed value (optional)
32
+ * @returns Validated number value
33
+ */
34
+ function getEnvNumber(key, defaultValue, min, max) {
35
+ const value = process.env[key];
36
+ if (value === undefined)
37
+ return defaultValue;
38
+ const parsed = parseInt(value, 10);
39
+ if (isNaN(parsed)) {
40
+ console.warn(`Invalid ${key}: "${value}". Using default: ${defaultValue}`);
41
+ return defaultValue;
42
+ }
43
+ if (min !== undefined && parsed < min) {
44
+ console.warn(`${key} too low: ${parsed}. Using minimum: ${min}`);
45
+ return min;
46
+ }
47
+ if (max !== undefined && parsed > max) {
48
+ console.warn(`${key} too high: ${parsed}. Using maximum: ${max}`);
49
+ return max;
50
+ }
51
+ return parsed;
52
+ }
53
+ export const CacheConfig = {
54
+ // Enable/disable caching globally
55
+ enabled: getEnvBoolean('CACHE_ENABLED', true),
56
+ // Maximum number of entries in cache before LRU eviction
57
+ // Min: 100, Max: 10000, Default: 1000
58
+ maxSize: getEnvNumber('CACHE_MAX_SIZE', 1000, 100, 10000),
59
+ // TTL values for different data types
60
+ ttl: {
61
+ // Grid coordinate lookups (lat/lon -> grid mapping)
62
+ // These are geographic and never change
63
+ gridCoordinates: Infinity,
64
+ // Weather station lists
65
+ // Stations rarely change
66
+ stations: 24 * HOUR,
67
+ // 7-day forecasts
68
+ // NOAA updates forecasts approximately hourly
69
+ forecast: 2 * HOUR,
70
+ // Current weather conditions
71
+ // Observations typically update every 20-60 minutes
72
+ currentConditions: 15 * MINUTE,
73
+ // Weather alerts
74
+ // Alerts can change rapidly, cache for shorter period
75
+ alerts: 5 * MINUTE,
76
+ // Recent historical data (< 7 days old)
77
+ // Recent data may still be updated/corrected
78
+ recentHistorical: 1 * HOUR,
79
+ // Historical data (> 1 day old from current time)
80
+ // Historical data beyond 1 day is finalized and won't change
81
+ historicalData: Infinity,
82
+ // Service health check status
83
+ // Check freshness periodically
84
+ serviceStatus: 5 * MINUTE,
85
+ },
86
+ };
87
+ /**
88
+ * Determine appropriate TTL for historical weather data based on date
89
+ * @param startDate Start date of the historical query
90
+ * @returns TTL in milliseconds
91
+ */
92
+ export function getHistoricalDataTTL(startDate) {
93
+ const start = typeof startDate === 'string' ? new Date(startDate) : startDate;
94
+ const now = new Date();
95
+ const daysDiff = (now.getTime() - start.getTime()) / DAY;
96
+ if (daysDiff > 1) {
97
+ // Data is more than 1 day old - it's finalized and won't change
98
+ return CacheConfig.ttl.historicalData;
99
+ }
100
+ else {
101
+ // Recent data may still be updated
102
+ return CacheConfig.ttl.recentHistorical;
103
+ }
104
+ }
105
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/config/cache.ts"],"names":[],"mappings":"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"}