# io.github.cyanheads/open-meteo-mcp-server (remote · open-meteo.caseyjhand.com)

Global weather via Open-Meteo: forecast, ERA5 archive, marine, air quality, geocoding, elevation.

- Trust score: 66/100 (medium)
- Change this week: +4
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-08-03

## Components

- remote · `open-meteo.caseyjhand.com`: 66/100 (this document), [markdown](https://verifymcp.io/servers/cyanheads-open-meteo-mcp-server/open-meteo.md), [page](https://verifymcp.io/servers/cyanheads-open-meteo-mcp-server/open-meteo)
- npm · `@cyanheads/open-meteo-mcp-server`: 35/100, [markdown](https://verifymcp.io/servers/cyanheads-open-meteo-mcp-server/cyanheads-open-meteo-mcp-server.md), [page](https://verifymcp.io/servers/cyanheads-open-meteo-mcp-server/cyanheads-open-meteo-mcp-server)

## Channel facts

- Endpoint: `https://open-meteo.caseyjhand.com/mcp`
- Transports: `streamable-http`
- Auth: `none`
- Version: `0.3.4`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-08-03.

- **Endpoint Security**: 66/100
  - The endpoint's TLS certificate is valid, in date, and uses a strong key.
  - Authorisation not fully verified: no authorisation is required to call this server, and 11 tool(s) never declared a destructiveHint. The MCP spec treats an absent hint as destructive by default, so we cannot call this surface safe.
  - HTTPS is enforced; there's no plaintext access path.
  - The HSTS (Strict-Transport-Security) header is present.
  - DNSSEC is configured correctly; the domain's records validate against the full chain to the root.
- **Transport & Reachability**: 100/100
  - Verified streamable-http transport via a live MCP handshake.
- **Schema Quality & AI Usability**: 57/100
  - AI-judged instruction clarity (excellent).
  - Context-footprint check failed: tool/resource definitions use about 7233 tokens (~657/item across 11 items; 11 tools + 0 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 18/100
  - Stability check failed: schema churn in the 8 days we've observed: 1 tool removals, 0 breaking changes, 0 auth/transport breaks, 1 additions.
- **Tool Coverage**: 100/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 100% of tool parameters carry a description.
  - Structured output schemas are declared (100% of tools); any adoption earns full credit.
- **Capabilities**: 100/100
  - Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.

## Install

### Claude

```bash
claude mcp add --transport http cyanheads-open-meteo-mcp-server https://open-meteo.caseyjhand.com/mcp
```

### Codex

```toml
[mcp_servers.cyanheads-open-meteo-mcp-server]
url = "https://open-meteo.caseyjhand.com/mcp"
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "cyanheads-open-meteo-mcp-server": {
      "type": "remote",
      "url": "https://open-meteo.caseyjhand.com/mcp",
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add cyanheads-open-meteo-mcp-server --url https://open-meteo.caseyjhand.com/mcp --transport streamable-http
```

### Hermes

```yaml
mcp_servers:
  cyanheads-open-meteo-mcp-server:
    url: "https://open-meteo.caseyjhand.com/mcp"
```

### Other

```json
{
  "mcpServers": {
    "cyanheads-open-meteo-mcp-server": {
      "type": "http",
      "url": "https://open-meteo.caseyjhand.com/mcp"
    }
  }
}
```

The mcpServers block is a cross-client convention. Remote transports vary, so check your client's docs.

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-08-03 (score 66, +1)

No change was recorded against any check on this day. Stability & Change Management went from 14 to 18.

### 2026-08-02 (score 65, +1)

No change was recorded against any check on this day. Stability & Change Management went from 11 to 14.

### 2026-08-01 (score 64, +2)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-07-31 (score 62, +47)

- [security regression] Stability: unverified → fail
- [security regression] Tool “openmeteo_geocode” was removed
- [security improvement] HSTS header: fail → pass
- [security improvement] Transport: fail → pass
- [security] Authorization: Authorisation not fully verified: no authorisation is required to call this server, and 11 tool(s) never declared a destructiveHint. The MCP spec treats an absent hint as destructive by default, so we cannot call this surface safe.
- [security] The server rewrote its instructions, which are the text every model session reads
- [security] Tool “openmeteo_get_air_quality” rewrote its description, which is the text the model reads
- [security] Tool “openmeteo_get_climate” rewrote its description, which is the text the model reads
- [security] Tool “openmeteo_get_ensemble” rewrote its description, which is the text the model reads
- [security] Tool “openmeteo_get_flood” rewrote its description, which is the text the model reads
- [security] Tool “openmeteo_get_forecast” rewrote its description, which is the text the model reads
- [security] Tool “openmeteo_get_historical” rewrote its description, which is the text the model reads
- [security] Tool “openmeteo_get_marine” rewrote its description, which is the text the model reads
- [security] Tool “openmeteo_dataframe_describe” rewrote its description, which is the text the model reads
- [security] Tool “openmeteo_dataframe_query” rewrote its description, which is the text the model reads
- [functional regression] Schema quality: 453 → 657
- [functional regression] Schema quality: 453 → 653
- [functional regression] Schema quality: 453 → 588
- [functional improvement] Endpoint reachability: not serving MCP → reachable
- [functional improvement] Tool coverage: unverified → 100
- [functional improvement] MCP protocol: unverified → pass
- [functional] Server version: 0.3.2 → 0.3.3
- [functional] Server version: 0.2.5 → 0.3.2
- [functional] New tool “openmeteo_search_locations”
- [cosmetic] “openmeteo_get_air_quality” added an optional parameter “canvas_id”
- [cosmetic] “openmeteo_get_air_quality” added an optional parameter “end_date”
- [cosmetic] “openmeteo_get_air_quality” added an optional parameter “past_days”
- [cosmetic] “openmeteo_get_air_quality” added an optional parameter “start_date”
- [cosmetic] “openmeteo_get_forecast” added an optional parameter “canvas_id”
- [cosmetic] “openmeteo_get_marine” added an optional parameter “canvas_id”
- [cosmetic] “openmeteo_get_marine” added an optional parameter “end_date”
- [cosmetic] “openmeteo_get_marine” added an optional parameter “past_days”
- [cosmetic] “openmeteo_get_marine” added an optional parameter “start_date”
- [cosmetic] “openmeteo_get_climate” reworded the description of “models”
- [cosmetic] “openmeteo_get_ensemble” reworded the description of “models”
- [cosmetic] “openmeteo_dataframe_describe” reworded the description of “canvas_id”
- [cosmetic] “openmeteo_dataframe_query” reworded the description of “canvas_id”
- [cosmetic] “openmeteo_get_air_quality” reworded the description of “forecast_days”
- [cosmetic] “openmeteo_get_air_quality” reworded the description of “latitude”
- [cosmetic] “openmeteo_get_climate” reworded the description of “latitude”
- [cosmetic] “openmeteo_get_ensemble” reworded the description of “daily_variables”
- [cosmetic] “openmeteo_get_ensemble” reworded the description of “hourly_variables”
- [cosmetic] “openmeteo_get_ensemble” reworded the description of “latitude”
- [cosmetic] “openmeteo_get_flood” reworded the description of “latitude”
- [cosmetic] “openmeteo_get_forecast” reworded the description of “daily_variables”
- [cosmetic] “openmeteo_get_forecast” reworded the description of “hourly_variables”
- [cosmetic] “openmeteo_get_forecast” reworded the description of “latitude”
- [cosmetic] “openmeteo_get_forecast” reworded the description of “timezone”
- [cosmetic] “openmeteo_get_historical” reworded the description of “daily_variables”
- [cosmetic] “openmeteo_get_historical” reworded the description of “hourly_variables”
- [cosmetic] “openmeteo_get_historical” reworded the description of “latitude”
- [cosmetic] “openmeteo_get_marine” reworded the description of “forecast_days”
- [cosmetic] “openmeteo_get_marine” reworded the description of “hourly_variables”
- [cosmetic] “openmeteo_get_marine” reworded the description of “latitude”
- [cosmetic] “openmeteo_get_marine” reworded the description of “daily_variables”

### 2026-07-30 (score 15, −48)

- [security regression] Endpoint reachability: reachable → not serving MCP
- [security regression] Stability: 0.10 → unverified
- [security regression] HSTS header: pass → fail
- [security regression] Transport: pass → fail
- [security] Authorization: Authorisation not fully verified: no authorisation is required to connect, but we couldn't read the tool list to see what that exposes.
- [functional regression] Tool coverage: 100 → unverified
- [functional regression] Capabilities: pass → unverified
- [functional] First check of Schema quality: unverified
- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-07-28 (score 63, +1)

No change was recorded against any check on this day. Stability & Change Management went from 3 to 7. That category is still filling its 30-day observation window: 1 days of observed history at the previous scan, 2 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-07-27 (score 62, +1)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-07-26 (score 61)

First indexed and scored.

## MCP tools (11)

### `openmeteo_search_locations` (~443 tokens)

Openmeteo Search Locations

Resolve a place name to ranked coordinate matches with country, region, elevation, timezone, and population. Required prerequisite for name-based queries — all weather tools take latitude/longitude, not place names. Search by a bare place name (city, region, or landmark); never fold a qualifier into it — pass "Baoding", not "Baoding Hebei", and "Paris", not "Paris, France". To disambiguate places that share a name, set the country input (ISO 3166-1 alpha-2, e.g. "US") and/or read the admin1 and country fields on each ranked result — admin1 is a result field for choosing among matches, not a search input. Returns up to 10 matches ranked by population/relevance.

Input parameters:

- `count` (integer): Max results to return (1–10). Default 5. Return more when disambiguating common names like "Springfield" or "Portland".
- `country` (string): ISO 3166-1 alpha-2 country code (e.g. "US", "FR") to disambiguate places that share a name. Omit for a global search.
- `language` (string): Language for matching and returning place names (ISO 639-1, e.g., "en", "de", "zh"). The API matches name against the localized index for this language, so set it to match the script of name — e.g. l…
- `name` (string, required): Place name to search — a bare city, region, or landmark ("Seattle", "Mount Rainier"). Do not fold in a region or country qualifier ("Baoding", not "Baoding Hebei"); use the country input to disambigu…

Output parameters:

- `count` (number): Number of results returned
- `results` (array): Ranked matches (most relevant first). Never empty — when nothing matches, the tool fails with no_results instead of returning an empty array.

### `openmeteo_get_elevation` (~116 tokens)

Openmeteo Get Elevation

Terrain elevation from the Copernicus Digital Elevation Model (~90m resolution) for one or more coordinate pairs. Accepts up to 100 pairs per call. Useful for geographic context, elevation-adjusted weather interpretation, or route planning.

Input parameters:

- `latitudes` (array, required): Array of latitudes in decimal degrees (up to 100). Must be same length as longitudes.
- `longitudes` (array, required): Array of longitudes in decimal degrees (up to 100). Must be same length as latitudes.

Output parameters:

- `elevations` (array): Elevation values in input order

### `openmeteo_get_forecast` (~807 tokens)

Openmeteo Get Forecast

Weather forecast for coordinates: hourly and/or daily variables for up to 16 days ahead, with optional past_days (up to 92) for recent history. Use past_days instead of openmeteo_get_historical for dates within the last 1–5 days, since ERA5 has a variable lag. Returns per-timestamp records — each hourly entry contains a "time" field (ISO 8601) plus one key per requested variable; each daily entry contains a "time" field (YYYY-MM-DD) plus requested variables. Common hourly variables: temperature_2m, precipitation, wind_speed_10m, relative_humidity_2m, cloud_cover, uv_index, apparent_temperature, precipitation_probability, weather_code, surface_pressure, visibility, wind_direction_10m, wind_gusts_10m, dew_point_2m. Common daily variables: temperature_2m_max, temperature_2m_min, precipitation_sum, wind_speed_10m_max, sunrise, sunset, uv_index_max, precipitation_hours, weather_code. A wide window — a large past_days plus many hourly variables — produces thousands of records; these spill to DataCanvas for SQL querying when canvas is enabled, and return a bounded preview with truncated: true when it is not. At least one of hourly_variables or daily_variables is required.

Input parameters:

- `canvas_id` (string): DataCanvas token for wide past_days or multi-variable queries. When a result is too large to return inline — driven by total payload size, so a wide multi-variable pull can spill at any row count — i…
- `daily_variables` (array): Daily summary variables (e.g., ["temperature_2m_max", "temperature_2m_min", "precipitation_sum", "wind_speed_10m_max", "sunrise", "sunset", "uv_index_max"]). Daily names only — an hourly name such as…
- `forecast_days` (integer): Number of forecast days (1–16). Default 7.
- `hourly_variables` (array): Hourly variables to fetch (e.g., ["temperature_2m", "precipitation", "wind_speed_10m", "relative_humidity_2m", "cloud_cover", "uv_index", "apparent_temperature"]). Hourly names only — a daily aggrega…
- `latitude` (number, required): Latitude in decimal degrees (e.g., 47.6062 for Seattle). Use openmeteo_search_locations to resolve a place name to coordinates.
- `longitude` (number, required): Longitude in decimal degrees (e.g., -122.3321 for Seattle).
- `past_days` (integer): Include this many days of past data before today (0–92). Use for recent history — ERA5 archive has a variable ~5-day lag. Default 0.
- `precipitation_unit` (string): Precipitation unit: "mm" or "inch". Default "mm".
- `temperature_unit` (string): Temperature unit. Default "celsius".
- `timezone` (string): IANA timezone (e.g., "America/Los_Angeles") or "auto" to use the location's local timezone. Default "auto". The timezone from openmeteo_search_locations is ideal to pass here.
- `wind_speed_unit` (string): Wind speed unit: "kmh" (km/h), "mph", "ms" (m/s), or "kn" (knots). Default "kmh".

Output parameters:

- `canvas_id` (string): DataCanvas token for the staged full dataset. Present only when truncated is true AND DataCanvas is enabled (CANVAS_PROVIDER_TYPE=duckdb) — absent otherwise, in which case the preview is all this res…
- `daily` (array): Per-day records. Each object has a "time" field (YYYY-MM-DD) plus one key per requested variable with its value. Units are in the daily_units map. Absent when only hourly_variables were requested. Wh…
- `daily_units` (object): Map of variable name → unit string for daily data. Absent when no daily_variables were requested.
- `elevation` (number): Terrain elevation at grid point (meters)
- `hourly` (array): Per-hour records. Each object has a "time" field (ISO 8601) plus one key per requested variable with its value. Units are in the hourly_units map. Absent when only daily_variables were requested. Whe…
- `hourly_units` (object): Map of variable name → unit string for hourly data (e.g., {"temperature_2m": "°C", "precipitation": "mm"}). Absent when no hourly_variables were requested.
- `latitude` (number): Snapped latitude (Open-Meteo snaps to nearest grid point)
- `longitude` (number): Snapped longitude
- `notice` (string): Warning that a requested variable came back with no data — names each column whose unit is "undefined", which is how the endpoint reports a name it parsed but does not serve in the requested cadence.
- `record_count` (number): Total number of records (hourly + daily rows) — the full upstream total when truncated is true, not the combined length of the hourly and daily previews.
- `table_name` (string): DuckDB table name for the staged data — pass to openmeteo_dataframe_query. Present only alongside canvas_id.
- `timezone` (string): Resolved IANA timezone
- `truncated` (boolean): True when the response was too large to return inline, so hourly and daily carry a bounded preview rather than the full set. With DataCanvas enabled the complete data is staged at canvas_id — every h…
- `utc_offset_seconds` (number): UTC offset in seconds for this timezone at query time

### `openmeteo_get_historical` (~601 tokens)

Openmeteo Get Historical

Historical weather from the ERA5 reanalysis archive (1940–present). Requires start_date and end_date (ISO 8601 date, e.g., "2024-07-01"). ERA5 has a variable lag of up to ~5 days — for dates within the last week, use openmeteo_get_forecast with past_days instead. Uses the same variable names as the forecast API for direct comparison. Large date ranges (multi-year hourly) produce thousands of records — these spill to DataCanvas for SQL querying when canvas is enabled, and return a bounded preview with truncated: true when it is not. At least one of hourly_variables or daily_variables is required.

Input parameters:

- `canvas_id` (string): DataCanvas token for multi-year or multi-variable queries. When a result is too large to return inline — driven by total payload size, so a wide multi-variable pull can spill at any row count — it sp…
- `daily_variables` (array): Daily summary variables (e.g., ["temperature_2m_max", "temperature_2m_min", "precipitation_sum", "wind_speed_10m_max"]). Daily names only — an hourly name such as cloud_cover or temperature_2m belong…
- `end_date` (string, required): End date (YYYY-MM-DD, inclusive). Must be on or after start_date. For dates within the last ~5 days, use openmeteo_get_forecast with past_days instead.
- `hourly_variables` (array): Hourly ERA5 variables (e.g., ["temperature_2m", "precipitation", "wind_speed_10m", "relative_humidity_2m", "cloud_cover", "soil_moisture_0_to_7cm"]). Hourly names only — a daily aggregate such as tem…
- `latitude` (number, required): Latitude in decimal degrees. Use openmeteo_search_locations to resolve a place name to coordinates.
- `longitude` (number, required): Longitude in decimal degrees.
- `precipitation_unit` (string): Precipitation unit. Default "mm".
- `start_date` (string, required): Start date (YYYY-MM-DD, e.g., "2024-07-01"). ERA5 covers from 1940-01-01 to approximately 5 days ago.
- `temperature_unit` (string): Temperature unit. Default "celsius".
- `timezone` (string): IANA timezone or "auto". Default "auto".
- `wind_speed_unit` (string): Wind speed unit. Default "kmh".

Output parameters:

- `canvas_id` (string): DataCanvas token for the staged full dataset. Present only when truncated is true AND DataCanvas is enabled (CANVAS_PROVIDER_TYPE=duckdb) — absent otherwise, in which case the preview is all this res…
- `daily` (array): Per-day records with "time" (YYYY-MM-DD) + variable keys. Absent when only hourly_variables were requested. When truncated, contains only a preview — query canvas_id for the full dataset when one is…
- `daily_units` (object): Variable → unit string for daily data. Absent when no daily_variables were requested.
- `date_range` (object): Date range of returned data
- `elevation` (number): Elevation at grid point (meters)
- `hourly` (array): Per-hour records with "time" (ISO 8601) + variable keys. Absent when only daily_variables were requested. When truncated, contains only a preview — query canvas_id for the full dataset when one is pr…
- `hourly_units` (object): Variable → unit string for hourly data (e.g., {"temperature_2m": "°C", "precipitation": "mm"}). Absent when no hourly_variables were requested.
- `latitude` (number): Snapped latitude
- `longitude` (number): Snapped longitude
- `notice` (string): Warning that a requested variable came back with no data — names each column whose unit is "undefined", which is how the archive reports a name it parsed but does not serve in the requested cadence.
- `record_count` (number): Total number of records (hourly + daily rows) — the full upstream total when truncated is true, not the combined length of the hourly and daily previews.
- `table_name` (string): DuckDB table name for the staged data — pass to openmeteo_dataframe_query. Present only alongside canvas_id.
- `timezone` (string): Resolved IANA timezone
- `truncated` (boolean): True when the response was too large to return inline, so hourly and daily carry a bounded preview rather than the full set. With DataCanvas enabled the complete data is staged at canvas_id — every h…

### `openmeteo_get_marine` (~769 tokens)

Openmeteo Get Marine

Marine wave and ocean conditions for a coastal or ocean coordinate: wave height, wave period, wave direction, wind-wave height, swell height, sea-surface temperature. Forecast horizon up to 8 days, with optional past_days (up to 92) for recent history — or start_date and end_date together for an archive range, which returns real wave values back to at least 2022. One window per call: a date range is mutually exclusive with forecast_days and past_days, and needs both ends — a lone start_date or end_date is rejected. Returns per-timestamp records — each entry contains a "time" field plus one key per requested variable. Best for open-ocean and coastal exposed points — sheltered inland waters return near-zero wave values. Common hourly variables: wave_height, wave_direction, wave_period, wind_wave_height, wind_wave_direction, wind_wave_period, swell_wave_height, swell_wave_direction, swell_wave_period. Common daily: wave_height_max, wave_direction_dominant, wave_period_max. Note: ocean_current_velocity is null for non-open-ocean coordinates. A wide window — a large past_days or date range plus many variables — produces thousands of records; these spill to DataCanvas for SQL querying when canvas is enabled, and return a bounded preview with truncated: true when it is not.

Input parameters:

- `canvas_id` (string): DataCanvas token for wide past_days, archive-range, or multi-variable queries. When a result is too large to return inline — driven by total payload size, so a wide multi-variable pull can spill at a…
- `daily_variables` (array): Daily marine summary variables (e.g., ["wave_height_max", "wave_direction_dominant", "wave_period_max"]). Daily names only — an hourly name such as wave_height belongs in hourly_variables and is reje…
- `end_date` (string): End date for the archive range (YYYY-MM-DD, inclusive). Must be on or after start_date. Requires start_date — the pair must be sent together, and neither combines with forecast_days or past_days.
- `forecast_days` (integer): Forecast horizon in days (1–8). Omit for the upstream default of 7. Mutually exclusive with start_date/end_date — omit it entirely when pulling an archive range.
- `hourly_variables` (array): Hourly marine variables (e.g., ["wave_height", "wave_direction", "wave_period", "wind_wave_height", "swell_wave_height"]). Hourly names only — a daily aggregate such as wave_height_max or wave_direct…
- `latitude` (number, required): Latitude of a coastal or ocean point. Use openmeteo_search_locations to resolve a place name. Inland points return near-zero wave values.
- `longitude` (number, required): Longitude in decimal degrees.
- `past_days` (integer): Include this many days of past data before today (0–92). Use for recent history instead of a start_date/end_date range. Default 0. Must stay 0 when start_date/end_date are used.
- `start_date` (string): Start date for the archive range (YYYY-MM-DD, e.g., "2024-07-01"). Real wave values go back to at least 2022. Requires end_date — the pair must be sent together, and neither combines with forecast_da…
- `timezone` (string): IANA timezone or "auto". Default "auto".

Output parameters:

- `canvas_id` (string): DataCanvas token for the staged full dataset. Present only when truncated is true AND DataCanvas is enabled (CANVAS_PROVIDER_TYPE=duckdb) — absent otherwise, in which case the preview is all this res…
- `daily` (array): Per-day summary records with "time" (YYYY-MM-DD) + variable keys (e.g., wave_height_max in meters, wave_direction_dominant in degrees, wave_period_max in seconds). When truncated, contains only a pre…
- `daily_units` (object): Variable → unit string for daily data. Absent when no daily_variables were requested.
- `hourly` (array): Per-hour records with "time" (ISO 8601) + one key per requested variable (e.g., wave_height in meters, wave_direction in degrees, wave_period in seconds). Absent when only daily_variables were reques…
- `hourly_units` (object): Variable → unit string for hourly data (e.g., {"wave_height": "m", "wave_period": "s"}). Absent when no hourly_variables were requested.
- `latitude` (number): Snapped latitude
- `longitude` (number): Snapped longitude
- `notice` (string): Warning that a requested variable came back with no data — names each column whose unit is "undefined", which is how the endpoint reports a name it parsed but does not serve.
- `record_count` (number): Total number of records (hourly + daily rows) — the full upstream total when truncated is true, not the combined length of the hourly and daily previews.
- `table_name` (string): DuckDB table name for the staged data — pass to openmeteo_dataframe_query. Present only alongside canvas_id.
- `timezone` (string): Resolved IANA timezone
- `truncated` (boolean): True when the response was too large to return inline, so hourly and daily carry a bounded preview rather than the full set. With DataCanvas enabled the complete data is staged at canvas_id — every h…

### `openmeteo_get_air_quality` (~668 tokens)

Openmeteo Get Air Quality

Modeled CAMS (Copernicus Atmosphere Monitoring Service) air quality: PM2.5, PM10, nitrogen dioxide, sulphur dioxide, ozone, carbon monoxide, dust, pollen, and European/US AQI indices. This is modeled grid data, not measured station readings — for measured data, use openaq-mcp-server. Forecast horizon up to 7 days, with optional past_days (up to 92) for recent history — or start_date and end_date together for an archive range, which returns real CAMS values back to at least 2022-10-01. One window per call: a date range is mutually exclusive with forecast_days and past_days, and needs both ends — a lone start_date or end_date is rejected. Common variables: pm2_5, pm10, carbon_monoxide, nitrogen_dioxide, sulphur_dioxide, ozone, dust, european_aqi, us_aqi, alder_pollen, birch_pollen, grass_pollen, mugwort_pollen, olive_pollen, ragweed_pollen. A wide window — a large past_days or date range plus many variables — produces thousands of records; these spill to DataCanvas for SQL querying when canvas is enabled, and return a bounded preview with truncated: true when it is not.

Input parameters:

- `canvas_id` (string): DataCanvas token for wide past_days, archive-range, or multi-variable queries. When a result is too large to return inline — driven by total payload size, so a wide multi-variable pull can spill at a…
- `end_date` (string): End date for the archive range (YYYY-MM-DD, inclusive). Must be on or after start_date. Requires start_date — the pair must be sent together, and neither combines with forecast_days or past_days.
- `forecast_days` (integer): Forecast horizon in days (1–7). Omit for the upstream default of 5. Mutually exclusive with start_date/end_date — omit it entirely when pulling an archive range.
- `hourly_variables` (array): Hourly air quality variables (e.g., ["pm2_5", "pm10", "ozone", "nitrogen_dioxide", "european_aqi", "us_aqi"]). At least one required.
- `latitude` (number, required): Latitude in decimal degrees. Use openmeteo_search_locations to resolve a place name.
- `longitude` (number, required): Longitude in decimal degrees.
- `past_days` (integer): Include this many days of past data before today (0–92). Use for recent history instead of a start_date/end_date range. Default 0. Must stay 0 when start_date/end_date are used.
- `start_date` (string): Start date for the archive range (YYYY-MM-DD, e.g., "2024-07-01"). Real CAMS values go back to at least 2022-10-01; earlier dates return rows of nulls. Requires end_date — the pair must be sent toget…
- `timezone` (string): IANA timezone or "auto". Default "auto".

Output parameters:

- `canvas_id` (string): DataCanvas token for the staged full dataset. Present only when truncated is true AND DataCanvas is enabled (CANVAS_PROVIDER_TYPE=duckdb) — absent otherwise, in which case the preview is all this res…
- `data_source` (string): Data source identifier — this is modeled CAMS data, forecast or archive, not measured station data.
- `hourly` (array): Per-hour records with "time" (ISO 8601) + one key per requested variable. Units: pm2_5/pm10/dust in μg/m³, carbon_monoxide in μg/m³, nitrogen_dioxide/sulphur_dioxide/ozone in μg/m³, european_aqi/us_a…
- `hourly_units` (object): Variable → unit string for hourly data (e.g., {"pm2_5": "μg/m³", "european_aqi": "EAQI"}).
- `latitude` (number): Snapped latitude
- `longitude` (number): Snapped longitude
- `notice` (string): Warning that a requested variable came back with no data — names each column whose unit is "undefined", which is how the endpoint reports a name it parsed but does not serve.
- `record_count` (number): Total number of hourly records — the full upstream total when truncated is true, not the length of the hourly preview.
- `table_name` (string): DuckDB table name for the staged data — pass to openmeteo_dataframe_query. Present only alongside canvas_id.
- `timezone` (string): Resolved IANA timezone
- `truncated` (boolean): True when the response was too large to return inline, so hourly carries a bounded preview rather than the full set. With DataCanvas enabled the complete data is staged at canvas_id. With it disabled…

### `openmeteo_get_ensemble` (~1328 tokens)

Openmeteo Get Ensemble

Probabilistic ensemble weather forecast — up to 64 ensemble members, up to 16 days ahead with optional past_days (0–92). Each member's values appear as separate columns named with a member suffix (e.g. temperature_2m_member01, temperature_2m_member02). Use the spread across members to compute exceedance probabilities, quantify forecast uncertainty, and build decision thresholds. Available models: ecmwf_ifs025_ensemble (51 members, global 0.25°), ecmwf_aifs025_ensemble (51, global 0.25°), ecmwf_ifs_europe_ensemble (51, Europe 9 km), ecmwf_aifs_europe_ensemble (51, Europe 31 km), google_weathernext2_ensemble (64, global 0.25°), ncep_gefs_seamless (31, global blend), ncep_gefs025 (31, global 0.25°), ncep_gefs05 (31, global 50 km, 35 days), ncep_aigefs025 (31, global 0.25°), icon_seamless_eps (20–40, global/Europe blend), icon_global_eps (40, global 26 km), icon_eu_eps (40, Europe 13 km), icon_d2_eps (20, Central Europe 2 km), gem_global_ensemble (21, global 0.25°), bom_access_global_ensemble (18, global 40 km), ukmo_global_ensemble_20km (18, global 20 km), ukmo_uk_ensemble_2km (3, UK 2 km), meteoswiss_icon_ch1_ensemble (11, Central Europe 1 km), meteoswiss_icon_ch2_ensemble (21, Central Europe 2 km). Omit models to use the API default blend. A regional model returns no data outside the area it covers; that comes back as an input error naming the coverage gap, not a transient failure, so pick a global model or move the coordinate inside the region rather than retrying. A model name this list does not carry is still sent upstream, so a newly added one keeps working. Large multi-member, multi-day pulls produce thousands of records and spill to DataCanvas when canvas is enabled, returning a bounded preview with truncated: true when it is not. At least one of hourly_variables or daily_variables is required.

Input parameters:

- `canvas_id` (string): DataCanvas token for large multi-member queries. When a result is too large to return inline — driven by total payload size, so a wide member fan-out can spill at any row count — it spills to this ca…
- `daily_variables` (array): Daily variables to fetch across all ensemble members (e.g., ["temperature_2m_max", "temperature_2m_min", "precipitation_sum"]). Each variable appears as temperature_2m_max_member01, … Daily names onl…
- `forecast_days` (integer): Forecast horizon in days (1–16). Default 7.
- `hourly_variables` (array): Hourly variables to fetch across all ensemble members (e.g., ["temperature_2m", "precipitation", "wind_speed_10m"]). Each variable appears as temperature_2m_member01, temperature_2m_member02, … in th…
- `latitude` (number, required): Latitude in decimal degrees. Use openmeteo_search_locations to resolve a place name to coordinates.
- `longitude` (number, required): Longitude in decimal degrees.
- `models` (string): Ensemble model to use, one name: ecmwf_ifs025_ensemble (51 members, global 0.25°), ecmwf_aifs025_ensemble (51, global 0.25°), ecmwf_ifs_europe_ensemble (51, Europe 9 km), ecmwf_aifs_europe_ensemble (…
- `past_days` (integer): Include this many days of past ensemble data before today (0–92). Default 0.
- `precipitation_unit` (string): Precipitation unit. Default "mm".
- `temperature_unit` (string): Temperature unit. Default "celsius".
- `timezone` (string): IANA timezone (e.g., "America/Los_Angeles") or "auto" to use the location's local timezone. Default "auto".
- `wind_speed_unit` (string): Wind speed unit. Default "kmh".

Output parameters:

- `canvas_id` (string): DataCanvas token for the staged full dataset. Present only when truncated is true AND DataCanvas is enabled (CANVAS_PROVIDER_TYPE=duckdb) — absent otherwise, in which case the preview is all this res…
- `daily` (array): Per-day records with "time" (YYYY-MM-DD) + per-member columns (e.g., temperature_2m_max_member01). Absent when only hourly_variables were requested. When truncated, contains a preview only — query ca…
- `daily_units` (object): Variable → unit string for daily data. Absent when no daily_variables were requested.
- `elevation` (number): Terrain elevation at grid point (meters)
- `hourly` (array): Per-hour records with "time" (ISO 8601) + per-member columns for each requested variable (e.g., temperature_2m_member01, temperature_2m_member02). Absent when only daily_variables were requested. Whe…
- `hourly_units` (object): Variable → unit string for hourly data (e.g., {"temperature_2m_member01": "°C"}). Absent when no hourly_variables were requested.
- `latitude` (number): Snapped latitude (Open-Meteo snaps to nearest grid point)
- `longitude` (number): Snapped longitude
- `member_count` (number): Number of distinct perturbed ensemble members in the response, counted from the _memberNN column suffixes. The unsuffixed base column (the control run) is not included in this count.
- `model` (string): Ensemble model used (e.g. "ecmwf_ifs025_ensemble") — echoes the requested models parameter. Absent when models was omitted (API default blend; the API reports no provenance).
- `notice` (string): Warning that a requested variable came back with no data across every member — names each variable whose unit is "undefined", which is how the endpoint reports a name the selected model does not carr…
- `record_count` (number): Total number of records (hourly + daily rows) — the full upstream total when truncated is true, not the combined length of the hourly and daily previews.
- `table_name` (string): DuckDB table name for the staged data — pass to openmeteo_dataframe_query. Present only alongside canvas_id.
- `timezone` (string): Resolved IANA timezone
- `truncated` (boolean): True when the response was too large to return inline, so hourly and daily carry a bounded preview rather than the full set. With DataCanvas enabled the complete data is staged at canvas_id — every h…

### `openmeteo_get_flood` (~567 tokens)

Openmeteo Get Flood

GloFAS (Global Flood Awareness System) river discharge forecast and historical reanalysis. Returns daily ensemble river discharge (m³/s) for the river nearest to the given coordinates — no river ID needed, the API snaps to the nearest stream. Forecast horizon up to 210 days ahead; reanalysis history back to 1984-01-01. One mode per call: forecast_days for the future outlook, or start_date and end_date together for reanalysis history. The two modes are mutually exclusive, and a date range needs both ends — a lone start_date or end_date is rejected. Available daily variables: "river_discharge" (ensemble mean), "river_discharge_mean", "river_discharge_min", "river_discharge_max", "river_discharge_median", "river_discharge_p25" (25th percentile), "river_discharge_p75" (75th percentile). Returns null for coordinates far from any river or in areas without GloFAS coverage. A wide reanalysis range produces thousands of daily records and spills to DataCanvas for SQL querying when canvas is enabled, returning a bounded preview with truncated: true when it is not.

Input parameters:

- `canvas_id` (string): DataCanvas token for wide reanalysis queries. When a result is too large to return inline — driven by total payload size, so a multi-variable pull can spill at any row count — it spills to this canva…
- `daily_variables` (array): Daily discharge variables to fetch (e.g., ["river_discharge", "river_discharge_p25", "river_discharge_p75", "river_discharge_min", "river_discharge_max"]). Required.
- `end_date` (string): End date for historical reanalysis (YYYY-MM-DD, inclusive). Must be on or after start_date. Requires start_date — the pair must be sent together, and neither combines with forecast_days.
- `forecast_days` (integer): Number of forecast days ahead (1–210). Mutually exclusive with start_date/end_date — omit it entirely when pulling a historical range.
- `latitude` (number, required): Latitude in decimal degrees. The API snaps to the nearest river — no river ID required. Use openmeteo_search_locations to resolve a place name.
- `longitude` (number, required): Longitude in decimal degrees.
- `start_date` (string): Start date for historical reanalysis (YYYY-MM-DD, e.g., "2023-01-01"). GloFAS reanalysis covers from 1984-01-01. Requires end_date — the pair must be sent together, and neither combines with forecast…
- `timezone` (string): IANA timezone or "auto". Default "auto".

Output parameters:

- `canvas_id` (string): DataCanvas token for the staged full dataset. Present only when truncated is true AND DataCanvas is enabled (CANVAS_PROVIDER_TYPE=duckdb) — absent otherwise, in which case the preview is all this res…
- `daily` (array): Per-day records with "time" (YYYY-MM-DD) + one key per requested variable containing discharge in m³/s, or null for coordinates outside GloFAS coverage. When truncated, contains only a preview — quer…
- `daily_units` (object): Variable → unit string for daily data (e.g., {"river_discharge": "m³/s"}).
- `latitude` (number): Snapped latitude (nearest river grid point)
- `longitude` (number): Snapped longitude
- `notice` (string): Warning that a requested variable came back with no data — names each column whose unit is "undefined", which is how the endpoint reports a name it parsed but does not serve.
- `record_count` (number): Total number of daily discharge records — the full staged count when truncated is true, not the length of the daily preview.
- `table_name` (string): DuckDB table name for the staged data — pass to openmeteo_dataframe_query. Present only alongside canvas_id.
- `timezone` (string): Resolved IANA timezone
- `truncated` (boolean): True when the response was too large to return inline, so daily carries a bounded preview rather than the full set. With DataCanvas enabled the complete data is staged at canvas_id. With it disabled…

### `openmeteo_get_climate` (~718 tokens)

Openmeteo Get Climate

Long-range climate projections from bias-corrected daily CMIP6 models, covering 1950-01-01 to 2050-12-31 at any coordinate. Answers "what will conditions look like through 2050?" — the future-projection counterpart to openmeteo_get_historical (ERA5, what happened). Daily resolution only. Available models: CMCC_CM2_VHR4, FGOALS_f3_H, HiRAM_SIT_HR, MRI_AGCM3_2_S, EC_Earth3P_HR, MPI_ESM1_2_XR, NICAM16_8S. A model name outside that list is sent upstream rather than rejected here, so a model Open-Meteo adds later still works; if upstream rejects the request, the error names the offending model on its own rather than the whole requested list. With 2+ models each variable appears once per model with the model name as suffix (e.g. temperature_2m_max_CMCC_CM2_VHR4); a single or omitted model returns plain variable names. Not all models carry all variables — missing combinations return null. Multi-decade daily pulls across several models produce thousands of records and spill to DataCanvas for SQL querying when canvas is enabled, returning a bounded preview with truncated: true when it is not.

Input parameters:

- `canvas_id` (string): DataCanvas token for multi-decade or multi-model queries. When a result is too large to return inline — driven by total payload size, so a wide multi-model pull can spill at any row count — it spills…
- `daily_variables` (array): Daily climate variables to fetch (e.g., ["temperature_2m_max", "temperature_2m_min", "precipitation_sum", "wind_speed_10m_mean", "shortwave_radiation_sum"]). Required — the Climate API is daily-only.
- `end_date` (string, required): End date (YYYY-MM-DD, inclusive, max 2050-12-31). Must be on or after start_date.
- `latitude` (number, required): Latitude in decimal degrees. Use openmeteo_search_locations to resolve a place name to coordinates.
- `longitude` (number, required): Longitude in decimal degrees.
- `models` (array): CMIP6 models to include: CMCC_CM2_VHR4, FGOALS_f3_H, HiRAM_SIT_HR, MRI_AGCM3_2_S, EC_Earth3P_HR, MPI_ESM1_2_XR, NICAM16_8S. With 2+ models each variable column is suffixed with the model name (e.g. t…
- `precipitation_unit` (string): Precipitation unit. Default "mm".
- `start_date` (string, required): Start date (YYYY-MM-DD, e.g., "2049-01-01"). CMIP6 projections cover 1950-01-01 to 2050-12-31.
- `temperature_unit` (string): Temperature unit. Default "celsius".
- `timezone` (string): IANA timezone or "auto". Default "auto".
- `wind_speed_unit` (string): Wind speed unit. Default "kmh".

Output parameters:

- `canvas_id` (string): DataCanvas token for the staged full dataset. Present only when truncated is true AND DataCanvas is enabled (CANVAS_PROVIDER_TYPE=duckdb) — absent otherwise, in which case the preview is all this res…
- `daily` (array): Per-day records with "time" (YYYY-MM-DD) + one key per requested variable — per-model suffixed keys when 2+ models were requested (e.g. temperature_2m_max_CMCC_CM2_VHR4). Null values mean the model d…
- `daily_units` (object): Column → unit string for daily data (e.g., {"temperature_2m_max_CMCC_CM2_VHR4": "°C"}).
- `date_range` (object): Date range of returned data
- `elevation` (number): Elevation at grid point (meters)
- `latitude` (number): Snapped latitude (Open-Meteo snaps to nearest grid point)
- `longitude` (number): Snapped longitude
- `models` (array): Climate models requested — echoes the models parameter. Absent when models was omitted (API default model; the response carries no provenance).
- `notice` (string): Warning that a requested variable came back with no data — names each column whose unit is "undefined", which is how the endpoint reports a name it parsed but does not serve.
- `record_count` (number): Total number of daily records — the full upstream total when truncated is true, not the length of the daily preview.
- `table_name` (string): DuckDB table name for the staged data — pass to openmeteo_dataframe_query. Present only alongside canvas_id.
- `timezone` (string): Resolved IANA timezone
- `truncated` (boolean): True when the response was too large to return inline, so daily carries a bounded preview rather than the full set. With DataCanvas enabled the complete data is staged at canvas_id. With it disabled…

### `openmeteo_dataframe_query` (~249 tokens)

Openmeteo Dataframe Query

Run a read-only SQL SELECT against tables staged on a DataCanvas by openmeteo_get_forecast, openmeteo_get_historical, openmeteo_get_marine, openmeteo_get_air_quality, openmeteo_get_ensemble, openmeteo_get_flood, or openmeteo_get_climate. Pass the canvas_id returned when any of those tools spills (truncated: true), and reference the exact table_name those tools return alongside it. Call openmeteo_dataframe_describe to list staged tables and their columns when you need to discover names.

Input parameters:

- `canvas_id` (string, required): Canvas ID returned by openmeteo_get_forecast, openmeteo_get_historical, openmeteo_get_marine, openmeteo_get_air_quality, openmeteo_get_ensemble, openmeteo_get_flood, or openmeteo_get_climate when tru…
- `sql` (string, required): Read-only SELECT statement. Reference table names from openmeteo_dataframe_describe. Example: SELECT AVG(temperature_2m) AS avg_temp, strftime(time, '%Y-%m') AS month FROM spilled_abc123 GROUP BY mon…

Output parameters:

- `canvas_id` (string): Canvas ID that was queried.
- `row_count` (number): Total rows in the full result before any cap.
- `rows` (array): Result rows — a preview capped at 100. When row_count exceeds this, page the rest by re-issuing the SQL with LIMIT / OFFSET.

### `openmeteo_dataframe_describe` (~155 tokens)

Openmeteo Dataframe Describe

List the tables and their columns on a DataCanvas staged by openmeteo_get_forecast, openmeteo_get_historical, openmeteo_get_marine, openmeteo_get_air_quality, openmeteo_get_ensemble, openmeteo_get_flood, or openmeteo_get_climate. Call this first to discover table names before querying with openmeteo_dataframe_query.

Input parameters:

- `canvas_id` (string, required): Canvas ID returned by openmeteo_get_forecast, openmeteo_get_historical, openmeteo_get_marine, openmeteo_get_air_quality, openmeteo_get_ensemble, openmeteo_get_flood, or openmeteo_get_climate when tru…

Output parameters:

- `canvas_id` (string): Canvas ID that was inspected.
- `expires_at` (string): ISO 8601 expiry after the sliding 24 h TTL.
- `tables` (array): Tables and views registered on this canvas.

## Diagnostics

Captured diagnostic sections: TLS, DNSSEC, Authorisation, Transports. The full working is on the page: https://verifymcp.io/servers/cyanheads-open-meteo-mcp-server/open-meteo#diagnostics

## Score history

- 2026-08-03: 66
- 2026-08-02: 65
- 2026-08-01: 64
- 2026-07-31: 62
- 2026-07-30: 15
- 2026-07-29: 63
- 2026-07-28: 63
- 2026-07-27: 62
- 2026-07-26: 61

## Links

- Remote endpoint: https://open-meteo.caseyjhand.com/mcp
- Repository: https://github.com/cyanheads/open-meteo-mcp-server
- Changelog RSS feed: https://verifymcp.io/servers/cyanheads-open-meteo-mcp-server/open-meteo/changelog.xml
- Changelog JSON feed: https://verifymcp.io/servers/cyanheads-open-meteo-mcp-server/open-meteo/changelog.json
- HTML version of this page: https://verifymcp.io/servers/cyanheads-open-meteo-mcp-server/open-meteo
