UNPKG

open-meteo-mcp-server

Version:

Model Context Protocol server for Open-Meteo weather APIs

644 lines (489 loc) 22.6 kB
# Open-Meteo MCP Server [![npm version](https://badge.fury.io/js/open-meteo-mcp-server.svg)](https://badge.fury.io/js/open-meteo-mcp-server) [![GitHub release](https://img.shields.io/github/release/cmer81/open-meteo-mcp.svg)](https://github.com/cmer81/open-meteo-mcp/releases) [![Docker Image](https://img.shields.io/badge/docker-ghcr.io-blue.svg)](https://github.com/cmer81/open-meteo-mcp/pkgs/container/open-meteo-mcp) A comprehensive [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server that provides access to Open-Meteo weather APIs for use with Large Language Models. ## Features This MCP server provides complete access to Open-Meteo APIs, including: ### Core Weather APIs - **Weather Forecast** (`weather_forecast`) - Forecasts up to 16 days (7 by default) with hourly and daily resolution - **Weather Archive** (`weather_archive`) - Historical ERA5 data from 1940 to present - **Air Quality** (`air_quality`) - PM2.5, PM10, ozone, nitrogen dioxide, pollen, European/US AQI indices, UV index and other pollutants - **Marine Weather** (`marine_weather`) - Wave height, wave period, wave direction and sea surface temperature - **Elevation** (`elevation`) - Digital elevation model data for given coordinates - **Geocoding** (`geocoding`) - Search locations worldwide by name or postal code, get coordinates and detailed location information ### Specialized Weather Models - **DWD ICON** (`dwd_icon_forecast`) - German weather service high-resolution model for Europe - **NOAA GFS** (`gfs_forecast`) - US weather service global model with high-resolution North America data - **Météo-France** (`meteofrance_forecast`) - French weather service AROME and ARPEGE models - **ECMWF** (`ecmwf_forecast`) - European Centre for Medium-Range Weather Forecasts - **JMA** (`jma_forecast`) - Japan Meteorological Agency high-resolution model for Asia - **MET Norway** (`metno_forecast`) - Norwegian weather service for Nordic countries - **Environment Canada GEM** (`gem_forecast`) - Canadian weather service model ### Advanced Forecasting Tools - **Flood Forecast** (`flood_forecast`) - River discharge and flood forecasts from GloFAS (Global Flood Awareness System) - **Seasonal Forecast** (`seasonal_forecast`) - Long-range forecasts up to ~7 months ahead - **Climate Projections** (`climate_projection`) - CMIP6 climate change projections for different warming scenarios - **Ensemble Forecast** (`ensemble_forecast`) - Multiple model runs showing forecast uncertainty ## Installation ### Requirements - Node.js >= 22.0.0 ### Method 1: Using npx (Recommended) No installation required! The server will run directly via npx. ### Method 2: Global Installation via npm ```bash npm install -g open-meteo-mcp-server ``` ### Method 3: From Source (Development) ```bash # Clone the repository git clone https://github.com/cmer81/open-meteo-mcp.git cd open-meteo-mcp # Install dependencies npm install # Build the project npm run build ``` ## Configuration ### Claude Desktop Configuration #### Simple Configuration (Recommended) Add the following configuration to your Claude Desktop config file: ```json { "mcpServers": { "open-meteo": { "command": "npx", "args": ["-y", "-p", "open-meteo-mcp-server", "open-meteo-mcp-server"] } } } ``` #### Full Configuration (with environment variables) ```json { "mcpServers": { "open-meteo": { "command": "npx", "args": ["-y", "-p", "open-meteo-mcp-server", "open-meteo-mcp-server"], "env": { "OPEN_METEO_API_URL": "https://api.open-meteo.com", "OPEN_METEO_AIR_QUALITY_API_URL": "https://air-quality-api.open-meteo.com", "OPEN_METEO_MARINE_API_URL": "https://marine-api.open-meteo.com", "OPEN_METEO_ARCHIVE_API_URL": "https://archive-api.open-meteo.com", "OPEN_METEO_SEASONAL_API_URL": "https://seasonal-api.open-meteo.com", "OPEN_METEO_ENSEMBLE_API_URL": "https://ensemble-api.open-meteo.com", "OPEN_METEO_GEOCODING_API_URL": "https://geocoding-api.open-meteo.com", "OPEN_METEO_FLOOD_API_URL": "https://flood-api.open-meteo.com", "OPEN_METEO_CLIMATE_API_URL": "https://climate-api.open-meteo.com" } } } } ``` #### Local Development Configuration If you're developing locally or installed from source: ```json { "mcpServers": { "open-meteo": { "command": "node", "args": ["/path/to/open-meteo-mcp/dist/index.js"], "env": { "OPEN_METEO_API_URL": "https://api.open-meteo.com", "OPEN_METEO_AIR_QUALITY_API_URL": "https://air-quality-api.open-meteo.com", "OPEN_METEO_MARINE_API_URL": "https://marine-api.open-meteo.com", "OPEN_METEO_ARCHIVE_API_URL": "https://archive-api.open-meteo.com", "OPEN_METEO_SEASONAL_API_URL": "https://seasonal-api.open-meteo.com", "OPEN_METEO_ENSEMBLE_API_URL": "https://ensemble-api.open-meteo.com", "OPEN_METEO_GEOCODING_API_URL": "https://geocoding-api.open-meteo.com", "OPEN_METEO_FLOOD_API_URL": "https://flood-api.open-meteo.com", "OPEN_METEO_CLIMATE_API_URL": "https://climate-api.open-meteo.com" } } } } ``` ### Custom Instance Configuration If you're using your own Open-Meteo instance: ```json { "mcpServers": { "open-meteo": { "command": "npx", "args": ["-y", "-p", "open-meteo-mcp-server", "open-meteo-mcp-server"], "env": { "OPEN_METEO_API_URL": "https://your-meteo-api.example.com", "OPEN_METEO_AIR_QUALITY_API_URL": "https://air-quality-api.example.com", "OPEN_METEO_MARINE_API_URL": "https://marine-api.example.com", "OPEN_METEO_ARCHIVE_API_URL": "https://archive-api.example.com", "OPEN_METEO_SEASONAL_API_URL": "https://seasonal-api.example.com", "OPEN_METEO_ENSEMBLE_API_URL": "https://ensemble-api.example.com", "OPEN_METEO_GEOCODING_API_URL": "https://geocoding-api.example.com", "OPEN_METEO_FLOOD_API_URL": "https://flood-api.example.com", "OPEN_METEO_CLIMATE_API_URL": "https://climate-api.example.com" } } } } ``` ### Streamable HTTP Transport The server also supports Streamable HTTP transport for remote deployments. Set the `TRANSPORT` environment variable to `http`: ```bash TRANSPORT=http PORT=3000 npx open-meteo-mcp-server ``` This starts an Express server on the specified port (default: 3000) with the MCP endpoint at `/mcp`. The HTTP transport supports session management with unique session IDs per client. > **The server binds to `127.0.0.1` by default**, so it is reachable only from the local machine. To accept connections from other hosts, set `HOST=0.0.0.0` explicitly. The Docker image already does this, so published ports work without extra configuration. For production deployments, bind to a reachable interface and enable authentication and rate limiting: ```bash HOST=0.0.0.0 API_KEY=your-secret-key RATE_LIMIT_RPM=60 TRANSPORT=http PORT=3000 npx open-meteo-mcp-server ``` If a browser-based client connects to the server, list its origin in `ALLOWED_ORIGINS` — requests carrying an unlisted `Origin` header are rejected with `403` as DNS rebinding protection. Clients must then include the key in every request: ``` Authorization: Bearer your-secret-key # or X-API-Key: your-secret-key ``` #### Using npm scripts ```bash # Start in HTTP mode (production) npm run start:http # Development with auto-reload in HTTP mode npm run dev:http ``` ### Docker Deployment The server can be easily deployed using Docker. #### Using Pre-built Image from GitHub Container Registry (Recommended) Pull and run the official image: ```bash # Pull the latest image docker pull ghcr.io/cmer81/open-meteo-mcp:latest # Run the container docker run -d \ --name open-meteo-mcp \ -p 3000:3000 \ ghcr.io/cmer81/open-meteo-mcp:latest # Check health curl http://localhost:3000/health ``` Available tags (no `v` prefix — the git tag `v2.0.0` publishes the image as `2.0.0`): - `latest` - Latest stable release - `2.0.0` - Specific version - `2.0` - Latest 2.0.x release - `2` - Latest 2.x.x release #### Using Docker Compose The repository includes two Docker Compose configurations: **Production (uses pre-built image):** ```bash # Start with pre-built image from GitHub Container Registry docker compose up -d # View logs docker compose logs -f # Stop the server docker compose down ``` **Development (builds from source):** ```bash # Build and start from local source docker compose -f docker-compose.dev.yml up -d # Rebuild after code changes docker compose -f docker-compose.dev.yml up -d --build ``` #### Building from Source If you prefer to build the image yourself: ```bash # Build the image npm run docker:build # or docker build -t open-meteo-mcp-server . # Run the container npm run docker:run # or docker run -p 3000:3000 open-meteo-mcp-server ``` #### Environment Configuration Copy `.env.example` to `.env` and customize as needed: ```bash cp .env.example .env # Edit .env with your configuration ``` Then update `docker-compose.yml` to use the `.env` file or pass environment variables directly. #### Health Check The HTTP server includes a health check endpoint: ```bash curl http://localhost:3000/health # Response: {"status":"ok"} ``` This endpoint is used by Docker's `HEALTHCHECK` and can be integrated with container orchestration platforms (Kubernetes, Docker Swarm, etc.). ### Environment Variables All environment variables are optional and have sensible defaults: - `OPEN_METEO_API_URL` - Base URL for Open-Meteo forecast API (default: https://api.open-meteo.com) - `OPEN_METEO_AIR_QUALITY_API_URL` - Air quality API URL (default: https://air-quality-api.open-meteo.com) - `OPEN_METEO_MARINE_API_URL` - Marine weather API URL (default: https://marine-api.open-meteo.com) - `OPEN_METEO_ARCHIVE_API_URL` - Historical data API URL (default: https://archive-api.open-meteo.com) - `OPEN_METEO_SEASONAL_API_URL` - Seasonal forecast API URL (default: https://seasonal-api.open-meteo.com) - `OPEN_METEO_ENSEMBLE_API_URL` - Ensemble forecast API URL (default: https://ensemble-api.open-meteo.com) - `OPEN_METEO_GEOCODING_API_URL` - Geocoding API URL (default: https://geocoding-api.open-meteo.com) - `OPEN_METEO_FLOOD_API_URL` - Flood forecast API URL (default: https://flood-api.open-meteo.com) - `OPEN_METEO_CLIMATE_API_URL` - Climate projection API URL (default: https://climate-api.open-meteo.com) - `TRANSPORT` - Transport mode: `http` for Streamable HTTP, omit for stdio (default: stdio) - `PORT` - HTTP server port when using HTTP transport (default: 3000) - `HOST` - Interface the HTTP transport binds to (default: `127.0.0.1`, loopback only). Set to `0.0.0.0` to accept connections from other machines. The Docker image sets this to `0.0.0.0` already, so published ports work out of the box. #### HTTP Transport Security (optional) - `API_KEY` - When set, all requests to `/mcp` must include this key via `Authorization: Bearer <key>` or `X-API-Key: <key>`. Leave unset for open access (local/dev mode). Enforced on `GET`, `POST` and `DELETE` alike. - `RATE_LIMIT_RPM` - Maximum requests per minute per IP (default: `60`). HTTP transport only. - `TRUSTED_PROXIES` - Comma-separated list of trusted proxy IPs or CIDR ranges (e.g. `10.0.0.0/8,172.16.0.0/12`). When set, `X-Forwarded-For` is honoured only for requests originating from these addresses. Leave unset to always use the direct connection IP. - `ALLOWED_ORIGINS` - Comma-separated list of browser origins permitted to reach the server (e.g. `http://localhost:5173,https://app.example`). Protects against DNS rebinding: any request carrying an `Origin` header that is not listed is rejected with `403`. Requests without an `Origin` header — CLI clients and SDK transports — are unaffected. Empty by default. `/health` stays reachable without a key and without rate limiting, so container probes keep working. ## Skills The `skills/` directory contains SKILL.md files that help AI assistants use this MCP server effectively. They act as contextual guides — the AI reads the relevant skill to know which tool to call and how to use its parameters. ### Available skills | Skill | File | Best for | |-------|------|----------| | `open-meteo` | `skills/open-meteo/SKILL.md` | Everyday weather: forecasts, historical data, air quality, marine conditions, elevation | | `open-meteo-advanced` | `skills/open-meteo-advanced/SKILL.md` | Specific models (ECMWF, GFS, DWD ICON…), ensemble uncertainty, seasonal outlooks, climate projections | ### Using with Claude Code (CLI) Copy the skill(s) to your Claude skills directory: ```bash cp -r skills/open-meteo ~/.claude/skills/ cp -r skills/open-meteo-advanced ~/.claude/skills/ ``` This installs them at `~/.claude/skills/open-meteo/SKILL.md` and `~/.claude/skills/open-meteo-advanced/SKILL.md`. Claude Code will load the relevant skill automatically when you ask weather-related questions. ### Using with Claude Desktop Upload the SKILL.md file directly as a document in your Claude Desktop conversation: - For everyday weather questions: upload `skills/open-meteo/SKILL.md` - For model selection, ensemble, or climate projections: upload `skills/open-meteo-advanced/SKILL.md` Upload one skill per conversation. The AI will use it as a reference guide throughout the session. ## Usage Examples ### Geocoding and Location Search ``` Find the coordinates for Paris, France ``` ``` Search for locations named "Berlin" and return the top 5 results ``` ``` What are the coordinates for postal code 75001? ``` ``` Search for "Lyon" in France only (countryCode: FR) with results in French (language: fr) ``` ``` Find all cities named "London" in the United Kingdom with English descriptions ``` ### Basic Weather Forecast ``` Can you get me the weather forecast for Paris (48.8566, 2.3522) with temperature, humidity, and precipitation for the next 3 days? ``` ### Historical Weather Data ``` What were the temperatures in London during January 2023? ``` ### Air Quality Monitoring ``` What's the current air quality in Beijing with PM2.5 and ozone levels? ``` ``` Give me the current European AQI, UV index, and pollen levels (birch, grass, ragweed) in Paris. ``` ### Marine Weather ``` Get me the wave height and sea surface temperature for coordinates 45.0, -125.0 for the next 5 days. ``` ### Flood Monitoring ``` Check the river discharge forecast for coordinates 52.5, 13.4 for the next 30 days. ``` ### Seasonal Forecast ``` Give me the weekly and monthly temperature outlook for Madrid over the next 4 months. ``` ### Ensemble Forecast ``` Compare the ICON and GFS ensemble forecasts for Berlin over the next 5 days and show the spread across members. ``` ### Climate Projections ``` Show me temperature projections for New York from 2050 to 2070 using CMIP6 models. ``` ## API Parameters ### Required Parameters - `latitude` : Latitude in WGS84 coordinate system (-90 to 90) - `longitude` : Longitude in WGS84 coordinate system (-180 to 180) ### Hourly Weather Variables - `temperature_2m` : Temperature at 2 meters - `relative_humidity_2m` : Relative humidity - `precipitation` : Precipitation - `wind_speed_10m` : Wind speed at 10 meters - `wind_direction_10m` : Wind direction - `pressure_msl` : Mean sea level pressure - `cloud_cover` : Cloud cover percentage - `weather_code` : Weather condition code - `visibility` : Visibility - `uv_index` : UV index - And many more... ### Daily Weather Variables - `temperature_2m_max/min` : Maximum/minimum temperatures - `precipitation_sum` : Total precipitation - `wind_speed_10m_max` : Maximum wind speed - `sunrise/sunset` : Sunrise and sunset times - `weather_code` : Weather condition code - `uv_index_max` : Maximum UV index ### Air Quality Variables - `pm10` : PM10 particles - `pm2_5` : PM2.5 particles - `carbon_monoxide` : Carbon monoxide - `nitrogen_dioxide` : Nitrogen dioxide - `ozone` : Ozone - `sulphur_dioxide` : Sulfur dioxide - `ammonia` : Ammonia - `dust` : Dust particles - `alder_pollen` : Alder pollen (Europe only) - `birch_pollen` : Birch pollen (Europe only) - `grass_pollen` : Grass pollen (Europe only) - `mugwort_pollen` : Mugwort pollen (Europe only) - `olive_pollen` : Olive pollen (Europe only) - `ragweed_pollen` : Ragweed pollen (Europe only) - `european_aqi` : European Air Quality Index - `european_aqi_pm2_5` : European AQI for PM2.5 - `european_aqi_pm10` : European AQI for PM10 - `european_aqi_nitrogen_dioxide` : European AQI for NO₂ - `european_aqi_ozone` : European AQI for ozone - `european_aqi_sulphur_dioxide` : European AQI for SO₂ - `us_aqi` : US Air Quality Index - `us_aqi_pm2_5` : US AQI for PM2.5 - `us_aqi_pm10` : US AQI for PM10 - `us_aqi_nitrogen_dioxide` : US AQI for NO₂ - `us_aqi_ozone` : US AQI for ozone - `us_aqi_sulphur_dioxide` : US AQI for SO₂ - `us_aqi_carbon_monoxide` : US AQI for CO - `uv_index` : UV index - `uv_index_clear_sky` : UV index under clear sky conditions ### Marine Weather Variables - `wave_height` : Wave height - `wave_direction` : Wave direction - `wave_period` : Wave period - `wind_wave_height` : Wind wave height - `swell_wave_height` : Swell wave height - `sea_surface_temperature` : Sea surface temperature ### Formatting Options - `temperature_unit` : `celsius`, `fahrenheit` - `wind_speed_unit` : `kmh`, `ms`, `mph`, `kn` - `precipitation_unit` : `mm`, `inch` - `timezone` : `Europe/Paris`, `America/New_York`, etc. ### Time Range Options - `forecast_days` : Number of forecast days (varies by API) - `past_days` : Include past days data - `start_date` / `end_date` : Date range for historical data (YYYY-MM-DD format) ## Development Scripts ```bash # Development with auto-reload npm run dev # Build TypeScript npm run build # Start production server npm start # Run tests npm test # Type checking npm run typecheck # Linting npm run lint ``` ## Evaluations The `evals/` directory holds an LLM-usability benchmark for this server's tools — a different check than `npm test`. Unit tests verify the code is correct; this verifies that an LLM given *only* this server's tools (no other context) can actually complete realistic tasks with them. - `evals/evaluation.xml` — 10 independent, read-only question/answer pairs built on stable historical data (ERA5 archive, CMIP6 projections, geocoding, elevation), so the expected answers never change over time. - `evals/scripts/evaluation.py` — harness that launches the server, lets an agent answer each question using only its tools, and compares the answer against the expected one. ### Running the evaluation ```bash npm run build pip install -r evals/scripts/requirements.txt export ANTHROPIC_API_KEY=your_api_key_here npm run eval # or directly: python3 evals/scripts/evaluation.py -t stdio -c node -a dist/index.js evals/evaluation.xml ``` This calls the real Anthropic API for every question, so it consumes tokens/credits — it's a manual quality check for tool design, not part of CI. When adding, removing, or renaming a tool, or materially changing a tool's description or schema, consider adding or updating a `qa_pair` in `evals/evaluation.xml` that exercises it. ## Project Structure ``` src/ ├── index.ts # MCP server entry point ├── client.ts # HTTP client for Open-Meteo API ├── tools.ts # MCP tool definitions ├── types.ts # Zod validation schemas ├── truncation.ts # Response size capping and serialization └── security.ts # Auth, origin validation, rate limiter, IP extraction ``` ## API Coverage This server provides access to all major Open-Meteo endpoints: ### Weather Data - Current weather conditions - Hourly forecasts (up to 16 days) - Daily forecasts (up to 16 days) - Historical weather data (1940-present) ### Specialized Models - High-resolution regional models (DWD ICON, Météo-France AROME) - Global models (NOAA GFS, ECMWF) - Regional specialists (JMA for Asia, MET Norway for Nordics) ### Environmental Data - Air quality forecasts - Marine and ocean conditions - River discharge and flood warnings - Climate change projections ### Advanced Features - Ensemble forecasts for uncertainty quantification - Seasonal forecasts for long-term planning - Multiple model comparison - Customizable units and timezones ## Error Handling The server provides comprehensive error handling with detailed error messages for: - Invalid coordinates - Missing required parameters - API rate limits - Network connectivity issues - Invalid date ranges ### Response Size Limits Tool responses are capped at 25,000 characters so a single wide query cannot overflow an LLM's context. When a response exceeds the limit, the time-series arrays (`hourly`, `daily`, `minutely_15`) are shortened by an equal ratio — keeping every parallel series aligned on the same timestamps — and two fields are added: ```json { "truncated": true, "truncation_message": "Response truncated from 95538 characters to stay within the 25000-character limit. Narrow the request (start_date/end_date, forecast_days, past_days, or fewer variables) to retrieve the full data." } ``` To get complete data, narrow the request: shorter date range, fewer `forecast_days`/`past_days`, or fewer variables. ## Performance - Efficient HTTP client with connection pooling - Optimized data serialization - Minimal memory footprint ## API Documentation For detailed API documentation, refer to the `openapi.yml` file and the [Open-Meteo API documentation](https://open-meteo.com/en/docs). ## Contributing Contributions are welcome! Please feel free to submit a Pull Request. ### Development Setup 1. Fork the repository 2. Clone your fork: `git clone https://github.com/your-username/open-meteo-mcp.git` 3. Install dependencies: `npm install` 4. Create a feature branch: `git checkout -b feature/amazing-feature` 5. Make your changes and add tests 6. Run tests: `npm test` 7. Commit your changes: `git commit -m 'Add amazing feature'` 8. Push to the branch: `git push origin feature/amazing-feature` 9. Open a Pull Request ### Releasing This project uses automated releases via GitHub Actions. To create a new release: ```bash # For a patch release (1.0.0 -> 1.0.1) npm run release:patch # For a minor release (1.0.0 -> 1.1.0) npm run release:minor # For a major release (1.0.0 -> 2.0.0) npm run release:major ``` The GitHub Action will automatically: - Run tests and build the project - Publish to npm with provenance - Create a GitHub release - Update version badges ## License MIT