@ansvar/ch-environmental-compliance-mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/check-freshness.yml +49 -0
- package/.github/workflows/ci.yml +21 -0
- package/.github/workflows/codeql.yml +25 -0
- package/.github/workflows/ghcr-build.yml +45 -0
- package/.github/workflows/gitleaks.yml +18 -0
- package/.github/workflows/ingest.yml +59 -0
- package/.github/workflows/publish.yml +24 -0
- package/CHANGELOG.md +15 -0
- package/CODEOWNERS +1 -0
- package/COVERAGE.md +50 -0
- package/DISCLAIMER.md +48 -0
- package/Dockerfile +26 -0
- package/LICENSE +17 -0
- package/PRIVACY.md +23 -0
- package/README.md +116 -0
- package/SECURITY.md +25 -0
- package/TOOLS.md +142 -0
- package/data/coverage.json +24 -0
- package/data/database.db +0 -0
- package/data/sources.yml +36 -0
- package/dist/db.d.ts +25 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +197 -0
- package/dist/db.js.map +1 -0
- package/dist/http-server.d.ts +2 -0
- package/dist/http-server.d.ts.map +1 -0
- package/dist/http-server.js +274 -0
- package/dist/http-server.js.map +1 -0
- package/dist/jurisdiction.d.ts +18 -0
- package/dist/jurisdiction.d.ts.map +1 -0
- package/dist/jurisdiction.js +16 -0
- package/dist/jurisdiction.js.map +1 -0
- package/dist/metadata.d.ts +10 -0
- package/dist/metadata.d.ts.map +1 -0
- package/dist/metadata.js +22 -0
- package/dist/metadata.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +220 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/about.d.ts +15 -0
- package/dist/tools/about.d.ts.map +1 -0
- package/dist/tools/about.js +27 -0
- package/dist/tools/about.js.map +1 -0
- package/dist/tools/check-environmental-compliance.d.ts +30 -0
- package/dist/tools/check-environmental-compliance.d.ts.map +1 -0
- package/dist/tools/check-environmental-compliance.js +103 -0
- package/dist/tools/check-environmental-compliance.js.map +1 -0
- package/dist/tools/check-freshness.d.ts +15 -0
- package/dist/tools/check-freshness.d.ts.map +1 -0
- package/dist/tools/check-freshness.js +26 -0
- package/dist/tools/check-freshness.js.map +1 -0
- package/dist/tools/get-ammonia-rules.d.ts +24 -0
- package/dist/tools/get-ammonia-rules.d.ts.map +1 -0
- package/dist/tools/get-ammonia-rules.js +31 -0
- package/dist/tools/get-ammonia-rules.js.map +1 -0
- package/dist/tools/get-bff-requirements.d.ts +26 -0
- package/dist/tools/get-bff-requirements.d.ts.map +1 -0
- package/dist/tools/get-bff-requirements.js +36 -0
- package/dist/tools/get-bff-requirements.js.map +1 -0
- package/dist/tools/get-buffer-zone-rules.d.ts +23 -0
- package/dist/tools/get-buffer-zone-rules.d.ts.map +1 -0
- package/dist/tools/get-buffer-zone-rules.js +30 -0
- package/dist/tools/get-buffer-zone-rules.js.map +1 -0
- package/dist/tools/get-eip-requirements.d.ts +31 -0
- package/dist/tools/get-eip-requirements.d.ts.map +1 -0
- package/dist/tools/get-eip-requirements.js +40 -0
- package/dist/tools/get-eip-requirements.js.map +1 -0
- package/dist/tools/get-nutrient-loss-limits.d.ts +24 -0
- package/dist/tools/get-nutrient-loss-limits.d.ts.map +1 -0
- package/dist/tools/get-nutrient-loss-limits.js +31 -0
- package/dist/tools/get-nutrient-loss-limits.js.map +1 -0
- package/dist/tools/get-water-protection-zones.d.ts +32 -0
- package/dist/tools/get-water-protection-zones.d.ts.map +1 -0
- package/dist/tools/get-water-protection-zones.js +36 -0
- package/dist/tools/get-water-protection-zones.js.map +1 -0
- package/dist/tools/list-sources.d.ts +18 -0
- package/dist/tools/list-sources.d.ts.map +1 -0
- package/dist/tools/list-sources.js +61 -0
- package/dist/tools/list-sources.js.map +1 -0
- package/dist/tools/search-environmental-rules.d.ts +25 -0
- package/dist/tools/search-environmental-rules.d.ts.map +1 -0
- package/dist/tools/search-environmental-rules.js +26 -0
- package/dist/tools/search-environmental-rules.js.map +1 -0
- package/docker-compose.yml +12 -0
- package/eslint.config.js +26 -0
- package/package.json +54 -0
- package/scripts/ingest.ts +911 -0
- package/server.json +16 -0
- package/src/db.ts +238 -0
- package/src/http-server.ts +307 -0
- package/src/jurisdiction.ts +30 -0
- package/src/metadata.ts +32 -0
- package/src/server.ts +244 -0
- package/src/tools/about.ts +28 -0
- package/src/tools/check-environmental-compliance.ts +143 -0
- package/src/tools/check-freshness.ts +42 -0
- package/src/tools/get-ammonia-rules.ts +44 -0
- package/src/tools/get-bff-requirements.ts +52 -0
- package/src/tools/get-buffer-zone-rules.ts +43 -0
- package/src/tools/get-eip-requirements.ts +57 -0
- package/src/tools/get-nutrient-loss-limits.ts +44 -0
- package/src/tools/get-water-protection-zones.ts +50 -0
- package/src/tools/list-sources.ts +75 -0
- package/src/tools/search-environmental-rules.ts +35 -0
- package/tests/db.test.ts +80 -0
- package/tests/helpers/seed-db.ts +173 -0
- package/tests/jurisdiction.test.ts +35 -0
- package/tests/tools/about.test.ts +26 -0
- package/tests/tools/check-freshness.test.ts +50 -0
- package/tests/tools/list-sources.test.ts +61 -0
- package/tests/tools/search-environmental-rules.test.ts +47 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
name: Check Data Freshness
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
schedule:
|
|
5
|
+
- cron: "0 8 * * *"
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
issues: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
freshness:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- uses: actions/setup-node@v4
|
|
18
|
+
with:
|
|
19
|
+
node-version: "20"
|
|
20
|
+
cache: npm
|
|
21
|
+
- run: npm ci
|
|
22
|
+
- name: Check freshness
|
|
23
|
+
id: check
|
|
24
|
+
run: |
|
|
25
|
+
if npm run freshness:check 2>&1; then
|
|
26
|
+
echo "stale=false" >> "$GITHUB_OUTPUT"
|
|
27
|
+
else
|
|
28
|
+
echo "stale=true" >> "$GITHUB_OUTPUT"
|
|
29
|
+
fi
|
|
30
|
+
- name: Create issue if stale
|
|
31
|
+
if: steps.check.outputs.stale == 'true'
|
|
32
|
+
uses: actions/github-script@v7
|
|
33
|
+
with:
|
|
34
|
+
script: |
|
|
35
|
+
const existing = await github.rest.issues.listForRepo({
|
|
36
|
+
owner: context.repo.owner,
|
|
37
|
+
repo: context.repo.repo,
|
|
38
|
+
labels: 'data-stale',
|
|
39
|
+
state: 'open'
|
|
40
|
+
});
|
|
41
|
+
if (existing.data.length === 0) {
|
|
42
|
+
await github.rest.issues.create({
|
|
43
|
+
owner: context.repo.owner,
|
|
44
|
+
repo: context.repo.repo,
|
|
45
|
+
title: 'Data is stale — re-ingestion needed',
|
|
46
|
+
body: 'The daily freshness check detected stale data. Run the ingestion workflow to update.\n\n`gh workflow run ingest.yml`',
|
|
47
|
+
labels: ['data-stale']
|
|
48
|
+
});
|
|
49
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, dev]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
build:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
- uses: actions/setup-node@v4
|
|
15
|
+
with:
|
|
16
|
+
node-version: "20"
|
|
17
|
+
cache: npm
|
|
18
|
+
- run: npm ci
|
|
19
|
+
- run: npm run typecheck
|
|
20
|
+
- run: npm run lint
|
|
21
|
+
- run: npm test
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
name: CodeQL
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
schedule:
|
|
9
|
+
- cron: "0 6 * * 1"
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
actions: read
|
|
13
|
+
contents: read
|
|
14
|
+
security-events: write
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
analyze:
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
- uses: github/codeql-action/init@v3
|
|
22
|
+
with:
|
|
23
|
+
languages: javascript-typescript
|
|
24
|
+
- uses: github/codeql-action/autobuild@v3
|
|
25
|
+
- uses: github/codeql-action/analyze@v3
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
name: Build and Push to GHCR
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
concurrency:
|
|
9
|
+
group: build-${{ github.ref }}
|
|
10
|
+
cancel-in-progress: true
|
|
11
|
+
|
|
12
|
+
env:
|
|
13
|
+
REGISTRY: ghcr.io
|
|
14
|
+
IMAGE_NAME: ch-environmental-compliance-mcp
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: read
|
|
18
|
+
packages: write
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
build-and-push:
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v4
|
|
25
|
+
- uses: docker/setup-buildx-action@v3
|
|
26
|
+
- uses: docker/login-action@v3
|
|
27
|
+
with:
|
|
28
|
+
registry: ghcr.io
|
|
29
|
+
username: ${{ github.actor }}
|
|
30
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
31
|
+
- uses: docker/metadata-action@v5
|
|
32
|
+
id: meta
|
|
33
|
+
with:
|
|
34
|
+
images: ${{ env.REGISTRY }}/ansvar-systems/${{ env.IMAGE_NAME }}
|
|
35
|
+
tags: |
|
|
36
|
+
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }}
|
|
37
|
+
type=sha,prefix=sha-,format=short
|
|
38
|
+
- uses: docker/build-push-action@v5
|
|
39
|
+
with:
|
|
40
|
+
context: .
|
|
41
|
+
push: true
|
|
42
|
+
tags: ${{ steps.meta.outputs.tags }}
|
|
43
|
+
platforms: linux/amd64
|
|
44
|
+
cache-from: type=gha
|
|
45
|
+
cache-to: type=gha,mode=max
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
name: Gitleaks
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, dev]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
scan:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
with:
|
|
15
|
+
fetch-depth: 0
|
|
16
|
+
- uses: gitleaks/gitleaks-action@v2
|
|
17
|
+
env:
|
|
18
|
+
GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
name: Re-ingest Data
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
schedule:
|
|
5
|
+
- cron: "0 4 1 * *"
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
inputs:
|
|
8
|
+
force:
|
|
9
|
+
description: "Force full rebuild even if no changes detected"
|
|
10
|
+
type: boolean
|
|
11
|
+
default: false
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: write
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
ingest:
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
- uses: actions/setup-node@v4
|
|
22
|
+
with:
|
|
23
|
+
node-version: "20"
|
|
24
|
+
cache: npm
|
|
25
|
+
- run: npm ci
|
|
26
|
+
|
|
27
|
+
- name: Fetch upstream data
|
|
28
|
+
run: npm run ingest:fetch
|
|
29
|
+
|
|
30
|
+
- name: Check for changes
|
|
31
|
+
id: diff
|
|
32
|
+
run: |
|
|
33
|
+
if [ "${{ inputs.force }}" = "true" ] || npm run ingest:diff 2>&1 | grep -q "changes detected"; then
|
|
34
|
+
echo "changed=true" >> "$GITHUB_OUTPUT"
|
|
35
|
+
else
|
|
36
|
+
echo "changed=false" >> "$GITHUB_OUTPUT"
|
|
37
|
+
echo "No upstream changes detected. Skipping rebuild."
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
- name: Rebuild database
|
|
41
|
+
if: steps.diff.outputs.changed == 'true'
|
|
42
|
+
run: npm run ingest:full
|
|
43
|
+
|
|
44
|
+
- name: Run tests
|
|
45
|
+
if: steps.diff.outputs.changed == 'true'
|
|
46
|
+
run: npm test
|
|
47
|
+
|
|
48
|
+
- name: Update coverage
|
|
49
|
+
if: steps.diff.outputs.changed == 'true'
|
|
50
|
+
run: npm run coverage:update
|
|
51
|
+
|
|
52
|
+
- name: Commit updated database
|
|
53
|
+
if: steps.diff.outputs.changed == 'true'
|
|
54
|
+
run: |
|
|
55
|
+
git config user.name "github-actions[bot]"
|
|
56
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
57
|
+
git add data/database.db data/coverage.json data/.source-hashes.json
|
|
58
|
+
git diff --staged --quiet || git commit -m "chore: re-ingest data $(date +%Y-%m-%d)"
|
|
59
|
+
git push
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name: Publish to npm
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
id-token: write
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
publish:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: actions/setup-node@v4
|
|
17
|
+
with:
|
|
18
|
+
node-version: "20"
|
|
19
|
+
registry-url: "https://registry.npmjs.org"
|
|
20
|
+
- run: npm ci
|
|
21
|
+
- run: npm run build
|
|
22
|
+
- run: npm publish --provenance --access public
|
|
23
|
+
env:
|
|
24
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.1.0] - 2026-04-05
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Initial release with 11 MCP tools (3 meta + 8 domain)
|
|
8
|
+
- SQLite + FTS5 database with schema for water protection zones, buffer zones, ammonia rules, BFF types, nutrient loss limits, environmental rules (UVP + VBBo)
|
|
9
|
+
- Compliance checker that evaluates applicable rules for a given agricultural operation
|
|
10
|
+
- Dual transport: stdio (npm) and Streamable HTTP (Docker)
|
|
11
|
+
- Jurisdiction validation (CH supported)
|
|
12
|
+
- Data freshness monitoring with 90-day staleness threshold
|
|
13
|
+
- Docker image with non-root user, health check
|
|
14
|
+
- CI/CD: TypeScript build, lint, test, CodeQL, Gitleaks, GHCR image build, npm publish
|
|
15
|
+
- Bilingual DE/EN disclaimer covering GSchG, LRV, DZV, VBBo, UVPV
|
package/CODEOWNERS
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
* @ansvar-systems/engineering
|
package/COVERAGE.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Coverage
|
|
2
|
+
|
|
3
|
+
## What Is Included
|
|
4
|
+
|
|
5
|
+
- **Water protection zones** (Grundwasserschutzzonen): S1, S2, S3, Sm, Zu with restrictions and legal basis from GSchG/GSchV
|
|
6
|
+
- **Buffer zones** (Pufferstreifen): distances and requirements along water bodies, hedges, field boundaries from OELN/ChemRRV
|
|
7
|
+
- **Ammonia emission rules**: emission factors by application technique, Schleppschlauch-Pflicht, Agrammon parameters from LRV
|
|
8
|
+
- **Biodiversity areas** (BFF): types, QI/QII payment rates, minimum area requirements, botanical criteria from DZV
|
|
9
|
+
- **Nutrient loss limits**: Pa.Iv. 19.475 Absenkpfad for N and P through 2030, yearly milestones, Suisse-Bilanz tolerances
|
|
10
|
+
- **Environmental impact assessment** (UVP): thresholds for agricultural buildings from UVPV
|
|
11
|
+
- **Soil contamination** (VBBo): Richtwerte for heavy metals (Cd, Cu, Zn, Pb) and remediation triggers
|
|
12
|
+
|
|
13
|
+
## Data Counts
|
|
14
|
+
|
|
15
|
+
| Table | Records |
|
|
16
|
+
|-------|---------|
|
|
17
|
+
| Water protection zones | 5 |
|
|
18
|
+
| Buffer zones | 9 |
|
|
19
|
+
| Ammonia rules | 10 |
|
|
20
|
+
| BFF types | 18 |
|
|
21
|
+
| Nutrient loss limits | 8 |
|
|
22
|
+
| Environmental rules (UVP + VBBo) | 16 |
|
|
23
|
+
| FTS5 search entries | 66 |
|
|
24
|
+
|
|
25
|
+
## Jurisdictions
|
|
26
|
+
|
|
27
|
+
| Code | Country | Status |
|
|
28
|
+
|------|---------|--------|
|
|
29
|
+
| CH | Switzerland | Supported |
|
|
30
|
+
|
|
31
|
+
## What Is NOT Included
|
|
32
|
+
|
|
33
|
+
- **Cantonal implementation details** -- federal rules only; cantonal ordinances and derogations vary by canton
|
|
34
|
+
- **Real-time cantonal zone maps** -- Grundwasserschutzzonen are mapped by cantons; this server lists the zone types and restrictions, not spatial data
|
|
35
|
+
- **Pesticide product approvals** -- covered by the Swiss Plant Protection Products Register (BLW), not this server
|
|
36
|
+
- **Animal welfare regulations** (TSchG/TSchV) -- separate legal domain
|
|
37
|
+
- **Agricultural direct payment calculations** -- DZV BFF payment rates are included, but full Suisse-Bilanz calculations require farm-specific inputs
|
|
38
|
+
- **Cross-compliance details** (OELN full checklist) -- only environmental compliance topics are covered
|
|
39
|
+
- **EU regulation cross-references** -- Swiss environmental law is federal, not EU-harmonised for agriculture
|
|
40
|
+
|
|
41
|
+
## Known Gaps
|
|
42
|
+
|
|
43
|
+
1. BFF botanical quality criteria are summarised; full species lists per BFF type are not included
|
|
44
|
+
2. Agrammon emission factor detail depends on model version at time of ingestion
|
|
45
|
+
3. VBBo Richtwerte cover the most common heavy metals; trace organics are not included
|
|
46
|
+
4. Pa.Iv. 19.475 targets may be revised by Parliament before 2030 -- check BLW publications
|
|
47
|
+
|
|
48
|
+
## Data Freshness
|
|
49
|
+
|
|
50
|
+
Run `check_data_freshness` to see when data was last updated. The ingestion pipeline runs monthly; manual triggers available via `gh workflow run ingest.yml`.
|
package/DISCLAIMER.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Haftungsausschluss / Disclaimer
|
|
2
|
+
|
|
3
|
+
## Keine Rechtsberatung / Not Legal Advice
|
|
4
|
+
|
|
5
|
+
### Deutsch
|
|
6
|
+
|
|
7
|
+
Diese Daten dienen ausschliesslich der Information und stellen keine rechtliche oder umweltfachliche Beratung dar. Vor Massnahmen im Gewaesserschutz, bei Ammoniakemissionen, Biodiversitaetsfoerderflaechen oder Naehrstoffverlusten ist stets die zustaendige kantonale Fachstelle oder das BAFU zu konsultieren.
|
|
8
|
+
|
|
9
|
+
### English
|
|
10
|
+
|
|
11
|
+
This data is provided for informational purposes only and does not constitute legal or environmental compliance advice. Always consult the relevant cantonal authority or BAFU before taking action.
|
|
12
|
+
|
|
13
|
+
## Datenquellen / Data Sources
|
|
14
|
+
|
|
15
|
+
Die Daten stammen aus folgenden Quellen / Data is sourced from:
|
|
16
|
+
|
|
17
|
+
- **GSchG (SR 814.20)** -- Gewaesserschutzgesetz / Federal Act on the Protection of Waters
|
|
18
|
+
- **GSchV (SR 814.201)** -- Gewaesserschutzverordnung / Waters Protection Ordinance
|
|
19
|
+
- **LRV (SR 814.318.142.1)** -- Luftreinhalte-Verordnung / Air Pollution Control Ordinance
|
|
20
|
+
- **DZV (SR 910.13)** -- Direktzahlungsverordnung / Direct Payments Ordinance
|
|
21
|
+
- **VBBo (SR 814.12)** -- Verordnung ueber Belastungen des Bodens / Ordinance on Soil Contamination
|
|
22
|
+
- **UVPV (SR 814.011)** -- Verordnung ueber die Umweltvertraeglichkeitspruefung
|
|
23
|
+
- **BAFU** -- Bundesamt fuer Umwelt (Federal Office for the Environment)
|
|
24
|
+
- **BLW** -- Bundesamt fuer Landwirtschaft (Federal Office for Agriculture)
|
|
25
|
+
- **Agroscope** -- Agrammon-Modell (Ammoniakemissionsfaktoren)
|
|
26
|
+
- **Pa.Iv. 19.475** -- Parlamentarische Initiative Absenkpfad Naehrstoffverluste
|
|
27
|
+
|
|
28
|
+
Alle Daten werden unter den Grundsaetzen der Weiterverwendung von oeffentlichen Informationen der Schweizerischen Eidgenossenschaft genutzt.
|
|
29
|
+
|
|
30
|
+
All data is used under Swiss Federal Administration free-reuse principles.
|
|
31
|
+
|
|
32
|
+
## Kantonale Abweichungen / Cantonal Variations
|
|
33
|
+
|
|
34
|
+
Die Schweiz ist foederalistisch organisiert. Kantone koennen strengere Auflagen als der Bund erlassen. Insbesondere bei Grundwasserschutzzonen, UVP-Schwellenwerten und BFF-Anforderungen koennen kantonale Regelungen abweichen.
|
|
35
|
+
|
|
36
|
+
Switzerland is a federal state. Cantons may impose stricter requirements than federal law. Water protection zones, EIA thresholds, and BFF requirements may differ by canton.
|
|
37
|
+
|
|
38
|
+
## Aktualitaet / Currency
|
|
39
|
+
|
|
40
|
+
Umweltvorschriften aendern sich. Insbesondere die Pa.Iv. 19.475 Absenkpfade werden jaehrlich aktualisiert. Pruefen Sie `check_data_freshness` fuer das Alter der Daten.
|
|
41
|
+
|
|
42
|
+
Environmental regulations change. Pa.Iv. 19.475 targets are updated annually. Use `check_data_freshness` to verify data age.
|
|
43
|
+
|
|
44
|
+
## Keine Gewaehrleistung / No Warranty
|
|
45
|
+
|
|
46
|
+
Diese Software wird ohne jegliche Gewaehrleistung bereitgestellt. Siehe Apache-2.0-Lizenz.
|
|
47
|
+
|
|
48
|
+
This software is provided "as is" without warranty of any kind. See the Apache-2.0 license for details.
|
package/Dockerfile
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
FROM node:20-slim AS builder
|
|
2
|
+
RUN apt-get update && apt-get install -y python3 make g++ && rm -rf /var/lib/apt/lists/*
|
|
3
|
+
WORKDIR /app
|
|
4
|
+
COPY package*.json ./
|
|
5
|
+
RUN npm ci
|
|
6
|
+
COPY tsconfig.json ./
|
|
7
|
+
COPY src/ src/
|
|
8
|
+
RUN npm run build
|
|
9
|
+
|
|
10
|
+
FROM node:20-slim
|
|
11
|
+
RUN apt-get update && apt-get install -y python3 make g++ && rm -rf /var/lib/apt/lists/*
|
|
12
|
+
RUN addgroup --system --gid 1001 nodejs && \
|
|
13
|
+
adduser --system --uid 1001 nodejs
|
|
14
|
+
WORKDIR /app
|
|
15
|
+
COPY package*.json ./
|
|
16
|
+
RUN npm ci --omit=dev && npm cache clean --force && apt-get purge -y python3 make g++ && apt-get autoremove -y
|
|
17
|
+
COPY --from=builder /app/dist dist/
|
|
18
|
+
COPY data/ data/
|
|
19
|
+
RUN chown -R nodejs:nodejs /app/data
|
|
20
|
+
USER nodejs
|
|
21
|
+
ENV NODE_ENV=production
|
|
22
|
+
ENV PORT=3000
|
|
23
|
+
EXPOSE 3000
|
|
24
|
+
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
|
|
25
|
+
CMD node -e "require('http').get('http://localhost:' + process.env.PORT + '/health', (r) => { process.exit(r.statusCode === 200 ? 0 : 1) })"
|
|
26
|
+
CMD ["node", "dist/http-server.js"]
|
package/LICENSE
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
you may not use this file except in compliance with the License.
|
|
7
|
+
You may obtain a copy of the License at
|
|
8
|
+
|
|
9
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
|
|
11
|
+
Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
See the License for the specific language governing permissions and
|
|
15
|
+
limitations under the License.
|
|
16
|
+
|
|
17
|
+
Copyright 2026 Ansvar Systems
|
package/PRIVACY.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Privacy Statement
|
|
2
|
+
|
|
3
|
+
## No Data Collection
|
|
4
|
+
|
|
5
|
+
This MCP server:
|
|
6
|
+
|
|
7
|
+
- Does **not** collect, store, or transmit any user data
|
|
8
|
+
- Does **not** use cookies, analytics, or telemetry
|
|
9
|
+
- Does **not** require user accounts or authentication
|
|
10
|
+
- Does **not** log queries or usage patterns
|
|
11
|
+
- Does **not** store any client-side state
|
|
12
|
+
|
|
13
|
+
## Data Served
|
|
14
|
+
|
|
15
|
+
All data returned by this server is sourced from publicly available Swiss federal publications (BAFU, BLW, Agroscope). No personal data, proprietary data, or confidential information is included.
|
|
16
|
+
|
|
17
|
+
## Self-Hosting
|
|
18
|
+
|
|
19
|
+
This server can be self-hosted. When you run it locally via npm or Docker, all processing happens on your machine. No external network calls are made at query time -- all data is embedded in the SQLite database.
|
|
20
|
+
|
|
21
|
+
## Contact
|
|
22
|
+
|
|
23
|
+
For privacy questions: privacy@ansvar.eu
|
package/README.md
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Switzerland Environmental Compliance MCP
|
|
2
|
+
|
|
3
|
+
[](https://github.com/ansvar-systems/ch-environmental-compliance-mcp/actions/workflows/ci.yml)
|
|
4
|
+
[](https://github.com/ansvar-systems/ch-environmental-compliance-mcp/actions/workflows/ghcr-build.yml)
|
|
5
|
+
[](https://opensource.org/licenses/Apache-2.0)
|
|
6
|
+
|
|
7
|
+
Swiss environmental compliance data for agriculture via the [Model Context Protocol](https://modelcontextprotocol.io). Water protection zones, buffer strips, ammonia emissions, biodiversity areas, nutrient loss targets, EIA thresholds, and soil contamination limits -- all from your AI assistant.
|
|
8
|
+
|
|
9
|
+
Part of [Ansvar Open Agriculture](https://ansvar.eu/open-agriculture).
|
|
10
|
+
|
|
11
|
+
## Why This Exists
|
|
12
|
+
|
|
13
|
+
Swiss farms must comply with federal environmental regulations across several domains: Gewaesserschutz (GSchG/GSchV), ammonia emissions (LRV), Biodiversitaetsfoerderflaechen (DZV), the Pa.Iv. 19.475 nutrient loss reduction pathway, and UVP/VBBo for building permits and soil protection. These rules are published by BAFU, BLW, and Agroscope but scattered across ordinances, fact sheets, and cantonal guidance. This MCP server brings them together in a structured, searchable format.
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
### Claude Desktop
|
|
18
|
+
|
|
19
|
+
Add to `claude_desktop_config.json`:
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"mcpServers": {
|
|
24
|
+
"ch-environmental-compliance": {
|
|
25
|
+
"command": "npx",
|
|
26
|
+
"args": ["-y", "@ansvar/ch-environmental-compliance-mcp"]
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Claude Code
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
claude mcp add ch-environmental-compliance npx @ansvar/ch-environmental-compliance-mcp
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Streamable HTTP (remote)
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
https://mcp.ansvar.eu/ch-environmental-compliance/mcp
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Docker (self-hosted)
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
docker run -p 3000:3000 ghcr.io/ansvar-systems/ch-environmental-compliance-mcp:latest
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### npm (stdio)
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
npx @ansvar/ch-environmental-compliance-mcp
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Example Queries
|
|
57
|
+
|
|
58
|
+
Ask your AI assistant:
|
|
59
|
+
|
|
60
|
+
- "Welche Grundwasserschutzzonen gibt es und was ist dort verboten?"
|
|
61
|
+
- "Wie breit muessen Pufferstreifen an Gewaessern sein?"
|
|
62
|
+
- "Ab wann gilt die Schleppschlauch-Pflicht fuer Guellausbringung?"
|
|
63
|
+
- "Welche BFF-Typen erhalten QII-Beitraege?"
|
|
64
|
+
- "Was sind die Naehrstoffverlust-Reduktionsziele fuer 2027?"
|
|
65
|
+
- "Check compliance for a 60-head dairy farm on 35 hectares"
|
|
66
|
+
|
|
67
|
+
## Stats
|
|
68
|
+
|
|
69
|
+
| Metric | Value |
|
|
70
|
+
|--------|-------|
|
|
71
|
+
| Tools | 11 (3 meta + 8 domain) |
|
|
72
|
+
| Jurisdiction | CH |
|
|
73
|
+
| Data sources | BAFU (GSchG/GSchV, LRV, VBBo), BLW (DZV, OELN), Agroscope (Agrammon), Parlament (Pa.Iv. 19.475) |
|
|
74
|
+
| License (data) | Swiss Federal Administration -- free reuse |
|
|
75
|
+
| License (code) | Apache-2.0 |
|
|
76
|
+
| Transport | stdio + Streamable HTTP |
|
|
77
|
+
|
|
78
|
+
## Tools
|
|
79
|
+
|
|
80
|
+
| Tool | Description |
|
|
81
|
+
|------|-------------|
|
|
82
|
+
| `about` | Server metadata and links |
|
|
83
|
+
| `list_sources` | Data sources with freshness info |
|
|
84
|
+
| `check_data_freshness` | Staleness status and refresh command |
|
|
85
|
+
| `search_environmental_rules` | FTS5 search across all environmental compliance topics |
|
|
86
|
+
| `get_water_protection_zones` | Grundwasserschutzzonen S1-S3/Sm/Zu with restrictions |
|
|
87
|
+
| `get_buffer_zone_rules` | Pufferstreifen distances and requirements |
|
|
88
|
+
| `get_ammonia_rules` | Ammoniakemissionen by technique (LRV) |
|
|
89
|
+
| `get_bff_requirements` | BFF types, QI/QII payment rates, botanical criteria |
|
|
90
|
+
| `get_nutrient_loss_limits` | Pa.Iv. 19.475 N/P reduction targets through 2030 |
|
|
91
|
+
| `get_eip_requirements` | UVP thresholds and VBBo soil contamination limits |
|
|
92
|
+
| `check_environmental_compliance` | Applicable rules for a given agricultural operation |
|
|
93
|
+
|
|
94
|
+
See [TOOLS.md](TOOLS.md) for full parameter documentation.
|
|
95
|
+
|
|
96
|
+
## Security Scanning
|
|
97
|
+
|
|
98
|
+
This repository runs security checks on every push:
|
|
99
|
+
|
|
100
|
+
- **CodeQL** -- static analysis for JavaScript/TypeScript
|
|
101
|
+
- **Gitleaks** -- secret detection across full history
|
|
102
|
+
- **Dependency review** -- via Dependabot
|
|
103
|
+
|
|
104
|
+
See [SECURITY.md](SECURITY.md) for reporting policy.
|
|
105
|
+
|
|
106
|
+
## Disclaimer
|
|
107
|
+
|
|
108
|
+
This data is for reference only. **Always consult the relevant cantonal authority or BAFU before taking action.** This tool is not legal or environmental compliance advice. See [DISCLAIMER.md](DISCLAIMER.md).
|
|
109
|
+
|
|
110
|
+
## Contributing
|
|
111
|
+
|
|
112
|
+
Issues and pull requests welcome. For security vulnerabilities, email security@ansvar.eu (do not open a public issue).
|
|
113
|
+
|
|
114
|
+
## License
|
|
115
|
+
|
|
116
|
+
Apache-2.0. Data sourced from Swiss Federal Administration publications under free-reuse principles.
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Reporting a Vulnerability
|
|
4
|
+
|
|
5
|
+
If you discover a security vulnerability, please report it responsibly:
|
|
6
|
+
|
|
7
|
+
1. **Do NOT open a public issue**
|
|
8
|
+
2. Email security@ansvar.eu with:
|
|
9
|
+
- Description of the vulnerability
|
|
10
|
+
- Steps to reproduce
|
|
11
|
+
- Potential impact
|
|
12
|
+
3. We will acknowledge within 48 hours and provide a timeline for fix
|
|
13
|
+
|
|
14
|
+
## Supported Versions
|
|
15
|
+
|
|
16
|
+
| Version | Supported |
|
|
17
|
+
|---------|-----------|
|
|
18
|
+
| Latest | Yes |
|
|
19
|
+
|
|
20
|
+
## Security Measures
|
|
21
|
+
|
|
22
|
+
- All dependencies scanned via CodeQL, Gitleaks, and Dependabot
|
|
23
|
+
- No secrets stored in code -- all data is public domain
|
|
24
|
+
- SQLite database is read-only at runtime
|
|
25
|
+
- Container runs as non-root with no-new-privileges and cap_drop ALL
|