├── vitest.config.ts ├── .eslintrc.json ├── tsconfig.json ├── LICENSE ├── .github └── workflows │ ├── release.yml │ └── ci.yml ├── .gitignore ├── package.json ├── src ├── index.test.ts ├── client.ts ├── index.ts ├── types.ts └── tools.ts ├── CLAUDE.md ├── README.md └── openapi.yml /vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vitest/config'; 2 | 3 | export default defineConfig({ 4 | test: { 5 | globals: true, 6 | environment: 'node', 7 | include: ['src/**/*.test.ts'], 8 | exclude: ['node_modules', 'dist'], 9 | coverage: { 10 | reporter: ['text', 'json', 'html'] 11 | } 12 | } 13 | }); -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "es2022": true, 4 | "node": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended" 8 | ], 9 | "parser": "@typescript-eslint/parser", 10 | "parserOptions": { 11 | "ecmaVersion": "latest", 12 | "sourceType": "module" 13 | }, 14 | "plugins": [ 15 | "@typescript-eslint" 16 | ], 17 | "rules": { 18 | "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }], 19 | "@typescript-eslint/no-explicit-any": "warn", 20 | "prefer-const": "error", 21 | "no-var": "error", 22 | "no-undef": "off" 23 | }, 24 | "overrides": [ 25 | { 26 | "files": ["*.ts", "*.tsx"], 27 | "rules": { 28 | "no-unused-vars": "off" 29 | } 30 | } 31 | ], 32 | "ignorePatterns": [ 33 | "dist/**/*", 34 | "node_modules/**/*", 35 | "*.js" 36 | ] 37 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2022", 4 | "module": "ESNext", 5 | "moduleResolution": "node", 6 | "esModuleInterop": true, 7 | "allowSyntheticDefaultImports": true, 8 | "strict": true, 9 | "skipLibCheck": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "outDir": "./dist", 12 | "rootDir": "./src", 13 | "declaration": true, 14 | "declarationMap": true, 15 | "sourceMap": true, 16 | "resolveJsonModule": true, 17 | "noUnusedLocals": true, 18 | "noUnusedParameters": true, 19 | "exactOptionalPropertyTypes": true, 20 | "noImplicitReturns": true, 21 | "noFallthroughCasesInSwitch": true, 22 | "noUncheckedIndexedAccess": true, 23 | "noImplicitOverride": true 24 | }, 25 | "include": [ 26 | "src/**/*" 27 | ], 28 | "exclude": [ 29 | "node_modules", 30 | "dist", 31 | "**/*.test.ts" 32 | ] 33 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release and Publish 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*' 7 | workflow_dispatch: 8 | 9 | jobs: 10 | release: 11 | runs-on: ubuntu-latest 12 | permissions: 13 | contents: write 14 | packages: write 15 | id-token: write 16 | 17 | steps: 18 | - name: Checkout repository 19 | uses: actions/checkout@v4 20 | 21 | - name: Setup Node.js 22 | uses: actions/setup-node@v4 23 | with: 24 | node-version: '18' 25 | registry-url: 'https://registry.npmjs.org' 26 | 27 | - name: Install dependencies 28 | run: npm ci 29 | 30 | - name: Run tests 31 | run: npm test 32 | 33 | - name: Build project 34 | run: npm run build 35 | 36 | - name: Publish to npm 37 | run: npm publish --provenance 38 | env: 39 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 40 | 41 | - name: Create GitHub Release 42 | uses: actions/create-release@v1 43 | env: 44 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 45 | with: 46 | tag_name: ${{ github.ref }} 47 | release_name: Release ${{ github.ref }} 48 | draft: false 49 | prerelease: false -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [ main, develop, 'feature/**', 'hotfix/**', 'release/**' ] 6 | pull_request: 7 | branches: [ main, develop ] 8 | # Allow manual trigger for any branch 9 | workflow_dispatch: 10 | 11 | jobs: 12 | test: 13 | runs-on: ubuntu-latest 14 | 15 | strategy: 16 | matrix: 17 | node-version: [18, 20, 21] 18 | 19 | steps: 20 | - name: Checkout repository 21 | uses: actions/checkout@v4 22 | 23 | - name: Setup Node.js ${{ matrix.node-version }} 24 | uses: actions/setup-node@v4 25 | with: 26 | node-version: ${{ matrix.node-version }} 27 | cache: 'npm' 28 | 29 | - name: Install dependencies 30 | run: npm ci 31 | 32 | - name: Type check 33 | run: npm run typecheck 34 | 35 | - name: Lint 36 | run: npm run lint 37 | 38 | - name: Run tests 39 | run: npm test 40 | 41 | - name: Build project 42 | run: npm run build 43 | 44 | - name: Test installation 45 | run: | 46 | npm pack 47 | npm install -g ./open-meteo-mcp-server-*.tgz 48 | 49 | security: 50 | runs-on: ubuntu-latest 51 | 52 | steps: 53 | - name: Checkout repository 54 | uses: actions/checkout@v4 55 | 56 | - name: Setup Node.js 57 | uses: actions/setup-node@v4 58 | with: 59 | node-version: '18' 60 | cache: 'npm' 61 | 62 | - name: Install dependencies 63 | run: npm ci 64 | 65 | - name: Run security audit 66 | run: npm audit --audit-level high -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | node_modules/ 3 | npm-debug.log* 4 | yarn-debug.log* 5 | yarn-error.log* 6 | 7 | # Build outputs 8 | dist/ 9 | build/ 10 | *.tsbuildinfo 11 | 12 | # Environment variables 13 | .env 14 | .env.local 15 | .env.development.local 16 | .env.test.local 17 | .env.production.local 18 | 19 | # Logs 20 | logs 21 | *.log 22 | lerna-debug.log* 23 | 24 | # Runtime data 25 | pids 26 | *.pid 27 | *.seed 28 | *.pid.lock 29 | 30 | # Coverage directory used by tools like istanbul 31 | coverage/ 32 | *.lcov 33 | 34 | # nyc test coverage 35 | .nyc_output 36 | 37 | # Dependency directories 38 | jspm_packages/ 39 | 40 | # Optional npm cache directory 41 | .npm 42 | 43 | # Optional eslint cache 44 | .eslintcache 45 | 46 | # Optional REPL history 47 | .node_repl_history 48 | 49 | # Output of 'npm pack' 50 | *.tgz 51 | 52 | # Yarn Integrity file 53 | .yarn-integrity 54 | 55 | # parcel-bundler cache (https://parceljs.org/) 56 | .cache 57 | .parcel-cache 58 | 59 | # next.js build output 60 | .next 61 | 62 | # nuxt.js build output 63 | .nuxt 64 | 65 | # vuepress build output 66 | .vuepress/dist 67 | 68 | # Serverless directories 69 | .serverless/ 70 | 71 | # FuseBox cache 72 | .fusebox/ 73 | 74 | # DynamoDB Local files 75 | .dynamodb/ 76 | 77 | # TernJS port file 78 | .tern-port 79 | 80 | # Stores VSCode versions used for testing VSCode extensions 81 | .vscode-test 82 | 83 | # Claude/MCP specific 84 | .claude/ 85 | .mcp.json 86 | 87 | # IDE files 88 | .vscode/ 89 | .idea/ 90 | *.swp 91 | *.swo 92 | *~ 93 | 94 | # OS generated files 95 | .DS_Store 96 | .DS_Store? 97 | ._* 98 | .Spotlight-V100 99 | .Trashes 100 | ehthumbs.db 101 | Thumbs.db 102 | 103 | # Temporary files 104 | *.tmp 105 | *.temp -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "open-meteo-mcp-server", 3 | "version": "1.1.1", 4 | "description": "Model Context Protocol server for Open-Meteo weather APIs", 5 | "main": "dist/index.js", 6 | "bin": { 7 | "open-meteo-mcp-server": "dist/index.js" 8 | }, 9 | "type": "module", 10 | "scripts": { 11 | "build": "tsc", 12 | "start": "node dist/index.js", 13 | "dev": "tsx src/index.ts", 14 | "test": "vitest", 15 | "lint": "eslint src/**/*.ts", 16 | "typecheck": "tsc --noEmit", 17 | "release": "npm run build && npm run test && npm run lint", 18 | "release:patch": "npm version patch && git push origin main --tags", 19 | "release:minor": "npm version minor && git push origin main --tags", 20 | "release:major": "npm version major && git push origin main --tags" 21 | }, 22 | "keywords": [ 23 | "mcp", 24 | "weather", 25 | "open-meteo", 26 | "forecast", 27 | "api" 28 | ], 29 | "author": "Claude Code", 30 | "license": "MIT", 31 | "repository": { 32 | "type": "git", 33 | "url": "https://github.com/cmer81/open-meteo-mcp.git" 34 | }, 35 | "bugs": { 36 | "url": "https://github.com/cmer81/open-meteo-mcp/issues" 37 | }, 38 | "homepage": "https://github.com/cmer81/open-meteo-mcp#readme", 39 | "files": [ 40 | "dist/**/*", 41 | "README.md", 42 | "LICENSE" 43 | ], 44 | "dependencies": { 45 | "@modelcontextprotocol/sdk": "^0.5.0", 46 | "axios": "^1.6.0", 47 | "zod": "^3.22.0" 48 | }, 49 | "devDependencies": { 50 | "@types/node": "^20.0.0", 51 | "@typescript-eslint/eslint-plugin": "^7.0.0", 52 | "@typescript-eslint/parser": "^7.0.0", 53 | "eslint": "^8.0.0", 54 | "tsx": "^4.0.0", 55 | "typescript": "^5.3.0", 56 | "vitest": "^1.0.0" 57 | }, 58 | "engines": { 59 | "node": ">=18.0.0" 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/index.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect } from 'vitest'; 2 | import { 3 | ForecastParamsSchema, 4 | ArchiveParamsSchema, 5 | AirQualityParamsSchema, 6 | MarineParamsSchema, 7 | ElevationParamsSchema, 8 | GeocodingParamsSchema, 9 | LocationSchema 10 | } from './types.js'; 11 | import { ALL_TOOLS } from './tools.js'; 12 | import { OpenMeteoClient } from './client.js'; 13 | 14 | // Basic import tests 15 | describe('Module imports', () => { 16 | it('should import types successfully', () => { 17 | expect(ForecastParamsSchema).toBeDefined(); 18 | expect(ArchiveParamsSchema).toBeDefined(); 19 | expect(AirQualityParamsSchema).toBeDefined(); 20 | expect(MarineParamsSchema).toBeDefined(); 21 | expect(ElevationParamsSchema).toBeDefined(); 22 | expect(GeocodingParamsSchema).toBeDefined(); 23 | expect(LocationSchema).toBeDefined(); 24 | }); 25 | 26 | it('should validate coordinates schema', () => { 27 | const validParams = { 28 | latitude: 48.8566, 29 | longitude: 2.3522 30 | }; 31 | 32 | expect(() => ForecastParamsSchema.parse(validParams)).not.toThrow(); 33 | 34 | const invalidParams = { 35 | latitude: 91, // Invalid latitude 36 | longitude: 2.3522 37 | }; 38 | 39 | expect(() => ForecastParamsSchema.parse(invalidParams)).toThrow(); 40 | }); 41 | 42 | it('should validate geocoding parameters', () => { 43 | const validGeocodingParams = { 44 | name: 'Paris', 45 | count: 5 46 | }; 47 | 48 | expect(() => GeocodingParamsSchema.parse(validGeocodingParams)).not.toThrow(); 49 | 50 | // Test avec les nouveaux paramètres optionnels 51 | const validGeocodingParamsWithOptional = { 52 | name: 'Berlin', 53 | count: 3, 54 | language: 'fr', 55 | countryCode: 'DE' 56 | }; 57 | 58 | expect(() => GeocodingParamsSchema.parse(validGeocodingParamsWithOptional)).not.toThrow(); 59 | 60 | const invalidGeocodingParams = { 61 | name: 'P', // Too short 62 | count: 5 63 | }; 64 | 65 | expect(() => GeocodingParamsSchema.parse(invalidGeocodingParams)).toThrow(); 66 | 67 | // Test avec un code pays invalide 68 | const invalidCountryCode = { 69 | name: 'Lyon', 70 | countryCode: 'FRA' // Doit être 2 caractères 71 | }; 72 | 73 | expect(() => GeocodingParamsSchema.parse(invalidCountryCode)).toThrow('Le code pays doit être au format ISO-3166-1 alpha2'); 74 | }); 75 | 76 | it('should import tools successfully', () => { 77 | expect(ALL_TOOLS).toBeDefined(); 78 | expect(Array.isArray(ALL_TOOLS)).toBe(true); 79 | expect(ALL_TOOLS.length).toBeGreaterThan(0); 80 | 81 | // Vérifier que l'outil de géocodage est présent 82 | const geocodingTool = ALL_TOOLS.find(tool => tool.name === 'geocoding'); 83 | expect(geocodingTool).toBeDefined(); 84 | expect(geocodingTool?.description).toContain('Search for locations'); 85 | }); 86 | 87 | it('should import client successfully', () => { 88 | expect(OpenMeteoClient).toBeDefined(); 89 | const client = new OpenMeteoClient(); 90 | expect(client).toBeInstanceOf(OpenMeteoClient); 91 | }); 92 | }); -------------------------------------------------------------------------------- /CLAUDE.md: -------------------------------------------------------------------------------- 1 | # CLAUDE.md 2 | 3 | This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. 4 | 5 | ## Repository Overview 6 | 7 | This is an Open-Meteo MCP (Model Context Protocol) server that provides comprehensive access to weather APIs for Large Language Models. It connects LLMs to Open-Meteo's weather forecasting, historical data, air quality, marine conditions, and climate projection services. 8 | 9 | ## Architecture 10 | 11 | ### Core Components 12 | 13 | - **`src/index.ts`** - Main MCP server implementation using `@modelcontextprotocol/sdk` 14 | - **`src/client.ts`** - HTTP client with multiple API endpoints (forecast, archive, air quality, marine, etc.) 15 | - **`src/tools.ts`** - MCP tool definitions with comprehensive JSON schemas 16 | - **`src/types.ts`** - Zod validation schemas for all API parameters and responses 17 | 18 | ### API Client Architecture 19 | 20 | The `OpenMeteoClient` class manages separate Axios instances for different Open-Meteo services: 21 | - Main forecast API (`api.open-meteo.com`) 22 | - Air quality API (`air-quality-api.open-meteo.com`) 23 | - Marine weather API (`marine-api.open-meteo.com`) 24 | - Archive/historical API (`archive-api.open-meteo.com`) 25 | - Seasonal forecast API (`seasonal-api.open-meteo.com`) 26 | - Ensemble forecast API (`ensemble-api.open-meteo.com`) 27 | 28 | Each service can be configured via environment variables with sensible defaults. 29 | 30 | ### Tool System 31 | 32 | Tools are organized by weather service type: 33 | - **Core weather tools**: `weather_forecast`, `weather_archive`, `air_quality`, `marine_weather`, `elevation` 34 | - **Specialized model tools**: `dwd_icon_forecast`, `gfs_forecast`, `meteofrance_forecast`, `ecmwf_forecast`, `jma_forecast`, `metno_forecast`, `gem_forecast` 35 | - **Advanced forecasting**: `flood_forecast`, `seasonal_forecast`, `climate_projection`, `ensemble_forecast` 36 | 37 | Each tool has comprehensive JSON schema validation with proper enum constraints for weather variables and units. 38 | 39 | ## Development Commands 40 | 41 | ```bash 42 | # Development with auto-reload 43 | npm run dev 44 | 45 | # Build TypeScript to dist/ 46 | npm run build 47 | 48 | # Start production server 49 | npm start 50 | 51 | # Run tests 52 | npm test 53 | 54 | # Type checking 55 | npm run typecheck 56 | 57 | # Linting 58 | npm run lint 59 | ``` 60 | 61 | ## Configuration 62 | 63 | The server uses environment variables for API endpoints with fallback defaults: 64 | - `OPEN_METEO_API_URL` - Main forecast API 65 | - `OPEN_METEO_AIR_QUALITY_API_URL` - Air quality service 66 | - `OPEN_METEO_MARINE_API_URL` - Marine weather service 67 | - `OPEN_METEO_ARCHIVE_API_URL` - Historical data service 68 | - `OPEN_METEO_SEASONAL_API_URL` - Seasonal forecasts 69 | - `OPEN_METEO_ENSEMBLE_API_URL` - Ensemble forecasts 70 | 71 | ## Key Implementation Patterns 72 | 73 | ### Parameter Building 74 | The `buildParams` method in `OpenMeteoClient` handles parameter serialization: 75 | - Arrays are joined with commas (e.g., `['temperature_2m', 'humidity']` → `"temperature_2m,humidity"`) 76 | - Null/undefined values are filtered out 77 | - All values are converted to strings for URL parameters 78 | 79 | ### Error Handling 80 | - Zod schema validation for all inputs with detailed error messages 81 | - Axios timeout configuration (30 seconds) 82 | - Comprehensive error catching in MCP tool handlers 83 | - Proper User-Agent headers for API identification 84 | 85 | ### Response Formatting 86 | All tool responses return JSON-stringified weather data with 2-space indentation for readability in LLM contexts. 87 | 88 | ## Schema Validation 89 | 90 | Uses Zod for runtime validation of: 91 | - Coordinate bounds (latitude: -90 to 90, longitude: -180 to 180) 92 | - Weather variable enums (prevents invalid parameter combinations) 93 | - Date format validation (YYYY-MM-DD pattern) 94 | - Unit constraints (temperature, wind speed, precipitation units) 95 | - Forecast day limits (varies by service: 7-16 days for most, up to 210 for flood forecasts) 96 | 97 | ## Weather Model Coverage 98 | 99 | The server supports major global and regional weather models: 100 | - **High-resolution regional**: DWD ICON (Europe), Météo-France AROME (France), JMA (Asia) 101 | - **Global models**: NOAA GFS, ECMWF IFS 102 | - **Regional specialists**: MET Norway (Nordics), Environment Canada GEM (North America) 103 | 104 | Each model tool uses the same parameter schema but connects to different Open-Meteo endpoints optimized for that model's strengths. -------------------------------------------------------------------------------- /src/client.ts: -------------------------------------------------------------------------------- 1 | import axios, { AxiosInstance } from 'axios'; 2 | import type { 3 | ForecastParams, 4 | ArchiveParams, 5 | AirQualityParams, 6 | MarineParams, 7 | FloodParams, 8 | ElevationParams, 9 | GeocodingParams, 10 | WeatherResponse, 11 | ElevationResponse, 12 | GeocodingResponse 13 | } from './types.js'; 14 | 15 | export class OpenMeteoClient { 16 | private client: AxiosInstance; 17 | private airQualityClient: AxiosInstance; 18 | private marineClient: AxiosInstance; 19 | private archiveClient: AxiosInstance; 20 | private seasonalClient: AxiosInstance; 21 | private ensembleClient: AxiosInstance; 22 | private geocodingClient: AxiosInstance; 23 | private floodClient: AxiosInstance; 24 | 25 | constructor(baseURL: string = process.env.OPEN_METEO_API_URL || 'https://api.open-meteo.com') { 26 | const config = { 27 | timeout: 30000, 28 | headers: { 29 | 'Accept': 'application/json', 30 | 'User-Agent': 'Open-Meteo-MCP-Server/1.0.0' 31 | } 32 | }; 33 | 34 | // Utilisation des variables d'environnement avec des valeurs par défaut 35 | const airQualityURL = process.env.OPEN_METEO_AIR_QUALITY_API_URL || 'https://air-quality-api.open-meteo.com'; 36 | const marineURL = process.env.OPEN_METEO_MARINE_API_URL || 'https://marine-api.open-meteo.com'; 37 | const archiveURL = process.env.OPEN_METEO_ARCHIVE_API_URL || 'https://archive-api.open-meteo.com'; 38 | const seasonalURL = process.env.OPEN_METEO_SEASONAL_API_URL || 'https://seasonal-api.open-meteo.com'; 39 | const ensembleURL = process.env.OPEN_METEO_ENSEMBLE_API_URL || 'https://ensemble-api.open-meteo.com'; 40 | const geocodingURL = process.env.OPEN_METEO_GEOCODING_API_URL || 'https://geocoding-api.open-meteo.com'; 41 | const floodURL = process.env.OPEN_METEO_FLOOD_API_URL || 'https://flood-api.open-meteo.com'; 42 | 43 | this.client = axios.create({ baseURL, ...config }); 44 | this.airQualityClient = axios.create({ baseURL: airQualityURL, ...config }); 45 | this.marineClient = axios.create({ baseURL: marineURL, ...config }); 46 | this.archiveClient = axios.create({ baseURL: archiveURL, ...config }); 47 | this.seasonalClient = axios.create({ baseURL: seasonalURL, ...config }); 48 | this.ensembleClient = axios.create({ baseURL: ensembleURL, ...config }); 49 | this.geocodingClient = axios.create({ baseURL: geocodingURL, ...config }); 50 | this.floodClient = axios.create({ baseURL: floodURL, ...config }); 51 | } 52 | 53 | private buildParams(params: Record): Record { 54 | const result: Record = {}; 55 | 56 | for (const [key, value] of Object.entries(params)) { 57 | if (value !== undefined && value !== null) { 58 | if (Array.isArray(value)) { 59 | result[key] = value.join(','); 60 | } else { 61 | result[key] = String(value); 62 | } 63 | } 64 | } 65 | 66 | return result; 67 | } 68 | 69 | async getForecast(params: ForecastParams): Promise { 70 | const response = await this.client.get('/v1/forecast', { 71 | params: this.buildParams(params) 72 | }); 73 | return response.data; 74 | } 75 | 76 | async getArchive(params: ArchiveParams): Promise { 77 | const response = await this.archiveClient.get('/v1/archive', { 78 | params: this.buildParams(params) 79 | }); 80 | return response.data; 81 | } 82 | 83 | async getDwdIcon(params: ForecastParams): Promise { 84 | const response = await this.client.get('/v1/dwd-icon', { 85 | params: this.buildParams(params) 86 | }); 87 | return response.data; 88 | } 89 | 90 | async getGfs(params: ForecastParams): Promise { 91 | const response = await this.client.get('/v1/gfs', { 92 | params: this.buildParams(params) 93 | }); 94 | return response.data; 95 | } 96 | 97 | async getMeteoFrance(params: ForecastParams): Promise { 98 | const response = await this.client.get('/v1/meteofrance', { 99 | params: this.buildParams(params) 100 | }); 101 | return response.data; 102 | } 103 | 104 | async getEcmwf(params: ForecastParams): Promise { 105 | const response = await this.client.get('/v1/ecmwf', { 106 | params: this.buildParams(params) 107 | }); 108 | return response.data; 109 | } 110 | 111 | async getJma(params: ForecastParams): Promise { 112 | const response = await this.client.get('/v1/jma', { 113 | params: this.buildParams(params) 114 | }); 115 | return response.data; 116 | } 117 | 118 | async getMetno(params: ForecastParams): Promise { 119 | const response = await this.client.get('/v1/metno', { 120 | params: this.buildParams(params) 121 | }); 122 | return response.data; 123 | } 124 | 125 | async getGem(params: ForecastParams): Promise { 126 | const response = await this.client.get('/v1/gem', { 127 | params: this.buildParams(params) 128 | }); 129 | return response.data; 130 | } 131 | 132 | async getAirQuality(params: AirQualityParams): Promise { 133 | const response = await this.airQualityClient.get('/v1/air-quality', { 134 | params: this.buildParams(params) 135 | }); 136 | return response.data; 137 | } 138 | 139 | async getMarine(params: MarineParams): Promise { 140 | const response = await this.marineClient.get('/v1/marine', { 141 | params: this.buildParams(params) 142 | }); 143 | return response.data; 144 | } 145 | 146 | async getEnsemble(params: ForecastParams): Promise { 147 | const response = await this.ensembleClient.get('/v1/ensemble', { 148 | params: this.buildParams(params) 149 | }); 150 | return response.data; 151 | } 152 | 153 | async getElevation(params: ElevationParams): Promise { 154 | const response = await this.client.get('/v1/elevation', { 155 | params: this.buildParams(params) 156 | }); 157 | return response.data; 158 | } 159 | 160 | async getFlood(params: FloodParams): Promise { 161 | const response = await this.floodClient.get('/v1/flood', { 162 | params: this.buildParams(params) 163 | }); 164 | return response.data; 165 | } 166 | 167 | async getSeasonal(params: ForecastParams): Promise { 168 | const response = await this.seasonalClient.get('/v1/seasonal', { 169 | params: this.buildParams(params) 170 | }); 171 | return response.data; 172 | } 173 | 174 | async getClimate(params: ForecastParams): Promise { 175 | const response = await this.client.get('/v1/climate', { 176 | params: this.buildParams(params) 177 | }); 178 | return response.data; 179 | } 180 | 181 | async getGeocoding(params: GeocodingParams): Promise { 182 | const response = await this.geocodingClient.get('/v1/search', { 183 | params: this.buildParams(params) 184 | }); 185 | return response.data; 186 | } 187 | } -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { Server } from '@modelcontextprotocol/sdk/server/index.js'; 4 | import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; 5 | import { 6 | CallToolRequestSchema, 7 | ListToolsRequestSchema, 8 | } from '@modelcontextprotocol/sdk/types.js'; 9 | import { OpenMeteoClient } from './client.js'; 10 | import { ALL_TOOLS } from './tools.js'; 11 | import { 12 | ForecastParamsSchema, 13 | ArchiveParamsSchema, 14 | AirQualityParamsSchema, 15 | MarineParamsSchema, 16 | FloodParamsSchema, 17 | ElevationParamsSchema, 18 | GeocodingParamsSchema, 19 | } from './types.js'; 20 | 21 | class OpenMeteoMCPServer { 22 | private server: Server; 23 | private client: OpenMeteoClient; 24 | 25 | constructor() { 26 | this.server = new Server( 27 | { 28 | name: 'open-meteo-mcp-server', 29 | version: '1.0.0', 30 | }, 31 | { 32 | capabilities: { 33 | tools: {}, 34 | }, 35 | } 36 | ); 37 | 38 | // Initialize with default Open-Meteo API URL, but allow override via environment 39 | const baseURL = process.env.OPEN_METEO_API_URL || 'https://api.open-meteo.com'; 40 | this.client = new OpenMeteoClient(baseURL); 41 | 42 | this.setupHandlers(); 43 | } 44 | 45 | private setupHandlers() { 46 | this.server.setRequestHandler(ListToolsRequestSchema, async () => { 47 | return { 48 | tools: ALL_TOOLS, 49 | }; 50 | }); 51 | 52 | this.server.setRequestHandler(CallToolRequestSchema, async (request) => { 53 | const { name, arguments: args } = request.params; 54 | 55 | try { 56 | switch (name) { 57 | case 'weather_forecast': { 58 | const params = ForecastParamsSchema.parse(args); 59 | const result = await this.client.getForecast(params); 60 | return { 61 | content: [ 62 | { 63 | type: 'text', 64 | text: JSON.stringify(result, null, 2), 65 | }, 66 | ], 67 | }; 68 | } 69 | 70 | case 'weather_archive': { 71 | const params = ArchiveParamsSchema.parse(args); 72 | const result = await this.client.getArchive(params); 73 | return { 74 | content: [ 75 | { 76 | type: 'text', 77 | text: JSON.stringify(result, null, 2), 78 | }, 79 | ], 80 | }; 81 | } 82 | 83 | case 'air_quality': { 84 | const params = AirQualityParamsSchema.parse(args); 85 | const result = await this.client.getAirQuality(params); 86 | return { 87 | content: [ 88 | { 89 | type: 'text', 90 | text: JSON.stringify(result, null, 2), 91 | }, 92 | ], 93 | }; 94 | } 95 | 96 | case 'marine_weather': { 97 | const params = MarineParamsSchema.parse(args); 98 | const result = await this.client.getMarine(params); 99 | return { 100 | content: [ 101 | { 102 | type: 'text', 103 | text: JSON.stringify(result, null, 2), 104 | }, 105 | ], 106 | }; 107 | } 108 | 109 | case 'elevation': { 110 | const params = ElevationParamsSchema.parse(args); 111 | const result = await this.client.getElevation(params); 112 | return { 113 | content: [ 114 | { 115 | type: 'text', 116 | text: JSON.stringify(result, null, 2), 117 | }, 118 | ], 119 | }; 120 | } 121 | 122 | case 'dwd_icon_forecast': { 123 | const params = ForecastParamsSchema.parse(args); 124 | const result = await this.client.getDwdIcon(params); 125 | return { 126 | content: [ 127 | { 128 | type: 'text', 129 | text: JSON.stringify(result, null, 2), 130 | }, 131 | ], 132 | }; 133 | } 134 | 135 | case 'gfs_forecast': { 136 | const params = ForecastParamsSchema.parse(args); 137 | const result = await this.client.getGfs(params); 138 | return { 139 | content: [ 140 | { 141 | type: 'text', 142 | text: JSON.stringify(result, null, 2), 143 | }, 144 | ], 145 | }; 146 | } 147 | 148 | case 'meteofrance_forecast': { 149 | const params = ForecastParamsSchema.parse(args); 150 | const result = await this.client.getMeteoFrance(params); 151 | return { 152 | content: [ 153 | { 154 | type: 'text', 155 | text: JSON.stringify(result, null, 2), 156 | }, 157 | ], 158 | }; 159 | } 160 | 161 | case 'ecmwf_forecast': { 162 | const params = ForecastParamsSchema.parse(args); 163 | const result = await this.client.getEcmwf(params); 164 | return { 165 | content: [ 166 | { 167 | type: 'text', 168 | text: JSON.stringify(result, null, 2), 169 | }, 170 | ], 171 | }; 172 | } 173 | 174 | case 'jma_forecast': { 175 | const params = ForecastParamsSchema.parse(args); 176 | const result = await this.client.getJma(params); 177 | return { 178 | content: [ 179 | { 180 | type: 'text', 181 | text: JSON.stringify(result, null, 2), 182 | }, 183 | ], 184 | }; 185 | } 186 | 187 | case 'metno_forecast': { 188 | const params = ForecastParamsSchema.parse(args); 189 | const result = await this.client.getMetno(params); 190 | return { 191 | content: [ 192 | { 193 | type: 'text', 194 | text: JSON.stringify(result, null, 2), 195 | }, 196 | ], 197 | }; 198 | } 199 | 200 | case 'gem_forecast': { 201 | const params = ForecastParamsSchema.parse(args); 202 | const result = await this.client.getGem(params); 203 | return { 204 | content: [ 205 | { 206 | type: 'text', 207 | text: JSON.stringify(result, null, 2), 208 | }, 209 | ], 210 | }; 211 | } 212 | 213 | case 'flood_forecast': { 214 | const params = FloodParamsSchema.parse(args); 215 | const result = await this.client.getFlood(params); 216 | return { 217 | content: [ 218 | { 219 | type: 'text', 220 | text: JSON.stringify(result, null, 2), 221 | }, 222 | ], 223 | }; 224 | } 225 | 226 | case 'seasonal_forecast': { 227 | const params = ForecastParamsSchema.parse(args); 228 | const result = await this.client.getSeasonal(params); 229 | return { 230 | content: [ 231 | { 232 | type: 'text', 233 | text: JSON.stringify(result, null, 2), 234 | }, 235 | ], 236 | }; 237 | } 238 | 239 | case 'climate_projection': { 240 | const params = ForecastParamsSchema.parse(args); 241 | const result = await this.client.getClimate(params); 242 | return { 243 | content: [ 244 | { 245 | type: 'text', 246 | text: JSON.stringify(result, null, 2), 247 | }, 248 | ], 249 | }; 250 | } 251 | 252 | case 'ensemble_forecast': { 253 | const params = ForecastParamsSchema.parse(args); 254 | const result = await this.client.getEnsemble(params); 255 | return { 256 | content: [ 257 | { 258 | type: 'text', 259 | text: JSON.stringify(result, null, 2), 260 | }, 261 | ], 262 | }; 263 | } 264 | 265 | case 'geocoding': { 266 | const params = GeocodingParamsSchema.parse(args); 267 | const result = await this.client.getGeocoding(params); 268 | return { 269 | content: [ 270 | { 271 | type: 'text', 272 | text: JSON.stringify(result, null, 2), 273 | }, 274 | ], 275 | }; 276 | } 277 | 278 | default: 279 | throw new Error(`Unknown tool: ${name}`); 280 | } 281 | } catch (error) { 282 | const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; 283 | return { 284 | content: [ 285 | { 286 | type: 'text', 287 | text: `Error: ${errorMessage}`, 288 | }, 289 | ], 290 | }; 291 | } 292 | }); 293 | } 294 | 295 | async run() { 296 | const transport = new StdioServerTransport(); 297 | await this.server.connect(transport); 298 | console.error('Open-Meteo MCP Server running on stdio'); 299 | } 300 | } 301 | 302 | const server = new OpenMeteoMCPServer(); 303 | server.run().catch((error) => { 304 | console.error('Server error:', error); 305 | process.exit(1); 306 | }); -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | import { z } from 'zod'; 2 | 3 | // Base parameter schemas 4 | export const CoordinateSchema = z.object({ 5 | latitude: z.number().min(-90).max(90), 6 | longitude: z.number().min(-180).max(180), 7 | }); 8 | 9 | export const TemperatureUnitSchema = z.enum(['celsius', 'fahrenheit']).default('celsius'); 10 | export const WindSpeedUnitSchema = z.enum(['kmh', 'ms', 'mph', 'kn']).default('kmh'); 11 | export const PrecipitationUnitSchema = z.enum(['mm', 'inch']).default('mm'); 12 | export const TimeFormatSchema = z.enum(['iso8601', 'unixtime']).default('iso8601'); 13 | 14 | // Geocoding schemas 15 | export const GeocodingParamsSchema = z.object({ 16 | name: z.string().min(2, 'Le nom doit contenir au moins 2 caractères'), 17 | count: z.number().min(1).max(100).default(10).optional(), 18 | language: z.string().optional(), 19 | countryCode: z.string().regex(/^[A-Z]{2}$/, 'Le code pays doit être au format ISO-3166-1 alpha2 (ex: FR, DE, US)').optional(), 20 | format: z.enum(['json', 'protobuf']).default('json').optional(), 21 | }); 22 | 23 | export const LocationSchema = z.object({ 24 | id: z.number(), 25 | name: z.string(), 26 | latitude: z.number().min(-90).max(90), 27 | longitude: z.number().min(-180).max(180), 28 | elevation: z.number().optional(), 29 | feature_code: z.string().optional(), 30 | country_code: z.string().regex(/^[A-Z]{2}$/).optional(), 31 | admin1_id: z.number().optional(), 32 | admin2_id: z.number().optional(), 33 | admin3_id: z.number().optional(), 34 | admin4_id: z.number().optional(), 35 | timezone: z.string().optional(), 36 | population: z.number().min(0).optional(), 37 | postcodes: z.array(z.string()).optional(), 38 | country_id: z.number().optional(), 39 | country: z.string().optional(), 40 | admin1: z.string().optional(), 41 | admin2: z.string().optional(), 42 | admin3: z.string().optional(), 43 | admin4: z.string().optional(), 44 | }); 45 | 46 | export const GeocodingResponseSchema = z.object({ 47 | results: z.array(LocationSchema), 48 | }); 49 | 50 | export const GeocodingErrorSchema = z.object({ 51 | error: z.boolean(), 52 | reason: z.string(), 53 | }); 54 | 55 | // Weather variables schemas 56 | export const HourlyVariablesSchema = z.array(z.enum([ 57 | // Temperature variables 58 | 'temperature_2m', 'relative_humidity_2m', 'dewpoint_2m', 'apparent_temperature', 'surface_temperature', 59 | // Pressure variables 60 | 'pressure_msl', 'surface_pressure', 61 | // Cloud variables 62 | 'cloud_cover', 'cloud_cover_low', 'cloud_cover_mid', 'cloud_cover_high', 63 | // Wind variables 64 | 'wind_speed_10m', 'wind_speed_80m', 'wind_speed_120m', 'wind_speed_180m', 65 | 'wind_direction_10m', 'wind_direction_80m', 'wind_direction_120m', 'wind_direction_180m', 66 | 'wind_gusts_10m', 'wind_u_component_10m', 'wind_v_component_10m', 67 | 'wind_u_component_80m', 'wind_v_component_80m', 'wind_u_component_120m', 'wind_v_component_120m', 68 | 'wind_u_component_180m', 'wind_v_component_180m', 69 | // Radiation variables 70 | 'shortwave_radiation', 'direct_radiation', 'direct_normal_irradiance', 'diffuse_radiation', 71 | 'terrestrial_radiation', 'sunshine_duration', 'uv_index', 'uv_index_clear_sky', 72 | // Precipitation variables 73 | 'precipitation', 'rain', 'showers', 'snowfall', 'precipitation_probability', 'snow_depth', 'snow_height', 74 | // Atmospheric variables 75 | 'vapour_pressure_deficit', 'et0_fao_evapotranspiration', 'weather_code', 'visibility', 'is_day', 76 | 'cape', 'lifted_index', 'convective_inhibition', 'freezing_level_height', 'boundary_layer_height', 77 | 'updraft_velocity', 'downdraft_velocity', 78 | // Soil variables 79 | 'soil_temperature_0cm', 'soil_temperature_6cm', 'soil_temperature_18cm', 'soil_temperature_54cm', 80 | 'soil_moisture_0_1cm', 'soil_moisture_1_3cm', 'soil_moisture_3_9cm', 'soil_moisture_9_27cm', 81 | 'soil_moisture_27_81cm', 82 | // Energy flux variables 83 | 'sensible_heat_flux', 'latent_heat_flux', 84 | // Agricultural variables 85 | 'growing_degree_days_base_0_limit_30', 'leaf_wetness_probability', 'skin_temperature' 86 | ])).optional(); 87 | 88 | export const DailyVariablesSchema = z.array(z.enum([ 89 | 'temperature_2m_max', 'temperature_2m_min', 'apparent_temperature_max', 'apparent_temperature_min', 90 | 'precipitation_sum', 'precipitation_hours', 'weather_code', 'sunrise', 'sunset', 91 | 'wind_speed_10m_max', 'wind_gusts_10m_max', 'wind_direction_10m_dominant', 92 | 'shortwave_radiation_sum', 'uv_index_max', 'uv_index_clear_sky_max', 'et0_fao_evapotranspiration' 93 | ])).optional(); 94 | 95 | export const WeatherModelsSchema = z.array(z.enum([ 96 | 'meteofrance_arome_france_hd', 'meteofrance_arome_france', 'meteofrance_arpege_europe', 97 | 'icon_eu', 'icon_global', 'ecmwf_ifs025', 'gfs013' 98 | ])).optional(); 99 | 100 | // Forecast parameters schema 101 | export const ForecastParamsSchema = CoordinateSchema.extend({ 102 | hourly: HourlyVariablesSchema, 103 | daily: DailyVariablesSchema, 104 | current_weather: z.boolean().optional(), 105 | temperature_unit: TemperatureUnitSchema, 106 | wind_speed_unit: WindSpeedUnitSchema, 107 | precipitation_unit: PrecipitationUnitSchema, 108 | timeformat: TimeFormatSchema, 109 | timezone: z.string().optional(), 110 | past_days: z.union([z.literal(1), z.literal(2)]).optional(), 111 | start_date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(), 112 | end_date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(), 113 | start_hour: z.string().regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$/).optional(), 114 | end_hour: z.string().regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$/).optional(), 115 | models: WeatherModelsSchema, 116 | }); 117 | 118 | // Archive parameters schema 119 | export const ArchiveParamsSchema = CoordinateSchema.extend({ 120 | hourly: HourlyVariablesSchema, 121 | daily: DailyVariablesSchema, 122 | start_date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/), 123 | end_date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/), 124 | temperature_unit: TemperatureUnitSchema, 125 | wind_speed_unit: WindSpeedUnitSchema, 126 | precipitation_unit: PrecipitationUnitSchema, 127 | timeformat: TimeFormatSchema, 128 | timezone: z.string().optional(), 129 | }); 130 | 131 | // Air quality variables 132 | export const AirQualityVariablesSchema = z.array(z.enum([ 133 | 'pm10', 'pm2_5', 'carbon_monoxide', 'nitrogen_dioxide', 'ozone', 134 | 'sulphur_dioxide', 'ammonia', 'dust', 'aerosol_optical_depth', 135 | 'carbon_dioxide', 'methane' 136 | ])).optional(); 137 | 138 | export const AirQualityParamsSchema = CoordinateSchema.extend({ 139 | hourly: AirQualityVariablesSchema, 140 | timezone: z.string().optional(), 141 | timeformat: TimeFormatSchema, 142 | past_days: z.number().min(1).max(7).optional(), 143 | forecast_days: z.number().min(1).max(16).optional(), 144 | }); 145 | 146 | // Marine variables 147 | export const MarineHourlyVariablesSchema = z.array(z.enum([ 148 | 'wave_height', 'wave_direction', 'wave_period', 149 | 'wind_wave_height', 'wind_wave_direction', 'wind_wave_period', 150 | 'swell_wave_height', 'swell_wave_direction', 'swell_wave_period', 151 | 'sea_surface_temperature' 152 | ])).optional(); 153 | 154 | export const MarineDailyVariablesSchema = z.array(z.enum([ 155 | 'wave_height_max', 'wind_wave_height_max', 'swell_wave_height_max' 156 | ])).optional(); 157 | 158 | export const MarineParamsSchema = CoordinateSchema.extend({ 159 | hourly: MarineHourlyVariablesSchema, 160 | daily: MarineDailyVariablesSchema, 161 | timezone: z.string().optional(), 162 | timeformat: TimeFormatSchema, 163 | past_days: z.number().min(1).max(7).optional(), 164 | forecast_days: z.number().min(1).max(16).optional(), 165 | }); 166 | 167 | // Flood variables 168 | export const FloodDailyVariablesSchema = z.array(z.enum([ 169 | 'river_discharge', 'river_discharge_mean', 'river_discharge_median', 170 | 'river_discharge_max', 'river_discharge_min', 'river_discharge_p25', 'river_discharge_p75' 171 | ])).optional(); 172 | 173 | export const FloodParamsSchema = CoordinateSchema.extend({ 174 | daily: FloodDailyVariablesSchema, 175 | timezone: z.string().optional(), 176 | timeformat: TimeFormatSchema, 177 | past_days: z.number().min(1).max(7).optional(), 178 | forecast_days: z.number().min(1).max(210).optional(), 179 | start_date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(), 180 | end_date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(), 181 | ensemble: z.boolean().optional(), 182 | cell_selection: z.enum(['land', 'sea', 'nearest']).default('nearest').optional(), 183 | }); 184 | 185 | // Elevation parameters 186 | export const ElevationParamsSchema = CoordinateSchema; 187 | 188 | // Response types 189 | export const WeatherResponseSchema = z.object({ 190 | latitude: z.number(), 191 | longitude: z.number(), 192 | elevation: z.number(), 193 | generationtime_ms: z.number(), 194 | utc_offset_seconds: z.number(), 195 | hourly: z.record(z.array(z.union([z.number(), z.string()]))).optional(), 196 | hourly_units: z.record(z.string()).optional(), 197 | daily: z.record(z.array(z.union([z.number(), z.string()]))).optional(), 198 | daily_units: z.record(z.string()).optional(), 199 | current_weather: z.object({ 200 | time: z.string(), 201 | temperature: z.number(), 202 | wind_speed: z.number(), 203 | wind_direction: z.number(), 204 | weather_code: z.number(), 205 | }).optional(), 206 | }); 207 | 208 | export const ElevationResponseSchema = z.object({ 209 | elevation: z.array(z.number()), 210 | }); 211 | 212 | export type ForecastParams = z.infer; 213 | export type ArchiveParams = z.infer; 214 | export type AirQualityParams = z.infer; 215 | export type MarineParams = z.infer; 216 | export type FloodParams = z.infer; 217 | export type ElevationParams = z.infer; 218 | export type WeatherResponse = z.infer; 219 | export type ElevationResponse = z.infer; 220 | export type GeocodingParams = z.infer; 221 | export type Location = z.infer; 222 | export type GeocodingResponse = z.infer; 223 | export type GeocodingError = z.infer; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Open-Meteo MCP Server 2 | 3 | [![npm version](https://badge.fury.io/js/open-meteo-mcp-server.svg)](https://badge.fury.io/js/open-meteo-mcp-server) 4 | [![GitHub release](https://img.shields.io/github/release/cmer81/open-meteo-mcp.svg)](https://github.com/cmer81/open-meteo-mcp/releases) 5 | 6 | A comprehensive [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server that provides access to Open-Meteo weather APIs for use with Large Language Models. 7 | 8 | ## Features 9 | 10 | This MCP server provides complete access to Open-Meteo APIs, including: 11 | 12 | ### Core Weather APIs 13 | - **Weather Forecast** (`weather_forecast`) - 7-day forecasts with hourly and daily resolution 14 | - **Weather Archive** (`weather_archive`) - Historical ERA5 data from 1940 to present 15 | - **Air Quality** (`air_quality`) - PM2.5, PM10, ozone, nitrogen dioxide and other pollutants 16 | - **Marine Weather** (`marine_weather`) - Wave height, wave period, wave direction and sea surface temperature 17 | - **Elevation** (`elevation`) - Digital elevation model data for given coordinates 18 | - **Geocoding** (`geocoding`) - Search locations worldwide by name or postal code, get coordinates and detailed location information 19 | 20 | ### Specialized Weather Models 21 | - **DWD ICON** (`dwd_icon_forecast`) - German weather service high-resolution model for Europe 22 | - **NOAA GFS** (`gfs_forecast`) - US weather service global model with high-resolution North America data 23 | - **Météo-France** (`meteofrance_forecast`) - French weather service AROME and ARPEGE models 24 | - **ECMWF** (`ecmwf_forecast`) - European Centre for Medium-Range Weather Forecasts 25 | - **JMA** (`jma_forecast`) - Japan Meteorological Agency high-resolution model for Asia 26 | - **MET Norway** (`metno_forecast`) - Norwegian weather service for Nordic countries 27 | - **Environment Canada GEM** (`gem_forecast`) - Canadian weather service model 28 | 29 | ### Advanced Forecasting Tools 30 | - **Flood Forecast** (`flood_forecast`) - River discharge and flood forecasts from GloFAS (Global Flood Awareness System) 31 | - **Seasonal Forecast** (`seasonal_forecast`) - Long-range forecasts up to 9 months ahead 32 | - **Climate Projections** (`climate_projection`) - CMIP6 climate change projections for different warming scenarios 33 | - **Ensemble Forecast** (`ensemble_forecast`) - Multiple model runs showing forecast uncertainty 34 | 35 | ## Installation 36 | 37 | ### Method 1: Using npx (Recommended) 38 | 39 | No installation required! The server will run directly via npx. 40 | 41 | ### Method 2: Global Installation via npm 42 | 43 | ```bash 44 | npm install -g open-meteo-mcp-server 45 | ``` 46 | 47 | ### Method 3: From Source (Development) 48 | 49 | ```bash 50 | # Clone the repository 51 | git clone https://github.com/cmer81/open-meteo-mcp.git 52 | cd open-meteo-mcp 53 | 54 | # Install dependencies 55 | npm install 56 | 57 | # Build the project 58 | npm run build 59 | ``` 60 | 61 | ## Configuration 62 | 63 | ### Claude Desktop Configuration 64 | 65 | #### Simple Configuration (Recommended) 66 | 67 | Add the following configuration to your Claude Desktop config file: 68 | 69 | ```json 70 | { 71 | "mcpServers": { 72 | "open-meteo": { 73 | "command": "npx", 74 | "args": ["open-meteo-mcp-server"] 75 | } 76 | } 77 | } 78 | ``` 79 | 80 | #### Full Configuration (with environment variables) 81 | 82 | ```json 83 | { 84 | "mcpServers": { 85 | "open-meteo": { 86 | "command": "npx", 87 | "args": ["open-meteo-mcp-server"], 88 | "env": { 89 | "OPEN_METEO_API_URL": "https://api.open-meteo.com", 90 | "OPEN_METEO_AIR_QUALITY_API_URL": "https://air-quality-api.open-meteo.com", 91 | "OPEN_METEO_MARINE_API_URL": "https://marine-api.open-meteo.com", 92 | "OPEN_METEO_ARCHIVE_API_URL": "https://archive-api.open-meteo.com", 93 | "OPEN_METEO_SEASONAL_API_URL": "https://seasonal-api.open-meteo.com", 94 | "OPEN_METEO_ENSEMBLE_API_URL": "https://ensemble-api.open-meteo.com", 95 | "OPEN_METEO_GEOCODING_API_URL": "https://geocoding-api.open-meteo.com" 96 | } 97 | } 98 | } 99 | } 100 | ``` 101 | 102 | #### Local Development Configuration 103 | 104 | If you're developing locally or installed from source: 105 | 106 | ```json 107 | { 108 | "mcpServers": { 109 | "open-meteo": { 110 | "command": "node", 111 | "args": ["/path/to/open-meteo-mcp/dist/index.js"], 112 | "env": { 113 | "OPEN_METEO_API_URL": "https://api.open-meteo.com", 114 | "OPEN_METEO_AIR_QUALITY_API_URL": "https://air-quality-api.open-meteo.com", 115 | "OPEN_METEO_MARINE_API_URL": "https://marine-api.open-meteo.com", 116 | "OPEN_METEO_ARCHIVE_API_URL": "https://archive-api.open-meteo.com", 117 | "OPEN_METEO_SEASONAL_API_URL": "https://seasonal-api.open-meteo.com", 118 | "OPEN_METEO_ENSEMBLE_API_URL": "https://ensemble-api.open-meteo.com", 119 | "OPEN_METEO_GEOCODING_API_URL": "https://geocoding-api.open-meteo.com" 120 | } 121 | } 122 | } 123 | } 124 | ``` 125 | 126 | ### Custom Instance Configuration 127 | 128 | If you're using your own Open-Meteo instance: 129 | 130 | ```json 131 | { 132 | "mcpServers": { 133 | "open-meteo": { 134 | "command": "npx", 135 | "args": ["open-meteo-mcp-server"], 136 | "env": { 137 | "OPEN_METEO_API_URL": "https://your-meteo-api.example.com", 138 | "OPEN_METEO_AIR_QUALITY_API_URL": "https://air-quality-api.example.com", 139 | "OPEN_METEO_MARINE_API_URL": "https://marine-api.example.com", 140 | "OPEN_METEO_ARCHIVE_API_URL": "https://archive-api.example.com", 141 | "OPEN_METEO_SEASONAL_API_URL": "https://seasonal-api.example.com", 142 | "OPEN_METEO_ENSEMBLE_API_URL": "https://ensemble-api.example.com", 143 | "OPEN_METEO_GEOCODING_API_URL": "https://geocoding-api.example.com" 144 | } 145 | } 146 | } 147 | } 148 | ``` 149 | 150 | ### Environment Variables 151 | 152 | All environment variables are optional and have sensible defaults: 153 | 154 | - `OPEN_METEO_API_URL` - Base URL for Open-Meteo forecast API (default: https://api.open-meteo.com) 155 | - `OPEN_METEO_AIR_QUALITY_API_URL` - Air quality API URL (default: https://air-quality-api.open-meteo.com) 156 | - `OPEN_METEO_MARINE_API_URL` - Marine weather API URL (default: https://marine-api.open-meteo.com) 157 | - `OPEN_METEO_ARCHIVE_API_URL` - Historical data API URL (default: https://archive-api.open-meteo.com) 158 | - `OPEN_METEO_SEASONAL_API_URL` - Seasonal forecast API URL (default: https://seasonal-api.open-meteo.com) 159 | - `OPEN_METEO_ENSEMBLE_API_URL` - Ensemble forecast API URL (default: https://ensemble-api.open-meteo.com) 160 | - `OPEN_METEO_GEOCODING_API_URL` - Geocoding API URL (default: https://geocoding-api.open-meteo.com) 161 | 162 | ## Usage Examples 163 | 164 | ### Geocoding and Location Search 165 | ``` 166 | Find the coordinates for Paris, France 167 | ``` 168 | 169 | ``` 170 | Search for locations named "Berlin" and return the top 5 results 171 | ``` 172 | 173 | ``` 174 | What are the coordinates for postal code 75001? 175 | ``` 176 | 177 | ``` 178 | Search for "Lyon" in France only (countryCode: FR) with results in French (language: fr) 179 | ``` 180 | 181 | ``` 182 | Find all cities named "London" in the United Kingdom with English descriptions 183 | ``` 184 | 185 | ### Basic Weather Forecast 186 | ``` 187 | Can you get me the weather forecast for Paris (48.8566, 2.3522) with temperature, humidity, and precipitation for the next 3 days? 188 | ``` 189 | 190 | ### Historical Weather Data 191 | ``` 192 | What were the temperatures in London during January 2023? 193 | ``` 194 | 195 | ### Air Quality Monitoring 196 | ``` 197 | What's the current air quality in Beijing with PM2.5 and ozone levels? 198 | ``` 199 | 200 | ### Marine Weather 201 | ``` 202 | Get me the wave height and sea surface temperature for coordinates 45.0, -125.0 for the next 5 days. 203 | ``` 204 | 205 | ### Flood Monitoring 206 | ``` 207 | Check the river discharge forecast for coordinates 52.5, 13.4 for the next 30 days. 208 | ``` 209 | 210 | ### Climate Projections 211 | ``` 212 | Show me temperature projections for New York from 2050 to 2070 using CMIP6 models. 213 | ``` 214 | 215 | ## API Parameters 216 | 217 | ### Required Parameters 218 | - `latitude` : Latitude in WGS84 coordinate system (-90 to 90) 219 | - `longitude` : Longitude in WGS84 coordinate system (-180 to 180) 220 | 221 | ### Hourly Weather Variables 222 | - `temperature_2m` : Temperature at 2 meters 223 | - `relative_humidity_2m` : Relative humidity 224 | - `precipitation` : Precipitation 225 | - `wind_speed_10m` : Wind speed at 10 meters 226 | - `wind_direction_10m` : Wind direction 227 | - `pressure_msl` : Mean sea level pressure 228 | - `cloud_cover` : Cloud cover percentage 229 | - `weather_code` : Weather condition code 230 | - `visibility` : Visibility 231 | - `uv_index` : UV index 232 | - And many more... 233 | 234 | ### Daily Weather Variables 235 | - `temperature_2m_max/min` : Maximum/minimum temperatures 236 | - `precipitation_sum` : Total precipitation 237 | - `wind_speed_10m_max` : Maximum wind speed 238 | - `sunrise/sunset` : Sunrise and sunset times 239 | - `weather_code` : Weather condition code 240 | - `uv_index_max` : Maximum UV index 241 | 242 | ### Air Quality Variables 243 | - `pm10` : PM10 particles 244 | - `pm2_5` : PM2.5 particles 245 | - `carbon_monoxide` : Carbon monoxide 246 | - `nitrogen_dioxide` : Nitrogen dioxide 247 | - `ozone` : Ozone 248 | - `sulphur_dioxide` : Sulfur dioxide 249 | - `ammonia` : Ammonia 250 | - `dust` : Dust particles 251 | 252 | ### Marine Weather Variables 253 | - `wave_height` : Wave height 254 | - `wave_direction` : Wave direction 255 | - `wave_period` : Wave period 256 | - `wind_wave_height` : Wind wave height 257 | - `swell_wave_height` : Swell wave height 258 | - `sea_surface_temperature` : Sea surface temperature 259 | 260 | ### Formatting Options 261 | - `temperature_unit` : `celsius`, `fahrenheit` 262 | - `wind_speed_unit` : `kmh`, `ms`, `mph`, `kn` 263 | - `precipitation_unit` : `mm`, `inch` 264 | - `timezone` : `Europe/Paris`, `America/New_York`, etc. 265 | 266 | ### Time Range Options 267 | - `forecast_days` : Number of forecast days (varies by API) 268 | - `past_days` : Include past days data 269 | - `start_date` / `end_date` : Date range for historical data (YYYY-MM-DD format) 270 | 271 | ## Development Scripts 272 | 273 | ```bash 274 | # Development with auto-reload 275 | npm run dev 276 | 277 | # Build TypeScript 278 | npm run build 279 | 280 | # Start production server 281 | npm start 282 | 283 | # Run tests 284 | npm test 285 | 286 | # Type checking 287 | npm run typecheck 288 | 289 | # Linting 290 | npm run lint 291 | ``` 292 | 293 | ## Project Structure 294 | 295 | ``` 296 | src/ 297 | ├── index.ts # MCP server entry point 298 | ├── client.ts # HTTP client for Open-Meteo API 299 | ├── tools.ts # MCP tool definitions 300 | └── types.ts # Zod validation schemas 301 | ``` 302 | 303 | ## API Coverage 304 | 305 | This server provides access to all major Open-Meteo endpoints: 306 | 307 | ### Weather Data 308 | - Current weather conditions 309 | - Hourly forecasts (up to 16 days) 310 | - Daily forecasts (up to 16 days) 311 | - Historical weather data (1940-present) 312 | 313 | ### Specialized Models 314 | - High-resolution regional models (DWD ICON, Météo-France AROME) 315 | - Global models (NOAA GFS, ECMWF) 316 | - Regional specialists (JMA for Asia, MET Norway for Nordics) 317 | 318 | ### Environmental Data 319 | - Air quality forecasts 320 | - Marine and ocean conditions 321 | - River discharge and flood warnings 322 | - Climate change projections 323 | 324 | ### Advanced Features 325 | - Ensemble forecasts for uncertainty quantification 326 | - Seasonal forecasts for long-term planning 327 | - Multiple model comparison 328 | - Customizable units and timezones 329 | 330 | ## Error Handling 331 | 332 | The server provides comprehensive error handling with detailed error messages for: 333 | - Invalid coordinates 334 | - Missing required parameters 335 | - API rate limits 336 | - Network connectivity issues 337 | - Invalid date ranges 338 | 339 | ## Performance 340 | 341 | - Efficient HTTP client with connection pooling 342 | - Request caching for repeated queries 343 | - Optimized data serialization 344 | - Minimal memory footprint 345 | 346 | ## API Documentation 347 | 348 | For detailed API documentation, refer to the `openapi.yml` file and the [Open-Meteo API documentation](https://open-meteo.com/en/docs). 349 | 350 | ## Contributing 351 | 352 | Contributions are welcome! Please feel free to submit a Pull Request. 353 | 354 | ### Development Setup 355 | 356 | 1. Fork the repository 357 | 2. Clone your fork: `git clone https://github.com/your-username/open-meteo-mcp.git` 358 | 3. Install dependencies: `npm install` 359 | 4. Create a feature branch: `git checkout -b feature/amazing-feature` 360 | 5. Make your changes and add tests 361 | 6. Run tests: `npm test` 362 | 7. Commit your changes: `git commit -m 'Add amazing feature'` 363 | 8. Push to the branch: `git push origin feature/amazing-feature` 364 | 9. Open a Pull Request 365 | 366 | ### Releasing 367 | 368 | This project uses automated releases via GitHub Actions. To create a new release: 369 | 370 | ```bash 371 | # For a patch release (1.0.0 -> 1.0.1) 372 | npm run release:patch 373 | 374 | # For a minor release (1.0.0 -> 1.1.0) 375 | npm run release:minor 376 | 377 | # For a major release (1.0.0 -> 2.0.0) 378 | npm run release:major 379 | ``` 380 | 381 | The GitHub Action will automatically: 382 | - Run tests and build the project 383 | - Publish to npm with provenance 384 | - Create a GitHub release 385 | - Update version badges 386 | 387 | ## License 388 | 389 | MIT -------------------------------------------------------------------------------- /src/tools.ts: -------------------------------------------------------------------------------- 1 | import { Tool } from '@modelcontextprotocol/sdk/types.js'; 2 | 3 | export const WEATHER_FORECAST_TOOL: Tool = { 4 | name: 'weather_forecast', 5 | description: 'Get weather forecast data for coordinates using Open-Meteo API. Supports hourly and daily data with various weather variables.', 6 | inputSchema: { 7 | type: 'object', 8 | properties: { 9 | latitude: { 10 | type: 'number', 11 | minimum: -90, 12 | maximum: 90, 13 | description: 'Latitude in WGS84 coordinate system' 14 | }, 15 | longitude: { 16 | type: 'number', 17 | minimum: -180, 18 | maximum: 180, 19 | description: 'Longitude in WGS84 coordinate system' 20 | }, 21 | hourly: { 22 | type: 'array', 23 | items: { 24 | type: 'string', 25 | enum: [ 26 | 'temperature_2m', 'relative_humidity_2m', 'dewpoint_2m', 'apparent_temperature', 27 | 'pressure_msl', 'surface_pressure', 'cloud_cover', 'wind_speed_10m', 'wind_direction_10m', 28 | 'wind_gusts_10m', 'shortwave_radiation', 'precipitation', 'rain', 'snowfall', 29 | 'precipitation_probability', 'weather_code', 'visibility', 'uv_index' 30 | ] 31 | }, 32 | description: 'Hourly weather variables to retrieve' 33 | }, 34 | daily: { 35 | type: 'array', 36 | items: { 37 | type: 'string', 38 | enum: [ 39 | 'temperature_2m_max', 'temperature_2m_min', 'apparent_temperature_max', 'apparent_temperature_min', 40 | 'precipitation_sum', 'weather_code', 'sunrise', 'sunset', 'wind_speed_10m_max', 41 | 'wind_gusts_10m_max', 'wind_direction_10m_dominant', 'shortwave_radiation_sum', 'uv_index_max' 42 | ] 43 | }, 44 | description: 'Daily weather variables to retrieve' 45 | }, 46 | current_weather: { 47 | type: 'boolean', 48 | description: 'Include current weather conditions' 49 | }, 50 | temperature_unit: { 51 | type: 'string', 52 | enum: ['celsius', 'fahrenheit'], 53 | default: 'celsius', 54 | description: 'Temperature unit' 55 | }, 56 | wind_speed_unit: { 57 | type: 'string', 58 | enum: ['kmh', 'ms', 'mph', 'kn'], 59 | default: 'kmh', 60 | description: 'Wind speed unit' 61 | }, 62 | precipitation_unit: { 63 | type: 'string', 64 | enum: ['mm', 'inch'], 65 | default: 'mm', 66 | description: 'Precipitation unit' 67 | }, 68 | timezone: { 69 | type: 'string', 70 | description: 'Timezone for timestamps (e.g., Europe/Paris, America/New_York)' 71 | }, 72 | past_days: { 73 | type: 'integer', 74 | enum: [1, 2], 75 | description: 'Include past days data' 76 | }, 77 | forecast_days: { 78 | type: 'integer', 79 | minimum: 1, 80 | maximum: 16, 81 | default: 7, 82 | description: 'Number of forecast days' 83 | } 84 | }, 85 | required: ['latitude', 'longitude'] 86 | } 87 | }; 88 | 89 | export const WEATHER_ARCHIVE_TOOL: Tool = { 90 | name: 'weather_archive', 91 | description: 'Get historical weather data from ERA5 reanalysis (1940-present) for specific coordinates and date range.', 92 | inputSchema: { 93 | type: 'object', 94 | properties: { 95 | latitude: { 96 | type: 'number', 97 | minimum: -90, 98 | maximum: 90, 99 | description: 'Latitude in WGS84 coordinate system' 100 | }, 101 | longitude: { 102 | type: 'number', 103 | minimum: -180, 104 | maximum: 180, 105 | description: 'Longitude in WGS84 coordinate system' 106 | }, 107 | start_date: { 108 | type: 'string', 109 | pattern: '^\\d{4}-\\d{2}-\\d{2}$', 110 | description: 'Start date in YYYY-MM-DD format' 111 | }, 112 | end_date: { 113 | type: 'string', 114 | pattern: '^\\d{4}-\\d{2}-\\d{2}$', 115 | description: 'End date in YYYY-MM-DD format' 116 | }, 117 | hourly: { 118 | type: 'array', 119 | items: { 120 | type: 'string', 121 | enum: [ 122 | 'temperature_2m', 'relative_humidity_2m', 'precipitation', 'pressure_msl', 123 | 'wind_speed_10m', 'wind_direction_10m', 'shortwave_radiation' 124 | ] 125 | }, 126 | description: 'Hourly weather variables to retrieve' 127 | }, 128 | daily: { 129 | type: 'array', 130 | items: { 131 | type: 'string', 132 | enum: [ 133 | 'temperature_2m_max', 'temperature_2m_min', 'precipitation_sum', 134 | 'wind_speed_10m_max', 'shortwave_radiation_sum' 135 | ] 136 | }, 137 | description: 'Daily weather variables to retrieve' 138 | }, 139 | temperature_unit: { 140 | type: 'string', 141 | enum: ['celsius', 'fahrenheit'], 142 | default: 'celsius' 143 | }, 144 | timezone: { 145 | type: 'string', 146 | description: 'Timezone for timestamps' 147 | } 148 | }, 149 | required: ['latitude', 'longitude', 'start_date', 'end_date'] 150 | } 151 | }; 152 | 153 | export const AIR_QUALITY_TOOL: Tool = { 154 | name: 'air_quality', 155 | description: 'Get air quality forecast data including PM2.5, PM10, ozone, nitrogen dioxide and other pollutants.', 156 | inputSchema: { 157 | type: 'object', 158 | properties: { 159 | latitude: { 160 | type: 'number', 161 | minimum: -90, 162 | maximum: 90, 163 | description: 'Latitude in WGS84 coordinate system' 164 | }, 165 | longitude: { 166 | type: 'number', 167 | minimum: -180, 168 | maximum: 180, 169 | description: 'Longitude in WGS84 coordinate system' 170 | }, 171 | hourly: { 172 | type: 'array', 173 | items: { 174 | type: 'string', 175 | enum: [ 176 | 'pm10', 'pm2_5', 'carbon_monoxide', 'nitrogen_dioxide', 'ozone', 177 | 'sulphur_dioxide', 'ammonia', 'dust', 'aerosol_optical_depth' 178 | ] 179 | }, 180 | description: 'Air quality variables to retrieve' 181 | }, 182 | timezone: { 183 | type: 'string', 184 | description: 'Timezone for timestamps' 185 | }, 186 | past_days: { 187 | type: 'integer', 188 | minimum: 1, 189 | maximum: 7, 190 | description: 'Include past days data' 191 | }, 192 | forecast_days: { 193 | type: 'integer', 194 | minimum: 1, 195 | maximum: 16, 196 | default: 7, 197 | description: 'Number of forecast days' 198 | } 199 | }, 200 | required: ['latitude', 'longitude'] 201 | } 202 | }; 203 | 204 | export const MARINE_WEATHER_TOOL: Tool = { 205 | name: 'marine_weather', 206 | description: 'Get marine weather forecast including wave height, wave period, wave direction and sea surface temperature.', 207 | inputSchema: { 208 | type: 'object', 209 | properties: { 210 | latitude: { 211 | type: 'number', 212 | minimum: -90, 213 | maximum: 90, 214 | description: 'Latitude in WGS84 coordinate system' 215 | }, 216 | longitude: { 217 | type: 'number', 218 | minimum: -180, 219 | maximum: 180, 220 | description: 'Longitude in WGS84 coordinate system' 221 | }, 222 | hourly: { 223 | type: 'array', 224 | items: { 225 | type: 'string', 226 | enum: [ 227 | 'wave_height', 'wave_direction', 'wave_period', 228 | 'wind_wave_height', 'wind_wave_direction', 'wind_wave_period', 229 | 'swell_wave_height', 'swell_wave_direction', 'swell_wave_period', 230 | 'sea_surface_temperature' 231 | ] 232 | }, 233 | description: 'Marine weather variables to retrieve' 234 | }, 235 | daily: { 236 | type: 'array', 237 | items: { 238 | type: 'string', 239 | enum: [ 240 | 'wave_height_max', 'wind_wave_height_max', 'swell_wave_height_max' 241 | ] 242 | }, 243 | description: 'Daily marine weather variables to retrieve' 244 | }, 245 | timezone: { 246 | type: 'string', 247 | description: 'Timezone for timestamps' 248 | }, 249 | past_days: { 250 | type: 'integer', 251 | minimum: 1, 252 | maximum: 7, 253 | description: 'Include past days data' 254 | }, 255 | forecast_days: { 256 | type: 'integer', 257 | minimum: 1, 258 | maximum: 16, 259 | default: 7, 260 | description: 'Number of forecast days' 261 | } 262 | }, 263 | required: ['latitude', 'longitude'] 264 | } 265 | }; 266 | 267 | export const ELEVATION_TOOL: Tool = { 268 | name: 'elevation', 269 | description: 'Get elevation data for given coordinates using digital elevation models.', 270 | inputSchema: { 271 | type: 'object', 272 | properties: { 273 | latitude: { 274 | type: 'number', 275 | minimum: -90, 276 | maximum: 90, 277 | description: 'Latitude in WGS84 coordinate system' 278 | }, 279 | longitude: { 280 | type: 'number', 281 | minimum: -180, 282 | maximum: 180, 283 | description: 'Longitude in WGS84 coordinate system' 284 | } 285 | }, 286 | required: ['latitude', 'longitude'] 287 | } 288 | }; 289 | 290 | export const WEATHER_MODEL_TOOLS: Tool[] = [ 291 | { 292 | name: 'dwd_icon_forecast', 293 | description: 'Get weather forecast from German DWD ICON model with high resolution data for Europe and global coverage.', 294 | inputSchema: WEATHER_FORECAST_TOOL.inputSchema 295 | }, 296 | { 297 | name: 'gfs_forecast', 298 | description: 'Get weather forecast from US NOAA GFS model with global coverage and high-resolution data for North America.', 299 | inputSchema: WEATHER_FORECAST_TOOL.inputSchema 300 | }, 301 | { 302 | name: 'meteofrance_forecast', 303 | description: 'Get weather forecast from French Météo-France models including AROME (high-resolution France) and ARPEGE (Europe).', 304 | inputSchema: WEATHER_FORECAST_TOOL.inputSchema 305 | }, 306 | { 307 | name: 'ecmwf_forecast', 308 | description: 'Get weather forecast from European Centre for Medium-Range Weather Forecasts with high-quality global forecasts.', 309 | inputSchema: WEATHER_FORECAST_TOOL.inputSchema 310 | }, 311 | { 312 | name: 'jma_forecast', 313 | description: 'Get weather forecast from Japan Meteorological Agency with high-resolution data for Japan and Asia.', 314 | inputSchema: WEATHER_FORECAST_TOOL.inputSchema 315 | }, 316 | { 317 | name: 'metno_forecast', 318 | description: 'Get weather forecast from Norwegian weather service with high-resolution data for Nordic countries.', 319 | inputSchema: WEATHER_FORECAST_TOOL.inputSchema 320 | }, 321 | { 322 | name: 'gem_forecast', 323 | description: 'Get weather forecast from Canadian weather service GEM model with high-resolution data for Canada and North America.', 324 | inputSchema: WEATHER_FORECAST_TOOL.inputSchema 325 | } 326 | ]; 327 | 328 | export const FLOOD_FORECAST_TOOL: Tool = { 329 | name: 'flood_forecast', 330 | description: 'Get river discharge and flood forecasts from GloFAS (Global Flood Awareness System).', 331 | inputSchema: { 332 | type: 'object', 333 | properties: { 334 | latitude: { 335 | type: 'number', 336 | minimum: -90, 337 | maximum: 90, 338 | description: 'Latitude in WGS84 coordinate system' 339 | }, 340 | longitude: { 341 | type: 'number', 342 | minimum: -180, 343 | maximum: 180, 344 | description: 'Longitude in WGS84 coordinate system' 345 | }, 346 | daily: { 347 | type: 'array', 348 | items: { 349 | type: 'string', 350 | enum: [ 351 | 'river_discharge', 'river_discharge_mean', 'river_discharge_median', 352 | 'river_discharge_max', 'river_discharge_min', 'river_discharge_p25', 'river_discharge_p75' 353 | ] 354 | }, 355 | description: 'River discharge variables to retrieve' 356 | }, 357 | timezone: { 358 | type: 'string', 359 | description: 'Timezone for timestamps' 360 | }, 361 | past_days: { 362 | type: 'integer', 363 | minimum: 1, 364 | maximum: 7, 365 | description: 'Include past days data' 366 | }, 367 | forecast_days: { 368 | type: 'integer', 369 | minimum: 1, 370 | maximum: 210, 371 | default: 92, 372 | description: 'Number of forecast days (up to 210 days possible)' 373 | }, 374 | ensemble: { 375 | type: 'boolean', 376 | description: 'If true, all forecast ensemble members will be returned' 377 | } 378 | }, 379 | required: ['latitude', 'longitude'] 380 | } 381 | }; 382 | 383 | export const SEASONAL_FORECAST_TOOL: Tool = { 384 | name: 'seasonal_forecast', 385 | description: 'Get long-range seasonal forecasts for temperature and precipitation up to 9 months ahead.', 386 | inputSchema: { 387 | type: 'object', 388 | properties: { 389 | latitude: { 390 | type: 'number', 391 | minimum: -90, 392 | maximum: 90, 393 | description: 'Latitude in WGS84 coordinate system' 394 | }, 395 | longitude: { 396 | type: 'number', 397 | minimum: -180, 398 | maximum: 180, 399 | description: 'Longitude in WGS84 coordinate system' 400 | }, 401 | hourly: { 402 | type: 'array', 403 | items: { 404 | type: 'string', 405 | enum: [ 406 | 'pressure_msl', 'temperature_2m', 'temperature_2m_max', 'temperature_2m_min', 'shortwave_radiation', 407 | 'cloud_cover', 'precipitation', 'showers', 'wind_speed_10m', 'wind_direction_10m', 408 | 'relative_humidity_2m', 'soil_temperature_0_to_10cm', 'soil_moisture_0_to_10cm', 'soil_moisture_10_to_40cm', 409 | 'soil_moisture_40_to_100cm', 'soil_moisture_100_to_200cm' 410 | ] 411 | }, 412 | description: '6-hourly weather variables to retrieve' 413 | }, 414 | daily: { 415 | type: 'array', 416 | items: { 417 | type: 'string', 418 | enum: [ 419 | 'temperature_2m_max', 'temperature_2m_min', 'shortwave_radiation_sum', 420 | 'precipitation_sum', 'rain_sum', 'precipitation_hours', 421 | 'wind_speed_10m_max', 'wind_direction_10m_dominant' 422 | ] 423 | }, 424 | description: 'Daily weather variables to retrieve' 425 | }, 426 | forecast_days: { 427 | type: 'integer', 428 | enum: [45, 92, 183, 274], 429 | default: 92, 430 | description: 'Number of forecast days: 45 days, 3 months (default), 6 months, or 9 months' 431 | }, 432 | past_days: { 433 | type: 'integer', 434 | minimum: 0, 435 | maximum: 92, 436 | description: 'Include past days data' 437 | }, 438 | start_date: { 439 | type: 'string', 440 | pattern: '^\\d{4}-\\d{2}-\\d{2}$', 441 | description: 'Start date in YYYY-MM-DD format' 442 | }, 443 | end_date: { 444 | type: 'string', 445 | pattern: '^\\d{4}-\\d{2}-\\d{2}$', 446 | description: 'End date in YYYY-MM-DD format' 447 | }, 448 | temperature_unit: { 449 | type: 'string', 450 | enum: ['celsius', 'fahrenheit'], 451 | default: 'celsius' 452 | }, 453 | wind_speed_unit: { 454 | type: 'string', 455 | enum: ['kmh', 'ms', 'mph', 'kn'], 456 | default: 'kmh' 457 | }, 458 | precipitation_unit: { 459 | type: 'string', 460 | enum: ['mm', 'inch'], 461 | default: 'mm' 462 | }, 463 | timezone: { 464 | type: 'string', 465 | description: 'Timezone for timestamps' 466 | } 467 | }, 468 | required: ['latitude', 'longitude'] 469 | } 470 | }; 471 | 472 | export const CLIMATE_PROJECTION_TOOL: Tool = { 473 | name: 'climate_projection', 474 | description: 'Get climate change projections from CMIP6 models for different warming scenarios.', 475 | inputSchema: { 476 | type: 'object', 477 | properties: { 478 | latitude: { 479 | type: 'number', 480 | minimum: -90, 481 | maximum: 90, 482 | description: 'Latitude in WGS84 coordinate system' 483 | }, 484 | longitude: { 485 | type: 'number', 486 | minimum: -180, 487 | maximum: 180, 488 | description: 'Longitude in WGS84 coordinate system' 489 | }, 490 | daily: { 491 | type: 'array', 492 | items: { 493 | type: 'string', 494 | enum: [ 495 | 'temperature_2m_max', 'temperature_2m_min', 'temperature_2m_mean', 496 | 'cloud_cover_mean', 'relative_humidity_2m_max', 'relative_humidity_2m_min', 497 | 'relative_humidity_2m_mean', 'soil_moisture_0_to_10cm_mean', 498 | 'precipitation_sum', 'rain_sum', 'snowfall_sum', 'wind_speed_10m_mean', 499 | 'wind_speed_10m_max', 'pressure_msl_mean', 'shortwave_radiation_sum' 500 | ] 501 | }, 502 | description: 'Climate projection variables to retrieve' 503 | }, 504 | start_date: { 505 | type: 'string', 506 | pattern: '^\\d{4}-\\d{2}-\\d{2}$', 507 | description: 'Start date in YYYY-MM-DD format' 508 | }, 509 | end_date: { 510 | type: 'string', 511 | pattern: '^\\d{4}-\\d{2}-\\d{2}$', 512 | description: 'End date in YYYY-MM-DD format' 513 | }, 514 | models: { 515 | type: 'array', 516 | items: { 517 | type: 'string', 518 | enum: [ 519 | 'meteofrance_arome_france_hd', 'meteofrance_arome_france', 'meteofrance_arpege_europe', 520 | 'icon_eu', 'icon_global', 'ecmwf_ifs025', 'gfs013' 521 | ] 522 | }, 523 | description: 'Climate models to use' 524 | }, 525 | temperature_unit: { 526 | type: 'string', 527 | enum: ['celsius', 'fahrenheit'], 528 | default: 'celsius' 529 | }, 530 | wind_speed_unit: { 531 | type: 'string', 532 | enum: ['kmh', 'ms', 'mph', 'kn'], 533 | default: 'kmh' 534 | }, 535 | precipitation_unit: { 536 | type: 'string', 537 | enum: ['mm', 'inch'], 538 | default: 'mm' 539 | }, 540 | disable_bias_correction: { 541 | type: 'boolean', 542 | default: false, 543 | description: 'Disable statistical downscaling and bias correction' 544 | } 545 | }, 546 | required: ['latitude', 'longitude', 'start_date', 'end_date', 'models', 'daily'] 547 | } 548 | }; 549 | 550 | export const ENSEMBLE_FORECAST_TOOL: Tool = { 551 | name: 'ensemble_forecast', 552 | description: 'Get ensemble forecasts showing forecast uncertainty with multiple model runs.', 553 | inputSchema: { 554 | type: 'object', 555 | properties: { 556 | latitude: { 557 | type: 'number', 558 | minimum: -90, 559 | maximum: 90, 560 | description: 'Latitude in WGS84 coordinate system' 561 | }, 562 | longitude: { 563 | type: 'number', 564 | minimum: -180, 565 | maximum: 180, 566 | description: 'Longitude in WGS84 coordinate system' 567 | }, 568 | models: { 569 | type: 'array', 570 | items: { 571 | type: 'string', 572 | enum: [ 573 | 'meteofrance_arome_france_hd', 'meteofrance_arome_france', 'meteofrance_arpege_europe', 574 | 'icon_eu', 'icon_global', 'ecmwf_ifs025', 'gfs013' 575 | ] 576 | }, 577 | description: 'Ensemble models to use' 578 | }, 579 | hourly: { 580 | type: 'array', 581 | items: { 582 | type: 'string', 583 | enum: [ 584 | 'temperature_2m', 'relative_humidity_2m', 'dew_point_2m', 'apparent_temperature', 585 | 'precipitation', 'rain', 'snowfall', 'snow_depth', 'weather_code', 586 | 'pressure_msl', 'surface_pressure', 'cloud_cover', 'visibility', 587 | 'wind_speed_10m', 'wind_direction_10m', 'wind_gusts_10m', 588 | 'wind_speed_80m', 'wind_direction_80m', 'wind_speed_100m', 'wind_direction_100m', 589 | 'surface_temperature', 'soil_temperature_0_to_10cm', 'cape', 590 | 'et0_fao_evapotranspiration', 'vapour_pressure_deficit', 'shortwave_radiation' 591 | ] 592 | }, 593 | description: 'Hourly weather variables to retrieve' 594 | }, 595 | daily: { 596 | type: 'array', 597 | items: { 598 | type: 'string', 599 | enum: [ 600 | 'temperature_2m_mean', 'temperature_2m_min', 'temperature_2m_max', 601 | 'apparent_temperature_mean', 'apparent_temperature_min', 'apparent_temperature_max', 602 | 'wind_speed_10m_mean', 'wind_speed_10m_min', 'wind_speed_10m_max', 603 | 'wind_direction_10m_dominant', 'wind_gusts_10m_mean', 'wind_gusts_10m_min', 'wind_gusts_10m_max', 604 | 'precipitation_sum', 'precipitation_hours', 'rain_sum', 'snowfall_sum', 605 | 'pressure_msl_mean', 'pressure_msl_min', 'pressure_msl_max', 606 | 'cloud_cover_mean', 'cloud_cover_min', 'cloud_cover_max', 607 | 'relative_humidity_2m_mean', 'relative_humidity_2m_min', 'relative_humidity_2m_max', 608 | 'cape_mean', 'cape_min', 'cape_max', 'shortwave_radiation_sum' 609 | ] 610 | }, 611 | description: 'Daily weather variables to retrieve' 612 | }, 613 | forecast_days: { 614 | type: 'integer', 615 | minimum: 1, 616 | maximum: 35, 617 | default: 7, 618 | description: 'Number of forecast days' 619 | }, 620 | temperature_unit: { 621 | type: 'string', 622 | enum: ['celsius', 'fahrenheit'], 623 | default: 'celsius' 624 | }, 625 | wind_speed_unit: { 626 | type: 'string', 627 | enum: ['kmh', 'ms', 'mph', 'kn'], 628 | default: 'kmh' 629 | }, 630 | precipitation_unit: { 631 | type: 'string', 632 | enum: ['mm', 'inch'], 633 | default: 'mm' 634 | }, 635 | timezone: { 636 | type: 'string', 637 | description: 'Timezone for timestamps' 638 | } 639 | }, 640 | required: ['latitude', 'longitude', 'models'] 641 | } 642 | }; 643 | 644 | export const GEOCODING_TOOL: Tool = { 645 | name: 'geocoding', 646 | description: 'Search for locations worldwide by place name or postal code. Returns geographic coordinates and detailed location information.', 647 | inputSchema: { 648 | type: 'object', 649 | properties: { 650 | name: { 651 | type: 'string', 652 | minLength: 2, 653 | description: 'Place name or postal code to search for. Minimum 2 characters required. Examples: "Paris", "Berlin", "75001", "10967"' 654 | }, 655 | count: { 656 | type: 'integer', 657 | minimum: 1, 658 | maximum: 100, 659 | default: 10, 660 | description: 'Number of search results to return (maximum 100)' 661 | }, 662 | language: { 663 | type: 'string', 664 | description: 'Language code for translated results (e.g., "fr", "en", "de"). Returns translated results if available, otherwise in English or native language.' 665 | }, 666 | countryCode: { 667 | type: 'string', 668 | pattern: '^[A-Z]{2}$', 669 | description: 'ISO-3166-1 alpha2 country code to filter results (e.g., "FR", "DE", "US"). Limits search to a specific country.' 670 | }, 671 | format: { 672 | type: 'string', 673 | enum: ['json', 'protobuf'], 674 | default: 'json', 675 | description: 'Return format for results' 676 | } 677 | }, 678 | required: ['name'] 679 | } 680 | }; 681 | 682 | export const ALL_TOOLS: Tool[] = [ 683 | WEATHER_FORECAST_TOOL, 684 | WEATHER_ARCHIVE_TOOL, 685 | AIR_QUALITY_TOOL, 686 | MARINE_WEATHER_TOOL, 687 | ELEVATION_TOOL, 688 | FLOOD_FORECAST_TOOL, 689 | SEASONAL_FORECAST_TOOL, 690 | CLIMATE_PROJECTION_TOOL, 691 | ENSEMBLE_FORECAST_TOOL, 692 | GEOCODING_TOOL, 693 | ...WEATHER_MODEL_TOOLS 694 | ]; -------------------------------------------------------------------------------- /openapi.yml: -------------------------------------------------------------------------------- 1 | openapi: 3.1.0 2 | info: 3 | title: Open-Meteo APIs 4 | description: 'Open-Meteo offers free weather forecast APIs for open-source developers and non-commercial use. No API key is required.' 5 | version: '1.0' 6 | contact: 7 | name: Open-Meteo 8 | url: https://open-meteo.com 9 | email: info@open-meteo.com 10 | license: 11 | name: Attribution 4.0 International (CC BY 4.0) 12 | url: https://creativecommons.org/licenses/by/4.0/ 13 | termsOfService: https://open-meteo.com/en/features#terms 14 | servers: 15 | - url: https://api.open-meteo.com 16 | description: Production API 17 | - url: https://meteo-api.cloud.cmer.fr 18 | description: Custom instance 19 | 20 | paths: 21 | /v1/forecast: 22 | get: 23 | tags: 24 | - Weather Forecast APIs 25 | summary: 7 day weather forecast for coordinates 26 | description: 7 day weather variables in hourly and daily resolution for given WGS84 latitude and longitude coordinates. Available worldwide. 27 | parameters: 28 | - name: hourly 29 | in: query 30 | explode: false 31 | schema: 32 | type: array 33 | items: 34 | type: string 35 | enum: 36 | # Temperature variables 37 | - temperature_2m 38 | - relative_humidity_2m 39 | - dewpoint_2m 40 | - apparent_temperature 41 | - surface_temperature 42 | # Pressure variables 43 | - pressure_msl 44 | - surface_pressure 45 | # Cloud variables 46 | - cloud_cover 47 | - cloud_cover_low 48 | - cloud_cover_mid 49 | - cloud_cover_high 50 | # Wind variables 51 | - wind_speed_10m 52 | - wind_speed_80m 53 | - wind_speed_120m 54 | - wind_speed_180m 55 | - wind_direction_10m 56 | - wind_direction_80m 57 | - wind_direction_120m 58 | - wind_direction_180m 59 | - wind_gusts_10m 60 | - wind_u_component_10m 61 | - wind_v_component_10m 62 | - wind_u_component_80m 63 | - wind_v_component_80m 64 | - wind_u_component_120m 65 | - wind_v_component_120m 66 | - wind_u_component_180m 67 | - wind_v_component_180m 68 | # Radiation variables 69 | - shortwave_radiation 70 | - direct_radiation 71 | - direct_normal_irradiance 72 | - diffuse_radiation 73 | - terrestrial_radiation 74 | - sunshine_duration 75 | - uv_index 76 | - uv_index_clear_sky 77 | # Precipitation variables 78 | - precipitation 79 | - rain 80 | - showers 81 | - snowfall 82 | - precipitation_probability 83 | - snow_depth 84 | - snow_height 85 | # Atmospheric variables 86 | - vapour_pressure_deficit 87 | - et0_fao_evapotranspiration 88 | - weather_code 89 | - visibility 90 | - is_day 91 | - cape 92 | - lifted_index 93 | - convective_inhibition 94 | - freezing_level_height 95 | - boundary_layer_height 96 | - updraft_velocity 97 | - downdraft_velocity 98 | # Soil variables 99 | - soil_temperature_0cm 100 | - soil_temperature_6cm 101 | - soil_temperature_18cm 102 | - soil_temperature_54cm 103 | - soil_moisture_0_1cm 104 | - soil_moisture_1_3cm 105 | - soil_moisture_3_9cm 106 | - soil_moisture_9_27cm 107 | - soil_moisture_27_81cm 108 | # Energy flux variables 109 | - sensible_heat_flux 110 | - latent_heat_flux 111 | # Agricultural variables 112 | - growing_degree_days_base_0_limit_30 113 | - leaf_wetness_probability 114 | - skin_temperature 115 | - name: daily 116 | in: query 117 | schema: 118 | type: array 119 | items: 120 | type: string 121 | enum: 122 | - temperature_2m_max 123 | - temperature_2m_min 124 | - apparent_temperature_max 125 | - apparent_temperature_min 126 | - precipitation_sum 127 | - precipitation_hours 128 | - weather_code 129 | - sunrise 130 | - sunset 131 | - wind_speed_10m_max 132 | - wind_gusts_10m_max 133 | - wind_direction_10m_dominant 134 | - shortwave_radiation_sum 135 | - uv_index_max 136 | - uv_index_clear_sky_max 137 | - et0_fao_evapotranspiration 138 | - name: latitude 139 | in: query 140 | required: true 141 | description: "WGS84 coordinate" 142 | schema: 143 | type: number 144 | format: double 145 | - name: longitude 146 | in: query 147 | required: true 148 | description: "WGS84 coordinate" 149 | schema: 150 | type: number 151 | format: double 152 | - name: current_weather 153 | in: query 154 | schema: 155 | type: boolean 156 | - name: temperature_unit 157 | in: query 158 | schema: 159 | type: string 160 | default: celsius 161 | enum: 162 | - celsius 163 | - fahrenheit 164 | - name: wind_speed_unit 165 | in: query 166 | schema: 167 | type: string 168 | default: kmh 169 | enum: 170 | - kmh 171 | - ms 172 | - mph 173 | - kn 174 | - name: precipitation_unit 175 | in: query 176 | description: "Other precipitation amount units" 177 | schema: 178 | type: string 179 | default: mm 180 | enum: 181 | - mm 182 | - inch 183 | - name: timeformat 184 | in: query 185 | description: If format `unixtime` is selected, all time values are returned in UNIX epoch time in seconds. Please not that all time is then in GMT+0! For daily values with unix timestamp, please apply `utc_offset_seconds` again to get the correct date. 186 | schema: 187 | type: string 188 | default: iso8601 189 | enum: 190 | - iso8601 191 | - unixtime 192 | - name: timezone 193 | in: query 194 | description: If `timezone` is set, all timestamps are returned as local-time and data is returned starting at 0:00 local-time. Any time zone name from the [time zone database](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) is supported. 195 | schema: 196 | type: string 197 | - name: past_days 198 | in: query 199 | description: If `past_days` is set, yesterdays or the day before yesterdays data are also returned. 200 | schema: 201 | type: integer 202 | enum: 203 | - 1 204 | - 2 205 | - name: start_date 206 | in: query 207 | description: "The time interval to get weather data. A day must be specified as an ISO8601 date (e.g. 2022-06-30)." 208 | schema: 209 | type: string 210 | format: date 211 | pattern: '^\d{4}-\d{2}-\d{2}$' 212 | - name: end_date 213 | in: query 214 | description: "The time interval to get weather data. A day must be specified as an ISO8601 date (e.g. 2022-06-30). Note: start_date is required when end_date is specified." 215 | schema: 216 | type: string 217 | format: date 218 | pattern: '^\d{4}-\d{2}-\d{2}$' 219 | - name: start_hour 220 | in: query 221 | description: "The time interval to get weather data for hourly or 15 minutely data. Time must be specified as an ISO8601 date (e.g. 2022-06-30T12:00)." 222 | schema: 223 | type: string 224 | format: date-time 225 | pattern: '^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$' 226 | - name: end_hour 227 | in: query 228 | description: "The time interval to get weather data for hourly or 15 minutely data. Time must be specified as an ISO8601 date (e.g. 2022-06-30T12:00)." 229 | schema: 230 | type: string 231 | format: date-time 232 | pattern: '^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$' 233 | - name: start_minutely_15 234 | in: query 235 | description: "The time interval to get weather data for hourly or 15 minutely data. Time must be specified as an ISO8601 date (e.g. 2022-06-30T12:00)." 236 | schema: 237 | type: string 238 | format: date-time 239 | pattern: '^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$' 240 | - name: end_minutely_15 241 | in: query 242 | description: "The time interval to get weather data for hourly or 15 minutely data. Time must be specified as an ISO8601 date (e.g. 2022-06-30T12:00)." 243 | schema: 244 | type: string 245 | format: date-time 246 | pattern: '^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$' 247 | - name: models 248 | in: query 249 | description: "Manually select one or more weather models. Available models: meteofrance_arome_france_hd (Météo-France HD France), meteofrance_arome_france (Météo-France AROME 0.025°), meteofrance_arpege_europe (Météo-France ARPÈGE Europe), icon_eu (DWD ICON Europe), icon_global (DWD ICON Global), ecmwf_ifs025 (ECMWF IFS 0.25°), gfs013 (NCEP GFS 0.13°). If not specified, the server will use its default selection algorithm." 250 | schema: 251 | type: array 252 | items: 253 | type: string 254 | enum: 255 | - meteofrance_arome_france_hd 256 | - meteofrance_arome_france 257 | - meteofrance_arpege_europe 258 | - icon_eu 259 | - icon_global 260 | - ecmwf_ifs025 261 | - gfs013 262 | responses: 263 | "200": 264 | description: OK 265 | content: 266 | application/json: 267 | schema: 268 | type: object 269 | properties: 270 | latitude: 271 | type: number 272 | example: 52.52 273 | description: WGS84 of the center of the weather grid-cell which was used to generate this forecast. This coordinate might be up to 5 km away. 274 | longitude: 275 | type: number 276 | example: 13.419.52 277 | description: WGS84 of the center of the weather grid-cell which was used to generate this forecast. This coordinate might be up to 5 km away. 278 | elevation: 279 | type: number 280 | example: 44.812 281 | description: The elevation in meters of the selected weather grid-cell. In mountain terrain it might differ from the location you would expect. 282 | generationtime_ms: 283 | type: number 284 | example: 2.2119 285 | description: Generation time of the weather forecast in milli seconds. This is mainly used for performance monitoring and improvements. 286 | utc_offset_seconds: 287 | type: integer 288 | example: 3600 289 | description: Applied timezone offset from the &timezone= parameter. 290 | hourly: 291 | $ref: "#/components/schemas/HourlyResponse" 292 | hourly_units: 293 | type: object 294 | additionalProperties: 295 | type: string 296 | description: For each selected weather variable, the unit will be listed here. 297 | daily: 298 | $ref: "#/components/schemas/DailyResponse" 299 | daily_units: 300 | type: object 301 | additionalProperties: 302 | type: string 303 | description: For each selected daily weather variable, the unit will be listed here. 304 | current_weather: 305 | $ref: "#/components/schemas/CurrentWeather" 306 | "400": 307 | description: Bad Request 308 | content: 309 | application/json: 310 | schema: 311 | type: object 312 | properties: 313 | error: 314 | type: boolean 315 | description: Always set true for errors 316 | reason: 317 | type: string 318 | description: Description of the error 319 | example: "Latitude must be in range of -90 to 90°. Given: 300" 320 | 321 | /v1/archive: 322 | get: 323 | tags: 324 | - Historical Weather APIs 325 | summary: 80 years of historical weather data 326 | description: Historical weather data from ERA5 reanalysis (1940-present) with hourly and daily resolution. 327 | parameters: 328 | - $ref: '#/components/parameters/latitude' 329 | - $ref: '#/components/parameters/longitude' 330 | - $ref: '#/components/parameters/hourly' 331 | - $ref: '#/components/parameters/daily' 332 | - $ref: '#/components/parameters/start_date' 333 | - $ref: '#/components/parameters/end_date' 334 | - $ref: '#/components/parameters/timezone' 335 | - $ref: '#/components/parameters/temperature_unit' 336 | - $ref: '#/components/parameters/wind_speed_unit' 337 | - $ref: '#/components/parameters/precipitation_unit' 338 | - $ref: '#/components/parameters/timeformat' 339 | responses: 340 | "200": 341 | $ref: '#/components/responses/WeatherResponse' 342 | "400": 343 | $ref: '#/components/responses/ErrorResponse' 344 | 345 | /v1/dwd-icon: 346 | get: 347 | tags: 348 | - Weather Model APIs 349 | summary: DWD ICON weather forecast 350 | description: German weather service (DWD) ICON model with high resolution data for Europe and global coverage. 351 | parameters: 352 | - $ref: '#/components/parameters/latitude' 353 | - $ref: '#/components/parameters/longitude' 354 | - $ref: '#/components/parameters/hourly' 355 | - $ref: '#/components/parameters/daily' 356 | - $ref: '#/components/parameters/current_weather' 357 | - $ref: '#/components/parameters/timezone' 358 | - $ref: '#/components/parameters/temperature_unit' 359 | - $ref: '#/components/parameters/wind_speed_unit' 360 | - $ref: '#/components/parameters/precipitation_unit' 361 | - $ref: '#/components/parameters/timeformat' 362 | - $ref: '#/components/parameters/past_days' 363 | - $ref: '#/components/parameters/forecast_days' 364 | responses: 365 | "200": 366 | $ref: '#/components/responses/WeatherResponse' 367 | "400": 368 | $ref: '#/components/responses/ErrorResponse' 369 | 370 | /v1/gfs: 371 | get: 372 | tags: 373 | - Weather Model APIs 374 | summary: NOAA GFS weather forecast 375 | description: US weather service (NOAA) GFS model with global coverage and high-resolution data for North America. 376 | parameters: 377 | - $ref: '#/components/parameters/latitude' 378 | - $ref: '#/components/parameters/longitude' 379 | - $ref: '#/components/parameters/hourly' 380 | - $ref: '#/components/parameters/daily' 381 | - $ref: '#/components/parameters/minutely_15' 382 | - $ref: '#/components/parameters/current_weather' 383 | - $ref: '#/components/parameters/timezone' 384 | - $ref: '#/components/parameters/temperature_unit' 385 | - $ref: '#/components/parameters/wind_speed_unit' 386 | - $ref: '#/components/parameters/precipitation_unit' 387 | - $ref: '#/components/parameters/timeformat' 388 | - $ref: '#/components/parameters/past_days' 389 | - $ref: '#/components/parameters/forecast_days' 390 | responses: 391 | "200": 392 | $ref: '#/components/responses/WeatherResponse' 393 | "400": 394 | $ref: '#/components/responses/ErrorResponse' 395 | 396 | /v1/meteofrance: 397 | get: 398 | tags: 399 | - Weather Model APIs 400 | summary: Météo-France weather forecast 401 | description: French weather service models including AROME (high-resolution France) and ARPEGE (Europe). 402 | parameters: 403 | - $ref: '#/components/parameters/latitude' 404 | - $ref: '#/components/parameters/longitude' 405 | - $ref: '#/components/parameters/hourly' 406 | - $ref: '#/components/parameters/daily' 407 | - $ref: '#/components/parameters/minutely_15' 408 | - $ref: '#/components/parameters/current_weather' 409 | - $ref: '#/components/parameters/timezone' 410 | - $ref: '#/components/parameters/temperature_unit' 411 | - $ref: '#/components/parameters/wind_speed_unit' 412 | - $ref: '#/components/parameters/precipitation_unit' 413 | - $ref: '#/components/parameters/timeformat' 414 | - $ref: '#/components/parameters/past_days' 415 | - $ref: '#/components/parameters/forecast_days' 416 | responses: 417 | "200": 418 | $ref: '#/components/responses/WeatherResponse' 419 | "400": 420 | $ref: '#/components/responses/ErrorResponse' 421 | 422 | /v1/ecmwf: 423 | get: 424 | tags: 425 | - Weather Model APIs 426 | summary: ECMWF weather forecast 427 | description: European Centre for Medium-Range Weather Forecasts with high-quality global forecasts. 428 | parameters: 429 | - $ref: '#/components/parameters/latitude' 430 | - $ref: '#/components/parameters/longitude' 431 | - $ref: '#/components/parameters/hourly' 432 | - $ref: '#/components/parameters/daily' 433 | - $ref: '#/components/parameters/timezone' 434 | - $ref: '#/components/parameters/temperature_unit' 435 | - $ref: '#/components/parameters/wind_speed_unit' 436 | - $ref: '#/components/parameters/precipitation_unit' 437 | - $ref: '#/components/parameters/timeformat' 438 | - $ref: '#/components/parameters/past_days' 439 | - $ref: '#/components/parameters/forecast_days' 440 | responses: 441 | "200": 442 | $ref: '#/components/responses/WeatherResponse' 443 | "400": 444 | $ref: '#/components/responses/ErrorResponse' 445 | 446 | /v1/jma: 447 | get: 448 | tags: 449 | - Weather Model APIs 450 | summary: JMA weather forecast 451 | description: Japan Meteorological Agency weather model with high-resolution data for Japan and Asia. 452 | parameters: 453 | - $ref: '#/components/parameters/latitude' 454 | - $ref: '#/components/parameters/longitude' 455 | - $ref: '#/components/parameters/hourly' 456 | - $ref: '#/components/parameters/daily' 457 | - $ref: '#/components/parameters/current_weather' 458 | - $ref: '#/components/parameters/timezone' 459 | - $ref: '#/components/parameters/temperature_unit' 460 | - $ref: '#/components/parameters/wind_speed_unit' 461 | - $ref: '#/components/parameters/precipitation_unit' 462 | - $ref: '#/components/parameters/timeformat' 463 | - $ref: '#/components/parameters/past_days' 464 | - $ref: '#/components/parameters/forecast_days' 465 | responses: 466 | "200": 467 | $ref: '#/components/responses/WeatherResponse' 468 | "400": 469 | $ref: '#/components/responses/ErrorResponse' 470 | 471 | /v1/metno: 472 | get: 473 | tags: 474 | - Weather Model APIs 475 | summary: MET Norway weather forecast 476 | description: Norwegian weather service model with high-resolution data for Nordic countries. 477 | parameters: 478 | - $ref: '#/components/parameters/latitude' 479 | - $ref: '#/components/parameters/longitude' 480 | - $ref: '#/components/parameters/hourly' 481 | - $ref: '#/components/parameters/daily' 482 | - $ref: '#/components/parameters/current_weather' 483 | - $ref: '#/components/parameters/timezone' 484 | - $ref: '#/components/parameters/temperature_unit' 485 | - $ref: '#/components/parameters/wind_speed_unit' 486 | - $ref: '#/components/parameters/precipitation_unit' 487 | - $ref: '#/components/parameters/timeformat' 488 | - $ref: '#/components/parameters/past_days' 489 | - $ref: '#/components/parameters/forecast_days' 490 | responses: 491 | "200": 492 | $ref: '#/components/responses/WeatherResponse' 493 | "400": 494 | $ref: '#/components/responses/ErrorResponse' 495 | 496 | /v1/gem: 497 | get: 498 | tags: 499 | - Weather Model APIs 500 | summary: Environment Canada GEM forecast 501 | description: Canadian weather service GEM model with high-resolution data for Canada and North America. 502 | parameters: 503 | - $ref: '#/components/parameters/latitude' 504 | - $ref: '#/components/parameters/longitude' 505 | - $ref: '#/components/parameters/hourly' 506 | - $ref: '#/components/parameters/daily' 507 | - $ref: '#/components/parameters/current_weather' 508 | - $ref: '#/components/parameters/timezone' 509 | - $ref: '#/components/parameters/temperature_unit' 510 | - $ref: '#/components/parameters/wind_speed_unit' 511 | - $ref: '#/components/parameters/precipitation_unit' 512 | - $ref: '#/components/parameters/timeformat' 513 | - $ref: '#/components/parameters/past_days' 514 | - $ref: '#/components/parameters/forecast_days' 515 | responses: 516 | "200": 517 | $ref: '#/components/responses/WeatherResponse' 518 | "400": 519 | $ref: '#/components/responses/ErrorResponse' 520 | 521 | /v1/air-quality: 522 | get: 523 | tags: 524 | - Specialized APIs 525 | summary: Air quality forecast 526 | description: Air quality data including PM2.5, PM10, ozone, nitrogen dioxide and other pollutants from CAMS. 527 | parameters: 528 | - $ref: '#/components/parameters/latitude' 529 | - $ref: '#/components/parameters/longitude' 530 | - name: hourly 531 | in: query 532 | explode: false 533 | schema: 534 | type: array 535 | items: 536 | type: string 537 | enum: 538 | - pm10 539 | - pm2_5 540 | - carbon_monoxide 541 | - nitrogen_dioxide 542 | - ozone 543 | - sulphur_dioxide 544 | - ammonia 545 | - dust 546 | - aerosol_optical_depth 547 | - carbon_dioxide 548 | - methane 549 | - $ref: '#/components/parameters/timezone' 550 | - $ref: '#/components/parameters/timeformat' 551 | - $ref: '#/components/parameters/past_days' 552 | - $ref: '#/components/parameters/forecast_days' 553 | responses: 554 | "200": 555 | $ref: '#/components/responses/WeatherResponse' 556 | "400": 557 | $ref: '#/components/responses/ErrorResponse' 558 | 559 | /v1/marine: 560 | get: 561 | tags: 562 | - Specialized APIs 563 | summary: Marine weather forecast 564 | description: Wave height, wave period, wave direction and sea surface temperature forecasts. 565 | parameters: 566 | - $ref: '#/components/parameters/latitude' 567 | - $ref: '#/components/parameters/longitude' 568 | - name: hourly 569 | in: query 570 | explode: false 571 | schema: 572 | type: array 573 | items: 574 | type: string 575 | enum: 576 | - wave_height 577 | - wave_direction 578 | - wave_period 579 | - wind_wave_height 580 | - wind_wave_direction 581 | - wind_wave_period 582 | - swell_wave_height 583 | - swell_wave_direction 584 | - swell_wave_period 585 | - sea_surface_temperature 586 | - name: daily 587 | in: query 588 | explode: false 589 | schema: 590 | type: array 591 | items: 592 | type: string 593 | enum: 594 | - wave_height_max 595 | - wind_wave_height_max 596 | - swell_wave_height_max 597 | - $ref: '#/components/parameters/timezone' 598 | - $ref: '#/components/parameters/timeformat' 599 | - $ref: '#/components/parameters/past_days' 600 | - $ref: '#/components/parameters/forecast_days' 601 | responses: 602 | "200": 603 | $ref: '#/components/responses/WeatherResponse' 604 | "400": 605 | $ref: '#/components/responses/ErrorResponse' 606 | 607 | /v1/ensemble: 608 | get: 609 | tags: 610 | - Specialized APIs 611 | summary: Ensemble weather forecast 612 | description: Ensemble forecasts showing forecast uncertainty with multiple model runs. 613 | parameters: 614 | - $ref: '#/components/parameters/latitude' 615 | - $ref: '#/components/parameters/longitude' 616 | - $ref: '#/components/parameters/hourly' 617 | - $ref: '#/components/parameters/daily' 618 | - $ref: '#/components/parameters/timezone' 619 | - $ref: '#/components/parameters/temperature_unit' 620 | - $ref: '#/components/parameters/wind_speed_unit' 621 | - $ref: '#/components/parameters/precipitation_unit' 622 | - $ref: '#/components/parameters/timeformat' 623 | - $ref: '#/components/parameters/forecast_days' 624 | responses: 625 | "200": 626 | $ref: '#/components/responses/WeatherResponse' 627 | "400": 628 | $ref: '#/components/responses/ErrorResponse' 629 | 630 | /v1/elevation: 631 | get: 632 | tags: 633 | - Utility APIs 634 | summary: Elevation data 635 | description: Get elevation data for given coordinates using digital elevation models. 636 | parameters: 637 | - $ref: '#/components/parameters/latitude' 638 | - $ref: '#/components/parameters/longitude' 639 | responses: 640 | "200": 641 | description: OK 642 | content: 643 | application/json: 644 | schema: 645 | type: object 646 | properties: 647 | elevation: 648 | type: array 649 | items: 650 | type: number 651 | description: Elevation in meters above sea level 652 | "400": 653 | $ref: '#/components/responses/ErrorResponse' 654 | 655 | /v1/flood: 656 | get: 657 | tags: 658 | - Specialized APIs 659 | summary: Flood forecast 660 | description: River discharge and flood forecasts from GloFAS (Global Flood Awareness System). 661 | parameters: 662 | - $ref: '#/components/parameters/latitude' 663 | - $ref: '#/components/parameters/longitude' 664 | - name: hourly 665 | in: query 666 | explode: false 667 | schema: 668 | type: array 669 | items: 670 | type: string 671 | enum: 672 | - river_discharge 673 | - river_discharge_mean 674 | - river_discharge_median 675 | - river_discharge_max 676 | - river_discharge_min 677 | - river_discharge_p25 678 | - river_discharge_p75 679 | - $ref: '#/components/parameters/timezone' 680 | - $ref: '#/components/parameters/timeformat' 681 | - $ref: '#/components/parameters/past_days' 682 | - $ref: '#/components/parameters/forecast_days' 683 | responses: 684 | "200": 685 | $ref: '#/components/responses/WeatherResponse' 686 | "400": 687 | $ref: '#/components/responses/ErrorResponse' 688 | 689 | /v1/seasonal: 690 | get: 691 | tags: 692 | - Specialized APIs 693 | summary: Seasonal weather forecast 694 | description: Long-range seasonal forecasts for temperature and precipitation up to 7 months ahead. 695 | parameters: 696 | - $ref: '#/components/parameters/latitude' 697 | - $ref: '#/components/parameters/longitude' 698 | - name: six_hourly 699 | in: query 700 | explode: false 701 | schema: 702 | type: array 703 | items: 704 | type: string 705 | enum: 706 | - temperature_2m_mean 707 | - temperature_2m_anomaly 708 | - precipitation_sum 709 | - precipitation_anomaly 710 | - $ref: '#/components/parameters/timezone' 711 | - $ref: '#/components/parameters/temperature_unit' 712 | - $ref: '#/components/parameters/precipitation_unit' 713 | - $ref: '#/components/parameters/timeformat' 714 | responses: 715 | "200": 716 | $ref: '#/components/responses/WeatherResponse' 717 | "400": 718 | $ref: '#/components/responses/ErrorResponse' 719 | 720 | /v1/climate: 721 | get: 722 | tags: 723 | - Specialized APIs 724 | summary: Climate change projections 725 | description: Climate change projections from CMIP6 models for different warming scenarios. 726 | parameters: 727 | - $ref: '#/components/parameters/latitude' 728 | - $ref: '#/components/parameters/longitude' 729 | - name: daily 730 | in: query 731 | explode: false 732 | schema: 733 | type: array 734 | items: 735 | type: string 736 | enum: 737 | - temperature_2m_mean 738 | - temperature_2m_max 739 | - temperature_2m_min 740 | - precipitation_sum 741 | - shortwave_radiation_sum 742 | - relative_humidity_2m_mean 743 | - wind_speed_10m_mean 744 | - $ref: '#/components/parameters/start_date' 745 | - $ref: '#/components/parameters/end_date' 746 | - $ref: '#/components/parameters/temperature_unit' 747 | - $ref: '#/components/parameters/precipitation_unit' 748 | - name: models 749 | in: query 750 | explode: false 751 | schema: 752 | type: array 753 | items: 754 | type: string 755 | enum: 756 | - EC_Earth3P_HR 757 | - FGOALS_f3_H 758 | - HiRAM_SIT_HR 759 | - MRI_AGCM3_2_S 760 | - EC_Earth3P 761 | - MPI_ESM1_2_XR 762 | - NICAM16_8S 763 | responses: 764 | "200": 765 | $ref: '#/components/responses/WeatherResponse' 766 | "400": 767 | $ref: '#/components/responses/ErrorResponse' 768 | components: 769 | parameters: 770 | latitude: 771 | name: latitude 772 | in: query 773 | required: true 774 | description: "WGS84 coordinate" 775 | schema: 776 | type: number 777 | format: double 778 | longitude: 779 | name: longitude 780 | in: query 781 | required: true 782 | description: "WGS84 coordinate" 783 | schema: 784 | type: number 785 | format: double 786 | hourly: 787 | name: hourly 788 | in: query 789 | explode: false 790 | schema: 791 | type: array 792 | items: 793 | type: string 794 | daily: 795 | name: daily 796 | in: query 797 | explode: false 798 | schema: 799 | type: array 800 | items: 801 | type: string 802 | minutely_15: 803 | name: minutely_15 804 | in: query 805 | explode: false 806 | schema: 807 | type: array 808 | items: 809 | type: string 810 | current_weather: 811 | name: current_weather 812 | in: query 813 | schema: 814 | type: boolean 815 | temperature_unit: 816 | name: temperature_unit 817 | in: query 818 | schema: 819 | type: string 820 | default: celsius 821 | enum: 822 | - celsius 823 | - fahrenheit 824 | wind_speed_unit: 825 | name: wind_speed_unit 826 | in: query 827 | schema: 828 | type: string 829 | default: kmh 830 | enum: 831 | - kmh 832 | - ms 833 | - mph 834 | - kn 835 | precipitation_unit: 836 | name: precipitation_unit 837 | in: query 838 | description: "Other precipitation amount units" 839 | schema: 840 | type: string 841 | default: mm 842 | enum: 843 | - mm 844 | - inch 845 | timeformat: 846 | name: timeformat 847 | in: query 848 | description: If format `unixtime` is selected, all time values are returned in UNIX epoch time in seconds. Please not that all time is then in GMT+0! For daily values with unix timestamp, please apply `utc_offset_seconds` again to get the correct date. 849 | schema: 850 | type: string 851 | default: iso8601 852 | enum: 853 | - iso8601 854 | - unixtime 855 | timezone: 856 | name: timezone 857 | in: query 858 | description: If `timezone` is set, all timestamps are returned as local-time and data is returned starting at 0:00 local-time. Any time zone name from the [time zone database](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) is supported. 859 | schema: 860 | type: string 861 | past_days: 862 | name: past_days 863 | in: query 864 | description: If `past_days` is set, yesterdays or the day before yesterdays data are also returned. 865 | schema: 866 | type: integer 867 | enum: 868 | - 1 869 | - 2 870 | - 3 871 | - 5 872 | - 7 873 | forecast_days: 874 | name: forecast_days 875 | in: query 876 | description: Number of forecast days 877 | schema: 878 | type: integer 879 | minimum: 1 880 | maximum: 16 881 | default: 7 882 | start_date: 883 | name: start_date 884 | in: query 885 | description: "The time interval to get weather data. A day must be specified as an ISO8601 date (e.g. 2022-06-30)." 886 | schema: 887 | type: string 888 | format: date 889 | pattern: '^\d{4}-\d{2}-\d{2}$' 890 | end_date: 891 | name: end_date 892 | in: query 893 | description: "The time interval to get weather data. A day must be specified as an ISO8601 date (e.g. 2022-06-30). Note: start_date is required when end_date is specified." 894 | schema: 895 | type: string 896 | format: date 897 | pattern: '^\d{4}-\d{2}-\d{2}$' 898 | 899 | responses: 900 | WeatherResponse: 901 | description: OK 902 | content: 903 | application/json: 904 | schema: 905 | type: object 906 | properties: 907 | latitude: 908 | type: number 909 | example: 52.52 910 | description: WGS84 of the center of the weather grid-cell which was used to generate this forecast. This coordinate might be up to 5 km away. 911 | longitude: 912 | type: number 913 | example: 13.41 914 | description: WGS84 of the center of the weather grid-cell which was used to generate this forecast. This coordinate might be up to 5 km away. 915 | elevation: 916 | type: number 917 | example: 44.812 918 | description: The elevation in meters of the selected weather grid-cell. In mountain terrain it might differ from the location you would expect. 919 | generationtime_ms: 920 | type: number 921 | example: 2.2119 922 | description: Generation time of the weather forecast in milli seconds. This is mainly used for performance monitoring and improvements. 923 | utc_offset_seconds: 924 | type: integer 925 | example: 3600 926 | description: Applied timezone offset from the &timezone= parameter. 927 | hourly: 928 | $ref: "#/components/schemas/HourlyResponse" 929 | hourly_units: 930 | type: object 931 | additionalProperties: 932 | type: string 933 | description: For each selected weather variable, the unit will be listed here. 934 | daily: 935 | $ref: "#/components/schemas/DailyResponse" 936 | daily_units: 937 | type: object 938 | additionalProperties: 939 | type: string 940 | description: For each selected daily weather variable, the unit will be listed here. 941 | current_weather: 942 | $ref: "#/components/schemas/CurrentWeather" 943 | ErrorResponse: 944 | description: Bad Request 945 | content: 946 | application/json: 947 | schema: 948 | type: object 949 | properties: 950 | error: 951 | type: boolean 952 | description: Always set true for errors 953 | reason: 954 | type: string 955 | description: Description of the error 956 | example: "Latitude must be in range of -90 to 90°. Given: 300" 957 | 958 | schemas: 959 | HourlyResponse: 960 | type: object 961 | description: For each selected weather variable, data will be returned as a floating point array. Additionally a `time` array will be returned with ISO8601 timestamps. 962 | required: 963 | - time 964 | properties: 965 | time: 966 | type: array 967 | items: 968 | type: string 969 | temperature_2m: 970 | type: array 971 | items: 972 | type: number 973 | # Temperature variables 974 | relative_humidity_2m: 975 | type: array 976 | items: 977 | type: number 978 | dewpoint_2m: 979 | type: array 980 | items: 981 | type: number 982 | apparent_temperature: 983 | type: array 984 | items: 985 | type: number 986 | surface_temperature: 987 | type: array 988 | items: 989 | type: number 990 | # Pressure variables 991 | pressure_msl: 992 | type: array 993 | items: 994 | type: number 995 | surface_pressure: 996 | type: array 997 | items: 998 | type: number 999 | # Cloud variables 1000 | cloud_cover: 1001 | type: array 1002 | items: 1003 | type: number 1004 | cloud_cover_low: 1005 | type: array 1006 | items: 1007 | type: number 1008 | cloud_cover_mid: 1009 | type: array 1010 | items: 1011 | type: number 1012 | cloud_cover_high: 1013 | type: array 1014 | items: 1015 | type: number 1016 | wind_speed_10m: 1017 | type: array 1018 | items: 1019 | type: number 1020 | wind_speed_80m: 1021 | type: array 1022 | items: 1023 | type: number 1024 | wind_speed_120m: 1025 | type: array 1026 | items: 1027 | type: number 1028 | wind_speed_180m: 1029 | type: array 1030 | items: 1031 | type: number 1032 | wind_direction_10m: 1033 | type: array 1034 | items: 1035 | type: number 1036 | wind_direction_80m: 1037 | type: array 1038 | items: 1039 | type: number 1040 | wind_direction_120m: 1041 | type: array 1042 | items: 1043 | type: number 1044 | wind_direction_180m: 1045 | type: array 1046 | items: 1047 | type: number 1048 | wind_gusts_10m: 1049 | type: array 1050 | items: 1051 | type: number 1052 | # Wind component variables 1053 | wind_u_component_10m: 1054 | type: array 1055 | items: 1056 | type: number 1057 | wind_v_component_10m: 1058 | type: array 1059 | items: 1060 | type: number 1061 | wind_u_component_80m: 1062 | type: array 1063 | items: 1064 | type: number 1065 | wind_v_component_80m: 1066 | type: array 1067 | items: 1068 | type: number 1069 | wind_u_component_120m: 1070 | type: array 1071 | items: 1072 | type: number 1073 | wind_v_component_120m: 1074 | type: array 1075 | items: 1076 | type: number 1077 | wind_u_component_180m: 1078 | type: array 1079 | items: 1080 | type: number 1081 | wind_v_component_180m: 1082 | type: array 1083 | items: 1084 | type: number 1085 | # Radiation variables 1086 | shortwave_radiation: 1087 | type: array 1088 | items: 1089 | type: number 1090 | direct_radiation: 1091 | type: array 1092 | items: 1093 | type: number 1094 | direct_normal_irradiance: 1095 | type: array 1096 | items: 1097 | type: number 1098 | diffuse_radiation: 1099 | type: array 1100 | items: 1101 | type: number 1102 | terrestrial_radiation: 1103 | type: array 1104 | items: 1105 | type: number 1106 | sunshine_duration: 1107 | type: array 1108 | items: 1109 | type: number 1110 | uv_index: 1111 | type: array 1112 | items: 1113 | type: number 1114 | uv_index_clear_sky: 1115 | type: array 1116 | items: 1117 | type: number 1118 | # Precipitation variables 1119 | precipitation: 1120 | type: array 1121 | items: 1122 | type: number 1123 | rain: 1124 | type: array 1125 | items: 1126 | type: number 1127 | showers: 1128 | type: array 1129 | items: 1130 | type: number 1131 | snowfall: 1132 | type: array 1133 | items: 1134 | type: number 1135 | precipitation_probability: 1136 | type: array 1137 | items: 1138 | type: number 1139 | snow_depth: 1140 | type: array 1141 | items: 1142 | type: number 1143 | snow_height: 1144 | type: array 1145 | items: 1146 | type: number 1147 | # Atmospheric variables 1148 | vapour_pressure_deficit: 1149 | type: array 1150 | items: 1151 | type: number 1152 | et0_fao_evapotranspiration: 1153 | type: array 1154 | items: 1155 | type: number 1156 | weather_code: 1157 | type: array 1158 | items: 1159 | type: number 1160 | visibility: 1161 | type: array 1162 | items: 1163 | type: number 1164 | is_day: 1165 | type: array 1166 | items: 1167 | type: number 1168 | cape: 1169 | type: array 1170 | items: 1171 | type: number 1172 | lifted_index: 1173 | type: array 1174 | items: 1175 | type: number 1176 | convective_inhibition: 1177 | type: array 1178 | items: 1179 | type: number 1180 | freezing_level_height: 1181 | type: array 1182 | items: 1183 | type: number 1184 | boundary_layer_height: 1185 | type: array 1186 | items: 1187 | type: number 1188 | updraft_velocity: 1189 | type: array 1190 | items: 1191 | type: number 1192 | downdraft_velocity: 1193 | type: array 1194 | items: 1195 | type: number 1196 | soil_temperature_0cm: 1197 | type: array 1198 | items: 1199 | type: number 1200 | soil_temperature_6cm: 1201 | type: array 1202 | items: 1203 | type: number 1204 | soil_temperature_18cm: 1205 | type: array 1206 | items: 1207 | type: number 1208 | soil_temperature_54cm: 1209 | type: array 1210 | items: 1211 | type: number 1212 | soil_moisture_0_1cm: 1213 | type: array 1214 | items: 1215 | type: number 1216 | soil_moisture_1_3cm: 1217 | type: array 1218 | items: 1219 | type: number 1220 | soil_moisture_3_9cm: 1221 | type: array 1222 | items: 1223 | type: number 1224 | soil_moisture_9_27cm: 1225 | type: array 1226 | items: 1227 | type: number 1228 | soil_moisture_27_81cm: 1229 | type: array 1230 | items: 1231 | type: number 1232 | # Energy flux variables 1233 | sensible_heat_flux: 1234 | type: array 1235 | items: 1236 | type: number 1237 | latent_heat_flux: 1238 | type: array 1239 | items: 1240 | type: number 1241 | # Agricultural variables 1242 | growing_degree_days_base_0_limit_30: 1243 | type: array 1244 | items: 1245 | type: number 1246 | leaf_wetness_probability: 1247 | type: array 1248 | items: 1249 | type: number 1250 | skin_temperature: 1251 | type: array 1252 | items: 1253 | type: number 1254 | DailyResponse: 1255 | type: object 1256 | description: For each selected daily weather variable, data will be returned as a floating point array. Additionally a `time` array will be returned with ISO8601 timestamps. 1257 | properties: 1258 | time: 1259 | type: array 1260 | items: 1261 | type: string 1262 | temperature_2m_max: 1263 | type: array 1264 | items: 1265 | type: number 1266 | temperature_2m_min: 1267 | type: array 1268 | items: 1269 | type: number 1270 | apparent_temperature_max: 1271 | type: array 1272 | items: 1273 | type: number 1274 | apparent_temperature_min: 1275 | type: array 1276 | items: 1277 | type: number 1278 | precipitation_sum: 1279 | type: array 1280 | items: 1281 | type: number 1282 | precipitation_hours: 1283 | type: array 1284 | items: 1285 | type: number 1286 | weather_code: 1287 | type: array 1288 | items: 1289 | type: number 1290 | sunrise: 1291 | type: array 1292 | items: 1293 | type: number 1294 | sunset: 1295 | type: array 1296 | items: 1297 | type: number 1298 | wind_speed_10m_max: 1299 | type: array 1300 | items: 1301 | type: number 1302 | wind_gusts_10m_max: 1303 | type: array 1304 | items: 1305 | type: number 1306 | wind_direction_10m_dominant: 1307 | type: array 1308 | items: 1309 | type: number 1310 | shortwave_radiation_sum: 1311 | type: array 1312 | items: 1313 | type: number 1314 | uv_index_max: 1315 | type: array 1316 | items: 1317 | type: number 1318 | uv_index_clear_sky_max: 1319 | type: array 1320 | items: 1321 | type: number 1322 | et0_fao_evapotranspiration: 1323 | type: array 1324 | items: 1325 | type: number 1326 | # Additional daily variables 1327 | precipitation_probability_max: 1328 | type: array 1329 | items: 1330 | type: number 1331 | precipitation_probability_min: 1332 | type: array 1333 | items: 1334 | type: number 1335 | precipitation_probability_mean: 1336 | type: array 1337 | items: 1338 | type: number 1339 | rain_sum: 1340 | type: array 1341 | items: 1342 | type: number 1343 | showers_sum: 1344 | type: array 1345 | items: 1346 | type: number 1347 | snowfall_sum: 1348 | type: array 1349 | items: 1350 | type: number 1351 | snow_depth_max: 1352 | type: array 1353 | items: 1354 | type: number 1355 | snow_depth_mean: 1356 | type: array 1357 | items: 1358 | type: number 1359 | windspeed_10m_max: 1360 | type: array 1361 | items: 1362 | type: number 1363 | windgusts_10m_max: 1364 | type: array 1365 | items: 1366 | type: number 1367 | winddirection_10m_dominant: 1368 | type: array 1369 | items: 1370 | type: number 1371 | # Soil daily variables 1372 | soil_temperature_0cm_mean: 1373 | type: array 1374 | items: 1375 | type: number 1376 | soil_temperature_6cm_mean: 1377 | type: array 1378 | items: 1379 | type: number 1380 | soil_temperature_18cm_mean: 1381 | type: array 1382 | items: 1383 | type: number 1384 | soil_temperature_54cm_mean: 1385 | type: array 1386 | items: 1387 | type: number 1388 | soil_moisture_0_1cm_mean: 1389 | type: array 1390 | items: 1391 | type: number 1392 | soil_moisture_1_3cm_mean: 1393 | type: array 1394 | items: 1395 | type: number 1396 | soil_moisture_3_9cm_mean: 1397 | type: array 1398 | items: 1399 | type: number 1400 | soil_moisture_9_27cm_mean: 1401 | type: array 1402 | items: 1403 | type: number 1404 | soil_moisture_27_81cm_mean: 1405 | type: array 1406 | items: 1407 | type: number 1408 | required: 1409 | - time 1410 | CurrentWeather: 1411 | type: object 1412 | description: "Current weather conditions with the attributes: time, temperature, wind_speed, wind_direction and weather_code" 1413 | properties: 1414 | time: 1415 | type: string 1416 | temperature: 1417 | type: number 1418 | wind_speed: 1419 | type: number 1420 | wind_direction: 1421 | type: number 1422 | weather_code: 1423 | type: integer 1424 | required: 1425 | - time 1426 | - temperature 1427 | - wind_speed 1428 | - wind_direction 1429 | - weather_code 1430 | --------------------------------------------------------------------------------