Wsl Envidat Mcp — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Wsl Envidat Mcp (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
🇨🇭 Part of the [Swiss Public Data MCP Portfolio](https://github.com/malkreide)
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.
This server is in Phase 1: Read-only Wrapper.
| Property | Status |
|---|---|
| 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/.
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](https://www.envidat.ch) 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: Claude using wsl_get_avalanche_data, wsl_get_forest_data and wsl_catalog_stats
pip or uv / uvx# 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]"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:
No API key required. Optional environment variables:
| Variable | Default | Description |
|---|---|---|
MCP_TRANSPORT | stdio | Transport mode: stdio or streamable-http (legacy streamable_http is accepted) |
MCP_HOST | 127.0.0.1 | Bind address for streamable-http. Use 0.0.0.0 only inside a container. |
PORT | 8000 | Port for Streamable HTTP mode |
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:latestKubernetes hardening (excerpt):
securityContext:
runAsNonRoot: true
runAsUser: 1000
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities: { drop: ["ALL"] }| Tool | Description |
|---|---|
wsl_search | Unified search — combine query, domain, organization, and bbox filters |
wsl_get_dataset | Full metadata, DOI, download URLs for a specific dataset |
wsl_list_organizations | List all WSL research units on EnviDat |
wsl_get_organization | Details of a specific research unit incl. datasets |
wsl_list_tags | Browse available tags/keywords |
wsl_get_recent_datasets | Most recently updated datasets |
wsl_get_avalanche_data | SLF avalanche & snow data (incl. fatal accidents since 1936) |
wsl_get_forest_data | Forest data incl. National Forest Inventory (LFI) & Sanasilva |
wsl_get_naturgefahren_data | Natural hazard datasets (landslides, rockfall, floods) |
wsl_catalog_stats | Catalog overview and statistics |
| Query | Tool |
|---|---|
| "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 |
| URI | Description |
|---|---|
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
┌─────────────────┐ ┌───────────────────────────┐ ┌──────────────────────────┐
│ 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 │ └──────────────────────────┘
└───────────────────────────┘| Component | Metaphor | Function |
|---|---|---|
api_client.py | Librarian | Handles all HTTP requests to EnviDat CKAN API |
server.py | Reception desk | Registers all 10 tools and 2 resources with FastMCP |
| Domain filters | Filing cabinet | Pre-configured keyword sets per research domain |
| Bounding box search | Map overlay | Spatial filtering via lat/lon coordinates |
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 versionThis server is part of the Swiss Open Data MCP Portfolio and integrates well with:
| Combination | Use Case |
|---|---|
+ zurich-opendata-mcp | Urban climate + forest condition around Zurich |
+ swiss-statistics-mcp | Population data + environmental quality |
+ swiss-transport-mcp | Avalanche risk + public transport connections |
+ fedlex-mcp | Forest protection law + actual LFI forest condition |
+ global-education-mcp | Compare environmental education data internationally |
OR is treated as a stopword — use single, specific search terms per querylimit and rows parameters conservatively. The server enforces a 30-second timeout per request.For the full security posture (egress allow-list, redirect handling, accepted risks) see SECURITY.md.
# 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.
See CHANGELOG.md
See CONTRIBUTING.md
MIT License — see LICENSE
Data on EnviDat is published under various open licenses (Creative Commons, CC0) — see individual dataset metadata.
Hayal Oezkan · malkreide
<!-- mcp-name: io.github.malkreide/wsl-envidat-mcp -->
<!-- BEGIN GENERATED: install -->
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"
]
}
}
}<!-- END GENERATED: install -->
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.