@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.
Files changed (113) hide show
  1. package/.github/workflows/check-freshness.yml +49 -0
  2. package/.github/workflows/ci.yml +21 -0
  3. package/.github/workflows/codeql.yml +25 -0
  4. package/.github/workflows/ghcr-build.yml +45 -0
  5. package/.github/workflows/gitleaks.yml +18 -0
  6. package/.github/workflows/ingest.yml +59 -0
  7. package/.github/workflows/publish.yml +24 -0
  8. package/CHANGELOG.md +15 -0
  9. package/CODEOWNERS +1 -0
  10. package/COVERAGE.md +50 -0
  11. package/DISCLAIMER.md +48 -0
  12. package/Dockerfile +26 -0
  13. package/LICENSE +17 -0
  14. package/PRIVACY.md +23 -0
  15. package/README.md +116 -0
  16. package/SECURITY.md +25 -0
  17. package/TOOLS.md +142 -0
  18. package/data/coverage.json +24 -0
  19. package/data/database.db +0 -0
  20. package/data/sources.yml +36 -0
  21. package/dist/db.d.ts +25 -0
  22. package/dist/db.d.ts.map +1 -0
  23. package/dist/db.js +197 -0
  24. package/dist/db.js.map +1 -0
  25. package/dist/http-server.d.ts +2 -0
  26. package/dist/http-server.d.ts.map +1 -0
  27. package/dist/http-server.js +274 -0
  28. package/dist/http-server.js.map +1 -0
  29. package/dist/jurisdiction.d.ts +18 -0
  30. package/dist/jurisdiction.d.ts.map +1 -0
  31. package/dist/jurisdiction.js +16 -0
  32. package/dist/jurisdiction.js.map +1 -0
  33. package/dist/metadata.d.ts +10 -0
  34. package/dist/metadata.d.ts.map +1 -0
  35. package/dist/metadata.js +22 -0
  36. package/dist/metadata.js.map +1 -0
  37. package/dist/server.d.ts +3 -0
  38. package/dist/server.d.ts.map +1 -0
  39. package/dist/server.js +220 -0
  40. package/dist/server.js.map +1 -0
  41. package/dist/tools/about.d.ts +15 -0
  42. package/dist/tools/about.d.ts.map +1 -0
  43. package/dist/tools/about.js +27 -0
  44. package/dist/tools/about.js.map +1 -0
  45. package/dist/tools/check-environmental-compliance.d.ts +30 -0
  46. package/dist/tools/check-environmental-compliance.d.ts.map +1 -0
  47. package/dist/tools/check-environmental-compliance.js +103 -0
  48. package/dist/tools/check-environmental-compliance.js.map +1 -0
  49. package/dist/tools/check-freshness.d.ts +15 -0
  50. package/dist/tools/check-freshness.d.ts.map +1 -0
  51. package/dist/tools/check-freshness.js +26 -0
  52. package/dist/tools/check-freshness.js.map +1 -0
  53. package/dist/tools/get-ammonia-rules.d.ts +24 -0
  54. package/dist/tools/get-ammonia-rules.d.ts.map +1 -0
  55. package/dist/tools/get-ammonia-rules.js +31 -0
  56. package/dist/tools/get-ammonia-rules.js.map +1 -0
  57. package/dist/tools/get-bff-requirements.d.ts +26 -0
  58. package/dist/tools/get-bff-requirements.d.ts.map +1 -0
  59. package/dist/tools/get-bff-requirements.js +36 -0
  60. package/dist/tools/get-bff-requirements.js.map +1 -0
  61. package/dist/tools/get-buffer-zone-rules.d.ts +23 -0
  62. package/dist/tools/get-buffer-zone-rules.d.ts.map +1 -0
  63. package/dist/tools/get-buffer-zone-rules.js +30 -0
  64. package/dist/tools/get-buffer-zone-rules.js.map +1 -0
  65. package/dist/tools/get-eip-requirements.d.ts +31 -0
  66. package/dist/tools/get-eip-requirements.d.ts.map +1 -0
  67. package/dist/tools/get-eip-requirements.js +40 -0
  68. package/dist/tools/get-eip-requirements.js.map +1 -0
  69. package/dist/tools/get-nutrient-loss-limits.d.ts +24 -0
  70. package/dist/tools/get-nutrient-loss-limits.d.ts.map +1 -0
  71. package/dist/tools/get-nutrient-loss-limits.js +31 -0
  72. package/dist/tools/get-nutrient-loss-limits.js.map +1 -0
  73. package/dist/tools/get-water-protection-zones.d.ts +32 -0
  74. package/dist/tools/get-water-protection-zones.d.ts.map +1 -0
  75. package/dist/tools/get-water-protection-zones.js +36 -0
  76. package/dist/tools/get-water-protection-zones.js.map +1 -0
  77. package/dist/tools/list-sources.d.ts +18 -0
  78. package/dist/tools/list-sources.d.ts.map +1 -0
  79. package/dist/tools/list-sources.js +61 -0
  80. package/dist/tools/list-sources.js.map +1 -0
  81. package/dist/tools/search-environmental-rules.d.ts +25 -0
  82. package/dist/tools/search-environmental-rules.d.ts.map +1 -0
  83. package/dist/tools/search-environmental-rules.js +26 -0
  84. package/dist/tools/search-environmental-rules.js.map +1 -0
  85. package/docker-compose.yml +12 -0
  86. package/eslint.config.js +26 -0
  87. package/package.json +54 -0
  88. package/scripts/ingest.ts +911 -0
  89. package/server.json +16 -0
  90. package/src/db.ts +238 -0
  91. package/src/http-server.ts +307 -0
  92. package/src/jurisdiction.ts +30 -0
  93. package/src/metadata.ts +32 -0
  94. package/src/server.ts +244 -0
  95. package/src/tools/about.ts +28 -0
  96. package/src/tools/check-environmental-compliance.ts +143 -0
  97. package/src/tools/check-freshness.ts +42 -0
  98. package/src/tools/get-ammonia-rules.ts +44 -0
  99. package/src/tools/get-bff-requirements.ts +52 -0
  100. package/src/tools/get-buffer-zone-rules.ts +43 -0
  101. package/src/tools/get-eip-requirements.ts +57 -0
  102. package/src/tools/get-nutrient-loss-limits.ts +44 -0
  103. package/src/tools/get-water-protection-zones.ts +50 -0
  104. package/src/tools/list-sources.ts +75 -0
  105. package/src/tools/search-environmental-rules.ts +35 -0
  106. package/tests/db.test.ts +80 -0
  107. package/tests/helpers/seed-db.ts +173 -0
  108. package/tests/jurisdiction.test.ts +35 -0
  109. package/tests/tools/about.test.ts +26 -0
  110. package/tests/tools/check-freshness.test.ts +50 -0
  111. package/tests/tools/list-sources.test.ts +61 -0
  112. package/tests/tools/search-environmental-rules.test.ts +47 -0
  113. 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
+ [![CI](https://github.com/ansvar-systems/ch-environmental-compliance-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/ansvar-systems/ch-environmental-compliance-mcp/actions/workflows/ci.yml)
4
+ [![GHCR](https://github.com/ansvar-systems/ch-environmental-compliance-mcp/actions/workflows/ghcr-build.yml/badge.svg)](https://github.com/ansvar-systems/ch-environmental-compliance-mcp/actions/workflows/ghcr-build.yml)
5
+ [![License: Apache-2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](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