open-meteo-mcp-server
Version:
Model Context Protocol server for Open-Meteo weather APIs
190 lines • 7.93 kB
JavaScript
import axios from 'axios';
export class OpenMeteoClient {
client;
airQualityClient;
marineClient;
archiveClient;
seasonalClient;
ensembleClient;
geocodingClient;
floodClient;
climateClient;
constructor(baseURL = process.env.OPEN_METEO_API_URL || 'https://api.open-meteo.com', version = 'unknown') {
const config = {
timeout: 30000,
headers: {
Accept: 'application/json',
'User-Agent': `Open-Meteo-MCP-Server/${version}`,
},
};
// Utilisation des variables d'environnement avec des valeurs par défaut
const airQualityURL = process.env.OPEN_METEO_AIR_QUALITY_API_URL || 'https://air-quality-api.open-meteo.com';
const marineURL = process.env.OPEN_METEO_MARINE_API_URL || 'https://marine-api.open-meteo.com';
const archiveURL = process.env.OPEN_METEO_ARCHIVE_API_URL || 'https://archive-api.open-meteo.com';
const seasonalURL = process.env.OPEN_METEO_SEASONAL_API_URL || 'https://seasonal-api.open-meteo.com';
const ensembleURL = process.env.OPEN_METEO_ENSEMBLE_API_URL || 'https://ensemble-api.open-meteo.com';
const geocodingURL = process.env.OPEN_METEO_GEOCODING_API_URL || 'https://geocoding-api.open-meteo.com';
const floodURL = process.env.OPEN_METEO_FLOOD_API_URL || 'https://flood-api.open-meteo.com';
const climateURL = process.env.OPEN_METEO_CLIMATE_API_URL || 'https://climate-api.open-meteo.com';
this.client = axios.create({ baseURL, ...config });
this.airQualityClient = axios.create({ baseURL: airQualityURL, ...config });
this.marineClient = axios.create({ baseURL: marineURL, ...config });
this.archiveClient = axios.create({ baseURL: archiveURL, ...config });
this.seasonalClient = axios.create({ baseURL: seasonalURL, ...config });
this.ensembleClient = axios.create({ baseURL: ensembleURL, ...config });
this.geocodingClient = axios.create({ baseURL: geocodingURL, ...config });
this.floodClient = axios.create({ baseURL: floodURL, ...config });
this.climateClient = axios.create({ baseURL: climateURL, ...config });
this.setupErrorInterceptors();
}
setupErrorInterceptors() {
for (const instance of [
this.client,
this.airQualityClient,
this.marineClient,
this.archiveClient,
this.seasonalClient,
this.ensembleClient,
this.geocodingClient,
this.floodClient,
this.climateClient,
]) {
instance.interceptors.response.use(undefined, OpenMeteoClient.mapHttpError);
}
}
static mapHttpError(error) {
if (axios.isAxiosError(error)) {
const status = error.response?.status;
const data = error.response?.data;
const apiMessage = data?.reason ??
data?.error ??
error.message;
if (status === 400)
throw new Error(`Invalid request parameters: ${apiMessage}`);
if (status === 422)
throw new Error(`Invalid parameter value: ${apiMessage}`);
if (status === 429)
throw new Error('Open-Meteo rate limit reached. Please retry later.');
if (status !== undefined && status >= 500)
throw new Error(`Open-Meteo server error (${status}): ${apiMessage}`);
}
throw error;
}
buildParams(params) {
const result = {};
for (const [key, value] of Object.entries(params)) {
if (value !== undefined && value !== null) {
if (Array.isArray(value)) {
result[key] = value.join(',');
}
else {
result[key] = String(value);
}
}
}
return result;
}
async getForecast(params) {
const response = await this.client
.get('/v1/forecast', { params: this.buildParams(params) })
.catch(OpenMeteoClient.mapHttpError);
return response.data;
}
async getArchive(params) {
const response = await this.archiveClient
.get('/v1/archive', { params: this.buildParams(params) })
.catch(OpenMeteoClient.mapHttpError);
return response.data;
}
async getDwdIcon(params) {
const response = await this.client
.get('/v1/dwd-icon', { params: this.buildParams(params) })
.catch(OpenMeteoClient.mapHttpError);
return response.data;
}
async getGfs(params) {
const response = await this.client
.get('/v1/gfs', { params: this.buildParams(params) })
.catch(OpenMeteoClient.mapHttpError);
return response.data;
}
async getMeteoFrance(params) {
const response = await this.client
.get('/v1/meteofrance', { params: this.buildParams(params) })
.catch(OpenMeteoClient.mapHttpError);
return response.data;
}
async getEcmwf(params) {
const response = await this.client
.get('/v1/ecmwf', { params: this.buildParams(params) })
.catch(OpenMeteoClient.mapHttpError);
return response.data;
}
async getJma(params) {
const response = await this.client
.get('/v1/jma', { params: this.buildParams(params) })
.catch(OpenMeteoClient.mapHttpError);
return response.data;
}
async getMetno(params) {
const response = await this.client
.get('/v1/metno', { params: this.buildParams(params) })
.catch(OpenMeteoClient.mapHttpError);
return response.data;
}
async getGem(params) {
const response = await this.client
.get('/v1/gem', { params: this.buildParams(params) })
.catch(OpenMeteoClient.mapHttpError);
return response.data;
}
async getAirQuality(params) {
const response = await this.airQualityClient
.get('/v1/air-quality', { params: this.buildParams(params) })
.catch(OpenMeteoClient.mapHttpError);
return response.data;
}
async getMarine(params) {
const response = await this.marineClient
.get('/v1/marine', { params: this.buildParams(params) })
.catch(OpenMeteoClient.mapHttpError);
return response.data;
}
async getEnsemble(params) {
const response = await this.ensembleClient
.get('/v1/ensemble', { params: this.buildParams(params) })
.catch(OpenMeteoClient.mapHttpError);
return response.data;
}
async getElevation(params) {
const response = await this.client
.get('/v1/elevation', { params: this.buildParams(params) })
.catch(OpenMeteoClient.mapHttpError);
return response.data;
}
async getFlood(params) {
const response = await this.floodClient
.get('/v1/flood', { params: this.buildParams(params) })
.catch(OpenMeteoClient.mapHttpError);
return response.data;
}
async getSeasonal(params) {
const response = await this.seasonalClient
.get('/v1/seasonal', { params: this.buildParams(params) })
.catch(OpenMeteoClient.mapHttpError);
return response.data;
}
async getClimate(params) {
const response = await this.climateClient
.get('/v1/climate', { params: this.buildParams(params) })
.catch(OpenMeteoClient.mapHttpError);
return response.data;
}
async getGeocoding(params) {
const response = await this.geocodingClient
.get('/v1/search', { params: this.buildParams(params) })
.catch(OpenMeteoClient.mapHttpError);
return response.data;
}
}
//# sourceMappingURL=client.js.map