@jablum/weather-mcp 1.7.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.
- package/LICENSE +21 -0
- package/README.md +1319 -0
- 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/api.d.ts +30 -0
- package/dist/config/api.d.ts.map +1 -0
- package/dist/config/api.js +32 -0
- package/dist/config/api.js.map +1 -0
- package/dist/config/cache.d.ts +31 -0
- package/dist/config/cache.d.ts.map +1 -0
- package/dist/config/cache.js +108 -0
- package/dist/config/cache.js.map +1 -0
- package/dist/config/displayThresholds.d.ts +83 -0
- package/dist/config/displayThresholds.d.ts.map +1 -0
- package/dist/config/displayThresholds.js +83 -0
- package/dist/config/displayThresholds.js.map +1 -0
- package/dist/config/tools.d.ts +44 -0
- package/dist/config/tools.d.ts.map +1 -0
- package/dist/config/tools.js +269 -0
- package/dist/config/tools.js.map +1 -0
- package/dist/errors/ApiError.d.ts +62 -0
- package/dist/errors/ApiError.d.ts.map +1 -0
- package/dist/errors/ApiError.js +171 -0
- package/dist/errors/ApiError.js.map +1 -0
- package/dist/handlers/airQualityHandler.d.ts +11 -0
- package/dist/handlers/airQualityHandler.d.ts.map +1 -0
- package/dist/handlers/airQualityHandler.js +154 -0
- package/dist/handlers/airQualityHandler.js.map +1 -0
- package/dist/handlers/alertsHandler.d.ts +11 -0
- package/dist/handlers/alertsHandler.d.ts.map +1 -0
- package/dist/handlers/alertsHandler.js +98 -0
- package/dist/handlers/alertsHandler.js.map +1 -0
- package/dist/handlers/currentConditionsHandler.d.ts +13 -0
- package/dist/handlers/currentConditionsHandler.d.ts.map +1 -0
- package/dist/handlers/currentConditionsHandler.js +296 -0
- package/dist/handlers/currentConditionsHandler.js.map +1 -0
- package/dist/handlers/forecastHandler.d.ts +16 -0
- package/dist/handlers/forecastHandler.d.ts.map +1 -0
- package/dist/handlers/forecastHandler.js +454 -0
- package/dist/handlers/forecastHandler.js.map +1 -0
- package/dist/handlers/historicalWeatherHandler.d.ts +12 -0
- package/dist/handlers/historicalWeatherHandler.d.ts.map +1 -0
- package/dist/handlers/historicalWeatherHandler.js +188 -0
- package/dist/handlers/historicalWeatherHandler.js.map +1 -0
- package/dist/handlers/lightningHandler.d.ts +14 -0
- package/dist/handlers/lightningHandler.d.ts.map +1 -0
- package/dist/handlers/lightningHandler.js +258 -0
- package/dist/handlers/lightningHandler.js.map +1 -0
- package/dist/handlers/locationHandler.d.ts +12 -0
- package/dist/handlers/locationHandler.d.ts.map +1 -0
- package/dist/handlers/locationHandler.js +149 -0
- package/dist/handlers/locationHandler.js.map +1 -0
- package/dist/handlers/marineConditionsHandler.d.ts +13 -0
- package/dist/handlers/marineConditionsHandler.d.ts.map +1 -0
- package/dist/handlers/marineConditionsHandler.js +270 -0
- package/dist/handlers/marineConditionsHandler.js.map +1 -0
- package/dist/handlers/riverConditionsHandler.d.ts +11 -0
- package/dist/handlers/riverConditionsHandler.d.ts.map +1 -0
- package/dist/handlers/riverConditionsHandler.js +176 -0
- package/dist/handlers/riverConditionsHandler.js.map +1 -0
- package/dist/handlers/savedLocationsHandler.d.ts +50 -0
- package/dist/handlers/savedLocationsHandler.d.ts.map +1 -0
- package/dist/handlers/savedLocationsHandler.js +397 -0
- package/dist/handlers/savedLocationsHandler.js.map +1 -0
- package/dist/handlers/statusHandler.d.ts +12 -0
- package/dist/handlers/statusHandler.d.ts.map +1 -0
- package/dist/handlers/statusHandler.js +115 -0
- package/dist/handlers/statusHandler.js.map +1 -0
- package/dist/handlers/weatherImageryHandler.d.ts +14 -0
- package/dist/handlers/weatherImageryHandler.d.ts.map +1 -0
- package/dist/handlers/weatherImageryHandler.js +143 -0
- package/dist/handlers/weatherImageryHandler.js.map +1 -0
- package/dist/handlers/wildfireHandler.d.ts +11 -0
- package/dist/handlers/wildfireHandler.d.ts.map +1 -0
- package/dist/handlers/wildfireHandler.js +186 -0
- package/dist/handlers/wildfireHandler.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +735 -0
- package/dist/index.js.map +1 -0
- package/dist/services/blitzortung.d.ts +67 -0
- package/dist/services/blitzortung.d.ts.map +1 -0
- package/dist/services/blitzortung.js +475 -0
- package/dist/services/blitzortung.js.map +1 -0
- 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/ncei.d.ts +61 -0
- package/dist/services/ncei.d.ts.map +1 -0
- package/dist/services/ncei.js +126 -0
- package/dist/services/ncei.js.map +1 -0
- package/dist/services/nifc.d.ts +44 -0
- package/dist/services/nifc.d.ts.map +1 -0
- package/dist/services/nifc.js +159 -0
- package/dist/services/nifc.js.map +1 -0
- package/dist/services/noaa.d.ts +161 -0
- package/dist/services/noaa.d.ts.map +1 -0
- package/dist/services/noaa.js +681 -0
- package/dist/services/noaa.js.map +1 -0
- 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 +189 -0
- package/dist/services/openmeteo.d.ts.map +1 -0
- package/dist/services/openmeteo.js +936 -0
- package/dist/services/openmeteo.js.map +1 -0
- package/dist/services/rainviewer.d.ts +37 -0
- package/dist/services/rainviewer.d.ts.map +1 -0
- package/dist/services/rainviewer.js +115 -0
- package/dist/services/rainviewer.js.map +1 -0
- package/dist/types/imagery.d.ts +82 -0
- package/dist/types/imagery.d.ts.map +1 -0
- package/dist/types/imagery.js +6 -0
- package/dist/types/imagery.js.map +1 -0
- package/dist/types/lightning.d.ts +89 -0
- package/dist/types/lightning.d.ts.map +1 -0
- package/dist/types/lightning.js +6 -0
- package/dist/types/lightning.js.map +1 -0
- package/dist/types/noaa.d.ts +535 -0
- package/dist/types/noaa.d.ts.map +1 -0
- package/dist/types/noaa.js +5 -0
- package/dist/types/noaa.js.map +1 -0
- 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/openmeteo.d.ts +583 -0
- package/dist/types/openmeteo.d.ts.map +1 -0
- package/dist/types/openmeteo.js +6 -0
- package/dist/types/openmeteo.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/types/wildfire.d.ts +83 -0
- package/dist/types/wildfire.d.ts.map +1 -0
- package/dist/types/wildfire.js +5 -0
- package/dist/types/wildfire.js.map +1 -0
- package/dist/utils/airQuality.d.ts +54 -0
- package/dist/utils/airQuality.d.ts.map +1 -0
- package/dist/utils/airQuality.js +251 -0
- package/dist/utils/airQuality.js.map +1 -0
- package/dist/utils/cache.d.ts +69 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +164 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/distance.d.ts +25 -0
- package/dist/utils/distance.d.ts.map +1 -0
- package/dist/utils/distance.js +40 -0
- package/dist/utils/distance.js.map +1 -0
- package/dist/utils/fireWeather.d.ts +76 -0
- package/dist/utils/fireWeather.d.ts.map +1 -0
- package/dist/utils/fireWeather.js +243 -0
- package/dist/utils/fireWeather.js.map +1 -0
- package/dist/utils/geography.d.ts +79 -0
- package/dist/utils/geography.d.ts.map +1 -0
- package/dist/utils/geography.js +266 -0
- package/dist/utils/geography.js.map +1 -0
- package/dist/utils/geohash.d.ts +62 -0
- package/dist/utils/geohash.d.ts.map +1 -0
- package/dist/utils/geohash.js +146 -0
- package/dist/utils/geohash.js.map +1 -0
- package/dist/utils/locationResolver.d.ts +34 -0
- package/dist/utils/locationResolver.d.ts.map +1 -0
- package/dist/utils/locationResolver.js +120 -0
- package/dist/utils/locationResolver.js.map +1 -0
- package/dist/utils/logger.d.ts +75 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +153 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/marine.d.ts +59 -0
- package/dist/utils/marine.d.ts.map +1 -0
- package/dist/utils/marine.js +215 -0
- package/dist/utils/marine.js.map +1 -0
- package/dist/utils/normals.d.ts +86 -0
- package/dist/utils/normals.d.ts.map +1 -0
- package/dist/utils/normals.js +223 -0
- package/dist/utils/normals.js.map +1 -0
- package/dist/utils/snow.d.ts +45 -0
- package/dist/utils/snow.d.ts.map +1 -0
- package/dist/utils/snow.js +144 -0
- package/dist/utils/snow.js.map +1 -0
- package/dist/utils/temperatureConversion.d.ts +12 -0
- package/dist/utils/temperatureConversion.d.ts.map +1 -0
- package/dist/utils/temperatureConversion.js +17 -0
- package/dist/utils/temperatureConversion.js.map +1 -0
- package/dist/utils/timezone.d.ts +56 -0
- package/dist/utils/timezone.d.ts.map +1 -0
- package/dist/utils/timezone.js +167 -0
- package/dist/utils/timezone.js.map +1 -0
- package/dist/utils/units.d.ts +69 -0
- package/dist/utils/units.d.ts.map +1 -0
- package/dist/utils/units.js +158 -0
- package/dist/utils/units.js.map +1 -0
- package/dist/utils/validation.d.ts +89 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +177 -0
- package/dist/utils/validation.js.map +1 -0
- package/dist/utils/version.d.ts +15 -0
- package/dist/utils/version.d.ts.map +1 -0
- package/dist/utils/version.js +24 -0
- package/dist/utils/version.js.map +1 -0
- package/package.json +74 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-Service Geocoding Service
|
|
3
|
+
* Implements automatic fallback strategy across multiple geocoding providers
|
|
4
|
+
* for maximum reliability and coverage
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Geocoding result with standardized format across all providers
|
|
8
|
+
*/
|
|
9
|
+
export interface GeocodingResult {
|
|
10
|
+
name: string;
|
|
11
|
+
display_name: string;
|
|
12
|
+
latitude: number;
|
|
13
|
+
longitude: number;
|
|
14
|
+
country?: string;
|
|
15
|
+
country_code?: string;
|
|
16
|
+
admin1?: string;
|
|
17
|
+
admin2?: string;
|
|
18
|
+
timezone?: string;
|
|
19
|
+
elevation?: number;
|
|
20
|
+
population?: number;
|
|
21
|
+
feature_code?: string;
|
|
22
|
+
confidence: 'high' | 'medium' | 'low';
|
|
23
|
+
source: 'census' | 'nominatim' | 'openmeteo';
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Multi-Service Geocoding Service
|
|
27
|
+
* Automatically tries multiple providers in order with intelligent fallback
|
|
28
|
+
*/
|
|
29
|
+
export declare class GeocodingService {
|
|
30
|
+
private census;
|
|
31
|
+
private nominatim;
|
|
32
|
+
private openmeteo;
|
|
33
|
+
constructor();
|
|
34
|
+
/**
|
|
35
|
+
* Detect if query is likely a US location
|
|
36
|
+
* Helps optimize provider selection
|
|
37
|
+
*/
|
|
38
|
+
private isLikelyUSLocation;
|
|
39
|
+
/**
|
|
40
|
+
* Geocode a location query with automatic multi-service fallback
|
|
41
|
+
*
|
|
42
|
+
* Strategy:
|
|
43
|
+
* 1. If likely US: Try Census.gov first (fast, authoritative)
|
|
44
|
+
* 2. Try Nominatim (worldwide, good natural language support)
|
|
45
|
+
* 3. Fallback to Open-Meteo (reliable, detailed metadata)
|
|
46
|
+
*
|
|
47
|
+
* @param query - Location search query (e.g., "Seattle, WA", "Paris, France")
|
|
48
|
+
* @param limit - Maximum number of results to return
|
|
49
|
+
* @returns Array of geocoding results from first successful provider
|
|
50
|
+
*/
|
|
51
|
+
geocode(query: string, limit?: number): Promise<GeocodingResult[]>;
|
|
52
|
+
/**
|
|
53
|
+
* Get service information for debugging
|
|
54
|
+
*/
|
|
55
|
+
getServiceInfo(): string;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=geocoding.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geocoding.d.ts","sourceRoot":"","sources":["../../src/services/geocoding.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACtC,MAAM,EAAE,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAC;CAC9C;AAkTD;;;GAGG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,SAAS,CAAoB;IACrC,OAAO,CAAC,SAAS,CAAoB;;IAQrC;;;OAGG;IACH,OAAO,CAAC,kBAAkB;IA0C1B;;;;;;;;;;;OAWG;IACG,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IA0D3E;;OAEG;IACH,cAAc,IAAI,MAAM;CAOzB"}
|
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-Service Geocoding Service
|
|
3
|
+
* Implements automatic fallback strategy across multiple geocoding providers
|
|
4
|
+
* for maximum reliability and coverage
|
|
5
|
+
*/
|
|
6
|
+
import axios from 'axios';
|
|
7
|
+
import { DataNotFoundError, RateLimitError, ServiceUnavailableError } from '../errors/ApiError.js';
|
|
8
|
+
import { logger } from '../utils/logger.js';
|
|
9
|
+
/**
|
|
10
|
+
* Rate limiter for controlling request frequency per provider
|
|
11
|
+
*/
|
|
12
|
+
class RateLimiter {
|
|
13
|
+
lastRequestTime = 0;
|
|
14
|
+
minInterval; // milliseconds between requests
|
|
15
|
+
constructor(requestsPerSecond) {
|
|
16
|
+
this.minInterval = 1000 / requestsPerSecond;
|
|
17
|
+
}
|
|
18
|
+
async throttle() {
|
|
19
|
+
const now = Date.now();
|
|
20
|
+
const timeSinceLastRequest = now - this.lastRequestTime;
|
|
21
|
+
if (timeSinceLastRequest < this.minInterval) {
|
|
22
|
+
const delay = this.minInterval - timeSinceLastRequest;
|
|
23
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
24
|
+
}
|
|
25
|
+
this.lastRequestTime = Date.now();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Census.gov Geocoding Provider
|
|
30
|
+
* Best for: US locations (cities, states, addresses)
|
|
31
|
+
* Coverage: United States only
|
|
32
|
+
* Rate limit: No strict limit (but we throttle to be respectful)
|
|
33
|
+
*/
|
|
34
|
+
class CensusGovProvider {
|
|
35
|
+
name = 'Census.gov';
|
|
36
|
+
client;
|
|
37
|
+
rateLimiter;
|
|
38
|
+
constructor() {
|
|
39
|
+
this.client = axios.create({
|
|
40
|
+
baseURL: 'https://geocoding.geo.census.gov/geocoder',
|
|
41
|
+
timeout: 10000,
|
|
42
|
+
headers: {
|
|
43
|
+
'Accept': 'application/json'
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
// Rate limit to 5 requests/second to be respectful
|
|
47
|
+
this.rateLimiter = new RateLimiter(5);
|
|
48
|
+
}
|
|
49
|
+
async geocode(query, limit) {
|
|
50
|
+
await this.rateLimiter.throttle();
|
|
51
|
+
try {
|
|
52
|
+
logger.debug(`Census.gov geocode: "${query}"`);
|
|
53
|
+
const response = await this.client.get('/locations/onelineaddress', {
|
|
54
|
+
params: {
|
|
55
|
+
address: query,
|
|
56
|
+
benchmark: 'Public_AR_Current',
|
|
57
|
+
format: 'json'
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
if (!response.data?.result?.addressMatches || response.data.result.addressMatches.length === 0) {
|
|
61
|
+
logger.debug('Census.gov: No results found');
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
const matches = response.data.result.addressMatches;
|
|
65
|
+
const results = [];
|
|
66
|
+
for (let i = 0; i < Math.min(matches.length, limit); i++) {
|
|
67
|
+
const match = matches[i];
|
|
68
|
+
const coords = match.coordinates;
|
|
69
|
+
if (!coords || coords.x === undefined || coords.y === undefined) {
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
// Census.gov uses longitude, latitude (x, y) order
|
|
73
|
+
const result = {
|
|
74
|
+
name: match.matchedAddress || query,
|
|
75
|
+
display_name: match.matchedAddress || query,
|
|
76
|
+
latitude: coords.y,
|
|
77
|
+
longitude: coords.x,
|
|
78
|
+
country: 'United States',
|
|
79
|
+
country_code: 'US',
|
|
80
|
+
admin1: match.addressComponents?.state,
|
|
81
|
+
admin2: match.addressComponents?.county,
|
|
82
|
+
confidence: 'high', // Census.gov is authoritative for US locations
|
|
83
|
+
source: 'census'
|
|
84
|
+
};
|
|
85
|
+
results.push(result);
|
|
86
|
+
}
|
|
87
|
+
logger.debug(`Census.gov: Found ${results.length} result(s)`);
|
|
88
|
+
return results;
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
if (axios.isAxiosError(error)) {
|
|
92
|
+
if (error.code === 'ECONNABORTED') {
|
|
93
|
+
throw new ServiceUnavailableError('OpenMeteo', 'Census.gov geocoding service timed out');
|
|
94
|
+
}
|
|
95
|
+
if (error.response?.status === 429) {
|
|
96
|
+
throw new RateLimitError('OpenMeteo', 'Census.gov geocoding rate limit exceeded');
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
logger.debug(`Census.gov error: ${error instanceof Error ? error.message : 'Unknown'}`);
|
|
100
|
+
return []; // Return empty array for fallback
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Nominatim (OpenStreetMap) Provider
|
|
106
|
+
* Best for: Worldwide locations, landmarks, natural language queries
|
|
107
|
+
* Coverage: Global
|
|
108
|
+
* Rate limit: 1 request/second (strictly enforced)
|
|
109
|
+
*/
|
|
110
|
+
class NominatimProvider {
|
|
111
|
+
name = 'Nominatim';
|
|
112
|
+
client;
|
|
113
|
+
rateLimiter;
|
|
114
|
+
constructor() {
|
|
115
|
+
this.client = axios.create({
|
|
116
|
+
baseURL: 'https://nominatim.openstreetmap.org',
|
|
117
|
+
timeout: 10000,
|
|
118
|
+
headers: {
|
|
119
|
+
'User-Agent': '(weather-mcp, github.com/weather-mcp/weather-mcp)',
|
|
120
|
+
'Accept': 'application/json'
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
// Strict 1 request/second rate limit as per Nominatim usage policy
|
|
124
|
+
this.rateLimiter = new RateLimiter(1);
|
|
125
|
+
}
|
|
126
|
+
async geocode(query, limit) {
|
|
127
|
+
await this.rateLimiter.throttle();
|
|
128
|
+
try {
|
|
129
|
+
logger.debug(`Nominatim geocode: "${query}"`);
|
|
130
|
+
const response = await this.client.get('/search', {
|
|
131
|
+
params: {
|
|
132
|
+
q: query,
|
|
133
|
+
format: 'json',
|
|
134
|
+
addressdetails: 1,
|
|
135
|
+
limit: Math.min(limit, 50), // Nominatim max is 50
|
|
136
|
+
'accept-language': 'en'
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
if (!response.data || response.data.length === 0) {
|
|
140
|
+
logger.debug('Nominatim: No results found');
|
|
141
|
+
return [];
|
|
142
|
+
}
|
|
143
|
+
const results = response.data.map((item) => {
|
|
144
|
+
const address = item.address || {};
|
|
145
|
+
// Determine confidence based on importance and type
|
|
146
|
+
let confidence = 'medium';
|
|
147
|
+
if (item.importance > 0.6)
|
|
148
|
+
confidence = 'high';
|
|
149
|
+
else if (item.importance < 0.3)
|
|
150
|
+
confidence = 'low';
|
|
151
|
+
return {
|
|
152
|
+
name: item.name || item.display_name,
|
|
153
|
+
display_name: item.display_name,
|
|
154
|
+
latitude: parseFloat(item.lat),
|
|
155
|
+
longitude: parseFloat(item.lon),
|
|
156
|
+
country: address.country,
|
|
157
|
+
country_code: address.country_code?.toUpperCase(),
|
|
158
|
+
admin1: address.state || address.region,
|
|
159
|
+
admin2: address.county,
|
|
160
|
+
feature_code: this.mapTypeToFeatureCode(item.type),
|
|
161
|
+
confidence,
|
|
162
|
+
source: 'nominatim'
|
|
163
|
+
};
|
|
164
|
+
});
|
|
165
|
+
logger.debug(`Nominatim: Found ${results.length} result(s)`);
|
|
166
|
+
return results;
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
if (axios.isAxiosError(error)) {
|
|
170
|
+
if (error.code === 'ECONNABORTED') {
|
|
171
|
+
throw new ServiceUnavailableError('OpenMeteo', 'Nominatim geocoding service timed out');
|
|
172
|
+
}
|
|
173
|
+
if (error.response?.status === 429) {
|
|
174
|
+
throw new RateLimitError('OpenMeteo', 'Nominatim geocoding rate limit exceeded (1 req/sec limit)');
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
logger.debug(`Nominatim error: ${error instanceof Error ? error.message : 'Unknown'}`);
|
|
178
|
+
return []; // Return empty array for fallback
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Map Nominatim type to GeoNames-style feature code
|
|
183
|
+
*/
|
|
184
|
+
mapTypeToFeatureCode(type) {
|
|
185
|
+
const typeMap = {
|
|
186
|
+
'city': 'PPL',
|
|
187
|
+
'town': 'PPL',
|
|
188
|
+
'village': 'PPL',
|
|
189
|
+
'administrative': 'ADM1',
|
|
190
|
+
'country': 'PCLI',
|
|
191
|
+
'state': 'ADM1',
|
|
192
|
+
'county': 'ADM2',
|
|
193
|
+
'island': 'ISL',
|
|
194
|
+
'airport': 'AIRP',
|
|
195
|
+
'park': 'PRK',
|
|
196
|
+
'lake': 'LAKE'
|
|
197
|
+
};
|
|
198
|
+
return typeMap[type.toLowerCase()] || type.toUpperCase();
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Open-Meteo Geocoding Provider (existing implementation as fallback)
|
|
203
|
+
* Best for: Reliable global coverage with detailed metadata
|
|
204
|
+
* Coverage: Global
|
|
205
|
+
* Rate limit: Part of 10,000 requests/day shared limit
|
|
206
|
+
*/
|
|
207
|
+
class OpenMeteoProvider {
|
|
208
|
+
name = 'Open-Meteo';
|
|
209
|
+
client;
|
|
210
|
+
constructor() {
|
|
211
|
+
this.client = axios.create({
|
|
212
|
+
baseURL: 'https://geocoding-api.open-meteo.com/v1',
|
|
213
|
+
timeout: 10000,
|
|
214
|
+
headers: {
|
|
215
|
+
'Accept': 'application/json'
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
async geocode(query, limit) {
|
|
220
|
+
try {
|
|
221
|
+
logger.debug(`Open-Meteo geocode: "${query}"`);
|
|
222
|
+
const response = await this.client.get('/search', {
|
|
223
|
+
params: {
|
|
224
|
+
name: query,
|
|
225
|
+
count: Math.min(limit, 100),
|
|
226
|
+
language: 'en',
|
|
227
|
+
format: 'json'
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
if (!response.data?.results || response.data.results.length === 0) {
|
|
231
|
+
logger.debug('Open-Meteo: No results found');
|
|
232
|
+
return [];
|
|
233
|
+
}
|
|
234
|
+
const results = response.data.results.map((item) => ({
|
|
235
|
+
name: item.name,
|
|
236
|
+
display_name: [item.name, item.admin1, item.admin2, item.country]
|
|
237
|
+
.filter(Boolean)
|
|
238
|
+
.join(', '),
|
|
239
|
+
latitude: item.latitude,
|
|
240
|
+
longitude: item.longitude,
|
|
241
|
+
country: item.country,
|
|
242
|
+
country_code: item.country_code,
|
|
243
|
+
admin1: item.admin1,
|
|
244
|
+
admin2: item.admin2,
|
|
245
|
+
timezone: item.timezone,
|
|
246
|
+
elevation: item.elevation,
|
|
247
|
+
population: item.population,
|
|
248
|
+
feature_code: item.feature_code,
|
|
249
|
+
confidence: 'medium', // Open-Meteo is reliable but not authoritative
|
|
250
|
+
source: 'openmeteo'
|
|
251
|
+
}));
|
|
252
|
+
logger.debug(`Open-Meteo: Found ${results.length} result(s)`);
|
|
253
|
+
return results;
|
|
254
|
+
}
|
|
255
|
+
catch (error) {
|
|
256
|
+
if (axios.isAxiosError(error)) {
|
|
257
|
+
if (error.code === 'ECONNABORTED') {
|
|
258
|
+
throw new ServiceUnavailableError('OpenMeteo', 'Open-Meteo geocoding service timed out');
|
|
259
|
+
}
|
|
260
|
+
if (error.response?.status === 429) {
|
|
261
|
+
throw new RateLimitError('OpenMeteo', 'Open-Meteo geocoding rate limit exceeded');
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
logger.debug(`Open-Meteo error: ${error instanceof Error ? error.message : 'Unknown'}`);
|
|
265
|
+
return []; // Return empty array for fallback
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Multi-Service Geocoding Service
|
|
271
|
+
* Automatically tries multiple providers in order with intelligent fallback
|
|
272
|
+
*/
|
|
273
|
+
export class GeocodingService {
|
|
274
|
+
census;
|
|
275
|
+
nominatim;
|
|
276
|
+
openmeteo;
|
|
277
|
+
constructor() {
|
|
278
|
+
this.census = new CensusGovProvider();
|
|
279
|
+
this.nominatim = new NominatimProvider();
|
|
280
|
+
this.openmeteo = new OpenMeteoProvider();
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Detect if query is likely a US location
|
|
284
|
+
* Helps optimize provider selection
|
|
285
|
+
*/
|
|
286
|
+
isLikelyUSLocation(query) {
|
|
287
|
+
const lowerQuery = query.toLowerCase();
|
|
288
|
+
// State abbreviations
|
|
289
|
+
const stateAbbreviations = [
|
|
290
|
+
'al', 'ak', 'az', 'ar', 'ca', 'co', 'ct', 'de', 'fl', 'ga',
|
|
291
|
+
'hi', 'id', 'il', 'in', 'ia', 'ks', 'ky', 'la', 'me', 'md',
|
|
292
|
+
'ma', 'mi', 'mn', 'ms', 'mo', 'mt', 'ne', 'nv', 'nh', 'nj',
|
|
293
|
+
'nm', 'ny', 'nc', 'nd', 'oh', 'ok', 'or', 'pa', 'ri', 'sc',
|
|
294
|
+
'sd', 'tn', 'tx', 'ut', 'vt', 'va', 'wa', 'wv', 'wi', 'wy'
|
|
295
|
+
];
|
|
296
|
+
// Check for state abbreviations (e.g., "Seattle, WA")
|
|
297
|
+
for (const state of stateAbbreviations) {
|
|
298
|
+
if (lowerQuery.includes(`, ${state}`) || lowerQuery.endsWith(` ${state}`)) {
|
|
299
|
+
return true;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
// Check for explicit country mentions (US or USA)
|
|
303
|
+
if (lowerQuery.includes('usa') ||
|
|
304
|
+
lowerQuery.includes('u.s.a') ||
|
|
305
|
+
lowerQuery.includes('united states')) {
|
|
306
|
+
return true;
|
|
307
|
+
}
|
|
308
|
+
// Check for explicit non-US country mentions
|
|
309
|
+
const nonUSKeywords = [
|
|
310
|
+
'france', 'germany', 'japan', 'china', 'uk', 'england',
|
|
311
|
+
'canada', 'mexico', 'australia', 'india', 'brazil'
|
|
312
|
+
];
|
|
313
|
+
for (const keyword of nonUSKeywords) {
|
|
314
|
+
if (lowerQuery.includes(keyword)) {
|
|
315
|
+
return false;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
// Default: Assume might be US (we'll try Census.gov first, then fallback)
|
|
319
|
+
return null; // null means "uncertain"
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Geocode a location query with automatic multi-service fallback
|
|
323
|
+
*
|
|
324
|
+
* Strategy:
|
|
325
|
+
* 1. If likely US: Try Census.gov first (fast, authoritative)
|
|
326
|
+
* 2. Try Nominatim (worldwide, good natural language support)
|
|
327
|
+
* 3. Fallback to Open-Meteo (reliable, detailed metadata)
|
|
328
|
+
*
|
|
329
|
+
* @param query - Location search query (e.g., "Seattle, WA", "Paris, France")
|
|
330
|
+
* @param limit - Maximum number of results to return
|
|
331
|
+
* @returns Array of geocoding results from first successful provider
|
|
332
|
+
*/
|
|
333
|
+
async geocode(query, limit = 5) {
|
|
334
|
+
const isLikelyUS = this.isLikelyUSLocation(query);
|
|
335
|
+
const providers = [];
|
|
336
|
+
// Build provider order based on query characteristics
|
|
337
|
+
if (isLikelyUS === true) {
|
|
338
|
+
// Definitely US - try Census.gov first
|
|
339
|
+
providers.push(this.census, this.nominatim, this.openmeteo);
|
|
340
|
+
logger.debug('Provider strategy: US-optimized (Census → Nominatim → Open-Meteo)');
|
|
341
|
+
}
|
|
342
|
+
else if (isLikelyUS === false) {
|
|
343
|
+
// Definitely non-US - skip Census.gov
|
|
344
|
+
providers.push(this.nominatim, this.openmeteo);
|
|
345
|
+
logger.debug('Provider strategy: International (Nominatim → Open-Meteo)');
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
348
|
+
// Uncertain - try all providers
|
|
349
|
+
providers.push(this.census, this.nominatim, this.openmeteo);
|
|
350
|
+
logger.debug('Provider strategy: Uncertain (Census → Nominatim → Open-Meteo)');
|
|
351
|
+
}
|
|
352
|
+
const errors = [];
|
|
353
|
+
// Try each provider in order
|
|
354
|
+
for (const provider of providers) {
|
|
355
|
+
try {
|
|
356
|
+
logger.debug(`Trying provider: ${provider.name}`);
|
|
357
|
+
const results = await provider.geocode(query, limit);
|
|
358
|
+
if (results.length > 0) {
|
|
359
|
+
logger.info(`Geocoding successful via ${provider.name}: ${results.length} result(s)`);
|
|
360
|
+
return results;
|
|
361
|
+
}
|
|
362
|
+
logger.debug(`${provider.name}: No results found`);
|
|
363
|
+
errors.push(`${provider.name}: No results found`);
|
|
364
|
+
}
|
|
365
|
+
catch (error) {
|
|
366
|
+
const errorMsg = error instanceof Error ? error.message : 'Unknown error';
|
|
367
|
+
logger.debug(`${provider.name} failed: ${errorMsg}`);
|
|
368
|
+
errors.push(`${provider.name}: ${errorMsg}`);
|
|
369
|
+
// Continue to next provider
|
|
370
|
+
continue;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
// All providers failed or returned no results
|
|
374
|
+
throw new DataNotFoundError('OpenMeteo', `No locations found matching "${query}".\n\n` +
|
|
375
|
+
`Tried ${providers.length} provider(s): ${errors.join('; ')}\n\n` +
|
|
376
|
+
`Suggestions:\n` +
|
|
377
|
+
`- Add more detail (e.g., "Paris, France" instead of "Paris")\n` +
|
|
378
|
+
`- Check spelling\n` +
|
|
379
|
+
`- Use a nearby major city\n` +
|
|
380
|
+
`- Try providing coordinates directly (latitude, longitude)`);
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Get service information for debugging
|
|
384
|
+
*/
|
|
385
|
+
getServiceInfo() {
|
|
386
|
+
return `Multi-Service Geocoding:\n` +
|
|
387
|
+
`- Census.gov (US locations, high accuracy)\n` +
|
|
388
|
+
`- Nominatim/OpenStreetMap (worldwide, 1 req/sec limit)\n` +
|
|
389
|
+
`- Open-Meteo (worldwide fallback)\n` +
|
|
390
|
+
`Automatic fallback strategy based on query characteristics`;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
//# sourceMappingURL=geocoding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geocoding.js","sourceRoot":"","sources":["../../src/services/geocoding.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Service for managing saved/favorite locations
|
|
3
|
+
* Stores locations in ~/.weather-mcp/locations.json
|
|
4
|
+
*/
|
|
5
|
+
import type { SavedLocation, SavedLocationsStore } from '../types/savedLocations.js';
|
|
6
|
+
export declare class LocationStore {
|
|
7
|
+
private readonly storePath;
|
|
8
|
+
private readonly storeDir;
|
|
9
|
+
private cache;
|
|
10
|
+
constructor(customPath?: string);
|
|
11
|
+
/**
|
|
12
|
+
* Ensure the storage directory exists
|
|
13
|
+
* @private
|
|
14
|
+
*/
|
|
15
|
+
private ensureDirectoryExists;
|
|
16
|
+
/**
|
|
17
|
+
* Load all saved locations from disk
|
|
18
|
+
*/
|
|
19
|
+
load(): SavedLocationsStore;
|
|
20
|
+
/**
|
|
21
|
+
* Save all locations to disk
|
|
22
|
+
* @private
|
|
23
|
+
*/
|
|
24
|
+
private save;
|
|
25
|
+
/**
|
|
26
|
+
* Get a saved location by alias
|
|
27
|
+
*/
|
|
28
|
+
get(alias: string): SavedLocation | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* Get all saved locations
|
|
31
|
+
*/
|
|
32
|
+
getAll(): SavedLocationsStore;
|
|
33
|
+
/**
|
|
34
|
+
* Save or update a location
|
|
35
|
+
*/
|
|
36
|
+
set(alias: string, location: Omit<SavedLocation, 'saved_at' | 'updated_at'>): SavedLocation;
|
|
37
|
+
/**
|
|
38
|
+
* Remove a saved location
|
|
39
|
+
*/
|
|
40
|
+
remove(alias: string): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Check if a location exists
|
|
43
|
+
*/
|
|
44
|
+
has(alias: string): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Get the number of saved locations
|
|
47
|
+
*/
|
|
48
|
+
count(): number;
|
|
49
|
+
/**
|
|
50
|
+
* Clear all saved locations
|
|
51
|
+
*/
|
|
52
|
+
clear(): void;
|
|
53
|
+
/**
|
|
54
|
+
* Get the storage file path
|
|
55
|
+
*/
|
|
56
|
+
getStorePath(): string;
|
|
57
|
+
/**
|
|
58
|
+
* Invalidate the cache, forcing reload on next access
|
|
59
|
+
*/
|
|
60
|
+
invalidateCache(): void;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=locationStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locationStore.d.ts","sourceRoot":"","sources":["../../src/services/locationStore.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAIrF,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,KAAK,CAAoC;gBAErC,UAAU,CAAC,EAAE,MAAM;IAU/B;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IAc7B;;OAEG;IACH,IAAI,IAAI,mBAAmB;IA6C3B;;;OAGG;IACH,OAAO,CAAC,IAAI;IAmBZ;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAM7C;;OAEG;IACH,MAAM,IAAI,mBAAmB;IAI7B;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC,aAAa,EAAE,UAAU,GAAG,YAAY,CAAC,GAAG,aAAa;IAoC3F;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAe9B;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAM3B;;OAEG;IACH,KAAK,IAAI,MAAM;IAKf;;OAEG;IACH,KAAK,IAAI,IAAI;IAKb;;OAEG;IACH,YAAY,IAAI,MAAM;IAItB;;OAEG;IACH,eAAe,IAAI,IAAI;CAGxB"}
|