Server definition
- Hash
- sha256:cff1aa6f5c223ca2fb7ebb6ce8d5fb81b1e0c5d806bc8cc24bad0c1bb2c2243f
- What it is
- What a remote MCP server returned when asked what it offers: 11 tools
The blob, as servednamed by its sha256
{
"instructions": "Open-Meteo global weather server — keyless, no API key required for non-commercial use.\nWeather data by Open-Meteo.com (CC BY 4.0).\n\nWorkflow:\n1. openmeteo_search_locations — resolve a place name to coordinates (required first step for name-based queries)\n2. openmeteo_get_forecast — up to 16 days ahead + 92 days past_days; current_variables for conditions right now, and/or hourly and daily variables. A wide window spills like the historical tool\n3. openmeteo_get_historical — archive from 1940; use start_date/end_date. Omitting models reads Open-Meteo Best Match (IFS HRES + ERA5 + ERA5-Land); set models to pin one source\n4. openmeteo_get_marine — wave/swell for coastal and ocean points; up to 8 forecast days, past_days, or a start_date+end_date archive range back to at least 2022\n5. openmeteo_get_air_quality — CAMS modeled PM2.5, PM10, ozone, AQI; current_variables for values right now, up to 7 forecast days, past_days, or a start_date+end_date archive range; the CAMS global archive begins in August 2022\n6. openmeteo_get_elevation — Copernicus DEM terrain elevation for up to 100 coordinate pairs\n7. openmeteo_get_ensemble — probabilistic ensemble forecast (up to 64 members, 16 days); use for exceedance probabilities and uncertainty quantification. A regional model queried outside its coverage area fails as an input error naming the gap — switch to a global model, do not retry\n8. openmeteo_get_flood — GloFAS river discharge forecast (up to 210 days) OR reanalysis (from 1984, start_date+end_date together); the two modes are mutually exclusive. Coordinate-based — discharge comes from the largest modeled river within 5 km of the point, not necessarily the closest; vary the coordinate by ~0.1° and compare when a result looks unrepresentative\n9. openmeteo_get_climate — bias-corrected daily CMIP6 climate projections (1950–2050, up to 7 models); use for multi-decade \"what will conditions look like\" questions\n\nDataCanvas workflow (requires CANVAS_PROVIDER_TYPE=duckdb):\n- openmeteo_get_forecast, openmeteo_get_historical, openmeteo_get_marine, openmeteo_get_air_quality, openmeteo_get_ensemble, openmeteo_get_flood, or openmeteo_get_climate with a large query returns canvas_id + truncated: true\n- openmeteo_dataframe_describe — list tables and columns on the canvas. Call it first: the staged table name is generated and its columns vary per request (per-member and per-model suffixes), so there is no valid SQL to write until the schema is read\n- openmeteo_dataframe_query — run SQL SELECT against staged tables\n\nNotes:\n- All weather tools take latitude/longitude — use openmeteo_search_locations first for place names\n- The archive default is the Best Match blend, so its provenance varies by date; its ERA5 components lag ~1–5 days while IFS HRES does not. For recent history, use openmeteo_get_forecast with past_days, or request models: [\"ecmwf_ifs\"] on openmeteo_get_historical\n- current_variables on openmeteo_get_forecast and openmeteo_get_air_quality answers \"right now\" — a current object plus current_units, and no hourly series needed. The block's interval field reports the update cadence in seconds: 900 on the forecast endpoint, 3600 on air quality\n- All responses use timezone=auto by default (localizes to the location)\n- Variable names are exact API names: temperature_2m, pm2_5, wave_height, river_discharge, etc.\n- hourly_variables and daily_variables take separate variable sets — cloud_cover is hourly, temperature_2m_max is daily. A variable passed in the wrong field is rejected before the request, naming the value and the field it belongs in\n- Large forecast/historical/marine/air-quality/ensemble/flood/climate queries spill to DataCanvas when CANVAS_PROVIDER_TYPE=duckdb; with it unset they return a bounded preview and truncated: true, so narrow the request or enable canvas to reach the rest. A two-cadence preview carries both hourly and daily rows in either configuration — neither is dropped for the other, and the two share one inline budget\n- The models value on openmeteo_get_ensemble, openmeteo_get_climate, and openmeteo_get_historical is not validated locally: a name the tool does not advertise still goes upstream, so a model Open-Meteo adds later works without a server update. When upstream rejects a multi-model climate request it names only the offending model — correct that one and leave the rest",
"tools": [
{
"description": "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.",
"inputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"properties": {
"canvas_id": {
"description": "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 truncated: true.",
"pattern": "^[A-Za-z0-9_-]{10}$",
"type": "string"
}
},
"required": [
"canvas_id"
],
"type": "object"
},
"name": "openmeteo_dataframe_describe",
"outputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"canvas_id",
"tables",
"expires_at"
]
},
{
"required": [
"error"
]
}
],
"properties": {
"canvas_id": {
"description": "Canvas ID that was inspected.",
"type": "string"
},
"error": {
"additionalProperties": {},
"description": "Present when the call failed. Absent on success.",
"properties": {
"code": {
"description": "JSON-RPC error code for this failure.",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"type": "integer"
},
"data": {
"additionalProperties": {},
"properties": {
"reason": {
"description": "Machine-readable failure mode. Declared by this tool: `canvas_not_enabled`: CANVAS_PROVIDER_TYPE is not set to duckdb. `canvas_not_found`: The canvas_id is unknown or has expired (TTL is 24 h sliding). Other values are possible when a failure originates below the handler.",
"examples": [
"canvas_not_enabled",
"canvas_not_found"
],
"type": "string"
},
"recovery": {
"additionalProperties": {},
"description": "Actionable next step for the caller.",
"properties": {
"hint": {
"type": "string"
}
},
"required": [
"hint"
],
"type": "object"
},
"retryable": {
"description": "Whether retrying may succeed.",
"type": "boolean"
}
},
"type": "object"
},
"message": {
"description": "Human-readable description of what went wrong.",
"type": "string"
}
},
"required": [
"code",
"message"
],
"type": "object"
},
"expires_at": {
"description": "ISO 8601 expiry after the sliding 24 h TTL.",
"type": "string"
},
"tables": {
"description": "Tables and views registered on this canvas.",
"items": {
"additionalProperties": false,
"description": "A table or view on the canvas: name, kind, row count, and column schema.",
"properties": {
"columns": {
"description": "Column schema.",
"items": {
"additionalProperties": false,
"description": "A column: name, DuckDB type, and nullability.",
"properties": {
"name": {
"description": "Column name.",
"type": "string"
},
"nullable": {
"description": "Whether the column allows NULL.",
"type": "boolean"
},
"type": {
"description": "DuckDB type (e.g. VARCHAR, DOUBLE, TIMESTAMP).",
"type": "string"
}
},
"required": [
"name",
"type",
"nullable"
],
"type": "object"
},
"type": "array"
},
"kind": {
"description": "Whether this is a base table or a view.",
"enum": [
"table",
"view"
],
"type": "string"
},
"name": {
"description": "Table name — pass to openmeteo_dataframe_query.",
"type": "string"
},
"row_count": {
"description": "Number of rows.",
"type": "number"
}
},
"required": [
"name",
"kind",
"row_count",
"columns"
],
"type": "object"
},
"type": "array"
}
},
"type": "object"
}
},
{
"description": "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.",
"inputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"properties": {
"canvas_id": {
"description": "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 truncated: true.",
"pattern": "^[A-Za-z0-9_-]{10}$",
"type": "string"
},
"sql": {
"description": "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 month ORDER BY month",
"type": "string"
}
},
"required": [
"canvas_id",
"sql"
],
"type": "object"
},
"name": "openmeteo_dataframe_query",
"outputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"rows",
"row_count",
"canvas_id"
]
},
{
"required": [
"error"
]
}
],
"properties": {
"canvas_id": {
"description": "Canvas ID that was queried.",
"type": "string"
},
"error": {
"additionalProperties": {},
"description": "Present when the call failed. Absent on success.",
"properties": {
"code": {
"description": "JSON-RPC error code for this failure.",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"type": "integer"
},
"data": {
"additionalProperties": {},
"properties": {
"reason": {
"description": "Machine-readable failure mode. Declared by this tool: `canvas_not_enabled`: CANVAS_PROVIDER_TYPE is not set to duckdb. `canvas_not_found`: The canvas_id is unknown or has expired (TTL is 24 h sliding). `system_catalog_access`: The SQL references a system catalog (information_schema, sqlite_master, pg_catalog, or a duckdb_*() function). `missing_table`: The SQL references a table that is not staged on this canvas — a mistyped name, or one that expired (24 h sliding TTL) or was dropped. Other values are possible when a failure originates below the handler.",
"examples": [
"canvas_not_enabled",
"canvas_not_found",
"system_catalog_access",
"missing_table"
],
"type": "string"
},
"recovery": {
"additionalProperties": {},
"description": "Actionable next step for the caller.",
"properties": {
"hint": {
"type": "string"
}
},
"required": [
"hint"
],
"type": "object"
},
"retryable": {
"description": "Whether retrying may succeed.",
"type": "boolean"
}
},
"type": "object"
},
"message": {
"description": "Human-readable description of what went wrong.",
"type": "string"
}
},
"required": [
"code",
"message"
],
"type": "object"
},
"row_count": {
"description": "Total rows in the full result before any cap.",
"type": "number"
},
"rows": {
"description": "Result rows — a preview capped at 100. When row_count exceeds this, page the rest by re-issuing the SQL with LIMIT / OFFSET.",
"items": {
"additionalProperties": {},
"propertyNames": {
"type": "string"
},
"type": "object"
},
"type": "array"
}
},
"type": "object"
}
},
{
"description": "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; the CAMS global archive begins in August 2022, and earlier dates return rows of nulls. 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. Set current_variables for pollutant and AQI values at this instant — returned as a current object plus a current_units map, and enough on its own without hourly_variables; the block’s interval field reports how often that value updates (3600 seconds on this endpoint). A wide window — a large past_days or date range plus many variables — produces thousands of records; these spill to a DataCanvas when canvas is enabled, returning canvas_id and table_name with truncated: true — inspect the staged columns with openmeteo_dataframe_describe, then query the full set with openmeteo_dataframe_query. With canvas disabled they return a bounded preview instead.",
"inputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"properties": {
"canvas_id": {
"description": "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 any row count — it spills to this canvas: pass the returned token to openmeteo_dataframe_describe to list the staged table and its columns, then to openmeteo_dataframe_query to run SQL against it. Omit to create a fresh canvas.",
"pattern": "^[A-Za-z0-9_-]{10}$",
"type": "string"
},
"current_variables": {
"description": "Air quality variables to return for the current instant (e.g., [\"pm2_5\", \"pm10\", \"european_aqi\", \"us_aqi\"]). Uses Open-Meteo's current-conditions data, so it answers \"what is the AQI now?\" without requesting an hourly series and picking a row; the returned interval reports the update cadence, 3600 seconds on this endpoint. Satisfies the variable requirement on its own.",
"items": {
"type": "string"
},
"maxItems": 50,
"type": "array"
},
"end_date": {
"description": "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.",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"type": "string"
},
"forecast_days": {
"description": "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.",
"maximum": 7,
"minimum": 1,
"type": "integer"
},
"hourly_variables": {
"description": "Hourly air quality variables (e.g., [\"pm2_5\", \"pm10\", \"ozone\", \"nitrogen_dioxide\", \"european_aqi\", \"us_aqi\"]). At least one of current_variables or hourly_variables is required.",
"items": {
"type": "string"
},
"maxItems": 50,
"type": "array"
},
"latitude": {
"description": "Latitude in decimal degrees. Use openmeteo_search_locations to resolve a place name.",
"maximum": 90,
"minimum": -90,
"type": "number"
},
"longitude": {
"description": "Longitude in decimal degrees.",
"maximum": 180,
"minimum": -180,
"type": "number"
},
"past_days": {
"default": 0,
"description": "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.",
"maximum": 92,
"minimum": 0,
"type": "integer"
},
"start_date": {
"description": "Start date for the archive range (YYYY-MM-DD, e.g., \"2024-07-01\"). The CAMS global archive begins in August 2022; earlier dates return rows of nulls, and us_aqi starts a day later than the pollutant series (european_aqi starts with it). Requires end_date — the pair must be sent together, and neither combines with forecast_days or past_days.",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"type": "string"
},
"timezone": {
"default": "auto",
"description": "IANA timezone or \"auto\". Default \"auto\".",
"type": "string"
}
},
"required": [
"latitude",
"longitude"
],
"type": "object"
},
"name": "openmeteo_get_air_quality",
"outputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"latitude",
"longitude",
"timezone",
"record_count",
"data_source",
"truncated"
]
},
{
"required": [
"error"
]
}
],
"properties": {
"canvas_id": {
"description": "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 response carries. Pass to openmeteo_dataframe_describe to list the staged table and its columns, then to openmeteo_dataframe_query to run SQL against it.",
"type": "string"
},
"current": {
"additionalProperties": {
"type": [
"string",
"number",
"null"
]
},
"description": "Pollutant and index values at a single instant: one key per requested current variable alongside time and interval. Units are in the current_units map. Absent when current_variables was not requested.",
"properties": {
"interval": {
"description": "Update cadence of the current-conditions data, in seconds (3600 = hourly on this endpoint) — metadata, not a requested variable",
"type": "number"
},
"time": {
"description": "Timestamp of these values (ISO 8601, in the resolved timezone)",
"type": "string"
}
},
"required": [
"time",
"interval"
],
"type": "object"
},
"current_units": {
"additionalProperties": {
"type": "string"
},
"description": "Key → unit string for the current block, covering time and interval as well as each requested variable (e.g., {\"interval\": \"seconds\", \"pm2_5\": \"μg/m³\"}). Absent when no current_variables were requested.",
"propertyNames": {
"type": "string"
},
"type": "object"
},
"data_source": {
"const": "CAMS",
"description": "Data source identifier — this is modeled CAMS data, forecast or archive, not measured station data.",
"type": "string"
},
"error": {
"additionalProperties": {},
"description": "Present when the call failed. Absent on success.",
"properties": {
"code": {
"description": "JSON-RPC error code for this failure.",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"type": "integer"
},
"data": {
"additionalProperties": {},
"properties": {
"reason": {
"description": "Machine-readable failure mode. Declared by this tool: `invalid_variable`: An unknown air quality variable name was requested. `no_variables_requested`: Neither current_variables nor hourly_variables was provided. `date_range_incomplete`: Only one of start_date / end_date was provided — the CAMS archive requires the pair together. `forecast_window_conflict`: forecast_days or a non-zero past_days was combined with start_date or end_date. `date_order_invalid`: end_date is before start_date. `invalid_timezone`: timezone was blank, or upstream did not recognize the requested time zone. `request_too_large`: Open-Meteo refused the request as asking for too much data in one call. Other values are possible when a failure originates below the handler.",
"examples": [
"invalid_variable",
"no_variables_requested",
"date_range_incomplete",
"forecast_window_conflict",
"date_order_invalid",
"invalid_timezone",
"request_too_large"
],
"type": "string"
},
"recovery": {
"additionalProperties": {},
"description": "Actionable next step for the caller.",
"properties": {
"hint": {
"type": "string"
}
},
"required": [
"hint"
],
"type": "object"
},
"retryable": {
"description": "Whether retrying may succeed.",
"type": "boolean"
}
},
"type": "object"
},
"message": {
"description": "Human-readable description of what went wrong.",
"type": "string"
}
},
"required": [
"code",
"message"
],
"type": "object"
},
"hourly": {
"description": "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_aqi as index values. When truncated, contains only a preview — query canvas_id for the full dataset when one is present.",
"items": {
"additionalProperties": {},
"propertyNames": {
"type": "string"
},
"type": "object"
},
"type": "array"
},
"hourly_units": {
"additionalProperties": {
"type": "string"
},
"description": "Variable → unit string for hourly data (e.g., {\"pm2_5\": \"μg/m³\", \"european_aqi\": \"EAQI\"}).",
"propertyNames": {
"type": "string"
},
"type": "object"
},
"latitude": {
"description": "Snapped latitude",
"type": "number"
},
"longitude": {
"description": "Snapped longitude",
"type": "number"
},
"notice": {
"description": "Everything this response needs to say beyond the data, composed into one advisory: columns the endpoint returned with the unit \"undefined\" (a name it parsed but does not serve); recognized variables whose requested window falls outside the CAMS archive, with the timestamps that do carry values; and, when the result spilled, either the canvas and table holding the full row set plus the two dataframe tools that read it, or — with DataCanvas disabled — why there is no canvas_id and how to reach the rows the preview omits.",
"type": "string"
},
"record_count": {
"description": "Total number of hourly records — the full upstream total when truncated is true, not the length of the hourly preview.",
"type": "number"
},
"table_name": {
"description": "DuckDB table name for the staged data — use as the FROM target in openmeteo_dataframe_query SQL; openmeteo_dataframe_describe lists its columns. Present only alongside canvas_id.",
"type": "string"
},
"timezone": {
"description": "Resolved IANA timezone",
"type": "string"
},
"truncated": {
"description": "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 there is no canvas_id, and the omitted rows are reached only by narrowing the request.",
"type": "boolean"
}
},
"type": "object"
}
},
{
"description": "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 (the observed archive, 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 a DataCanvas when canvas is enabled, returning canvas_id and table_name with truncated: true — inspect the staged columns with openmeteo_dataframe_describe, then query the full set with openmeteo_dataframe_query. With canvas disabled they return a bounded preview instead.",
"inputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"properties": {
"canvas_id": {
"description": "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 to this canvas: pass the returned token to openmeteo_dataframe_describe to list the staged table and its per-model columns, then to openmeteo_dataframe_query to run SQL against it. Omit to create a fresh canvas.",
"pattern": "^[A-Za-z0-9_-]{10}$",
"type": "string"
},
"daily_variables": {
"description": "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.",
"items": {
"type": "string"
},
"maxItems": 50,
"type": "array"
},
"end_date": {
"description": "End date (YYYY-MM-DD, inclusive, max 2050-12-31). Must be on or after start_date.",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"type": "string"
},
"latitude": {
"description": "Latitude in decimal degrees. Use openmeteo_search_locations to resolve a place name to coordinates.",
"maximum": 90,
"minimum": -90,
"type": "number"
},
"longitude": {
"description": "Longitude in decimal degrees.",
"maximum": 180,
"minimum": -180,
"type": "number"
},
"models": {
"description": "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. temperature_2m_max_MRI_AGCM3_2_S). Omit to use the API default (a single model, unsuffixed columns). A name outside this list is sent upstream rather than rejected here.",
"items": {
"type": "string"
},
"maxItems": 7,
"type": "array"
},
"precipitation_unit": {
"default": "mm",
"description": "Precipitation unit. Default \"mm\".",
"enum": [
"mm",
"inch"
],
"type": "string"
},
"start_date": {
"description": "Start date (YYYY-MM-DD, e.g., \"2049-01-01\"). CMIP6 projections cover 1950-01-01 to 2050-12-31.",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"type": "string"
},
"temperature_unit": {
"default": "celsius",
"description": "Temperature unit. Default \"celsius\".",
"enum": [
"celsius",
"fahrenheit"
],
"type": "string"
},
"timezone": {
"default": "auto",
"description": "IANA timezone or \"auto\". Default \"auto\".",
"type": "string"
},
"wind_speed_unit": {
"default": "kmh",
"description": "Wind speed unit. Default \"kmh\".",
"enum": [
"kmh",
"mph",
"ms",
"kn"
],
"type": "string"
}
},
"required": [
"latitude",
"longitude",
"start_date",
"end_date"
],
"type": "object"
},
"name": "openmeteo_get_climate",
"outputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"latitude",
"longitude",
"elevation",
"timezone",
"date_range",
"record_count",
"daily",
"truncated"
]
},
{
"required": [
"error"
]
}
],
"properties": {
"canvas_id": {
"description": "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 response carries. Pass to openmeteo_dataframe_describe to list the staged table and its per-model columns, then to openmeteo_dataframe_query to run SQL against it.",
"type": "string"
},
"daily": {
"description": "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 does not carry that variable. When truncated, contains only a preview — query canvas_id for the full dataset when one is present.",
"items": {
"additionalProperties": {},
"propertyNames": {
"type": "string"
},
"type": "object"
},
"type": "array"
},
"daily_units": {
"additionalProperties": {
"type": "string"
},
"description": "Column → unit string for daily data (e.g., {\"temperature_2m_max_CMCC_CM2_VHR4\": \"°C\"}).",
"propertyNames": {
"type": "string"
},
"type": "object"
},
"date_range": {
"additionalProperties": false,
"description": "Date range of returned data",
"properties": {
"end": {
"description": "Actual end date of returned data",
"type": "string"
},
"start": {
"description": "Actual start date of returned data",
"type": "string"
}
},
"required": [
"start",
"end"
],
"type": "object"
},
"elevation": {
"description": "Elevation at grid point (meters)",
"type": "number"
},
"error": {
"additionalProperties": {},
"description": "Present when the call failed. Absent on success.",
"properties": {
"code": {
"description": "JSON-RPC error code for this failure.",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"type": "integer"
},
"data": {
"additionalProperties": {},
"properties": {
"reason": {
"description": "Machine-readable failure mode. Declared by this tool: `date_out_of_range`: start_date predates 1950-01-01 or end_date is after 2050-12-31. `date_order_invalid`: end_date is before start_date. `no_variables_requested`: daily_variables was not provided or is empty. `invalid_variable`: An unknown variable name or unsupported climate model was requested. `invalid_timezone`: timezone was blank, or upstream did not recognize the requested time zone. `request_too_large`: Open-Meteo refused the request as asking for too much data in one call. Other values are possible when a failure originates below the handler.",
"examples": [
"date_out_of_range",
"date_order_invalid",
"no_variables_requested",
"invalid_variable",
"invalid_timezone",
"request_too_large"
],
"type": "string"
},
"recovery": {
"additionalProperties": {},
"description": "Actionable next step for the caller.",
"properties": {
"hint": {
"type": "string"
}
},
"required": [
"hint"
],
"type": "object"
},
"retryable": {
"description": "Whether retrying may succeed.",
"type": "boolean"
}
},
"type": "object"
},
"message": {
"description": "Human-readable description of what went wrong.",
"type": "string"
}
},
"required": [
"code",
"message"
],
"type": "object"
},
"latitude": {
"description": "Snapped latitude (Open-Meteo snaps to nearest grid point)",
"type": "number"
},
"longitude": {
"description": "Snapped longitude",
"type": "number"
},
"models": {
"description": "Climate models requested — echoes the models parameter. Absent when models was omitted (API default model; the response carries no provenance).",
"items": {
"type": "string"
},
"type": "array"
},
"notice": {
"description": "Everything this response needs to say beyond the data, composed into one advisory: columns the endpoint returned with the unit \"undefined\" (a name it parsed but does not serve); recognized variables a selected model carries no values for, with the dates that do carry values; and, when the result spilled, either the canvas and table holding the full row set plus the two dataframe tools that read it, or — with DataCanvas disabled — why there is no canvas_id and how to reach the rows the preview omits.",
"type": "string"
},
"record_count": {
"description": "Total number of daily records — the full upstream total when truncated is true, not the length of the daily preview.",
"type": "number"
},
"table_name": {
"description": "DuckDB table name for the staged data — use as the FROM target in openmeteo_dataframe_query SQL; openmeteo_dataframe_describe lists its columns, which is the only way to learn the per-model suffixes this request produced. Present only alongside canvas_id.",
"type": "string"
},
"timezone": {
"description": "Resolved IANA timezone",
"type": "string"
},
"truncated": {
"description": "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 there is no canvas_id, and the omitted rows are reached only by narrowing the request.",
"type": "boolean"
}
},
"type": "object"
}
},
{
"description": "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.",
"inputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"properties": {
"latitudes": {
"description": "Array of latitudes in decimal degrees (up to 100). Must be same length as longitudes.",
"items": {
"maximum": 90,
"minimum": -90,
"type": "number"
},
"maxItems": 100,
"minItems": 1,
"type": "array"
},
"longitudes": {
"description": "Array of longitudes in decimal degrees (up to 100). Must be same length as latitudes.",
"items": {
"maximum": 180,
"minimum": -180,
"type": "number"
},
"maxItems": 100,
"minItems": 1,
"type": "array"
}
},
"required": [
"latitudes",
"longitudes"
],
"type": "object"
},
"name": "openmeteo_get_elevation",
"outputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"elevations"
]
},
{
"required": [
"error"
]
}
],
"properties": {
"elevations": {
"description": "Elevation values in input order",
"items": {
"additionalProperties": false,
"description": "Elevation for a single coordinate pair",
"properties": {
"elevation_m": {
"description": "Terrain elevation in meters above sea level",
"type": "number"
},
"latitude": {
"description": "Input latitude",
"type": "number"
},
"longitude": {
"description": "Input longitude",
"type": "number"
}
},
"required": [
"latitude",
"longitude",
"elevation_m"
],
"type": "object"
},
"type": "array"
},
"error": {
"additionalProperties": {},
"description": "Present when the call failed. Absent on success.",
"properties": {
"code": {
"description": "JSON-RPC error code for this failure.",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"type": "integer"
},
"data": {
"additionalProperties": {},
"properties": {
"reason": {
"description": "Machine-readable failure mode. Declared by this tool: `coordinate_count_mismatch`: latitudes and longitudes arrays have different lengths. Other values are possible when a failure originates below the handler.",
"examples": [
"coordinate_count_mismatch"
],
"type": "string"
},
"recovery": {
"additionalProperties": {},
"description": "Actionable next step for the caller.",
"properties": {
"hint": {
"type": "string"
}
},
"required": [
"hint"
],
"type": "object"
},
"retryable": {
"description": "Whether retrying may succeed.",
"type": "boolean"
}
},
"type": "object"
},
"message": {
"description": "Human-readable description of what went wrong.",
"type": "string"
}
},
"required": [
"code",
"message"
],
"type": "object"
}
},
"type": "object"
}
},
{
"description": "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 a DataCanvas when canvas is enabled, returning canvas_id and table_name with truncated: true — inspect the staged columns with openmeteo_dataframe_describe, then query the full set with openmeteo_dataframe_query. With canvas disabled they return a bounded preview instead. At least one of hourly_variables or daily_variables is required.",
"inputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"properties": {
"canvas_id": {
"description": "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 canvas: pass the returned token to openmeteo_dataframe_describe to list the staged table and its per-member columns, then to openmeteo_dataframe_query to run SQL against it. Omit to create a fresh canvas.",
"pattern": "^[A-Za-z0-9_-]{10}$",
"type": "string"
},
"daily_variables": {
"description": "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 only — an hourly name such as precipitation or temperature_2m belongs in hourly_variables and is rejected here; for a daily summary use its published aggregate (precipitation_sum, temperature_2m_max). At least one of hourly_variables or daily_variables required.",
"items": {
"type": "string"
},
"maxItems": 50,
"type": "array"
},
"forecast_days": {
"default": 7,
"description": "Forecast horizon in days (1–16). Default 7.",
"maximum": 16,
"minimum": 1,
"type": "integer"
},
"hourly_variables": {
"description": "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 the output. Hourly names only — a daily-only aggregate such as precipitation_sum or wind_speed_10m_max belongs in daily_variables and is rejected here; temperature_2m_max and temperature_2m_min are an exception, published here as 3-hourly aggregations as well as daily. At least one of hourly_variables or daily_variables required.",
"items": {
"type": "string"
},
"maxItems": 50,
"type": "array"
},
"latitude": {
"description": "Latitude in decimal degrees. Use openmeteo_search_locations to resolve a place name to coordinates.",
"maximum": 90,
"minimum": -90,
"type": "number"
},
"longitude": {
"description": "Longitude in decimal degrees.",
"maximum": 180,
"minimum": -180,
"type": "number"
},
"models": {
"description": "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 (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). Member counts include the control run. Omit to use the API default blend. A name outside this list is sent upstream rather than rejected here, so a model Open-Meteo adds later still works.",
"type": "string"
},
"past_days": {
"default": 0,
"description": "Include this many days of past ensemble data before today (0–92). Default 0.",
"maximum": 92,
"minimum": 0,
"type": "integer"
},
"precipitation_unit": {
"default": "mm",
"description": "Precipitation unit. Default \"mm\".",
"enum": [
"mm",
"inch"
],
"type": "string"
},
"temperature_unit": {
"default": "celsius",
"description": "Temperature unit. Default \"celsius\".",
"enum": [
"celsius",
"fahrenheit"
],
"type": "string"
},
"timezone": {
"default": "auto",
"description": "IANA timezone (e.g., \"America/Los_Angeles\") or \"auto\" to use the location's local timezone. Default \"auto\".",
"type": "string"
},
"wind_speed_unit": {
"default": "kmh",
"description": "Wind speed unit. Default \"kmh\".",
"enum": [
"kmh",
"mph",
"ms",
"kn"
],
"type": "string"
}
},
"required": [
"latitude",
"longitude"
],
"type": "object"
},
"name": "openmeteo_get_ensemble",
"outputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"latitude",
"longitude",
"elevation",
"timezone",
"record_count",
"truncated"
]
},
{
"required": [
"error"
]
}
],
"properties": {
"canvas_id": {
"description": "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 response carries. Pass to openmeteo_dataframe_describe to list the staged table and its per-member columns, then to openmeteo_dataframe_query to run SQL against it.",
"type": "string"
},
"daily": {
"description": "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 canvas_id for the full dataset when one is present.",
"items": {
"additionalProperties": {},
"propertyNames": {
"type": "string"
},
"type": "object"
},
"type": "array"
},
"daily_units": {
"additionalProperties": {
"type": "string"
},
"description": "Variable → unit string for daily data. Absent when no daily_variables were requested.",
"propertyNames": {
"type": "string"
},
"type": "object"
},
"elevation": {
"description": "Terrain elevation at grid point (meters)",
"type": "number"
},
"error": {
"additionalProperties": {},
"description": "Present when the call failed. Absent on success.",
"properties": {
"code": {
"description": "JSON-RPC error code for this failure.",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"type": "integer"
},
"data": {
"additionalProperties": {},
"properties": {
"reason": {
"description": "Machine-readable failure mode. Declared by this tool: `no_variables_requested`: Neither hourly_variables nor daily_variables was provided. `invalid_variable`: An unknown variable name or unsupported model was requested. `variable_wrong_cadence`: A variable the ensemble API documents under one cadence was passed in the other cadence field — for example precipitation_sum in hourly_variables, or precipitation in daily_variables. `invalid_timezone`: timezone was blank, or upstream did not recognize the requested time zone. `request_too_large`: Open-Meteo refused the request as asking for too much data in one call. Other values are possible when a failure originates below the handler.",
"examples": [
"no_variables_requested",
"invalid_variable",
"variable_wrong_cadence",
"invalid_timezone",
"request_too_large"
],
"type": "string"
},
"recovery": {
"additionalProperties": {},
"description": "Actionable next step for the caller.",
"properties": {
"hint": {
"type": "string"
}
},
"required": [
"hint"
],
"type": "object"
},
"retryable": {
"description": "Whether retrying may succeed.",
"type": "boolean"
}
},
"type": "object"
},
"message": {
"description": "Human-readable description of what went wrong.",
"type": "string"
}
},
"required": [
"code",
"message"
],
"type": "object"
},
"hourly": {
"description": "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. When truncated, contains a preview only — query canvas_id for the full dataset when one is present.",
"items": {
"additionalProperties": {},
"propertyNames": {
"type": "string"
},
"type": "object"
},
"type": "array"
},
"hourly_units": {
"additionalProperties": {
"type": "string"
},
"description": "Variable → unit string for hourly data (e.g., {\"temperature_2m_member01\": \"°C\"}). Absent when no hourly_variables were requested.",
"propertyNames": {
"type": "string"
},
"type": "object"
},
"latitude": {
"description": "Snapped latitude (Open-Meteo snaps to nearest grid point)",
"type": "number"
},
"longitude": {
"description": "Snapped longitude",
"type": "number"
},
"member_count": {
"description": "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.",
"type": "number"
},
"model": {
"description": "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).",
"type": "string"
},
"notice": {
"description": "Everything this response needs to say beyond the data, composed into one advisory: variables the endpoint returned with the unit \"undefined\" across every member (a name the selected model does not carry); recognized variables whose requested window runs past the model's horizon, with the timestamps that do carry values; and, when the result spilled, either the canvas and table holding the full row set plus the two dataframe tools that read it, or — with DataCanvas disabled — why there is no canvas_id and how to reach the rows the preview omits.",
"type": "string"
},
"record_count": {
"description": "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.",
"type": "number"
},
"table_name": {
"description": "DuckDB table name for the staged data — use as the FROM target in openmeteo_dataframe_query SQL; openmeteo_dataframe_describe lists its columns, which is the only way to learn the per-member suffixes this request produced. Present only alongside canvas_id.",
"type": "string"
},
"timezone": {
"description": "Resolved IANA timezone",
"type": "string"
},
"truncated": {
"description": "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 hourly and daily row, including any column the preview omits. With it disabled there is no canvas_id, and the omitted rows are reached only by narrowing the request.",
"type": "boolean"
}
},
"type": "object"
}
},
{
"description": "GloFAS (Global Flood Awareness System) river discharge forecast and historical reanalysis. Returns daily ensemble river discharge (m³/s) for the largest modeled river within 5 km of the given coordinates — no river ID needed. That river is not always the closest one: at 5 km resolution a point near a confluence or a pair of parallel channels can resolve to an unintended reach. When the returned discharge looks unrepresentative for the intended river, Open-Meteo suggests varying the coordinate by about 0.1° and comparing the values. 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 a DataCanvas when canvas is enabled, returning canvas_id and table_name with truncated: true — inspect the staged columns with openmeteo_dataframe_describe, then query the full set with openmeteo_dataframe_query. With canvas disabled it returns a bounded preview instead.",
"inputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"properties": {
"canvas_id": {
"description": "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 canvas: pass the returned token to openmeteo_dataframe_describe to list the staged table and its columns, then to openmeteo_dataframe_query to run SQL against it. Omit to create a fresh canvas.",
"pattern": "^[A-Za-z0-9_-]{10}$",
"type": "string"
},
"daily_variables": {
"description": "Daily discharge variables to fetch (e.g., [\"river_discharge\", \"river_discharge_p25\", \"river_discharge_p75\", \"river_discharge_min\", \"river_discharge_max\"]). Required.",
"items": {
"type": "string"
},
"maxItems": 20,
"type": "array"
},
"end_date": {
"description": "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.",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"type": "string"
},
"forecast_days": {
"description": "Number of forecast days ahead (1–210). Mutually exclusive with start_date/end_date — omit it entirely when pulling a historical range.",
"maximum": 210,
"minimum": 1,
"type": "integer"
},
"latitude": {
"description": "Latitude in decimal degrees. Discharge is returned for the largest modeled river within 5 km of this point — no river ID required, and not necessarily the closest river. Vary the coordinate by about 0.1° and compare when the result looks unrepresentative. Use openmeteo_search_locations to resolve a place name.",
"maximum": 90,
"minimum": -90,
"type": "number"
},
"longitude": {
"description": "Longitude in decimal degrees. With latitude it selects the largest modeled river within 5 km, which is not necessarily the closest one.",
"maximum": 180,
"minimum": -180,
"type": "number"
},
"start_date": {
"description": "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_days.",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"type": "string"
},
"timezone": {
"default": "auto",
"description": "IANA timezone or \"auto\". Default \"auto\".",
"type": "string"
}
},
"required": [
"latitude",
"longitude"
],
"type": "object"
},
"name": "openmeteo_get_flood",
"outputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"latitude",
"longitude",
"timezone",
"record_count",
"daily",
"truncated"
]
},
{
"required": [
"error"
]
}
],
"properties": {
"canvas_id": {
"description": "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 response carries. Pass to openmeteo_dataframe_describe to list the staged table and its columns, then to openmeteo_dataframe_query to run SQL against it.",
"type": "string"
},
"daily": {
"description": "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 — query canvas_id for the full dataset when one is present.",
"items": {
"additionalProperties": {},
"propertyNames": {
"type": "string"
},
"type": "object"
},
"type": "array"
},
"daily_units": {
"additionalProperties": {
"type": "string"
},
"description": "Variable → unit string for daily data (e.g., {\"river_discharge\": \"m³/s\"}).",
"propertyNames": {
"type": "string"
},
"type": "object"
},
"error": {
"additionalProperties": {},
"description": "Present when the call failed. Absent on success.",
"properties": {
"code": {
"description": "JSON-RPC error code for this failure.",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"type": "integer"
},
"data": {
"additionalProperties": {},
"properties": {
"reason": {
"description": "Machine-readable failure mode. Declared by this tool: `no_variables_requested`: daily_variables was not provided or is empty. `date_range_incomplete`: Only one of start_date / end_date was provided — GloFAS requires the pair together. `forecast_days_conflict`: forecast_days was combined with start_date or end_date. `date_order_invalid`: end_date is before start_date. `date_out_of_range`: start_date predates 1984-01-01 or date range is otherwise invalid. `invalid_variable`: An unknown discharge variable name was requested. `invalid_timezone`: timezone was blank, or upstream did not recognize the requested time zone. `request_too_large`: Open-Meteo refused the request as asking for too much data in one call. Other values are possible when a failure originates below the handler.",
"examples": [
"no_variables_requested",
"date_range_incomplete",
"forecast_days_conflict",
"date_order_invalid",
"date_out_of_range",
"invalid_variable",
"invalid_timezone",
"request_too_large"
],
"type": "string"
},
"recovery": {
"additionalProperties": {},
"description": "Actionable next step for the caller.",
"properties": {
"hint": {
"type": "string"
}
},
"required": [
"hint"
],
"type": "object"
},
"retryable": {
"description": "Whether retrying may succeed.",
"type": "boolean"
}
},
"type": "object"
},
"message": {
"description": "Human-readable description of what went wrong.",
"type": "string"
}
},
"required": [
"code",
"message"
],
"type": "object"
},
"latitude": {
"description": "Snapped latitude — grid point of the selected river",
"type": "number"
},
"longitude": {
"description": "Snapped longitude — grid point of the selected river",
"type": "number"
},
"notice": {
"description": "Everything this response needs to say beyond the data, composed into one advisory: columns GloFAS returned with the unit \"undefined\" (a name it parsed but does not serve); recognized variables whose requested range falls outside the coordinate's discharge record, with the dates that do carry values; and, when the result spilled, either the canvas and table holding the full row set plus the two dataframe tools that read it, or — with DataCanvas disabled — why there is no canvas_id and how to reach the rows the preview omits.",
"type": "string"
},
"record_count": {
"description": "Total number of daily discharge records — the full staged count when truncated is true, not the length of the daily preview.",
"type": "number"
},
"table_name": {
"description": "DuckDB table name for the staged data — use as the FROM target in openmeteo_dataframe_query SQL; openmeteo_dataframe_describe lists its columns. Present only alongside canvas_id.",
"type": "string"
},
"timezone": {
"description": "Resolved IANA timezone",
"type": "string"
},
"truncated": {
"description": "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 there is no canvas_id, and the omitted rows are reached only by narrowing the request.",
"type": "boolean"
}
},
"type": "object"
}
},
{
"description": "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 the archive’s ERA5 components lag by up to ~5 days. 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. Set current_variables for conditions at this instant — Open-Meteo serves those from 15-minute model data, which is more precise than picking the nearest hourly row, and the response carries a current object plus a current_units map. A wide window — a large past_days plus many hourly variables — produces thousands of records; these spill to a DataCanvas when canvas is enabled, returning canvas_id and table_name with truncated: true — inspect the staged columns with openmeteo_dataframe_describe, then query the full set with openmeteo_dataframe_query. With canvas disabled they return a bounded preview instead. At least one of current_variables, hourly_variables, or daily_variables is required.",
"inputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"properties": {
"canvas_id": {
"description": "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 — it spills to this canvas: pass the returned token to openmeteo_dataframe_describe to list the staged table and its columns, then to openmeteo_dataframe_query to run SQL against it. Omit to create a fresh canvas.",
"pattern": "^[A-Za-z0-9_-]{10}$",
"type": "string"
},
"current_variables": {
"description": "Variables to return for the current instant (e.g., [\"temperature_2m\", \"precipitation\", \"wind_speed_10m\", \"weather_code\"]). Uses Open-Meteo's 15-minute current-conditions data, so it answers \"what is it doing right now?\" without requesting an hourly series and picking a row. Takes the hourly variable names; a daily-only name such as temperature_2m_max comes back null with the unit \"undefined\" and is reported in the notice. Satisfies the variable requirement on its own.",
"items": {
"type": "string"
},
"maxItems": 50,
"type": "array"
},
"daily_variables": {
"description": "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 cloud_cover or temperature_2m belongs in hourly_variables and is rejected here; for a daily summary of an hourly variable use its published aggregate (cloud_cover_max, cloud_cover_mean, cloud_cover_min). At least one of current_variables, hourly_variables, or daily_variables is required.",
"items": {
"type": "string"
},
"maxItems": 50,
"type": "array"
},
"forecast_days": {
"default": 7,
"description": "Number of forecast days (1–16). Default 7.",
"maximum": 16,
"minimum": 1,
"type": "integer"
},
"hourly_variables": {
"description": "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 aggregate such as temperature_2m_max or precipitation_sum belongs in daily_variables and is rejected here. At least one of current_variables, hourly_variables, or daily_variables is required.",
"items": {
"type": "string"
},
"maxItems": 50,
"type": "array"
},
"latitude": {
"description": "Latitude in decimal degrees (e.g., 47.6062 for Seattle). Use openmeteo_search_locations to resolve a place name to coordinates.",
"maximum": 90,
"minimum": -90,
"type": "number"
},
"longitude": {
"description": "Longitude in decimal degrees (e.g., -122.3321 for Seattle).",
"maximum": 180,
"minimum": -180,
"type": "number"
},
"past_days": {
"default": 0,
"description": "Include this many days of past data before today (0–92). Use for recent history — the archive’s ERA5 components lag by up to ~5 days. Default 0.",
"maximum": 92,
"minimum": 0,
"type": "integer"
},
"precipitation_unit": {
"default": "mm",
"description": "Precipitation unit: \"mm\" or \"inch\". Default \"mm\".",
"enum": [
"mm",
"inch"
],
"type": "string"
},
"temperature_unit": {
"default": "celsius",
"description": "Temperature unit. Default \"celsius\".",
"enum": [
"celsius",
"fahrenheit"
],
"type": "string"
},
"timezone": {
"default": "auto",
"description": "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.",
"type": "string"
},
"wind_speed_unit": {
"default": "kmh",
"description": "Wind speed unit: \"kmh\" (km/h), \"mph\", \"ms\" (m/s), or \"kn\" (knots). Default \"kmh\".",
"enum": [
"kmh",
"mph",
"ms",
"kn"
],
"type": "string"
}
},
"required": [
"latitude",
"longitude"
],
"type": "object"
},
"name": "openmeteo_get_forecast",
"outputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"latitude",
"longitude",
"elevation",
"timezone",
"utc_offset_seconds",
"record_count",
"truncated"
]
},
{
"required": [
"error"
]
}
],
"properties": {
"canvas_id": {
"description": "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 response carries. Pass to openmeteo_dataframe_describe to list the staged table and its columns, then to openmeteo_dataframe_query to run SQL against it.",
"type": "string"
},
"current": {
"additionalProperties": {
"type": [
"string",
"number",
"null"
]
},
"description": "Conditions at a single instant: one key per requested current variable alongside time and interval. Units are in the current_units map. Absent when current_variables was not requested.",
"properties": {
"interval": {
"description": "Update cadence of the current-conditions data, in seconds (900 = 15 minutes) — metadata, not a requested variable",
"type": "number"
},
"time": {
"description": "Timestamp of these values (ISO 8601, in the resolved timezone)",
"type": "string"
}
},
"required": [
"time",
"interval"
],
"type": "object"
},
"current_units": {
"additionalProperties": {
"type": "string"
},
"description": "Map of key → unit string for the current block, covering time and interval as well as each requested variable (e.g., {\"interval\": \"seconds\", \"temperature_2m\": \"°C\"}). Absent when no current_variables were requested.",
"propertyNames": {
"type": "string"
},
"type": "object"
},
"daily": {
"description": "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. When truncated, contains only a preview — query canvas_id for the full dataset when one is present.",
"items": {
"additionalProperties": {},
"propertyNames": {
"type": "string"
},
"type": "object"
},
"type": "array"
},
"daily_units": {
"additionalProperties": {
"type": "string"
},
"description": "Map of variable name → unit string for daily data. Absent when no daily_variables were requested.",
"propertyNames": {
"type": "string"
},
"type": "object"
},
"elevation": {
"description": "Terrain elevation at grid point (meters)",
"type": "number"
},
"error": {
"additionalProperties": {},
"description": "Present when the call failed. Absent on success.",
"properties": {
"code": {
"description": "JSON-RPC error code for this failure.",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"type": "integer"
},
"data": {
"additionalProperties": {},
"properties": {
"reason": {
"description": "Machine-readable failure mode. Declared by this tool: `invalid_variable`: An unknown variable name was requested. `variable_wrong_cadence`: A variable Open-Meteo documents under one cadence was passed in the other cadence field — for example cloud_cover in daily_variables, or temperature_2m_max in hourly_variables. `no_variables_requested`: None of current_variables, hourly_variables, or daily_variables was provided. `invalid_timezone`: timezone was blank, or upstream did not recognize the requested time zone. `request_too_large`: Open-Meteo refused the request as asking for too much data in one call. Other values are possible when a failure originates below the handler.",
"examples": [
"invalid_variable",
"variable_wrong_cadence",
"no_variables_requested",
"invalid_timezone",
"request_too_large"
],
"type": "string"
},
"recovery": {
"additionalProperties": {},
"description": "Actionable next step for the caller.",
"properties": {
"hint": {
"type": "string"
}
},
"required": [
"hint"
],
"type": "object"
},
"retryable": {
"description": "Whether retrying may succeed.",
"type": "boolean"
}
},
"type": "object"
},
"message": {
"description": "Human-readable description of what went wrong.",
"type": "string"
}
},
"required": [
"code",
"message"
],
"type": "object"
},
"hourly": {
"description": "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. When truncated, contains only a preview — query canvas_id for the full dataset when one is present.",
"items": {
"additionalProperties": {},
"propertyNames": {
"type": "string"
},
"type": "object"
},
"type": "array"
},
"hourly_units": {
"additionalProperties": {
"type": "string"
},
"description": "Map of variable name → unit string for hourly data (e.g., {\"temperature_2m\": \"°C\", \"precipitation\": \"mm\"}). Absent when no hourly_variables were requested.",
"propertyNames": {
"type": "string"
},
"type": "object"
},
"latitude": {
"description": "Snapped latitude (Open-Meteo snaps to nearest grid point)",
"type": "number"
},
"longitude": {
"description": "Snapped longitude",
"type": "number"
},
"notice": {
"description": "Everything this response needs to say beyond the data, composed into one advisory: columns the endpoint returned with the unit \"undefined\" (a name it parsed but does not serve in the requested cadence); recognized variables whose requested window falls outside the data's coverage, with the timestamps that do carry values; and, when the result spilled, either the canvas and table holding the full row set plus the two dataframe tools that read it, or — with DataCanvas disabled — why there is no canvas_id and how to reach the rows the preview omits.",
"type": "string"
},
"record_count": {
"description": "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.",
"type": "number"
},
"table_name": {
"description": "DuckDB table name for the staged data — use as the FROM target in openmeteo_dataframe_query SQL; openmeteo_dataframe_describe lists its columns. Present only alongside canvas_id.",
"type": "string"
},
"timezone": {
"description": "Resolved IANA timezone",
"type": "string"
},
"truncated": {
"description": "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 hourly and daily row, including any column the preview omits. With it disabled there is no canvas_id, and the omitted rows are reached only by narrowing the request.",
"type": "boolean"
},
"utc_offset_seconds": {
"description": "UTC offset in seconds for this timezone at query time",
"type": "number"
}
},
"type": "object"
}
},
{
"description": "Historical weather from the Open-Meteo reanalysis archive (1940–present). Requires start_date and end_date (ISO 8601 date, e.g., \"2024-07-01\"). With models omitted the archive answers from Best Match, which blends IFS HRES, ERA5, and ERA5-Land seamlessly — so the source varies by date and no single update lag describes the response. Set models to pin a consistent source for a multi-decade series: the ERA5 family updates daily with about a 5-day delay, while IFS HRES has none, so for the last few days either request models: [\"ecmwf_ifs\"] or use openmeteo_get_forecast with past_days. Available models: best_match (default, blends IFS HRES + ERA5 + ERA5-Land), ecmwf_ifs (global 9 km, updated every 6 hours, no delay), ecmwf_ifs_analysis_long_window (global 9 km, daily, 2 days delay), era5_seamless (ERA5 and ERA5-Land combined), era5 (global 0.25° (~25 km), daily, 5 days delay), era5_land (global 0.1° (~11 km), daily, 5 days delay), era5_ensemble (global 0.5° (~55 km), daily, 5 days delay), cerra (Europe only, 5 km, no real-time updates). 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 a DataCanvas when canvas is enabled, returning canvas_id and table_name with truncated: true; inspect the staged columns with openmeteo_dataframe_describe, then query the full set with openmeteo_dataframe_query. With canvas disabled they return a bounded preview instead. At least one of hourly_variables or daily_variables is required.",
"inputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"properties": {
"canvas_id": {
"description": "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 spills to this canvas: pass the returned token to openmeteo_dataframe_describe to list the staged table and its columns, then to openmeteo_dataframe_query to run SQL against it. Omit to create a fresh canvas.",
"pattern": "^[A-Za-z0-9_-]{10}$",
"type": "string"
},
"daily_variables": {
"description": "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 belongs in hourly_variables and is rejected here; for a daily summary of an hourly variable use its published aggregate (cloud_cover_max, cloud_cover_mean, cloud_cover_min). At least one of hourly_variables or daily_variables required.",
"items": {
"type": "string"
},
"maxItems": 50,
"type": "array"
},
"end_date": {
"description": "End date (YYYY-MM-DD, inclusive). Must be on or after start_date. For the last few days, either request models: [\"ecmwf_ifs\"] or use openmeteo_get_forecast with past_days.",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"type": "string"
},
"hourly_variables": {
"description": "Hourly archive 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 temperature_2m_max or precipitation_sum belongs in daily_variables and is rejected here. At least one of hourly_variables or daily_variables required.",
"items": {
"type": "string"
},
"maxItems": 50,
"type": "array"
},
"latitude": {
"description": "Latitude in decimal degrees. Use openmeteo_search_locations to resolve a place name to coordinates.",
"maximum": 90,
"minimum": -90,
"type": "number"
},
"longitude": {
"description": "Longitude in decimal degrees.",
"maximum": 180,
"minimum": -180,
"type": "number"
},
"models": {
"description": "Archive models to read from: best_match (default, blends IFS HRES + ERA5 + ERA5-Land), ecmwf_ifs (global 9 km, updated every 6 hours, no delay), ecmwf_ifs_analysis_long_window (global 9 km, daily, 2 days delay), era5_seamless (ERA5 and ERA5-Land combined), era5 (global 0.25° (~25 km), daily, 5 days delay), era5_land (global 0.1° (~11 km), daily, 5 days delay), era5_ensemble (global 0.5° (~55 km), daily, 5 days delay), cerra (Europe only, 5 km, no real-time updates). Omit to use Open-Meteo's Best Match default, which blends IFS HRES, ERA5, and ERA5-Land — pin a model instead when a consistent source matters across the range. With 2+ models each variable column is suffixed with the model name. cerra covers Europe only and is rejected as a coverage gap elsewhere. A name outside this list is sent upstream rather than rejected here.",
"items": {
"type": "string"
},
"maxItems": 8,
"type": "array"
},
"precipitation_unit": {
"default": "mm",
"description": "Precipitation unit. Default \"mm\".",
"enum": [
"mm",
"inch"
],
"type": "string"
},
"start_date": {
"description": "Start date (YYYY-MM-DD, e.g., \"2024-07-01\"). The archive covers from 1940-01-01; how close to today it reaches depends on the model — the ERA5 family runs about 5 days behind, IFS HRES is current.",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"type": "string"
},
"temperature_unit": {
"default": "celsius",
"description": "Temperature unit. Default \"celsius\".",
"enum": [
"celsius",
"fahrenheit"
],
"type": "string"
},
"timezone": {
"default": "auto",
"description": "IANA timezone or \"auto\". Default \"auto\".",
"type": "string"
},
"wind_speed_unit": {
"default": "kmh",
"description": "Wind speed unit. Default \"kmh\".",
"enum": [
"kmh",
"mph",
"ms",
"kn"
],
"type": "string"
}
},
"required": [
"latitude",
"longitude",
"start_date",
"end_date"
],
"type": "object"
},
"name": "openmeteo_get_historical",
"outputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"latitude",
"longitude",
"elevation",
"timezone",
"date_range",
"record_count",
"truncated"
]
},
{
"required": [
"error"
]
}
],
"properties": {
"canvas_id": {
"description": "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 response carries. Pass to openmeteo_dataframe_describe to list the staged table and its columns, then to openmeteo_dataframe_query to run SQL against it.",
"type": "string"
},
"daily": {
"description": "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 present.",
"items": {
"additionalProperties": {},
"propertyNames": {
"type": "string"
},
"type": "object"
},
"type": "array"
},
"daily_units": {
"additionalProperties": {
"type": "string"
},
"description": "Variable → unit string for daily data. Absent when no daily_variables were requested.",
"propertyNames": {
"type": "string"
},
"type": "object"
},
"date_range": {
"additionalProperties": false,
"description": "Date range of returned data",
"properties": {
"end": {
"description": "Actual end date of returned data",
"type": "string"
},
"start": {
"description": "Actual start date of returned data",
"type": "string"
}
},
"required": [
"start",
"end"
],
"type": "object"
},
"elevation": {
"description": "Elevation at grid point (meters)",
"type": "number"
},
"error": {
"additionalProperties": {},
"description": "Present when the call failed. Absent on success.",
"properties": {
"code": {
"description": "JSON-RPC error code for this failure.",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"type": "integer"
},
"data": {
"additionalProperties": {},
"properties": {
"reason": {
"description": "Machine-readable failure mode. Declared by this tool: `date_out_of_range`: start_date predates 1940-01-01, or the requested dates fall outside the coverage of the selected model. `date_order_invalid`: end_date is before start_date. `no_variables_requested`: Neither hourly_variables nor daily_variables was provided. `invalid_variable`: An unknown variable name or unsupported archive model was requested. `variable_wrong_cadence`: A variable Open-Meteo documents under one cadence was passed in the other cadence field — for example cloud_cover in daily_variables, or temperature_2m_max in hourly_variables. `invalid_timezone`: timezone was blank, or upstream did not recognize the requested time zone. `request_too_large`: Open-Meteo refused the request as asking for too much data in one call. Other values are possible when a failure originates below the handler.",
"examples": [
"date_out_of_range",
"date_order_invalid",
"no_variables_requested",
"invalid_variable",
"variable_wrong_cadence",
"invalid_timezone",
"request_too_large"
],
"type": "string"
},
"recovery": {
"additionalProperties": {},
"description": "Actionable next step for the caller.",
"properties": {
"hint": {
"type": "string"
}
},
"required": [
"hint"
],
"type": "object"
},
"retryable": {
"description": "Whether retrying may succeed.",
"type": "boolean"
}
},
"type": "object"
},
"message": {
"description": "Human-readable description of what went wrong.",
"type": "string"
}
},
"required": [
"code",
"message"
],
"type": "object"
},
"hourly": {
"description": "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 present.",
"items": {
"additionalProperties": {},
"propertyNames": {
"type": "string"
},
"type": "object"
},
"type": "array"
},
"hourly_units": {
"additionalProperties": {
"type": "string"
},
"description": "Variable → unit string for hourly data (e.g., {\"temperature_2m\": \"°C\", \"precipitation\": \"mm\"}). Absent when no hourly_variables were requested.",
"propertyNames": {
"type": "string"
},
"type": "object"
},
"latitude": {
"description": "Snapped latitude",
"type": "number"
},
"longitude": {
"description": "Snapped longitude",
"type": "number"
},
"models": {
"description": "Archive models requested — echoes the models parameter. Absent when models was omitted, which means the data came from Open-Meteo Best Match (IFS HRES + ERA5 + ERA5-Land) and the source varies by date.",
"items": {
"type": "string"
},
"type": "array"
},
"notice": {
"description": "Everything this response needs to say beyond the data, composed into one advisory: columns the archive returned with the unit \"undefined\" (a name it parsed but does not serve in the requested cadence); recognized variables whose requested window falls outside the data's coverage, with the timestamps that do carry values; and, when the result spilled, either the canvas and table holding the full row set plus the two dataframe tools that read it, or — with DataCanvas disabled — why there is no canvas_id and how to reach the rows the preview omits.",
"type": "string"
},
"record_count": {
"description": "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.",
"type": "number"
},
"table_name": {
"description": "DuckDB table name for the staged data — use as the FROM target in openmeteo_dataframe_query SQL; openmeteo_dataframe_describe lists its columns. Present only alongside canvas_id.",
"type": "string"
},
"timezone": {
"description": "Resolved IANA timezone",
"type": "string"
},
"truncated": {
"description": "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 hourly and daily row, including any column the preview omits. With it disabled there is no canvas_id, and the omitted rows are reached only by narrowing the request.",
"type": "boolean"
}
},
"type": "object"
}
},
{
"description": "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 a DataCanvas when canvas is enabled, returning canvas_id and table_name with truncated: true — inspect the staged columns with openmeteo_dataframe_describe, then query the full set with openmeteo_dataframe_query. With canvas disabled they return a bounded preview instead.",
"inputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"properties": {
"canvas_id": {
"description": "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 any row count — it spills to this canvas: pass the returned token to openmeteo_dataframe_describe to list the staged table and its columns, then to openmeteo_dataframe_query to run SQL against it. Omit to create a fresh canvas.",
"pattern": "^[A-Za-z0-9_-]{10}$",
"type": "string"
},
"daily_variables": {
"description": "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 rejected here; for a daily summary use its published aggregate (wave_height_max). At least one of hourly_variables or daily_variables required.",
"items": {
"type": "string"
},
"maxItems": 50,
"type": "array"
},
"end_date": {
"description": "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.",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"type": "string"
},
"forecast_days": {
"description": "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.",
"maximum": 8,
"minimum": 1,
"type": "integer"
},
"hourly_variables": {
"description": "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_direction_dominant belongs in daily_variables and is rejected here. At least one of hourly_variables or daily_variables required.",
"items": {
"type": "string"
},
"maxItems": 50,
"type": "array"
},
"latitude": {
"description": "Latitude of a coastal or ocean point. Use openmeteo_search_locations to resolve a place name. Inland points return near-zero wave values.",
"maximum": 90,
"minimum": -90,
"type": "number"
},
"longitude": {
"description": "Longitude in decimal degrees.",
"maximum": 180,
"minimum": -180,
"type": "number"
},
"past_days": {
"default": 0,
"description": "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.",
"maximum": 92,
"minimum": 0,
"type": "integer"
},
"start_date": {
"description": "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_days or past_days.",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"type": "string"
},
"timezone": {
"default": "auto",
"description": "IANA timezone or \"auto\". Default \"auto\".",
"type": "string"
}
},
"required": [
"latitude",
"longitude"
],
"type": "object"
},
"name": "openmeteo_get_marine",
"outputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"latitude",
"longitude",
"timezone",
"record_count",
"truncated"
]
},
{
"required": [
"error"
]
}
],
"properties": {
"canvas_id": {
"description": "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 response carries. Pass to openmeteo_dataframe_describe to list the staged table and its columns, then to openmeteo_dataframe_query to run SQL against it.",
"type": "string"
},
"daily": {
"description": "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). Absent when only hourly_variables were requested. When truncated, contains only a preview — query canvas_id for the full dataset when one is present.",
"items": {
"additionalProperties": {},
"propertyNames": {
"type": "string"
},
"type": "object"
},
"type": "array"
},
"daily_units": {
"additionalProperties": {
"type": "string"
},
"description": "Variable → unit string for daily data. Absent when no daily_variables were requested.",
"propertyNames": {
"type": "string"
},
"type": "object"
},
"error": {
"additionalProperties": {},
"description": "Present when the call failed. Absent on success.",
"properties": {
"code": {
"description": "JSON-RPC error code for this failure.",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"type": "integer"
},
"data": {
"additionalProperties": {},
"properties": {
"reason": {
"description": "Machine-readable failure mode. Declared by this tool: `invalid_variable`: An unknown marine variable name was requested. `variable_wrong_cadence`: A variable Open-Meteo documents under one cadence was passed in the other cadence field — for example wave_height in daily_variables, or wave_height_max in hourly_variables. `no_variables_requested`: Neither hourly_variables nor daily_variables was provided. `date_range_incomplete`: Only one of start_date / end_date was provided — the marine archive requires the pair together. `forecast_window_conflict`: forecast_days or a non-zero past_days was combined with start_date or end_date. `date_order_invalid`: end_date is before start_date. `invalid_timezone`: timezone was blank, or upstream did not recognize the requested time zone. `request_too_large`: Open-Meteo refused the request as asking for too much data in one call. Other values are possible when a failure originates below the handler.",
"examples": [
"invalid_variable",
"variable_wrong_cadence",
"no_variables_requested",
"date_range_incomplete",
"forecast_window_conflict",
"date_order_invalid",
"invalid_timezone",
"request_too_large"
],
"type": "string"
},
"recovery": {
"additionalProperties": {},
"description": "Actionable next step for the caller.",
"properties": {
"hint": {
"type": "string"
}
},
"required": [
"hint"
],
"type": "object"
},
"retryable": {
"description": "Whether retrying may succeed.",
"type": "boolean"
}
},
"type": "object"
},
"message": {
"description": "Human-readable description of what went wrong.",
"type": "string"
}
},
"required": [
"code",
"message"
],
"type": "object"
},
"hourly": {
"description": "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 requested. When truncated, contains only a preview — query canvas_id for the full dataset when one is present.",
"items": {
"additionalProperties": {},
"propertyNames": {
"type": "string"
},
"type": "object"
},
"type": "array"
},
"hourly_units": {
"additionalProperties": {
"type": "string"
},
"description": "Variable → unit string for hourly data (e.g., {\"wave_height\": \"m\", \"wave_period\": \"s\"}). Absent when no hourly_variables were requested.",
"propertyNames": {
"type": "string"
},
"type": "object"
},
"latitude": {
"description": "Snapped latitude",
"type": "number"
},
"longitude": {
"description": "Snapped longitude",
"type": "number"
},
"notice": {
"description": "Everything this response needs to say beyond the data, composed into one advisory: columns the endpoint returned with the unit \"undefined\" (a name it parsed but does not serve); recognized variables whose requested window falls outside the data's coverage, with the timestamps that do carry values; and, when the result spilled, either the canvas and table holding the full row set plus the two dataframe tools that read it, or — with DataCanvas disabled — why there is no canvas_id and how to reach the rows the preview omits.",
"type": "string"
},
"record_count": {
"description": "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.",
"type": "number"
},
"table_name": {
"description": "DuckDB table name for the staged data — use as the FROM target in openmeteo_dataframe_query SQL; openmeteo_dataframe_describe lists its columns. Present only alongside canvas_id.",
"type": "string"
},
"timezone": {
"description": "Resolved IANA timezone",
"type": "string"
},
"truncated": {
"description": "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 hourly and daily row, including any column the preview omits. With it disabled there is no canvas_id, and the omitted rows are reached only by narrowing the request.",
"type": "boolean"
}
},
"type": "object"
}
},
{
"description": "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.",
"inputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"properties": {
"count": {
"default": 5,
"description": "Max results to return (1–10). Default 5. Return more when disambiguating common names like \"Springfield\" or \"Portland\".",
"maximum": 10,
"minimum": 1,
"type": "integer"
},
"country": {
"description": "ISO 3166-1 alpha-2 country code (e.g. \"US\", \"FR\") to disambiguate places that share a name. Omit for a global search.",
"pattern": "^[A-Za-z]{2}$",
"type": "string"
},
"language": {
"default": "en",
"description": "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. language \"zh\" for \"上海\", \"ru\" for \"Москва\". This resolves a native-script name of three or more characters, which is matched by normalized prefix; a one- or two-character name must equal an index entry exactly, so setting language alone will not find \"서울\" or \"大阪\" — retry those with the full administrative name (\"서울특별시\", \"大阪市\") or the romanized name (\"Seoul\", \"Osaka\"). Default \"en\"; a query in a recognized non-Latin script (CJK, Hangul, Cyrillic, Arabic, Greek, Hebrew, Thai, Devanagari) that misses under \"en\" is retried once with the language inferred from its script.",
"type": "string"
},
"name": {
"description": "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 disambiguate. A one- or two-character native-script name (\"서울\", \"大阪\") needs the full administrative name (\"서울특별시\", \"大阪市\") or the romanized name (\"Seoul\", \"Osaka\") — see the language field. Weather tools require coordinates — use the lat/lon from this result.",
"maxLength": 100,
"minLength": 1,
"type": "string"
}
},
"required": [
"name"
],
"type": "object"
},
"name": "openmeteo_search_locations",
"outputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"anyOf": [
{
"not": {
"required": [
"error"
]
},
"required": [
"results",
"count"
]
},
{
"required": [
"error"
]
}
],
"properties": {
"count": {
"description": "Number of results returned",
"type": "number"
},
"error": {
"additionalProperties": {},
"description": "Present when the call failed. Absent on success.",
"properties": {
"code": {
"description": "JSON-RPC error code for this failure.",
"maximum": 9007199254740991,
"minimum": -9007199254740991,
"type": "integer"
},
"data": {
"additionalProperties": {},
"properties": {
"reason": {
"description": "Machine-readable failure mode. Declared by this tool: `no_results`: The search returned no matching places. Other values are possible when a failure originates below the handler.",
"examples": [
"no_results"
],
"type": "string"
},
"recovery": {
"additionalProperties": {},
"description": "Actionable next step for the caller.",
"properties": {
"hint": {
"type": "string"
}
},
"required": [
"hint"
],
"type": "object"
},
"retryable": {
"description": "Whether retrying may succeed.",
"type": "boolean"
}
},
"type": "object"
},
"message": {
"description": "Human-readable description of what went wrong.",
"type": "string"
}
},
"required": [
"code",
"message"
],
"type": "object"
},
"notice": {
"description": "Advisory on the confidence of the top match, present only when its population is null or under 100,000 — the shape a historic or colonial exonym returns, where the upstream index answers with an unrelated small feature and never surfaces the modern city. Names the returned place, country, and feature_code, and asks the caller to verify the coordinates or retry with the place’s current official name. Never changes results or count.",
"type": "string"
},
"results": {
"description": "Ranked matches (most relevant first). Never empty — when nothing matches, the tool fails with no_results instead of returning an empty array.",
"items": {
"additionalProperties": false,
"description": "A single geocoding result with coordinates and administrative context",
"properties": {
"admin1": {
"description": "State, province, or region",
"type": [
"string",
"null"
]
},
"admin2": {
"description": "County or district",
"type": [
"string",
"null"
]
},
"country": {
"description": "Country name — null for non-country features like continents and oceans",
"type": [
"string",
"null"
]
},
"country_code": {
"description": "ISO 3166-1 alpha-2 country code — null for non-country features like continents and oceans",
"type": [
"string",
"null"
]
},
"elevation": {
"description": "Elevation in meters above sea level",
"type": [
"number",
"null"
]
},
"feature_code": {
"description": "GeoNames feature code describing the place type (e.g., \"PPLA2\" = state capital city, \"PPL\" = populated place)",
"type": "string"
},
"id": {
"description": "Open-Meteo place ID — stable reference for this location",
"type": "number"
},
"latitude": {
"description": "Latitude in decimal degrees",
"type": "number"
},
"longitude": {
"description": "Longitude in decimal degrees",
"type": "number"
},
"name": {
"description": "Place name",
"type": "string"
},
"population": {
"description": "Population (when available) — useful for disambiguating same-named cities",
"type": [
"number",
"null"
]
},
"timezone": {
"description": "IANA timezone (e.g., \"America/Los_Angeles\") — pass to weather tools as the timezone parameter. Null when the API omits it.",
"type": [
"string",
"null"
]
}
},
"required": [
"id",
"name",
"latitude",
"longitude",
"elevation",
"timezone",
"country",
"country_code",
"admin1",
"admin2",
"population",
"feature_code"
],
"type": "object"
},
"type": "array"
}
},
"type": "object"
}
}
]
}Verify it yourself
curl -s https://api.teppi.xyz/v1/evidence/sha256:cff1aa6f5c223ca2fb7ebb6ce8d5fb81b1e0c5d806bc8cc24bad0c1bb2c2243f | sha256sum