@dangahagan/weather-mcp 0.2.0 → 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 +252 -53
  2. package/dist/config/cache.d.ts +1 -0
  3. package/dist/config/cache.d.ts.map +1 -1
  4. package/dist/config/cache.js +45 -2
  5. package/dist/config/cache.js.map +1 -1
  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 +148 -376
  39. package/dist/index.js.map +1 -1
  40. package/dist/services/noaa.d.ts +14 -1
  41. package/dist/services/noaa.d.ts.map +1 -1
  42. package/dist/services/noaa.js +74 -42
  43. package/dist/services/noaa.js.map +1 -1
  44. package/dist/services/openmeteo.d.ts +54 -3
  45. package/dist/services/openmeteo.d.ts.map +1 -1
  46. package/dist/services/openmeteo.js +256 -112
  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 +11 -4
  53. package/dist/utils/cache.d.ts.map +1 -1
  54. package/dist/utils/cache.js +33 -4
  55. package/dist/utils/cache.js.map +1 -1
  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,83 @@
1
+ /**
2
+ * Display thresholds and constants for weather data formatting
3
+ *
4
+ * These values determine when certain weather metrics are shown or highlighted
5
+ */
6
+ export const DisplayThresholds = {
7
+ /**
8
+ * Temperature thresholds (in Fahrenheit)
9
+ */
10
+ temperature: {
11
+ /** Show heat index when temperature is above this value */
12
+ showHeatIndex: 80,
13
+ /** Show wind chill when temperature is below this value */
14
+ showWindChill: 50,
15
+ },
16
+ /**
17
+ * Wind thresholds
18
+ */
19
+ wind: {
20
+ /** Show gusts if they are this ratio higher than sustained wind speed (1.2 = 20% higher) */
21
+ gustSignificanceRatio: 1.2,
22
+ },
23
+ /**
24
+ * Visibility thresholds (in miles)
25
+ */
26
+ visibility: {
27
+ /** Dense fog */
28
+ denseFog: 0.25,
29
+ /** Fog */
30
+ fog: 1.0,
31
+ /** Haze or mist */
32
+ hazeMist: 3.0,
33
+ /** Clear visibility */
34
+ clear: 10.0,
35
+ },
36
+ /**
37
+ * Precipitation thresholds
38
+ */
39
+ precipitation: {
40
+ /** Light precipitation (inches per hour) */
41
+ light: 0.1,
42
+ /** Moderate precipitation (inches per hour) */
43
+ moderate: 0.3,
44
+ /** Heavy precipitation (inches per hour) */
45
+ heavy: 0.5,
46
+ },
47
+ };
48
+ /**
49
+ * API-related constants
50
+ */
51
+ export const ApiConstants = {
52
+ /**
53
+ * Historical data threshold (in days)
54
+ * Data older than this uses archival API instead of recent observations
55
+ */
56
+ historicalDataThresholdDays: 7,
57
+ /**
58
+ * Maximum date range for hourly historical data (in days)
59
+ */
60
+ maxHourlyHistoricalDays: 31,
61
+ };
62
+ /**
63
+ * Formatting constants
64
+ */
65
+ export const FormatConstants = {
66
+ /**
67
+ * Default forecast periods to show
68
+ */
69
+ defaultForecastDays: 7,
70
+ /**
71
+ * Maximum forecast days (Open-Meteo supports up to 16 days)
72
+ */
73
+ maxForecastDays: 16,
74
+ /**
75
+ * Default observation limit for historical data
76
+ */
77
+ defaultHistoricalLimit: 168, // One week of hourly data
78
+ /**
79
+ * Maximum observations to return
80
+ */
81
+ maxHistoricalLimit: 500,
82
+ };
83
+ //# sourceMappingURL=displayThresholds.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"displayThresholds.js","sourceRoot":"","sources":["../../src/config/displayThresholds.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B;;OAEG;IACH,WAAW,EAAE;QACX,2DAA2D;QAC3D,aAAa,EAAE,EAAE;QACjB,2DAA2D;QAC3D,aAAa,EAAE,EAAE;KAClB;IAED;;OAEG;IACH,IAAI,EAAE;QACJ,4FAA4F;QAC5F,qBAAqB,EAAE,GAAG;KAC3B;IAED;;OAEG;IACH,UAAU,EAAE;QACV,gBAAgB;QAChB,QAAQ,EAAE,IAAI;QACd,UAAU;QACV,GAAG,EAAE,GAAG;QACR,mBAAmB;QACnB,QAAQ,EAAE,GAAG;QACb,uBAAuB;QACvB,KAAK,EAAE,IAAI;KACZ;IAED;;OAEG;IACH,aAAa,EAAE;QACb,4CAA4C;QAC5C,KAAK,EAAE,GAAG;QACV,+CAA+C;QAC/C,QAAQ,EAAE,GAAG;QACb,4CAA4C;QAC5C,KAAK,EAAE,GAAG;KACX;CACO,CAAC;AAEX;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B;;;OAGG;IACH,2BAA2B,EAAE,CAAC;IAE9B;;OAEG;IACH,uBAAuB,EAAE,EAAE;CACnB,CAAC;AAEX;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B;;OAEG;IACH,mBAAmB,EAAE,CAAC;IAEtB;;OAEG;IACH,eAAe,EAAE,EAAE;IAEnB;;OAEG;IACH,sBAAsB,EAAE,GAAG,EAAE,0BAA0B;IAEvD;;OAEG;IACH,kBAAkB,EAAE,GAAG;CACf,CAAC"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Custom error classes for better error handling and logging
3
+ */
4
+ /**
5
+ * Base error class for API-related errors
6
+ */
7
+ export declare class ApiError extends Error {
8
+ readonly statusCode: number;
9
+ readonly service: 'NOAA' | 'OpenMeteo';
10
+ readonly userMessage: string;
11
+ readonly helpLinks: string[];
12
+ readonly isRetryable: boolean;
13
+ constructor(message: string, statusCode: number, service: 'NOAA' | 'OpenMeteo', userMessage: string, helpLinks?: string[], isRetryable?: boolean);
14
+ /**
15
+ * Format error for display to user
16
+ */
17
+ toUserMessage(): string;
18
+ }
19
+ /**
20
+ * Rate limit error - too many requests
21
+ */
22
+ export declare class RateLimitError extends ApiError {
23
+ readonly retryAfter?: number;
24
+ constructor(service: 'NOAA' | 'OpenMeteo', retryAfter?: number);
25
+ }
26
+ /**
27
+ * Service unavailable error - API is down or timing out
28
+ */
29
+ export declare class ServiceUnavailableError extends ApiError {
30
+ constructor(service: 'NOAA' | 'OpenMeteo', originalError?: Error);
31
+ }
32
+ /**
33
+ * Invalid location error - coordinates not supported or out of range
34
+ */
35
+ export declare class InvalidLocationError extends ApiError {
36
+ readonly latitude?: number;
37
+ readonly longitude?: number;
38
+ constructor(service: 'NOAA' | 'OpenMeteo', message: string, latitude?: number, longitude?: number);
39
+ }
40
+ /**
41
+ * Data not found error - requested data doesn't exist
42
+ */
43
+ export declare class DataNotFoundError extends ApiError {
44
+ constructor(service: 'NOAA' | 'OpenMeteo', message: string);
45
+ }
46
+ /**
47
+ * Validation error - invalid input parameters
48
+ */
49
+ export declare class ValidationError extends Error {
50
+ readonly field?: string;
51
+ readonly value?: any;
52
+ constructor(message: string, field?: string, value?: any);
53
+ }
54
+ /**
55
+ * Check if an error is retryable
56
+ */
57
+ export declare function isRetryableError(error: Error): boolean;
58
+ /**
59
+ * Format error for user display
60
+ */
61
+ export declare function formatErrorForUser(error: Error): string;
62
+ //# sourceMappingURL=ApiError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApiError.d.ts","sourceRoot":"","sources":["../../src/errors/ApiError.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC,SAAgB,UAAU,EAAE,MAAM,CAAC;IACnC,SAAgB,OAAO,EAAE,MAAM,GAAG,WAAW,CAAC;IAC9C,SAAgB,WAAW,EAAE,MAAM,CAAC;IACpC,SAAgB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpC,SAAgB,WAAW,EAAE,OAAO,CAAC;gBAGnC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GAAG,WAAW,EAC7B,WAAW,EAAE,MAAM,EACnB,SAAS,GAAE,MAAM,EAAO,EACxB,WAAW,GAAE,OAAe;IAgB9B;;OAEG;IACH,aAAa,IAAI,MAAM;CAYxB;AAED;;GAEG;AACH,qBAAa,cAAe,SAAQ,QAAQ;IAC1C,SAAgB,UAAU,CAAC,EAAE,MAAM,CAAC;gBAExB,OAAO,EAAE,MAAM,GAAG,WAAW,EAAE,UAAU,CAAC,EAAE,MAAM;CAoB/D;AAED;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,QAAQ;gBACvC,OAAO,EAAE,MAAM,GAAG,WAAW,EAAE,aAAa,CAAC,EAAE,KAAK;CAoBjE;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,QAAQ;IAChD,SAAgB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClC,SAAgB,SAAS,CAAC,EAAE,MAAM,CAAC;gBAGjC,OAAO,EAAE,MAAM,GAAG,WAAW,EAC7B,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,MAAM;CAerB;AAED;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,QAAQ;gBACjC,OAAO,EAAE,MAAM,GAAG,WAAW,EAAE,OAAO,EAAE,MAAM;CAY3D;AAED;;GAEG;AACH,qBAAa,eAAgB,SAAQ,KAAK;IACxC,SAAgB,KAAK,CAAC,EAAE,MAAM,CAAC;IAC/B,SAAgB,KAAK,CAAC,EAAE,GAAG,CAAC;gBAEhB,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG;CAUzD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAetD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAgBvD"}
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Custom error classes for better error handling and logging
3
+ */
4
+ /**
5
+ * Base error class for API-related errors
6
+ */
7
+ export class ApiError extends Error {
8
+ statusCode;
9
+ service;
10
+ userMessage;
11
+ helpLinks;
12
+ isRetryable;
13
+ constructor(message, statusCode, service, userMessage, helpLinks = [], isRetryable = false) {
14
+ super(message);
15
+ this.name = 'ApiError';
16
+ this.statusCode = statusCode;
17
+ this.service = service;
18
+ this.userMessage = userMessage;
19
+ this.helpLinks = helpLinks;
20
+ this.isRetryable = isRetryable;
21
+ // Maintains proper stack trace for where our error was thrown (only available on V8)
22
+ if (Error.captureStackTrace) {
23
+ Error.captureStackTrace(this, this.constructor);
24
+ }
25
+ }
26
+ /**
27
+ * Format error for display to user
28
+ */
29
+ toUserMessage() {
30
+ let message = `${this.service} API Error: ${this.userMessage}`;
31
+ if (this.helpLinks.length > 0) {
32
+ message += '\n\nFor more information:\n';
33
+ this.helpLinks.forEach(link => {
34
+ message += `- ${link}\n`;
35
+ });
36
+ }
37
+ return message;
38
+ }
39
+ }
40
+ /**
41
+ * Rate limit error - too many requests
42
+ */
43
+ export class RateLimitError extends ApiError {
44
+ retryAfter;
45
+ constructor(service, retryAfter) {
46
+ const userMessage = retryAfter
47
+ ? `Rate limit exceeded. Please retry after ${retryAfter} seconds.`
48
+ : 'Rate limit exceeded. Please retry in a few seconds.';
49
+ super(`Rate limit exceeded for ${service}`, 429, service, userMessage, [
50
+ 'https://weather.gov/documentation/services-web-api',
51
+ 'https://open-meteo.com/en/features#api-documentation',
52
+ ], true // Retryable after waiting
53
+ );
54
+ this.name = 'RateLimitError';
55
+ this.retryAfter = retryAfter;
56
+ }
57
+ }
58
+ /**
59
+ * Service unavailable error - API is down or timing out
60
+ */
61
+ export class ServiceUnavailableError extends ApiError {
62
+ constructor(service, originalError) {
63
+ super(`${service} API is currently unavailable`, 503, service, `The ${service} weather service is temporarily unavailable. Please try again in a few minutes.`, [
64
+ service === 'NOAA'
65
+ ? 'https://www.weather.gov/'
66
+ : 'https://open-meteo.com/',
67
+ ], true // Retryable
68
+ );
69
+ this.name = 'ServiceUnavailableError';
70
+ if (originalError && originalError.stack) {
71
+ this.stack = `${this.stack}\nCaused by: ${originalError.stack}`;
72
+ }
73
+ }
74
+ }
75
+ /**
76
+ * Invalid location error - coordinates not supported or out of range
77
+ */
78
+ export class InvalidLocationError extends ApiError {
79
+ latitude;
80
+ longitude;
81
+ constructor(service, message, latitude, longitude) {
82
+ super(message, 400, service, message, [], false // Not retryable
83
+ );
84
+ this.name = 'InvalidLocationError';
85
+ this.latitude = latitude;
86
+ this.longitude = longitude;
87
+ }
88
+ }
89
+ /**
90
+ * Data not found error - requested data doesn't exist
91
+ */
92
+ export class DataNotFoundError extends ApiError {
93
+ constructor(service, message) {
94
+ super(message, 404, service, message, [], false // Not retryable
95
+ );
96
+ this.name = 'DataNotFoundError';
97
+ }
98
+ }
99
+ /**
100
+ * Validation error - invalid input parameters
101
+ */
102
+ export class ValidationError extends Error {
103
+ field;
104
+ value;
105
+ constructor(message, field, value) {
106
+ super(message);
107
+ this.name = 'ValidationError';
108
+ this.field = field;
109
+ this.value = value;
110
+ if (Error.captureStackTrace) {
111
+ Error.captureStackTrace(this, this.constructor);
112
+ }
113
+ }
114
+ }
115
+ /**
116
+ * Check if an error is retryable
117
+ */
118
+ export function isRetryableError(error) {
119
+ if (error instanceof ApiError) {
120
+ return error.isRetryable;
121
+ }
122
+ // Network errors are generally retryable
123
+ if (error.message.includes('ECONNREFUSED') ||
124
+ error.message.includes('ETIMEDOUT') ||
125
+ error.message.includes('ENOTFOUND')) {
126
+ return true;
127
+ }
128
+ return false;
129
+ }
130
+ /**
131
+ * Format error for user display
132
+ */
133
+ export function formatErrorForUser(error) {
134
+ if (error instanceof ApiError) {
135
+ return error.toUserMessage();
136
+ }
137
+ if (error instanceof ValidationError) {
138
+ return `Validation Error: ${error.message}`;
139
+ }
140
+ // Sanitize generic errors to avoid leaking sensitive information
141
+ const sanitizedMessage = error.message
142
+ .replace(/ECONNREFUSED/, 'Connection refused')
143
+ .replace(/ETIMEDOUT/, 'Connection timed out')
144
+ .replace(/ENOTFOUND/, 'Service not found');
145
+ return `Error: ${sanitizedMessage}`;
146
+ }
147
+ //# sourceMappingURL=ApiError.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApiError.js","sourceRoot":"","sources":["../../src/errors/ApiError.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Handler for get_alerts tool
3
+ */
4
+ import { NOAAService } from '../services/noaa.js';
5
+ export declare function handleGetAlerts(args: unknown, noaaService: NOAAService): Promise<{
6
+ content: Array<{
7
+ type: string;
8
+ text: string;
9
+ }>;
10
+ }>;
11
+ //# sourceMappingURL=alertsHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"alertsHandler.d.ts","sourceRoot":"","sources":["../../src/handlers/alertsHandler.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AASlD,wBAAsB,eAAe,CACnC,IAAI,EAAE,OAAO,EACb,WAAW,EAAE,WAAW,GACvB,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,CA+F7D"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Handler for get_alerts tool
3
+ */
4
+ import { validateCoordinates, validateOptionalBoolean } from '../utils/validation.js';
5
+ export async function handleGetAlerts(args, noaaService) {
6
+ // Validate input parameters with runtime checks
7
+ const { latitude, longitude } = validateCoordinates(args);
8
+ const active_only = validateOptionalBoolean(args?.active_only, 'active_only', true);
9
+ // Get alerts data
10
+ const alertsData = await noaaService.getAlerts(latitude, longitude, active_only);
11
+ const alerts = alertsData.features;
12
+ // Format the alerts for display
13
+ let output = `# Weather Alerts\n\n`;
14
+ output += `**Location:** ${latitude.toFixed(4)}, ${longitude.toFixed(4)}\n`;
15
+ output += `**Status:** ${active_only ? 'Active alerts only' : 'All alerts'}\n`;
16
+ if (alertsData.updated) {
17
+ output += `**Updated:** ${new Date(alertsData.updated).toLocaleString()}\n`;
18
+ }
19
+ output += `\n`;
20
+ if (alerts.length === 0) {
21
+ output += `✅ **No active weather alerts for this location.**\n\n`;
22
+ output += `The area is currently clear of weather warnings, watches, and advisories.\n`;
23
+ }
24
+ else {
25
+ output += `⚠️ **${alerts.length} active alert${alerts.length > 1 ? 's' : ''} found**\n\n`;
26
+ const severityOrder = {
27
+ 'Extreme': 0,
28
+ 'Severe': 1,
29
+ 'Moderate': 2,
30
+ 'Minor': 3,
31
+ 'Unknown': 4
32
+ };
33
+ const sortedAlerts = alerts.sort((a, b) => {
34
+ const severityA = severityOrder[a.properties.severity] ?? 4;
35
+ const severityB = severityOrder[b.properties.severity] ?? 4;
36
+ return severityA - severityB;
37
+ });
38
+ for (const alert of sortedAlerts) {
39
+ const props = alert.properties;
40
+ // Severity emoji
41
+ const severityEmoji = props.severity === 'Extreme' ? '🔴' :
42
+ props.severity === 'Severe' ? '🟠' :
43
+ props.severity === 'Moderate' ? '🟡' :
44
+ props.severity === 'Minor' ? '🔵' : '⚪';
45
+ output += `${severityEmoji} **${props.event}**\n`;
46
+ output += `---\n`;
47
+ if (props.headline) {
48
+ output += `**${props.headline}**\n\n`;
49
+ }
50
+ output += `**Severity:** ${props.severity} | **Urgency:** ${props.urgency} | **Certainty:** ${props.certainty}\n`;
51
+ output += `**Area:** ${props.areaDesc}\n`;
52
+ output += `**Effective:** ${new Date(props.effective).toLocaleString()}\n`;
53
+ output += `**Expires:** ${new Date(props.expires).toLocaleString()}\n`;
54
+ if (props.onset && props.onset !== props.effective) {
55
+ output += `**Onset:** ${new Date(props.onset).toLocaleString()}\n`;
56
+ }
57
+ if (props.ends) {
58
+ output += `**Ends:** ${new Date(props.ends).toLocaleString()}\n`;
59
+ }
60
+ output += `\n**Description:**\n${props.description}\n`;
61
+ if (props.instruction) {
62
+ output += `\n**Instructions:**\n${props.instruction}\n`;
63
+ }
64
+ output += `\n**Recommended Response:** ${props.response}\n`;
65
+ output += `**Sender:** ${props.senderName}\n\n`;
66
+ }
67
+ }
68
+ output += `---\n`;
69
+ output += `*Data source: NOAA National Weather Service*\n`;
70
+ return {
71
+ content: [
72
+ {
73
+ type: 'text',
74
+ text: output
75
+ }
76
+ ]
77
+ };
78
+ }
79
+ //# sourceMappingURL=alertsHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"alertsHandler.js","sourceRoot":"","sources":["../../src/handlers/alertsHandler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Handler for get_current_conditions tool
3
+ */
4
+ import { NOAAService } from '../services/noaa.js';
5
+ export declare function handleGetCurrentConditions(args: unknown, noaaService: NOAAService): Promise<{
6
+ content: Array<{
7
+ type: string;
8
+ text: string;
9
+ }>;
10
+ }>;
11
+ //# sourceMappingURL=currentConditionsHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"currentConditionsHandler.d.ts","sourceRoot":"","sources":["../../src/handlers/currentConditionsHandler.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAKlD,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,OAAO,EACb,WAAW,EAAE,WAAW,GACvB,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,CAkL7D"}
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Handler for get_current_conditions tool
3
+ */
4
+ import { validateCoordinates } from '../utils/validation.js';
5
+ import { convertToFahrenheit } from '../utils/temperatureConversion.js';
6
+ import { DisplayThresholds } from '../config/displayThresholds.js';
7
+ export async function handleGetCurrentConditions(args, noaaService) {
8
+ // Validate input parameters with runtime checks
9
+ const { latitude, longitude } = validateCoordinates(args);
10
+ // Get current observation
11
+ const observation = await noaaService.getCurrentConditions(latitude, longitude);
12
+ const props = observation.properties;
13
+ // Format current conditions
14
+ let output = `# Current Weather Conditions\n\n`;
15
+ output += `**Station:** ${props.station}\n`;
16
+ output += `**Time:** ${new Date(props.timestamp).toLocaleString()}\n\n`;
17
+ // Main conditions
18
+ if (props.textDescription) {
19
+ output += `**Conditions:** ${props.textDescription}\n`;
20
+ }
21
+ // Temperature section
22
+ const tempF = convertToFahrenheit(props.temperature.value, props.temperature.unitCode);
23
+ if (tempF !== null) {
24
+ output += `**Temperature:** ${Math.round(tempF)}°F\n`;
25
+ // Show heat index when temperature is high and heat index is available
26
+ if (props.heatIndex) {
27
+ const heatIndexF = convertToFahrenheit(props.heatIndex.value, props.heatIndex.unitCode);
28
+ if (heatIndexF !== null && tempF > DisplayThresholds.temperature.showHeatIndex && heatIndexF > tempF) {
29
+ output += `**Feels Like (Heat Index):** ${Math.round(heatIndexF)}°F\n`;
30
+ }
31
+ }
32
+ // Show wind chill when temperature is low and wind chill is available
33
+ if (props.windChill) {
34
+ const windChillF = convertToFahrenheit(props.windChill.value, props.windChill.unitCode);
35
+ if (windChillF !== null && tempF < DisplayThresholds.temperature.showWindChill && windChillF < tempF) {
36
+ output += `**Feels Like (Wind Chill):** ${Math.round(windChillF)}°F\n`;
37
+ }
38
+ }
39
+ }
40
+ // 24-hour temperature range
41
+ const max24F = props.maxTemperatureLast24Hours ? convertToFahrenheit(props.maxTemperatureLast24Hours.value, props.maxTemperatureLast24Hours.unitCode) : null;
42
+ const min24F = props.minTemperatureLast24Hours ? convertToFahrenheit(props.minTemperatureLast24Hours.value, props.minTemperatureLast24Hours.unitCode) : null;
43
+ if (max24F !== null || min24F !== null) {
44
+ let range = `**24-Hour Range:**`;
45
+ if (max24F !== null)
46
+ range += ` High ${Math.round(max24F)}°F`;
47
+ if (max24F !== null && min24F !== null)
48
+ range += ` /`;
49
+ if (min24F !== null)
50
+ range += ` Low ${Math.round(min24F)}°F`;
51
+ output += `${range}\n`;
52
+ }
53
+ if (props.dewpoint.value !== null) {
54
+ const dewF = convertToFahrenheit(props.dewpoint.value, props.dewpoint.unitCode);
55
+ if (dewF !== null) {
56
+ output += `**Dewpoint:** ${Math.round(dewF)}°F\n`;
57
+ }
58
+ }
59
+ if (props.relativeHumidity.value !== null) {
60
+ output += `**Humidity:** ${Math.round(props.relativeHumidity.value)}%\n`;
61
+ }
62
+ // Wind section
63
+ if (props.windSpeed && props.windSpeed.value !== null) {
64
+ const windMph = props.windSpeed.unitCode.includes('km_h')
65
+ ? props.windSpeed.value * 0.621371
66
+ : props.windSpeed.value * 2.23694; // m/s to mph
67
+ const windDir = props.windDirection?.value ?? null;
68
+ output += `**Wind:** ${Math.round(windMph)} mph`;
69
+ if (windDir !== null) {
70
+ output += ` from ${Math.round(windDir)}°`;
71
+ }
72
+ // Add wind gust if available and significant
73
+ if (props.windGust && props.windGust.value !== null) {
74
+ const gustMph = props.windGust.unitCode.includes('km_h')
75
+ ? props.windGust.value * 0.621371
76
+ : props.windGust.value * 2.23694;
77
+ if (gustMph > windMph * DisplayThresholds.wind.gustSignificanceRatio) {
78
+ output += `, gusting to ${Math.round(gustMph)} mph`;
79
+ }
80
+ }
81
+ output += `\n`;
82
+ }
83
+ if (props.barometricPressure && props.barometricPressure.value !== null) {
84
+ const pressureInHg = props.barometricPressure.value * 0.0002953;
85
+ output += `**Pressure:** ${pressureInHg.toFixed(2)} inHg\n`;
86
+ }
87
+ // Enhanced visibility and cloud cover
88
+ if (props.visibility && props.visibility.value !== null) {
89
+ const visibilityMiles = props.visibility.value * 0.000621371;
90
+ output += `**Visibility:** ${visibilityMiles.toFixed(1)} miles`;
91
+ // Add descriptive text for visibility
92
+ if (visibilityMiles < DisplayThresholds.visibility.denseFog) {
93
+ output += ` (dense fog)`;
94
+ }
95
+ else if (visibilityMiles < DisplayThresholds.visibility.fog) {
96
+ output += ` (fog)`;
97
+ }
98
+ else if (visibilityMiles < DisplayThresholds.visibility.hazeMist) {
99
+ output += ` (haze/mist)`;
100
+ }
101
+ else if (visibilityMiles >= DisplayThresholds.visibility.clear) {
102
+ output += ` (clear)`;
103
+ }
104
+ output += `\n`;
105
+ }
106
+ // Cloud cover details
107
+ if (props.cloudLayers && props.cloudLayers.length > 0) {
108
+ const cloudDescriptions = {
109
+ 'FEW': 'Few clouds',
110
+ 'SCT': 'Scattered clouds',
111
+ 'BKN': 'Broken clouds',
112
+ 'OVC': 'Overcast',
113
+ 'CLR': 'Clear',
114
+ 'SKC': 'Sky clear'
115
+ };
116
+ const clouds = props.cloudLayers
117
+ .filter(layer => layer.amount)
118
+ .map(layer => {
119
+ const desc = cloudDescriptions[layer.amount] || layer.amount;
120
+ if (layer.base?.value !== null && layer.base?.value !== undefined) {
121
+ const heightFt = layer.base.unitCode.includes('m')
122
+ ? layer.base.value * 3.28084
123
+ : layer.base.value;
124
+ return `${desc} at ${Math.round(heightFt).toLocaleString()} ft`;
125
+ }
126
+ return desc;
127
+ });
128
+ if (clouds.length > 0) {
129
+ output += `**Cloud Cover:** ${clouds.join(', ')}\n`;
130
+ }
131
+ }
132
+ // Precipitation section
133
+ const precip1h = props.precipitationLastHour?.value ?? null;
134
+ const precip3h = props.precipitationLast3Hours?.value ?? null;
135
+ const precip6h = props.precipitationLast6Hours?.value ?? null;
136
+ if (precip1h !== null || precip3h !== null || precip6h !== null) {
137
+ output += `\n## Recent Precipitation\n`;
138
+ if (precip1h !== null && props.precipitationLastHour) {
139
+ const precipIn = props.precipitationLastHour.unitCode.includes('mm')
140
+ ? precip1h * 0.0393701
141
+ : precip1h;
142
+ output += `**Last Hour:** ${precipIn.toFixed(2)} inches\n`;
143
+ }
144
+ if (precip3h !== null && props.precipitationLast3Hours) {
145
+ const precipIn = props.precipitationLast3Hours.unitCode.includes('mm')
146
+ ? precip3h * 0.0393701
147
+ : precip3h;
148
+ output += `**Last 3 Hours:** ${precipIn.toFixed(2)} inches\n`;
149
+ }
150
+ if (precip6h !== null && props.precipitationLast6Hours) {
151
+ const precipIn = props.precipitationLast6Hours.unitCode.includes('mm')
152
+ ? precip6h * 0.0393701
153
+ : precip6h;
154
+ output += `**Last 6 Hours:** ${precipIn.toFixed(2)} inches\n`;
155
+ }
156
+ }
157
+ output += `\n---\n`;
158
+ output += `*Data source: NOAA National Weather Service*\n`;
159
+ return {
160
+ content: [
161
+ {
162
+ type: 'text',
163
+ text: output
164
+ }
165
+ ]
166
+ };
167
+ }
168
+ //# sourceMappingURL=currentConditionsHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"currentConditionsHandler.js","sourceRoot":"","sources":["../../src/handlers/currentConditionsHandler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Handler for get_forecast tool
3
+ * Supports both NOAA (US) and Open-Meteo (global) forecast sources
4
+ */
5
+ import { NOAAService } from '../services/noaa.js';
6
+ import { OpenMeteoService } from '../services/openmeteo.js';
7
+ export declare function handleGetForecast(args: unknown, noaaService: NOAAService, openMeteoService: OpenMeteoService): Promise<{
8
+ content: Array<{
9
+ type: string;
10
+ text: string;
11
+ }>;
12
+ }>;
13
+ //# sourceMappingURL=forecastHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forecastHandler.d.ts","sourceRoot":"","sources":["../../src/handlers/forecastHandler.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AA+B5D,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,OAAO,EACb,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,CA2C7D"}