open-meteo-mcp-server
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@open-meteo-mcp-serverweather forecast for Tokyo"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Public Hosted Server: https://open-meteo.caseyjhand.com/mcp
Tools
Eleven tools covering geocoding, weather forecasts, historical climate, probabilistic ensemble forecasts, marine conditions, air quality, terrain elevation, river discharge, CMIP6 climate projections, and SQL analytics over large datasets:
Tool | Description |
| Resolve a place name to ranked coordinate matches with country, region, elevation, timezone, and population |
| Weather forecast for coordinates: hourly and/or daily variables for up to 16 days, with optional recent past data; wide windows spill to DataCanvas |
| Historical weather from the ERA5 reanalysis archive (1940–present); large ranges spill to DataCanvas |
| Marine wave and ocean conditions for coastal or ocean coordinates: wave height, period, direction, swell, and sea-surface temperature; up to 8 forecast days, |
| Modeled CAMS air quality: PM2.5, PM10, NO2, O3, CO, dust, pollen, and European/US AQI indices; up to 7 forecast days, |
| Terrain elevation from Copernicus DEM (~90m resolution) for up to 100 coordinate pairs per call |
| Probabilistic ensemble forecast: per-member hourly/daily time series (up to 51 members, 16 days) for exceedance and uncertainty analysis |
| GloFAS river discharge forecast (up to 210 days) or reanalysis (1984–present); coordinate-based, snaps to nearest river; large ranges spill to DataCanvas |
| Bias-corrected daily CMIP6 climate projections (1950–2050) across up to 7 models; large ranges spill to DataCanvas |
| List tables and columns on a DataCanvas staged by |
| Run a read-only SQL SELECT against tables staged on a DataCanvas |
openmeteo_search_locations
Resolve a free-text place name to ranked coordinate matches. Required first step for name-based queries — all weather tools accept latitude/longitude, not place names.
Returns name, country, admin1/admin2, latitude, longitude, elevation, IANA timezone, population, and GeoNames feature code
Search by a bare place name — a city, region, or landmark ("Baoding", not "Baoding Hebei"; "Paris", not "Paris, France"); a compound "City Region" or "City, Country" string matches nothing
Disambiguate same-named places (e.g., "Springfield") with the optional
countryfilter (ISO 3166-1 alpha-2, e.g.US) or by raisingcount(default 5, up to 10) and reading theadmin1/countryfields on each result — those are output fields for choosing among matches, not search inputsPass the timezone from an
openmeteo_search_locationsresult directly to weather tools as thetimezoneparameterFails with a
no_resultserror (not an empty array) when nothing matches — retry the bare place name without qualifiers, or for a physical feature/landmark search the nearest populated place instead
openmeteo_get_forecast
Weather forecast for a coordinate pair with hourly and/or daily variable selection.
Up to 16 forecast days ahead (
forecast_days 1–16, default 7)past_days(0–92) covers recent history via the forecast model — use instead ofopenmeteo_get_historicalfor dates within the last ~5 days to avoid ERA5 lagCommon 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_2mCommon daily variables:
temperature_2m_max,temperature_2m_min,precipitation_sum,wind_speed_10m_max,sunrise,sunset,uv_index_max,precipitation_hours,weather_codeAt least one of
hourly_variablesordaily_variablesis requiredHourly and daily are separate variable sets. A variable Open-Meteo documents under the other cadence is rejected before the request, by name, with the field it belongs in and the same-cadence alternatives (
cloud_coverindaily_variables→cloud_cover_max/_mean/_min). Names in neither set are passed upstream unchangedConfigurable temperature unit (Celsius/Fahrenheit), wind speed unit (km/h, mph, m/s, knots), and precipitation unit (mm/inch)
Reshapes the API's columnar response into per-timestamp records with a parallel
hourly_units/daily_unitsmapA wide window (a large
past_daysplus many hourly variables) spills to DataCanvas whenCANVAS_PROVIDER_TYPE=duckdb— output includescanvas_idandtruncated: true; query withopenmeteo_dataframe_query
openmeteo_get_historical
Historical weather from the ERA5 reanalysis archive, covering 1940 to approximately 5 days ago.
Requires
start_dateandend_date(YYYY-MM-DD); ERA5 has a variable ~1–5 day lagSame variable vocabulary as
openmeteo_get_forecast— past and forecast data are directly comparable on one schemaAt least one of
hourly_variablesordaily_variablesis requiredHourly and daily are separate variable sets; a variable documented under the other cadence is rejected before the request, by name, with the field it belongs in
Large date ranges (multi-year hourly queries) spill to DataCanvas when
CANVAS_PROVIDER_TYPE=duckdb— output includescanvas_idandtruncated: truewhenever a result is too large to return inline, which a wide multi-variable pull can be at any row countSpill → query workflow: call
openmeteo_dataframe_describewith thecanvas_idto list tables, thenopenmeteo_dataframe_queryto run SQL SELECT against the staged data
openmeteo_get_marine
Marine wave and ocean conditions for coastal and open-ocean coordinates.
Up to 8 forecast days (
forecast_days 1–8, upstream default 7) with optionalpast_days(0–92)Or an archive range via
start_dateandend_date— real wave values go back to at least 2022One window per call: a date range is mutually exclusive with
forecast_days/past_days, and needs both ends — a lonestart_dateorend_dateis rejectedCommon 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_periodCommon daily variables:
wave_height_max,wave_direction_dominant,wave_period_maxAt least one of
hourly_variablesordaily_variablesis requiredHourly and daily are separate variable sets; a variable documented under the other cadence is rejected before the request, by name, with the field it belongs in
Inland or sheltered-water points return near-zero wave values (physically correct);
ocean_current_velocityis null for non-open-ocean coordinatesWide windows spill to DataCanvas when
CANVAS_PROVIDER_TYPE=duckdb— output includescanvas_idandtruncated: true; query withopenmeteo_dataframe_query
openmeteo_get_air_quality
Modeled CAMS air quality, forecast and archive.
Up to 7 forecast days (
forecast_days 1–7, upstream default 5) with optionalpast_days(0–92)Or an archive range via
start_dateandend_date— real CAMS values go back to at least2022-10-01; earlier dates return rows of nullsOne window per call: a date range is mutually exclusive with
forecast_days/past_days, and needs both ends — a lonestart_dateorend_dateis rejectedCommon 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_pollenAt least one variable from
hourly_variablesis requiredGrid-modeled data from CAMS — resolution is coarser than ground stations; for measured station readings, cross-reference
openaq-mcp-serverOutput includes
data_source: "CAMS"to distinguish modeled from measured dataWide windows spill to DataCanvas when
CANVAS_PROVIDER_TYPE=duckdb— output includescanvas_idandtruncated: true; query withopenmeteo_dataframe_query
openmeteo_get_elevation
Terrain elevation from the Copernicus Digital Elevation Model (~90m resolution).
Accepts parallel
latitudes[]andlongitudes[]arrays; both must have equal length (up to 100 pairs)Returns results in input order:
{ latitude, longitude, elevation_m }Useful for geographic context, elevation-adjusted weather interpretation, or route planning
openmeteo_get_ensemble
Probabilistic ensemble weather forecast exposing all individual model member trajectories.
Up to 16 forecast days (
forecast_days 1–16, default 7) with optionalpast_days(0–92)Each requested variable is returned as per-member columns:
temperature_2m_member01,temperature_2m_member02, … Use the spread across members to compute exceedance probabilities, interquantile ranges, and decision thresholdsAvailable ensemble models (member counts include the control run):
Global —
ecmwf_ifs025_ensemble(51),ecmwf_aifs025_ensemble(51),google_weathernext2_ensemble(64),ncep_gefs_seamless(31),ncep_gefs025(31),ncep_gefs05(31, 35-day horizon),ncep_aigefs025(31),icon_seamless_eps(20–40, global/Europe blend),icon_global_eps(40),gem_global_ensemble(21),bom_access_global_ensemble(18),ukmo_global_ensemble_20km(18)Regional —
ecmwf_ifs_europe_ensemble(51),ecmwf_aifs_europe_ensemble(51),icon_eu_eps(40),icon_d2_eps(20),meteoswiss_icon_ch2_ensemble(21),meteoswiss_icon_ch1_ensemble(11),ukmo_uk_ensemble_2km(3). A regional model returns no data outside the area it covers. Upstream reports that two ways —No data is available for this locationfrom themeteoswiss_*pair, an HTTP 200 carryingnancoordinates from the rest — and both surface as a non-retryable input error naming the coverage gap, so switch to a global model rather than retrying
Omit
modelsto use the API default blend. The list is not an allowlist — a model name it does not carry is still sent upstream, so a model Open-Meteo adds later keeps workingResponse includes
model(system used) andmember_count(perturbed members, excluding the control run)At least one of
hourly_variablesordaily_variablesis requiredHourly and daily are separate variable sets; a variable documented under the other cadence is rejected before the request, by name, with the field it belongs in. The ensemble API's own catalog applies — it publishes
temperature_2m_maxandtemperature_2m_minas 3-hourly aggregations as well as daily, so those are accepted in either fieldLarge multi-member, multi-day pulls spill to DataCanvas when
CANVAS_PROVIDER_TYPE=duckdb— output includescanvas_idandtruncated: true; query withopenmeteo_dataframe_queryConfigurable temperature, wind speed, and precipitation units
openmeteo_get_flood
GloFAS (Global Flood Awareness System) river discharge forecast and reanalysis via the Open-Meteo Flood API.
Coordinate-based — no river ID needed; the API snaps to the nearest river grid point automatically
Forecast horizon up to 210 days; reanalysis history from 1984-01-01 to present
One mode per call:
forecast_daysfor the future outlook, orstart_dateandend_datetogether for historical analysis. The two are mutually exclusive, and a date range needs both ends — a lonestart_dateorend_dateis rejectedAvailable 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) — all in m³/sReturns null for coordinates outside GloFAS coverage (e.g., open ocean or areas without river network data)
Discharge values reflect the GloFAS ensemble — percentile variables expose the uncertainty spread
Wide reanalysis ranges spill to DataCanvas when
CANVAS_PROVIDER_TYPE=duckdb— output includescanvas_idandtruncated: true; query withopenmeteo_dataframe_query
openmeteo_get_climate
Long-range climate projections from bias-corrected daily CMIP6 models — the future-projection counterpart to openmeteo_get_historical.
Coverage: 1950-01-01 to 2050-12-31, 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. Not an allowlist — an unlisted name is still sent upstream; when upstream rejects a multi-model request, the error names only the model outside the documented set, not the whole listWith 2+ models, each variable appears once per model with the model name as column suffix (e.g.
temperature_2m_max_CMCC_CM2_VHR4); a single or omitted model returns plain variable namesCommon daily variables:
temperature_2m_max,temperature_2m_min,temperature_2m_mean,precipitation_sum,rain_sum,snowfall_sum,wind_speed_10m_mean,wind_speed_10m_max,shortwave_radiation_sum,cloud_cover_mean,relative_humidity_2m_mean,pressure_msl_meanNot all models carry all variables — missing combinations return null (e.g.
CMCC_CM2_VHR4has noshortwave_radiation_sum)Multi-decade daily pulls across several models spill to DataCanvas when
CANVAS_PROVIDER_TYPE=duckdb— output includescanvas_idandtruncated: true; query withopenmeteo_dataframe_queryConfigurable temperature, wind speed, and precipitation units
Related MCP server: weather-mcp
Features
Built on @cyanheads/mcp-ts-core:
Declarative tool definitions — single file per tool, framework handles registration and validation
Unified error handling — handlers throw, framework catches, classifies, and formats
Pluggable auth:
none,jwt,oauthSwappable storage backends:
in-memory,filesystem,Supabase,Cloudflare KV/R2/D1Structured logging with optional OpenTelemetry tracing
STDIO and Streamable HTTP transports
Open-Meteo–specific:
No API key required for non-commercial use — zero-config out of the box
Self-contained geocoding:
openmeteo_search_locationsresolves place names so agents don't need a separate geocoderERA5 archive from 1940 to present with same variable schema as the forecast API — direct past/forecast comparisons on one schema
Automatic columnar-to-record reshape: Open-Meteo returns parallel time/variable arrays; handlers convert to per-timestamp records with a
*_unitsmapDataCanvas spillover for
openmeteo_get_forecast,openmeteo_get_historical,openmeteo_get_marine,openmeteo_get_air_quality,openmeteo_get_ensemble,openmeteo_get_flood, andopenmeteo_get_climate: a result too large to return inline registers a DuckDB dataframe for SQL querying, staging every hourly and daily row with its upstream numeric type intact. WithCANVAS_PROVIDER_TYPE=none(the default) the same size check still applies — those tools return a bounded preview withtruncated: trueand nocanvas_id, never an unbounded payload claiming to be completeConfigurable base URLs for all eight API endpoints (forecast, archive, marine, air quality, geocoding, ensemble, flood, climate) — override for testing or self-hosted deployments
Attribution: Weather data by Open-Meteo.com (CC BY 4.0). Non-commercial use is free and keyless; commercial use requires Open-Meteo's paid API tier (~10,000 req/day, 5,000/hour fair-use ceiling for non-commercial)
Agent-friendly output:
Location-first workflow:
openmeteo_search_locationsreturns the IANA timezone alongside coordinates — pass it directly astimezoneto any weather toolRecovery hints on all error contracts — invalid variable names surface correction guidance with common variable examples
Cadence-aware variable validation on
openmeteo_get_forecast,openmeteo_get_historical,openmeteo_get_marine, andopenmeteo_get_ensemble: a variable documented under the opposite cadence is rejected before the upstream call, naming the exact value and the field it belongs in, so the next attempt converges instead of re-guessing against an error that echoes the whole requested list. This is not an allowlist — a name in neither documented set goes upstream untouchedUnserved-variable notice on all seven weather tools: Open-Meteo answers a variable name it parses but does not serve with an all-null column and the unit
"undefined"rather than an error, so the result carries a notice naming those columns instead of presenting them as a data gap.openmeteo_get_air_quality,openmeteo_get_flood, andopenmeteo_get_climatetake a single cadence bucket, so they carry the notice without a cadence guardCoordinate snapping transparency — responses echo the snapped
latitude/longitude(Open-Meteo quantizes to the nearest model grid point) so agents can reason about grid alignmentdata_source: "CAMS"label on air quality results distinguishes modeled data from measured station readings
Getting started
Public Hosted Instance
A public instance is available at https://open-meteo.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:
{
"mcpServers": {
"open-meteo-mcp-server": {
"type": "streamable-http",
"url": "https://open-meteo.caseyjhand.com/mcp"
}
}
}Self-Hosted / Local
Add the following to your MCP client configuration file.
{
"mcpServers": {
"open-meteo-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/open-meteo-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}Or with npx (no Bun required):
{
"mcpServers": {
"open-meteo-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/open-meteo-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}Or with Docker:
{
"mcpServers": {
"open-meteo-mcp-server": {
"type": "stdio",
"command": "docker",
"args": ["run", "-i", "--rm", "-e", "MCP_TRANSPORT_TYPE=stdio", "ghcr.io/cyanheads/open-meteo-mcp-server:latest"]
}
}
}For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcpPrerequisites
Bun v1.3.0 or higher (or Node.js v24+).
No API key required. Non-commercial use is free and keyless.
Commercial use requires Open-Meteo's paid API tier.
Installation
Clone the repository:
git clone https://github.com/cyanheads/open-meteo-mcp-server.gitNavigate into the directory:
cd open-meteo-mcp-serverInstall dependencies:
bun installConfiguration
All configuration is validated at startup via Zod schemas. No API key is required for non-commercial use — all variables are optional.
Variable | Description | Default |
| Transport: |
|
| HTTP server port |
|
| HTTP endpoint path |
|
| Public origin for TLS-terminating reverse-proxy deployments | — |
| Auth mode: |
|
| Log level ( |
|
| Opt-in forced-GC interval (ms, Bun only). Set to |
|
| Directory for log files (Node.js only) |
|
| Storage backend: |
|
| Canvas engine for |
|
| Override for the main forecast + elevation API |
|
| Override for the ERA5 historical archive API |
|
| Override for the marine forecast API |
|
| Override for the CAMS air quality API |
|
| Override for the geocoding API |
|
| Override for the ensemble forecast API |
|
| Override for the GloFAS flood API |
|
| Override for the CMIP6 climate projections API |
|
| Enable OpenTelemetry tracing and metrics |
|
See .env.example for the full list of optional overrides.
Running the server
Local development
Build and run the production version:
# One-time build bun run rebuild # Run the built server bun run start:http # or bun run start:stdioRun checks and tests:
bun run devcheck # Lint, format, typecheck, security bun run test # Vitest test suite
Docker
docker build -t open-meteo-mcp-server .
docker run --rm -p 3010:3010 open-meteo-mcp-serverThe Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/open-meteo-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
Project structure
Directory | Purpose |
|
|
| Server-specific environment variable parsing and validation with Zod |
| Tool definitions ( |
| Open-Meteo HTTP client wrapping all nine endpoints with retry, error classification, and columnar reshape |
| DataCanvas accessor for |
| Unit and integration tests mirroring |
Development guide
See CLAUDE.md for development guidelines and architectural rules. The short version:
Handlers throw, framework catches — no
try/catchin tool logicUse
ctx.logfor request-scoped logging,ctx.statefor tenant-scoped storageRegister new tools in the
tools[]array insrc/index.tsWrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields
Contributing
Issues and pull requests are welcome. Run checks and tests before submitting:
bun run devcheck
bun run testLicense
Apache-2.0 — see LICENSE for details.
Weather data by Open-Meteo.com — licensed CC BY 4.0.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- FlicenseAqualityDmaintenanceA comprehensive MCP server providing tools for real-time, forecast, and historical weather data, alongside air quality, marine conditions, and climate projections. It also includes geocoding services to search for locations and retrieve precise coordinates for environmental analysis.7
- Alicense-qualityBmaintenanceExposes weather data from the free Open-Meteo API via decorator-driven MCP tools with Zod schemas, supporting stdio and HTTP transports.15MIT
- FlicenseAqualityCmaintenanceProvides weather alerts and forecasts via MCP tools, supporting both STDIO and SSE transports.2
- Alicense-qualityBmaintenanceMCP server for Open-Meteo free weather APIs, offering 16 tools for forecast, historical, air quality, marine, flood, ensemble, climate, seasonal, and scheduled data collection with no API key required.32MIT
Related MCP Connectors
Open-Meteo MCP — weather forecast + historical reanalysis + sister APIs
Visual Crossing Weather MCP — wraps the Visual Crossing Weather Timeline API
Meteostat MCP — historical weather from 11k+ stations (no auth)
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/cyanheads/open-meteo-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server