@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
@@ -0,0 +1,188 @@
1
+ /**
2
+ * Handler for get_historical_weather tool
3
+ */
4
+ import { validateHistoricalWeatherParams } from '../utils/validation.js';
5
+ import { convertToFahrenheit } from '../utils/temperatureConversion.js';
6
+ import { ApiConstants, FormatConstants } from '../config/displayThresholds.js';
7
+ export async function handleGetHistoricalWeather(args, noaaService, openMeteoService) {
8
+ // Validate input parameters with runtime checks
9
+ const { latitude, longitude, start_date, end_date, limit = FormatConstants.defaultHistoricalLimit } = validateHistoricalWeatherParams(args);
10
+ // Parse dates
11
+ const startTime = new Date(start_date);
12
+ const endTime = new Date(end_date);
13
+ // Validate dates are not in the future
14
+ const now = new Date();
15
+ if (startTime > now) {
16
+ throw new Error(`Start date (${start_date}) cannot be in the future. Current date is ${now.toISOString().split('T')[0]}.`);
17
+ }
18
+ if (endTime > now) {
19
+ throw new Error(`End date (${end_date}) cannot be in the future. Current date is ${now.toISOString().split('T')[0]}.`);
20
+ }
21
+ // Determine which API to use based on date range
22
+ // If start date is older than threshold, use archival API
23
+ const thresholdDate = new Date(now.getTime() - ApiConstants.historicalDataThresholdDays * 24 * 60 * 60 * 1000);
24
+ const useArchivalData = startTime < thresholdDate;
25
+ if (useArchivalData) {
26
+ // Use Open-Meteo API for historical/archival data
27
+ try {
28
+ // Determine whether to use hourly or daily data based on date range
29
+ const daysDiff = Math.ceil((endTime.getTime() - startTime.getTime()) / (1000 * 60 * 60 * 24));
30
+ const useHourly = daysDiff <= ApiConstants.maxHourlyHistoricalDays;
31
+ const weatherData = await openMeteoService.getHistoricalWeather(latitude, longitude, start_date.split('T')[0], // Ensure YYYY-MM-DD format
32
+ end_date.split('T')[0], useHourly);
33
+ // Format the response based on data granularity
34
+ if (useHourly && weatherData.hourly) {
35
+ // Format hourly observations
36
+ let output = `# Historical Weather Observations (Hourly)\n\n`;
37
+ output += `**Period:** ${startTime.toLocaleDateString()} to ${endTime.toLocaleDateString()}\n`;
38
+ output += `**Location:** ${weatherData.latitude.toFixed(4)}°N, ${Math.abs(weatherData.longitude).toFixed(4)}°${weatherData.longitude >= 0 ? 'E' : 'W'} (${weatherData.elevation}m elevation)\n`;
39
+ output += `**Number of observations:** ${weatherData.hourly.time.length}\n`;
40
+ output += `**Data source:** Open-Meteo Historical Weather API (Reanalysis)\n\n`;
41
+ const maxObservations = Math.min(limit, weatherData.hourly.time.length);
42
+ for (let i = 0; i < maxObservations; i++) {
43
+ const time = new Date(weatherData.hourly.time[i]);
44
+ output += `## ${time.toLocaleString()}\n`;
45
+ if (weatherData.hourly.temperature_2m?.[i] !== null && weatherData.hourly.temperature_2m?.[i] !== undefined) {
46
+ output += `- **Temperature:** ${Math.round(weatherData.hourly.temperature_2m[i])}°F\n`;
47
+ }
48
+ if (weatherData.hourly.apparent_temperature?.[i] !== null && weatherData.hourly.apparent_temperature?.[i] !== undefined) {
49
+ output += `- **Feels Like:** ${Math.round(weatherData.hourly.apparent_temperature[i])}°F\n`;
50
+ }
51
+ if (weatherData.hourly.weather_code?.[i] !== null && weatherData.hourly.weather_code?.[i] !== undefined) {
52
+ output += `- **Conditions:** ${openMeteoService.getWeatherDescription(weatherData.hourly.weather_code[i])}\n`;
53
+ }
54
+ if (weatherData.hourly.precipitation?.[i] !== null && weatherData.hourly.precipitation?.[i] !== undefined && weatherData.hourly.precipitation[i] > 0) {
55
+ output += `- **Precipitation:** ${weatherData.hourly.precipitation[i].toFixed(2)} in\n`;
56
+ }
57
+ if (weatherData.hourly.snowfall?.[i] !== null && weatherData.hourly.snowfall?.[i] !== undefined && weatherData.hourly.snowfall[i] > 0) {
58
+ output += `- **Snowfall:** ${weatherData.hourly.snowfall[i].toFixed(1)} in\n`;
59
+ }
60
+ if (weatherData.hourly.wind_speed_10m?.[i] !== null && weatherData.hourly.wind_speed_10m?.[i] !== undefined) {
61
+ output += `- **Wind:** ${Math.round(weatherData.hourly.wind_speed_10m[i])} mph`;
62
+ if (weatherData.hourly.wind_direction_10m?.[i] !== null && weatherData.hourly.wind_direction_10m?.[i] !== undefined) {
63
+ output += ` from ${Math.round(weatherData.hourly.wind_direction_10m[i])}°`;
64
+ }
65
+ output += `\n`;
66
+ }
67
+ if (weatherData.hourly.relative_humidity_2m?.[i] !== null && weatherData.hourly.relative_humidity_2m?.[i] !== undefined) {
68
+ output += `- **Humidity:** ${Math.round(weatherData.hourly.relative_humidity_2m[i])}%\n`;
69
+ }
70
+ if (weatherData.hourly.pressure_msl?.[i] !== null && weatherData.hourly.pressure_msl?.[i] !== undefined) {
71
+ const pressureInHg = weatherData.hourly.pressure_msl[i] * 0.02953;
72
+ output += `- **Pressure:** ${pressureInHg.toFixed(2)} inHg\n`;
73
+ }
74
+ if (weatherData.hourly.cloud_cover?.[i] !== null && weatherData.hourly.cloud_cover?.[i] !== undefined) {
75
+ output += `- **Cloud Cover:** ${weatherData.hourly.cloud_cover[i]}%\n`;
76
+ }
77
+ output += `\n`;
78
+ }
79
+ return {
80
+ content: [
81
+ {
82
+ type: 'text',
83
+ text: output
84
+ }
85
+ ]
86
+ };
87
+ }
88
+ else if (weatherData.daily) {
89
+ // Format daily summaries
90
+ let output = `# Historical Weather Data (Daily Summaries)\n\n`;
91
+ output += `**Period:** ${startTime.toLocaleDateString()} to ${endTime.toLocaleDateString()}\n`;
92
+ output += `**Location:** ${weatherData.latitude.toFixed(4)}°N, ${Math.abs(weatherData.longitude).toFixed(4)}°${weatherData.longitude >= 0 ? 'E' : 'W'} (${weatherData.elevation}m elevation)\n`;
93
+ output += `**Number of days:** ${weatherData.daily.time.length}\n`;
94
+ output += `**Data source:** Open-Meteo Historical Weather API (Reanalysis)\n\n`;
95
+ for (let i = 0; i < weatherData.daily.time.length; i++) {
96
+ const date = new Date(weatherData.daily.time[i]);
97
+ output += `## ${date.toLocaleDateString()}\n`;
98
+ if (weatherData.daily.temperature_2m_max?.[i] !== null && weatherData.daily.temperature_2m_max?.[i] !== undefined) {
99
+ output += `- **High Temperature:** ${Math.round(weatherData.daily.temperature_2m_max[i])}°F\n`;
100
+ }
101
+ if (weatherData.daily.temperature_2m_min?.[i] !== null && weatherData.daily.temperature_2m_min?.[i] !== undefined) {
102
+ output += `- **Low Temperature:** ${Math.round(weatherData.daily.temperature_2m_min[i])}°F\n`;
103
+ }
104
+ if (weatherData.daily.temperature_2m_mean?.[i] !== null && weatherData.daily.temperature_2m_mean?.[i] !== undefined) {
105
+ output += `- **Average Temperature:** ${Math.round(weatherData.daily.temperature_2m_mean[i])}°F\n`;
106
+ }
107
+ if (weatherData.daily.weather_code?.[i] !== null && weatherData.daily.weather_code?.[i] !== undefined) {
108
+ output += `- **Conditions:** ${openMeteoService.getWeatherDescription(weatherData.daily.weather_code[i])}\n`;
109
+ }
110
+ if (weatherData.daily.precipitation_sum?.[i] !== null && weatherData.daily.precipitation_sum?.[i] !== undefined) {
111
+ output += `- **Precipitation:** ${weatherData.daily.precipitation_sum[i].toFixed(2)} in\n`;
112
+ }
113
+ if (weatherData.daily.snowfall_sum?.[i] !== null && weatherData.daily.snowfall_sum?.[i] !== undefined && weatherData.daily.snowfall_sum[i] > 0) {
114
+ output += `- **Snowfall:** ${weatherData.daily.snowfall_sum[i].toFixed(1)} in\n`;
115
+ }
116
+ if (weatherData.daily.wind_speed_10m_max?.[i] !== null && weatherData.daily.wind_speed_10m_max?.[i] !== undefined) {
117
+ output += `- **Max Wind Speed:** ${Math.round(weatherData.daily.wind_speed_10m_max[i])} mph\n`;
118
+ }
119
+ output += `\n`;
120
+ }
121
+ return {
122
+ content: [
123
+ {
124
+ type: 'text',
125
+ text: output
126
+ }
127
+ ]
128
+ };
129
+ }
130
+ else {
131
+ throw new Error('No weather data available in response');
132
+ }
133
+ }
134
+ catch (error) {
135
+ // If Open-Meteo API fails, provide helpful error message
136
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
137
+ throw new Error(`Unable to retrieve historical data: ${errorMessage}`);
138
+ }
139
+ }
140
+ else {
141
+ // Use real-time NOAA API for recent data (last 7 days)
142
+ const observations = await noaaService.getHistoricalObservations(latitude, longitude, startTime, endTime, limit);
143
+ if (!observations.features || observations.features.length === 0) {
144
+ return {
145
+ content: [
146
+ {
147
+ type: 'text',
148
+ text: `No historical observations found for the specified date range (${start_date} to ${end_date}).\n\nThis may occur because:\n- The dates are outside the station's available data range\n- There are gaps in the observation records for this location\n- The weather station near this location may not have archived data for these dates\n\nNote: Historical weather data availability varies by location and weather station. Some stations have limited historical records.`
149
+ }
150
+ ]
151
+ };
152
+ }
153
+ // Format the observations
154
+ let output = `# Historical Weather Observations\n\n`;
155
+ output += `**Period:** ${startTime.toLocaleDateString()} to ${endTime.toLocaleDateString()}\n`;
156
+ output += `**Number of observations:** ${observations.features.length}\n`;
157
+ output += `**Data source:** NOAA Real-time API\n\n`;
158
+ for (const obs of observations.features) {
159
+ const props = obs.properties;
160
+ output += `## ${new Date(props.timestamp).toLocaleString()}\n`;
161
+ if (props.temperature.value !== null) {
162
+ const tempF = convertToFahrenheit(props.temperature.value, props.temperature.unitCode);
163
+ if (tempF !== null) {
164
+ output += `- **Temperature:** ${Math.round(tempF)}°F\n`;
165
+ }
166
+ }
167
+ if (props.textDescription) {
168
+ output += `- **Conditions:** ${props.textDescription}\n`;
169
+ }
170
+ if (props.windSpeed.value !== null) {
171
+ const windMph = props.windSpeed.unitCode.includes('km_h')
172
+ ? props.windSpeed.value * 0.621371
173
+ : props.windSpeed.value * 2.23694;
174
+ output += `- **Wind:** ${Math.round(windMph)} mph\n`;
175
+ }
176
+ output += `\n`;
177
+ }
178
+ return {
179
+ content: [
180
+ {
181
+ type: 'text',
182
+ text: output
183
+ }
184
+ ]
185
+ };
186
+ }
187
+ }
188
+ //# sourceMappingURL=historicalWeatherHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"historicalWeatherHandler.js","sourceRoot":"","sources":["../../src/handlers/historicalWeatherHandler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Handler for search_location tool
3
+ */
4
+ import { OpenMeteoService } from '../services/openmeteo.js';
5
+ export declare function handleSearchLocation(args: unknown, openMeteoService: OpenMeteoService): Promise<{
6
+ content: Array<{
7
+ type: string;
8
+ text: string;
9
+ }>;
10
+ }>;
11
+ //# sourceMappingURL=locationHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locationHandler.d.ts","sourceRoot":"","sources":["../../src/handlers/locationHandler.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAQ5D,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,OAAO,EACb,gBAAgB,EAAE,gBAAgB,GACjC,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,CA0F7D"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Handler for search_location tool
3
+ */
4
+ import { DataNotFoundError } from '../errors/ApiError.js';
5
+ export async function handleSearchLocation(args, openMeteoService) {
6
+ // Validate input parameters
7
+ const locationArgs = args;
8
+ if (!locationArgs.query || typeof locationArgs.query !== 'string') {
9
+ throw new Error('query parameter is required and must be a string');
10
+ }
11
+ const query = locationArgs.query.trim();
12
+ const limit = typeof locationArgs.limit === 'number' ?
13
+ Math.min(Math.max(1, locationArgs.limit), 100) : 5;
14
+ // Search for locations
15
+ const response = await openMeteoService.searchLocation(query, limit);
16
+ if (!response.results || response.results.length === 0) {
17
+ throw new DataNotFoundError('OpenMeteo', `No locations found matching "${query}". Try:\n` +
18
+ `- Using a different spelling\n` +
19
+ `- Being more specific (e.g., "Paris, France" instead of "Paris")\n` +
20
+ `- Using a nearby city or landmark`);
21
+ }
22
+ // Format the results for display
23
+ let output = `# Location Search Results\n\n`;
24
+ output += `**Query:** "${query}"\n`;
25
+ output += `**Found:** ${response.results.length} location${response.results.length > 1 ? 's' : ''}\n\n`;
26
+ output += `---\n\n`;
27
+ for (let i = 0; i < response.results.length; i++) {
28
+ const location = response.results[i];
29
+ output += `## ${i + 1}. ${location.name}\n\n`;
30
+ // Build location description
31
+ const parts = [location.name];
32
+ if (location.admin1)
33
+ parts.push(location.admin1);
34
+ if (location.admin2 && location.admin2 !== location.admin1)
35
+ parts.push(location.admin2);
36
+ if (location.country)
37
+ parts.push(location.country);
38
+ output += `**Full Name:** ${parts.join(', ')}\n`;
39
+ output += `**Coordinates:** ${location.latitude.toFixed(4)}°, ${location.longitude.toFixed(4)}°\n`;
40
+ if (location.country_code) {
41
+ output += `**Country Code:** ${location.country_code.toUpperCase()}\n`;
42
+ }
43
+ if (location.timezone) {
44
+ output += `**Timezone:** ${location.timezone}\n`;
45
+ }
46
+ if (location.elevation !== undefined) {
47
+ const elevationFt = Math.round(location.elevation * 3.28084);
48
+ output += `**Elevation:** ${location.elevation}m (${elevationFt}ft)\n`;
49
+ }
50
+ if (location.population !== undefined && location.population > 0) {
51
+ output += `**Population:** ${location.population.toLocaleString()}\n`;
52
+ }
53
+ if (location.feature_code) {
54
+ const featureDescription = getFeatureDescription(location.feature_code);
55
+ if (featureDescription) {
56
+ output += `**Type:** ${featureDescription}\n`;
57
+ }
58
+ }
59
+ output += `\n`;
60
+ // Add usage example
61
+ output += `*To get weather for this location, use these coordinates:*\n`;
62
+ output += `*Latitude: ${location.latitude}, Longitude: ${location.longitude}*\n\n`;
63
+ if (i < response.results.length - 1) {
64
+ output += `---\n\n`;
65
+ }
66
+ }
67
+ output += `---\n`;
68
+ output += `*Data source: Open-Meteo Geocoding API*\n`;
69
+ return {
70
+ content: [
71
+ {
72
+ type: 'text',
73
+ text: output
74
+ }
75
+ ]
76
+ };
77
+ }
78
+ /**
79
+ * Get human-readable description for feature code
80
+ * Based on GeoNames feature codes: https://www.geonames.org/export/codes.html
81
+ */
82
+ function getFeatureDescription(code) {
83
+ const featureCodes = {
84
+ 'PPL': 'Populated place',
85
+ 'PPLA': 'Administrative capital',
86
+ 'PPLA2': 'Second-order administrative capital',
87
+ 'PPLA3': 'Third-order administrative capital',
88
+ 'PPLA4': 'Fourth-order administrative capital',
89
+ 'PPLC': 'National capital',
90
+ 'PPLG': 'Seat of government',
91
+ 'PPLS': 'Populated places',
92
+ 'PPLX': 'Section of populated place',
93
+ 'ADM1': 'First-order administrative division',
94
+ 'ADM2': 'Second-order administrative division',
95
+ 'ADM3': 'Third-order administrative division',
96
+ 'ADM4': 'Fourth-order administrative division',
97
+ 'PCLI': 'Independent political entity',
98
+ 'PCLD': 'Dependent political entity',
99
+ 'ISL': 'Island',
100
+ 'MT': 'Mountain',
101
+ 'MTS': 'Mountains',
102
+ 'LAKE': 'Lake',
103
+ 'RSTN': 'Railroad station',
104
+ 'AIRP': 'Airport',
105
+ 'AIRF': 'Airfield',
106
+ 'PRK': 'Park',
107
+ 'RES': 'Reserve',
108
+ 'RESN': 'Nature reserve',
109
+ 'RESW': 'Wildlife reserve'
110
+ };
111
+ return featureCodes[code] || null;
112
+ }
113
+ //# sourceMappingURL=locationHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locationHandler.js","sourceRoot":"","sources":["../../src/handlers/locationHandler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Handler for check_service_status tool
3
+ */
4
+ import { NOAAService } from '../services/noaa.js';
5
+ import { OpenMeteoService } from '../services/openmeteo.js';
6
+ export declare function handleCheckServiceStatus(noaaService: NOAAService, openMeteoService: OpenMeteoService): Promise<{
7
+ content: Array<{
8
+ type: string;
9
+ text: string;
10
+ }>;
11
+ }>;
12
+ //# sourceMappingURL=statusHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"statusHandler.d.ts","sourceRoot":"","sources":["../../src/handlers/statusHandler.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAG5D,wBAAsB,wBAAwB,CAC5C,WAAW,EAAE,WAAW,EACxB,gBAAgB,EAAE,gBAAgB,GACjC,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,CA+G7D"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Handler for check_service_status tool
3
+ */
4
+ import { CacheConfig } from '../config/cache.js';
5
+ export async function handleCheckServiceStatus(noaaService, openMeteoService) {
6
+ // Check status of both services
7
+ const noaaStatus = await noaaService.checkServiceStatus();
8
+ const openMeteoStatus = await openMeteoService.checkServiceStatus();
9
+ // Format the status report
10
+ let output = `# Weather API Service Status\n\n`;
11
+ output += `**Check Time:** ${new Date().toLocaleString()}\n\n`;
12
+ // NOAA Status
13
+ output += `## NOAA Weather API (Forecasts & Current Conditions)\n\n`;
14
+ output += `**Status:** ${noaaStatus.operational ? '✅ Operational' : '❌ Issues Detected'}\n`;
15
+ output += `**Message:** ${noaaStatus.message}\n`;
16
+ output += `**Status Page:** ${noaaStatus.statusPage}\n`;
17
+ output += `**Coverage:** United States locations only\n\n`;
18
+ if (!noaaStatus.operational) {
19
+ output += `**Recommended Actions:**\n`;
20
+ output += `- Check planned outages: https://weather-gov.github.io/api/planned-outages\n`;
21
+ output += `- View service notices: https://www.weather.gov/notification\n`;
22
+ output += `- Report issues: nco.ops@noaa.gov or (301) 683-1518\n\n`;
23
+ }
24
+ // Open-Meteo Status
25
+ output += `## Open-Meteo API (Historical Weather Data)\n\n`;
26
+ output += `**Status:** ${openMeteoStatus.operational ? '✅ Operational' : '❌ Issues Detected'}\n`;
27
+ output += `**Message:** ${openMeteoStatus.message}\n`;
28
+ output += `**Status Page:** ${openMeteoStatus.statusPage}\n`;
29
+ output += `**Coverage:** Global (worldwide locations)\n\n`;
30
+ if (!openMeteoStatus.operational) {
31
+ output += `**Recommended Actions:**\n`;
32
+ output += `- Check production status: https://open-meteo.com/en/docs/model-updates\n`;
33
+ output += `- View GitHub issues: https://github.com/open-meteo/open-meteo/issues\n`;
34
+ output += `- Review documentation: https://open-meteo.com/en/docs\n\n`;
35
+ }
36
+ // Cache Statistics
37
+ if (CacheConfig.enabled) {
38
+ output += `## Cache Statistics\n\n`;
39
+ const noaaStats = noaaService.getCacheStats();
40
+ const openMeteoStats = openMeteoService.getCacheStats();
41
+ const totalHits = noaaStats.hits + openMeteoStats.hits;
42
+ const totalMisses = noaaStats.misses + openMeteoStats.misses;
43
+ const totalRequests = totalHits + totalMisses;
44
+ const overallHitRate = totalRequests > 0 ? ((totalHits / totalRequests) * 100).toFixed(1) : '0.0';
45
+ output += `**Cache Status:** ✅ Enabled\n`;
46
+ output += `**Overall Hit Rate:** ${overallHitRate}%\n`;
47
+ output += `**Total Cache Hits:** ${totalHits}\n`;
48
+ output += `**Total Cache Misses:** ${totalMisses}\n`;
49
+ output += `**Total Requests:** ${totalRequests}\n\n`;
50
+ const noaaHitRate = (noaaStats.hits + noaaStats.misses) > 0
51
+ ? ((noaaStats.hits / (noaaStats.hits + noaaStats.misses)) * 100).toFixed(1)
52
+ : '0.0';
53
+ const openMeteoHitRate = (openMeteoStats.hits + openMeteoStats.misses) > 0
54
+ ? ((openMeteoStats.hits / (openMeteoStats.hits + openMeteoStats.misses)) * 100).toFixed(1)
55
+ : '0.0';
56
+ output += `### NOAA Service Cache\n`;
57
+ output += `- Entries: ${noaaStats.size} / ${noaaStats.maxSize}\n`;
58
+ output += `- Hit Rate: ${noaaHitRate}%\n`;
59
+ output += `- Hits: ${noaaStats.hits}\n`;
60
+ output += `- Misses: ${noaaStats.misses}\n`;
61
+ output += `- Evictions: ${noaaStats.evictions}\n\n`;
62
+ output += `### Open-Meteo Service Cache\n`;
63
+ output += `- Entries: ${openMeteoStats.size} / ${openMeteoStats.maxSize}\n`;
64
+ output += `- Hit Rate: ${openMeteoHitRate}%\n`;
65
+ output += `- Hits: ${openMeteoStats.hits}\n`;
66
+ output += `- Misses: ${openMeteoStats.misses}\n`;
67
+ output += `- Evictions: ${openMeteoStats.evictions}\n\n`;
68
+ output += `*Cache reduces API calls and improves performance for repeated queries.*\n\n`;
69
+ }
70
+ else {
71
+ output += `## Cache Statistics\n\n`;
72
+ output += `**Cache Status:** ❌ Disabled\n`;
73
+ output += `*Set CACHE_ENABLED=true in environment to enable caching.*\n\n`;
74
+ }
75
+ // Overall status summary
76
+ const bothOperational = noaaStatus.operational && openMeteoStatus.operational;
77
+ const neitherOperational = !noaaStatus.operational && !openMeteoStatus.operational;
78
+ if (bothOperational) {
79
+ output += `## Overall Status: ✅ All Services Operational\n\n`;
80
+ output += `Both NOAA and Open-Meteo APIs are functioning normally. Weather data requests should succeed.\n`;
81
+ }
82
+ else if (neitherOperational) {
83
+ output += `## Overall Status: ❌ Multiple Service Issues\n\n`;
84
+ output += `Both weather APIs are experiencing issues. Please check the status pages above for updates.\n`;
85
+ }
86
+ else {
87
+ output += `## Overall Status: ⚠️ Partial Service Availability\n\n`;
88
+ if (noaaStatus.operational) {
89
+ output += `NOAA API is operational: Forecasts and current conditions for US locations are available.\n`;
90
+ output += `Open-Meteo API has issues: Historical weather data may be unavailable.\n`;
91
+ }
92
+ else {
93
+ output += `Open-Meteo API is operational: Historical weather data is available globally.\n`;
94
+ output += `NOAA API has issues: Forecasts and current conditions for US locations may be unavailable.\n`;
95
+ }
96
+ }
97
+ return {
98
+ content: [
99
+ {
100
+ type: 'text',
101
+ text: output
102
+ }
103
+ ]
104
+ };
105
+ }
106
+ //# sourceMappingURL=statusHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"statusHandler.js","sourceRoot":"","sources":["../../src/handlers/statusHandler.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,WAAwB,EACxB,gBAAkC;IAElC,gCAAgC;IAChC,MAAM,UAAU,GAAG,MAAM,WAAW,CAAC,kBAAkB,EAAE,CAAC;IAC1D,MAAM,eAAe,GAAG,MAAM,gBAAgB,CAAC,kBAAkB,EAAE,CAAC;IAEpE,2BAA2B;IAC3B,IAAI,MAAM,GAAG,kCAAkC,CAAC;IAChD,MAAM,IAAI,mBAAmB,IAAI,IAAI,EAAE,CAAC,cAAc,EAAE,MAAM,CAAC;IAE/D,cAAc;IACd,MAAM,IAAI,0DAA0D,CAAC;IACrE,MAAM,IAAI,eAAe,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,mBAAmB,IAAI,CAAC;IAC5F,MAAM,IAAI,gBAAgB,UAAU,CAAC,OAAO,IAAI,CAAC;IACjD,MAAM,IAAI,oBAAoB,UAAU,CAAC,UAAU,IAAI,CAAC;IACxD,MAAM,IAAI,gDAAgD,CAAC;IAE3D,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC;QAC5B,MAAM,IAAI,4BAA4B,CAAC;QACvC,MAAM,IAAI,8EAA8E,CAAC;QACzF,MAAM,IAAI,gEAAgE,CAAC;QAC3E,MAAM,IAAI,yDAAyD,CAAC;IACtE,CAAC;IAED,oBAAoB;IACpB,MAAM,IAAI,iDAAiD,CAAC;IAC5D,MAAM,IAAI,eAAe,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,mBAAmB,IAAI,CAAC;IACjG,MAAM,IAAI,gBAAgB,eAAe,CAAC,OAAO,IAAI,CAAC;IACtD,MAAM,IAAI,oBAAoB,eAAe,CAAC,UAAU,IAAI,CAAC;IAC7D,MAAM,IAAI,gDAAgD,CAAC;IAE3D,IAAI,CAAC,eAAe,CAAC,WAAW,EAAE,CAAC;QACjC,MAAM,IAAI,4BAA4B,CAAC;QACvC,MAAM,IAAI,2EAA2E,CAAC;QACtF,MAAM,IAAI,yEAAyE,CAAC;QACpF,MAAM,IAAI,4DAA4D,CAAC;IACzE,CAAC;IAED,mBAAmB;IACnB,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;QACxB,MAAM,IAAI,yBAAyB,CAAC;QAEpC,MAAM,SAAS,GAAG,WAAW,CAAC,aAAa,EAAE,CAAC;QAC9C,MAAM,cAAc,GAAG,gBAAgB,CAAC,aAAa,EAAE,CAAC;QACxD,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,GAAG,cAAc,CAAC,IAAI,CAAC;QACvD,MAAM,WAAW,GAAG,SAAS,CAAC,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC;QAC7D,MAAM,aAAa,GAAG,SAAS,GAAG,WAAW,CAAC;QAC9C,MAAM,cAAc,GAAG,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,aAAa,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QAElG,MAAM,IAAI,+BAA+B,CAAC;QAC1C,MAAM,IAAI,yBAAyB,cAAc,KAAK,CAAC;QACvD,MAAM,IAAI,yBAAyB,SAAS,IAAI,CAAC;QACjD,MAAM,IAAI,2BAA2B,WAAW,IAAI,CAAC;QACrD,MAAM,IAAI,uBAAuB,aAAa,MAAM,CAAC;QAErD,MAAM,WAAW,GAAG,CAAC,SAAS,CAAC,IAAI,GAAG,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC;YACzD,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC,SAAS,CAAC,IAAI,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;YAC3E,CAAC,CAAC,KAAK,CAAC;QACV,MAAM,gBAAgB,GAAG,CAAC,cAAc,CAAC,IAAI,GAAG,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC;YACxE,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,GAAG,CAAC,cAAc,CAAC,IAAI,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;YAC1F,CAAC,CAAC,KAAK,CAAC;QAEV,MAAM,IAAI,0BAA0B,CAAC;QACrC,MAAM,IAAI,cAAc,SAAS,CAAC,IAAI,MAAM,SAAS,CAAC,OAAO,IAAI,CAAC;QAClE,MAAM,IAAI,eAAe,WAAW,KAAK,CAAC;QAC1C,MAAM,IAAI,WAAW,SAAS,CAAC,IAAI,IAAI,CAAC;QACxC,MAAM,IAAI,aAAa,SAAS,CAAC,MAAM,IAAI,CAAC;QAC5C,MAAM,IAAI,gBAAgB,SAAS,CAAC,SAAS,MAAM,CAAC;QAEpD,MAAM,IAAI,gCAAgC,CAAC;QAC3C,MAAM,IAAI,cAAc,cAAc,CAAC,IAAI,MAAM,cAAc,CAAC,OAAO,IAAI,CAAC;QAC5E,MAAM,IAAI,eAAe,gBAAgB,KAAK,CAAC;QAC/C,MAAM,IAAI,WAAW,cAAc,CAAC,IAAI,IAAI,CAAC;QAC7C,MAAM,IAAI,aAAa,cAAc,CAAC,MAAM,IAAI,CAAC;QACjD,MAAM,IAAI,gBAAgB,cAAc,CAAC,SAAS,MAAM,CAAC;QAEzD,MAAM,IAAI,8EAA8E,CAAC;IAC3F,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,yBAAyB,CAAC;QACpC,MAAM,IAAI,gCAAgC,CAAC;QAC3C,MAAM,IAAI,gEAAgE,CAAC;IAC7E,CAAC;IAED,yBAAyB;IACzB,MAAM,eAAe,GAAG,UAAU,CAAC,WAAW,IAAI,eAAe,CAAC,WAAW,CAAC;IAC9E,MAAM,kBAAkB,GAAG,CAAC,UAAU,CAAC,WAAW,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC;IAEnF,IAAI,eAAe,EAAE,CAAC;QACpB,MAAM,IAAI,mDAAmD,CAAC;QAC9D,MAAM,IAAI,iGAAiG,CAAC;IAC9G,CAAC;SAAM,IAAI,kBAAkB,EAAE,CAAC;QAC9B,MAAM,IAAI,kDAAkD,CAAC;QAC7D,MAAM,IAAI,+FAA+F,CAAC;IAC5G,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,wDAAwD,CAAC;QACnE,IAAI,UAAU,CAAC,WAAW,EAAE,CAAC;YAC3B,MAAM,IAAI,6FAA6F,CAAC;YACxG,MAAM,IAAI,0EAA0E,CAAC;QACvF,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,iFAAiF,CAAC;YAC5F,MAAM,IAAI,8FAA8F,CAAC;QAC3G,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,MAAM;aACb;SACF;KACF,CAAC;AACJ,CAAC"}