Skip to main content

Swiss Weather MCP Server

PyPI License Release Tests

A Model Context Protocol (MCP) server that exposes Swiss weather forecast data as callable tools. It fetches data from the official MeteoSwiss meteodata-lab, caches it locally, and serves predictions such as rainfall, sunshine, temperature, etc. The prediction data is from the ICON-CH2-EPS forecast system that produces data for up to 5 days ahead.

Additionally there is also an MCP client that can be run to test the server using the stdio transport.

Note: This project is not an official MeteoSwiss product. All forecast data are from the MeteoSwiss Open Data portal. Source: MeteoSwiss

Table of Contents

Project Structure

swiss-weather-mcp/
├── src/swiss_weather_mcp/
│   ├── server.py           # MCP server
│   ├── predictions.py      # Data fetching logic
│   └── client.py           # MCP client (optional)
├── tests/swiss_weather_mcp/  # Pytest suite
├── .github/workflows/      # CI and release pipelines
├── docs/                   # Documentation
├── pyproject.toml          # Project metadata and dependencies
├── uv.lock                 # Pinned, reproducible dependency set
├── .env                    # NOMINATIM_USER_AGENT (not committed)
└── Dockerfile

Caches live outside the project, under your OS's standard cache directory (see Installation).

Quick Start

1. Installation

Install the server globally to run it anywhere on your system:

uv tool install swiss-weather-mcp

2. Configuration

Create a .env file with your Nominatim user agent (see Configuration):

echo 'NOMINATIM_USER_AGENT="YourWeatherMCPServer/1.0 (yourname@example.com)"' > .env

3. Execution

Run the server from the directory containing your .env file:

swiss-weather-mcp-server

Installation

As a Global CLI Tool

uv tool install swiss-weather-mcp

# With the optional MCP client, which pulls in the OpenAI SDK
uv tool install 'swiss-weather-mcp[client]'

As a Library Dependency

# Using uv
uv add swiss-weather-mcp

# Using pip
pip install swiss-weather-mcp

# With the optional MCP client, which pulls in the OpenAI SDK
uv add 'swiss-weather-mcp[client]'
pip install 'swiss-weather-mcp[client]'

From Source

git clone https://github.com/cuolm/swiss-weather-mcp.git
cd swiss-weather-mcp

# Using uv (Recommended)
uv sync --extra client

# Using pip
python3 -m venv .venv
source .venv/bin/activate  # On Windows: .venv\Scripts\activate
pip install -e ".[client]"

Note: uv sync installs the server only. --extra client adds the OpenAI SDK needed by swiss-weather-mcp-client.

Note:

  • llama-server must already be running when you start swiss-weather-mcp-client, which talks to it but never starts it. The MCP server itself does not need it.
  • The .env file is read from the current working directory, so run the server from the directory holding it. Exporting NOMINATIM_USER_AGENT works when you start the server yourself, but not through swiss-weather-mcp-client: the MCP stdio transport forwards only a fixed list of variables.
  • A .env file is read only by the two entry points, not when the package is imported as a library. MeteoSwissPredictions takes NOMINATIM_USER_AGENT from the environment, and the calling application decides how it gets there.
  • Caches live in your OS cache directory (via platformdirs, e.g. ~/Library/Caches/swiss-weather-mcp on macOS, ~/.cache/swiss-weather-mcp on Linux), independent of where the server runs, so forecasts and geocoded locations are reused. Delete EarthKitCache/ or nominatim_geocode_cache.json to clear them.

Configuration

Create a .env file in the directory you'll run the server from, specifying an environment variable that tells Nominatim (the geocoding service) who is making the call.

echo 'NOMINATIM_USER_AGENT="YourWeatherMCPServer/1.0 (yourname@example.com)"' > .env

Note: Replace the name and address with your own. The Nominatim usage policy requires a user agent identifying a real application and contact address, and blocks requests without one. Keep lookups to at most one per second. Results are cached, so only new locations reach the service.

Usage

Running the Server

If installed via uv tool install or pip:

# stdio (default)
swiss-weather-mcp-server

# streamable-http
swiss-weather-mcp-server --transport=streamable-http --host=localhost --port=8050

If running within the source repository cloned from GitHub:

# Using uv (Recommended)
uv run swiss-weather-mcp-server

# Using pip, with the virtual environment activated
swiss-weather-mcp-server

Optional flags: --help

Running the Server with Docker

Images are built and published automatically by GitHub Actions to the project's GitHub Container Registry, tagged :latest (newest release) and by version.

  1. Create a .env file containing your Nominatim user agent environment variable (replace "YourWeatherMCPServer/1.0 (yourname@example.com)"):
    echo 'NOMINATIM_USER_AGENT="YourWeatherMCPServer/1.0 (yourname@example.com)"' > .env
    
  2. Run the published image, passing the .env file and mapping port 8050:
    docker run --env-file .env -p 8050:8050 ghcr.io/cuolm/swiss-weather-mcp:latest
    
  3. Access the server at:
    http://localhost:8050/mcp/
    

Manual Build

docker build -t swiss-weather-mcp .
docker run --env-file .env -p 8050:8050 swiss-weather-mcp

Running the MCP Client using Stdio Transport

The bundled MCP client can be used to test the server over the stdio transport. It requires the client extra (see Installation). The client starts the MCP server itself, but not the model server, which has to be running first.

  1. Install llama.cpp, which provides llama-server:
    brew install llama.cpp
    
  2. Start it in its own terminal, downloading the model on first use:
    llama-server --jinja --no-mmproj -hf unsloth/Qwen3.5-4B-GGUF --port 8080
    
  3. Run the client against it in a second terminal:
    swiss-weather-mcp-client --model=unsloth/Qwen3.5-4B-GGUF --base-url=http://localhost:8080/v1
    
    # From a source checkout, using uv
    uv run --extra client swiss-weather-mcp-client --model=unsloth/Qwen3.5-4B-GGUF --base-url=http://localhost:8080/v1
    

Note: --jinja applies the model's chat template, without which tool calling is unsupported, and --no-mmproj skips the vision projector that -hf downloads alongside some models. --base-url defaults to llama-server's address, and any other OpenAI compatible backend works by pointing it elsewhere, for example LM Studio or vLLM. Pass --model exactly as the server reports it under /v1/models.

Available Tools

Tool Purpose Example Call
current_date_and_time() Current date and time (weekday day.month.year hour:minute:second) in Swiss local time current_date_and_time()
total_rainfall(location, lead_time_start_swiss, lead_time_end_swiss) Total rainfall (mm) for a period total_rainfall("Zurich", 24, 48)
sunshine_hours(location, lead_time_start_swiss, lead_time_end_swiss) Sunshine hours for a period sunshine_hours("Zurich", 24, 48)
temperature(location, lead_time_swiss) Max temperature (°C) at a specific lead time temperature("Zurich", 36)
wind_speed(location, lead_time_swiss) Wind speed (m/s) at a specific lead time wind_speed("Zurich", 36)
pressure_msl(location, lead_time_swiss) Sea‑level pressure (Pa) at a specific lead time pressure_msl("Zurich", 36)
total_cloud_cover(location, lead_time_swiss) Cloud cover (%) at a specific lead time total_cloud_cover("Zurich", 36)
snow_depth(location, lead_time_swiss) Snow depth (m) at a specific lead time snow_depth("Zurich", 36)
precipitation_rate(location, lead_time_swiss) Precipitation rate (mm/s) at a specific lead time precipitation_rate("Zurich", 36)

Lead Time

  • Lead time is the number of hours counted from Swiss local time 00:00, internally converted to UTC (the ICON-CH2-EPS forecast system uses UTC).
  • Example: A lead time of 36 hours returns the forecast for 12:00 Swiss local time tomorrow.
  • Minimum lead time: 2 hours, maximum lead time: 121 hours.

Example Usage with LMStudio

Using the streamable-http transport layer

Configure the mcp.json file in LMStudio:

{
  "mcpServers": {
    "swiss_weather_mcp_server": {
      "url": "http://localhost:8050/mcp/"
    }
  }
}

Run the MCP server with the streamable-http transport layer:

uv run swiss-weather-mcp-server --transport=streamable-http --host=localhost --port=8050

Using the stdio transport layer

Configure the mcp.json file in LMStudio. Replace <path-to-the-project> with your actual local path:

{
  "mcpServers": {
    "swiss_weather_mcp_server": {
      "command": "<path-to-the-project>/.venv/bin/swiss-weather-mcp-server"
    }
  }
}

LMStudioMCPServer

Tests

Run the test suite from the project root with:

uv run pytest

# Or, with an activated virtual environment
pytest

Every push and pull request runs the suite plus a Docker build check via the Tests workflow.

Releasing

Versions are derived from Git tags by hatch-vcs — there is no version string to bump by hand.

  • Pushing a pre-release tag (e.g. 0.2.0rc1) triggers release_test.yaml: tests, publish to TestPyPI, push a versioned image to GHCR, and create a prerelease GitHub Release.
  • Pushing a final tag (e.g. 0.2.0) triggers release.yaml: tests, publish to PyPI, push :<version> and :latest images to GHCR, and create a GitHub Release.

Both publish jobs use PyPI trusted publishing via the pypi / testpypi GitHub environments — no API tokens are stored in the repository.

Resources

License

Licensed under the Apache License 2.0.

Release files for swiss-weather-mcp 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for swiss-weather-mcp 0.1.1
File Size Uploaded
swiss_weather_mcp-0.1.1.tar.gz 365.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for swiss-weather-mcp 0.1.1
File Interpreter ABI Platform
swiss_weather_mcp-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 387.4 kB

Release files / swiss_weather_mcp-0.1.1.tar.gz

Download URL swiss_weather_mcp-0.1.1.tar.gz
Size 365.8 kB
Tags Source
SHA-256 checksum
How to use checksums
b7e4b88039fb6d3be781769f5f64d47117be28436902e26a6e594a11dbe2b945
BLAKE2b-256 checksum
How to use checksums
706cc9ae52325d4430a7560ea512208b2a446b88c39bd60477ae674d9aad21d9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 22, 2026.

Transparency log

Release files / swiss_weather_mcp-0.1.1-py3-none-any.whl

Download URL swiss_weather_mcp-0.1.1-py3-none-any.whl
Size 21.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
23ddd61c610a4f664ed6e16bb3a9bd38b98309d1cbc2ce7031cae1751d7fe0be
BLAKE2b-256 checksum
How to use checksums
b29af9bad52097838224d5391b82995344cad9dafa8d9688ccb0f0f64eedf2b5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 22, 2026.

Transparency log

Release history Release notifications | RSS feed

0.2.0

2 release files

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page