Back to Discover

wsl-envidat-mcp

connector

malkreide

WSL / EnviDat environmental research datasets via CKAN

View on GitHub
0 starsSynced Aug 2, 2026

Install to Claude Code

/plugin marketplace add malkreide/wsl-envidat-mcp

README

πŸ‡¨πŸ‡­ Part of the Swiss Public Data MCP Portfolio

wsl-envidat-mcp πŸŒ²β„οΈβ›°οΈ

Version License: MIT Python 3.11+ MCP Data Source No API Key CI

MCP server connecting AI models to Swiss environmental research data from WSL via EnviDat β€” forest, snow, avalanches, natural hazards and biodiversity, no API key required.

πŸ‡©πŸ‡ͺ Deutsche Version


Phase

This server is in Phase 1: Read-only Wrapper.

PropertyStatus
Read toolsβœ… 10 tools, all readOnlyHint: true
Write tools❌ none (EnviDat is read-only public data)
Semantic Layer⚠️ partial β€” three domain tools curate Solr queries
OAuth / Auth Gateway❌ not required (Public Open Data, no API key)
Container hardeningβœ… multi-stage Dockerfile, non-root
Test suiteβœ… 38 offline unit tests + 31 live integration tests
Audit runβœ… 2026-05-27 (mcp-audit-skill v1.0.0)

Phase-2 ideas (caching layer, semantic aggregation tool combining forest + snow + hazard data into a "Lage-Übersicht"): tracked under docs/.


Overview

The WSL (EidgenΓΆssische Forschungsanstalt fΓΌr Wald, Schnee und Landschaft / Swiss Federal Research Institute for Forest, Snow and Landscape) is one of Europe's leading environmental research institutes. Its open data platform EnviDat provides access to 1,000+ research datasets, time series of up to 130 years, and data from 6,000+ monitoring stations.

This MCP server exposes the EnviDat CKAN API as 10 tools and 2 resources, enabling AI assistants to search, filter and retrieve WSL research data by keyword, domain, or geographic bounding box β€” all without an API key.

Anchor demo query: "How was air quality and forest health around Schulhaus Leutschenbach in Zurich β€” and what does the WSL say about the current forest condition in the canton?"

Demo

Demo: Claude using wsl_get_avalanche_data, wsl_get_forest_data and wsl_catalog_stats


Features

  • 10 tools covering full-text search, domain-specific queries, spatial search, and curated thematic tools (avalanche, forest, natural hazards)
  • 2 MCP resources for organizations and research domains
  • 5 research domains: Forest Β· Biodiversity Β· Natural Hazards Β· Snow & Ice Β· Landscape
  • 815+ datasets, time series since 1890, data from the SLF avalanche research institute
  • No API key required β€” all data publicly accessible via open licenses
  • Dual transport: stdio (Claude Desktop / local) + Streamable HTTP (cloud deployment)
  • Model-agnostic: works with Claude, GPT-4, and any MCP-compatible client

Prerequisites

  • Python 3.11+
  • pip or uv / uvx
  • Internet connection (live API calls to envidat.ch)

Installation

# Recommended: uvx (no installation needed)
uvx wsl-envidat-mcp

# Or with pip
pip install wsl-envidat-mcp

# Development
git clone https://github.com/malkreide/wsl-envidat-mcp.git
cd wsl-envidat-mcp
pip install -e ".[dev]"

Quickstart

Claude Desktop

Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):

{
  "mcpServers": {
    "wsl-envidat": {
      "command": "uvx",
      "args": ["wsl-envidat-mcp"]
    }
  }
}

Restart Claude Desktop, then ask:

  • "What WSL datasets exist on fatal avalanche accidents in Switzerland?"
  • "Show me forest inventory data from the LFI for the canton of Zurich."
  • "Which natural hazard research data does the SLF publish on EnviDat?"
  • "Are there WSL datasets on drought conditions in summer 2022?"
  • "What biodiversity data is available for alpine ecosystems?"

Configuration

No API key required. Optional environment variables:

VariableDefaultDescription
MCP_TRANSPORTstdioTransport mode: stdio or streamable-http (legacy streamable_http is accepted)
MCP_HOST127.0.0.1Bind address for streamable-http. Use 0.0.0.0 only inside a container.
PORT8000Port for Streamable HTTP mode

Cloud Deployment (Streamable HTTP)

For use via claude.ai in the browser (e.g. on managed workstations without local software):

# Local: keep MCP_HOST at its default 127.0.0.1
MCP_TRANSPORT=streamable-http PORT=8000 python -m wsl_envidat_mcp.server

# Container: bind to all interfaces inside the container only
MCP_TRANSPORT=streamable-http MCP_HOST=0.0.0.0 PORT=8000 python -m wsl_envidat_mcp.server

πŸ’‘ "stdio for the developer laptop, streamable-http for the browser."

⚠️ Multi-Replica Cloud Deployments: Session state lives in the server. Run a single replica or enable sticky sessions (Railway/Render setting, or sessionAffinity: ClientIP on Kubernetes Services).

⚠️ Multi-Tenant / Unauthenticated Streamable HTTP: This server has no auth layer (auth_model: none). Streamable HTTP without a reverse-proxy + OAuth/API-Gateway is intended only for single-user deployments (e.g. one user's claude.ai browser session). For multi-tenant use, front the server with an authenticating gateway.

Container image (recommended for cloud)

A hardened multi-stage image is published to GitHub Container Registry on every main push and semver tag. Runs as non-root (uid=1000), no build tools in the runtime layer, multi-arch (linux/amd64 + linux/arm64).

docker run --rm -p 8000:8000 \
  --read-only --tmpfs /tmp \
  --cap-drop=ALL --security-opt=no-new-privileges \
  ghcr.io/malkreide/wsl-envidat-mcp:latest

Kubernetes hardening (excerpt):

securityContext:
  runAsNonRoot: true
  runAsUser: 1000
  readOnlyRootFilesystem: true
  allowPrivilegeEscalation: false
  capabilities: { drop: ["ALL"] }

Available Tools

ToolDescription
wsl_searchUnified search β€” combine query, domain, organization, and bbox filters
wsl_get_datasetFull metadata, DOI, download URLs for a specific dataset
wsl_list_organizationsList all WSL research units on EnviDat
wsl_get_organizationDetails of a specific research unit incl. datasets
wsl_list_tagsBrowse available tags/keywords
wsl_get_recent_datasetsMost recently updated datasets
wsl_get_avalanche_dataSLF avalanche & snow data (incl. fatal accidents since 1936)
wsl_get_forest_dataForest data incl. National Forest Inventory (LFI) & Sanasilva
wsl_get_naturgefahren_dataNatural hazard datasets (landslides, rockfall, floods)
wsl_catalog_statsCatalog overview and statistics

Example Use Cases

QueryTool
"Fatal avalanche accidents in Valais since 2000?"wsl_get_avalanche_data
"Forest health data for canton Zurich?"wsl_get_forest_data
"Landslide risk datasets near Brienz?"wsl_get_naturgefahren_data
"Most recent WSL publications on biodiversity?"wsl_search(domain="biodiversitaet")
"Which datasets cover the area around Lake Constance?"wsl_search(bbox=[9.0, 47.5, 9.7, 47.8])
"How many datasets does SLF publish?"wsl_get_organization

Resources

URIDescription
envidat://organization/{name}Research unit (e.g. slf, wsl)
envidat://domain/{domain}Domain overview with top datasets

Valid domain values: wald, biodiversitaet, naturgefahren, schnee_eis, landschaft


Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Claude / AI   │────▢│    WSL EnviDat MCP        │────▢│       envidat.ch          β”‚
β”‚   (MCP Host)    │◀────│    (MCP Server)           │◀────│                          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚                           β”‚     β”‚  CKAN API  (REST/JSON)   β”‚
                        β”‚  10 Tools Β· 2 Resources   β”‚     β”‚  Solr full-text search   β”‚
                        β”‚  Stdio | Streamable HTTP  β”‚     β”‚  1,000+ research datasetsβ”‚
                        β”‚                           β”‚     β”‚  815+ open datasets      β”‚
                        β”‚  server.py                β”‚     β”‚  Time series since 1890  β”‚
                        β”‚  api_client.py            β”‚     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Infrastructure Components

ComponentMetaphorFunction
api_client.pyLibrarianHandles all HTTP requests to EnviDat CKAN API
server.pyReception deskRegisters all 10 tools and 2 resources with FastMCP
Domain filtersFiling cabinetPre-configured keyword sets per research domain
Bounding box searchMap overlaySpatial filtering via lat/lon coordinates

Project Structure

wsl-envidat-mcp/
β”œβ”€β”€ src/wsl_envidat_mcp/
β”‚   β”œβ”€β”€ __init__.py         # Package
β”‚   β”œβ”€β”€ server.py           # MCP server β€” 10 tools, 2 resources
β”‚   └── api_client.py       # HTTP client for EnviDat CKAN API
β”œβ”€β”€ tests/
β”‚   └── test_integration.py # 11 live API integration tests
β”œβ”€β”€ .github/workflows/
β”‚   └── ci.yml              # GitHub Actions CI (Python 3.11–3.13)
β”œβ”€β”€ pyproject.toml          # Project config (hatchling build backend)
β”œβ”€β”€ CHANGELOG.md
β”œβ”€β”€ CONTRIBUTING.md         # Contribution guide (English)
β”œβ”€β”€ CONTRIBUTING.de.md      # Contribution guide (German)
β”œβ”€β”€ SECURITY.md             # Security policy & posture (English)
β”œβ”€β”€ SECURITY.de.md          # Security policy & posture (German)
β”œβ”€β”€ LICENSE                 # MIT
β”œβ”€β”€ README.md               # This file (English)
└── README.de.md            # German version

Combination with Other MCP Servers

This server is part of the Swiss Open Data MCP Portfolio and integrates well with:

CombinationUse Case
+ zurich-opendata-mcpUrban climate + forest condition around Zurich
+ swiss-statistics-mcpPopulation data + environmental quality
+ swiss-transport-mcpAvalanche risk + public transport connections
+ fedlex-mcpForest protection law + actual LFI forest condition
+ global-education-mcpCompare environmental education data internationally

Known Limitations

  • Solr search: OR is treated as a stopword β€” use single, specific search terms per query
  • Domain search: Results depend on WSL's internal keyword tagging β€” not all datasets are tagged consistently
  • Spatial search: Bounding box filtering is approximate; verify coordinates with individual dataset metadata
  • Live API: All tools make live calls to envidat.ch β€” results depend on availability of the public API
  • Languages: Dataset metadata is primarily in English and German; some older entries may be in German only

Safety & Limits

  • Read-only: All tools perform HTTP GET requests only β€” no data is written, modified, or deleted on EnviDat.
  • No personal data: The API returns research metadata, dataset descriptions, and download URLs. No personally identifiable information (PII) is processed or stored by this server.
  • Rate limits: The EnviDat CKAN API is public without documented rate limits. Use limit and rows parameters conservatively. The server enforces a 30-second timeout per request.
  • Data freshness: All tools make live API calls β€” results reflect the current state of the EnviDat catalog at query time. No caching is performed by this server.
  • Terms of service: Data is subject to the EnviDat Terms of Use. Individual datasets are published under various open licenses (Creative Commons, CC0) β€” see dataset metadata.
  • No guarantees: This is a community project, not affiliated with WSL or EnviDat. Availability depends on the upstream EnviDat API.

For the full security posture (egress allow-list, redirect handling, accepted risks) see SECURITY.md.


Testing

# Unit tests β€” offline, no network access, all CKAN responses mocked via respx
PYTHONPATH=src pytest -m "not live"

# Live integration tests β€” actual HTTP calls to envidat.ch
PYTHONPATH=src pytest -m live

# Linting
ruff check src/
ruff format --check src/

CI runs the offline suite on every PR. The live suite runs only on main pushes and manual workflow_dispatch triggers, so build status is not coupled to upstream availability.


Changelog

See CHANGELOG.md


Contributing

See CONTRIBUTING.md


Security

See SECURITY.md (Deutsch) for the security posture and how to report a vulnerability.


License

MIT License β€” see LICENSE

Data on EnviDat is published under various open licenses (Creative Commons, CC0) β€” see individual dataset metadata.


Author

Hayal Oezkan Β· malkreide


Credits & Related Projects

Installation

Run via uv's uvx β€” no clone or manual install needed. Add to your MCP client config (mcpServers for Claude Desktop, Cursor and Windsurf; use a top-level servers key for VS Code in .vscode/mcp.json):

{
  "mcpServers": {
    "wsl-envidat-mcp": {
      "command": "uvx",
      "args": [
        "wsl-envidat-mcp"
      ]
    }
  }
}

Rendered live from malkreide/wsl-envidat-mcp's GitHub README β€” not stored, always reflects the source repo.

1 Install Method

NameDescriptionCategorySource
pypi packageInstall via pypi (stdio transport)mcp-serverwsl-envidat-mcp

0 Comments

Login required
Log in to post a comment or update on this repo.

No comments yet β€” be the first to share an update.