@ansvar/ch-farm-safety-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 (109) hide show
  1. package/.github/workflows/check-freshness.yml +53 -0
  2. package/.github/workflows/ci.yml +21 -0
  3. package/.github/workflows/codeql.yml +30 -0
  4. package/.github/workflows/ghcr-build.yml +45 -0
  5. package/.github/workflows/gitleaks.yml +24 -0
  6. package/.github/workflows/ingest.yml +67 -0
  7. package/.github/workflows/publish.yml +24 -0
  8. package/CHANGELOG.md +23 -0
  9. package/CODEOWNERS +1 -0
  10. package/COVERAGE.md +54 -0
  11. package/DISCLAIMER.md +51 -0
  12. package/Dockerfile +26 -0
  13. package/LICENSE +17 -0
  14. package/PRIVACY.md +25 -0
  15. package/README.md +129 -0
  16. package/SECURITY.md +25 -0
  17. package/TOOLS.md +140 -0
  18. package/data/coverage.json +22 -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 +200 -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 +250 -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 +20 -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 +196 -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-freshness.d.ts +15 -0
  46. package/dist/tools/check-freshness.d.ts.map +1 -0
  47. package/dist/tools/check-freshness.js +26 -0
  48. package/dist/tools/check-freshness.js.map +1 -0
  49. package/dist/tools/get-accident-reporting.d.ts +49 -0
  50. package/dist/tools/get-accident-reporting.d.ts.map +1 -0
  51. package/dist/tools/get-accident-reporting.js +31 -0
  52. package/dist/tools/get-accident-reporting.js.map +1 -0
  53. package/dist/tools/get-chemical-safety.d.ts +47 -0
  54. package/dist/tools/get-chemical-safety.d.ts.map +1 -0
  55. package/dist/tools/get-chemical-safety.js +31 -0
  56. package/dist/tools/get-chemical-safety.js.map +1 -0
  57. package/dist/tools/get-machinery-safety.d.ts +46 -0
  58. package/dist/tools/get-machinery-safety.d.ts.map +1 -0
  59. package/dist/tools/get-machinery-safety.js +31 -0
  60. package/dist/tools/get-machinery-safety.js.map +1 -0
  61. package/dist/tools/get-risk-assessment-requirements.d.ts +47 -0
  62. package/dist/tools/get-risk-assessment-requirements.d.ts.map +1 -0
  63. package/dist/tools/get-risk-assessment-requirements.js +31 -0
  64. package/dist/tools/get-risk-assessment-requirements.js.map +1 -0
  65. package/dist/tools/get-young-worker-rules.d.ts +47 -0
  66. package/dist/tools/get-young-worker-rules.d.ts.map +1 -0
  67. package/dist/tools/get-young-worker-rules.js +31 -0
  68. package/dist/tools/get-young-worker-rules.js.map +1 -0
  69. package/dist/tools/list-sources.d.ts +18 -0
  70. package/dist/tools/list-sources.d.ts.map +1 -0
  71. package/dist/tools/list-sources.js +51 -0
  72. package/dist/tools/list-sources.js.map +1 -0
  73. package/dist/tools/search-bul-guidance.d.ts +23 -0
  74. package/dist/tools/search-bul-guidance.d.ts.map +1 -0
  75. package/dist/tools/search-bul-guidance.js +35 -0
  76. package/dist/tools/search-bul-guidance.js.map +1 -0
  77. package/dist/tools/search-safety-rules.d.ts +25 -0
  78. package/dist/tools/search-safety-rules.d.ts.map +1 -0
  79. package/dist/tools/search-safety-rules.js +26 -0
  80. package/dist/tools/search-safety-rules.js.map +1 -0
  81. package/docker-compose.yml +12 -0
  82. package/eslint.config.js +27 -0
  83. package/package.json +54 -0
  84. package/scripts/ingest.ts +879 -0
  85. package/server.json +31 -0
  86. package/src/db.ts +241 -0
  87. package/src/http-server.ts +282 -0
  88. package/src/jurisdiction.ts +30 -0
  89. package/src/metadata.ts +30 -0
  90. package/src/server.ts +219 -0
  91. package/src/tools/about.ts +28 -0
  92. package/src/tools/check-freshness.ts +42 -0
  93. package/src/tools/get-accident-reporting.ts +52 -0
  94. package/src/tools/get-chemical-safety.ts +52 -0
  95. package/src/tools/get-machinery-safety.ts +52 -0
  96. package/src/tools/get-risk-assessment-requirements.ts +52 -0
  97. package/src/tools/get-young-worker-rules.ts +52 -0
  98. package/src/tools/list-sources.ts +65 -0
  99. package/src/tools/search-bul-guidance.ts +51 -0
  100. package/src/tools/search-safety-rules.ts +35 -0
  101. package/tests/db.test.ts +121 -0
  102. package/tests/helpers/seed-db.ts +134 -0
  103. package/tests/jurisdiction.test.ts +54 -0
  104. package/tests/tools/about.test.ts +44 -0
  105. package/tests/tools/check-freshness.test.ts +68 -0
  106. package/tests/tools/list-sources.test.ts +75 -0
  107. package/tests/tools/search-safety-rules.test.ts +75 -0
  108. package/tsconfig.json +19 -0
  109. package/vitest.config.ts +9 -0
@@ -0,0 +1,53 @@
1
+ name: Check Data Freshness
2
+
3
+ on:
4
+ schedule:
5
+ - cron: "0 6 * * 1"
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
+
23
+ - name: Check freshness
24
+ id: check
25
+ run: |
26
+ OUTPUT=$(npm run freshness:check --silent 2>&1 || true)
27
+ echo "$OUTPUT"
28
+ if echo "$OUTPUT" | grep -q '"status":"stale"'; then
29
+ echo "stale=true" >> "$GITHUB_OUTPUT"
30
+ else
31
+ echo "stale=false" >> "$GITHUB_OUTPUT"
32
+ fi
33
+
34
+ - name: Open issue if stale
35
+ if: steps.check.outputs.stale == 'true'
36
+ uses: actions/github-script@v7
37
+ with:
38
+ script: |
39
+ const existing = await github.rest.issues.listForRepo({
40
+ owner: context.repo.owner,
41
+ repo: context.repo.repo,
42
+ labels: 'data-freshness',
43
+ state: 'open',
44
+ });
45
+ if (existing.data.length === 0) {
46
+ await github.rest.issues.create({
47
+ owner: context.repo.owner,
48
+ repo: context.repo.repo,
49
+ title: 'Data is stale — re-ingestion needed',
50
+ body: 'The `check_data_freshness` tool reports data is older than 90 days.\n\nRun `gh workflow run ingest.yml` or `npm run ingest:full` to refresh.',
51
+ labels: ['data-freshness'],
52
+ });
53
+ }
@@ -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,30 @@
1
+ name: CodeQL
2
+
3
+ on:
4
+ push:
5
+ branches: [main, dev]
6
+ pull_request:
7
+ branches: [main]
8
+ schedule:
9
+ - cron: "30 4 * * 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
+ strategy:
20
+ matrix:
21
+ language: [javascript-typescript]
22
+ steps:
23
+ - uses: actions/checkout@v4
24
+ - uses: github/codeql-action/init@v3
25
+ with:
26
+ languages: ${{ matrix.language }}
27
+ - uses: github/codeql-action/autobuild@v3
28
+ - uses: github/codeql-action/analyze@v3
29
+ with:
30
+ category: "/language:${{ matrix.language }}"
@@ -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-farm-safety-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,24 @@
1
+ name: Gitleaks
2
+
3
+ on:
4
+ push:
5
+ branches: [main, dev]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ scan:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ with:
18
+ fetch-depth: 0
19
+ - name: Install gitleaks
20
+ run: |
21
+ curl -sSfL https://github.com/gitleaks/gitleaks/releases/download/v8.18.4/gitleaks_8.18.4_linux_x64.tar.gz | tar xz
22
+ sudo mv gitleaks /usr/local/bin/
23
+ - name: Run gitleaks
24
+ run: gitleaks detect --source . --verbose
@@ -0,0 +1,67 @@
1
+ name: Ingest Data
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ mode:
7
+ description: "Ingestion mode"
8
+ required: true
9
+ default: "incremental"
10
+ type: choice
11
+ options:
12
+ - incremental
13
+ - full
14
+ - diff-only
15
+ schedule:
16
+ - cron: "0 3 1 * *"
17
+
18
+ permissions:
19
+ contents: write
20
+ pull-requests: write
21
+
22
+ jobs:
23
+ ingest:
24
+ runs-on: ubuntu-latest
25
+ steps:
26
+ - uses: actions/checkout@v4
27
+ - uses: actions/setup-node@v4
28
+ with:
29
+ node-version: "20"
30
+ cache: npm
31
+ - run: npm ci
32
+
33
+ - name: Run ingestion
34
+ run: |
35
+ case "${{ inputs.mode || 'incremental' }}" in
36
+ full) npm run ingest:full ;;
37
+ diff-only) npm run ingest:diff ;;
38
+ *) npm run ingest ;;
39
+ esac
40
+
41
+ - name: Update coverage.json
42
+ run: npm run coverage:update
43
+
44
+ - name: Check for changes
45
+ id: changes
46
+ run: |
47
+ if git diff --quiet data/; then
48
+ echo "changed=false" >> "$GITHUB_OUTPUT"
49
+ else
50
+ echo "changed=true" >> "$GITHUB_OUTPUT"
51
+ fi
52
+
53
+ - name: Create PR
54
+ if: steps.changes.outputs.changed == 'true'
55
+ uses: peter-evans/create-pull-request@v6
56
+ with:
57
+ branch: auto/ingest-update
58
+ title: "data: update Swiss farm safety data"
59
+ body: |
60
+ Automated data ingestion run.
61
+
62
+ Mode: `${{ inputs.mode || 'incremental' }}`
63
+ Date: `${{ github.event.repository.updated_at }}`
64
+
65
+ Review the data changes in `data/` before merging.
66
+ commit-message: "data: update Swiss farm safety data"
67
+ delete-branch: true
@@ -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,23 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ Format based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
+
7
+ ## [0.1.0] - 2026-04-05
8
+
9
+ ### Added
10
+
11
+ - Initial release with 10 tools for Swiss farm workplace safety
12
+ - `search_safety_rules` with tiered FTS5 search (phrase, AND, prefix, stemmed, OR, LIKE fallback)
13
+ - `get_risk_assessment_requirements` for EKAS/VUV obligations by activity type
14
+ - `get_machinery_safety` for ROPS, Gurtpflicht, MFK, PTO requirements
15
+ - `get_chemical_safety` for MAK exposure limits, PPE, storage rules
16
+ - `get_young_worker_rules` for Jugendarbeitsschutz restrictions (ArGV 5)
17
+ - `get_accident_reporting` for deadlines, forms, insurer by severity
18
+ - `search_bul_guidance` for BUL/SPAA documents and campaigns
19
+ - `about`, `list_sources`, `check_data_freshness` metadata tools
20
+ - Streamable HTTP transport for remote access
21
+ - Docker image with non-root user and health check
22
+ - CI/CD: GHCR build, npm publish, CodeQL, Gitleaks, freshness check
23
+ - Data from BUL/SPAA, Suva, EKAS, Agriss, SECO
package/CODEOWNERS ADDED
@@ -0,0 +1 @@
1
+ * @ansvar-systems/mcp-team
package/COVERAGE.md ADDED
@@ -0,0 +1,54 @@
1
+ # Coverage — ch-farm-safety-mcp
2
+
3
+ ## Jurisdiction
4
+
5
+ Switzerland (CH)
6
+
7
+ ## Data Summary
8
+
9
+ | Table | Records | Description |
10
+ |-------|---------|-------------|
11
+ | safety_rules | 30 | BUL lebenswichtige Regeln, Suva requirements, EKAS guidelines |
12
+ | risk_assessments | 7 | Risk assessment obligations per activity type (VUV/EKAS) |
13
+ | machinery_safety | 10 | ROPS, Gurtpflicht, MFK, PTO guards by machine type |
14
+ | chemical_safety | 7 | MAK exposure limits, PPE, storage rules by substance |
15
+ | young_worker_rules | 5 | Jugendarbeitsschutz restrictions by age group (ArGV 5) |
16
+ | accident_reporting | 5 | Reporting deadlines, forms, insurer by severity |
17
+ | bul_guidance | 15 | BUL/SPAA guidance documents, fact sheets, campaigns |
18
+ | **Total** | **79** | |
19
+
20
+ ## Safety Areas (search_safety_rules topics)
21
+
22
+ - `maschinen` -- agricultural machinery (Traktor, Maehdrescher, Motorsaege)
23
+ - `tiere` -- livestock handling (Rinder, Pferde, Schweine)
24
+ - `wald` -- forestry work (Holzerei, Baumfaellen)
25
+ - `hoehe` -- working at height (Silo, Dach, Leiter)
26
+ - `chemie` -- chemical exposure (PSM, Duenger)
27
+ - `silogas` -- silo gas hazards (CO2, NO2)
28
+ - `allgemein` -- general farm safety
29
+
30
+ ## Legal Framework Covered
31
+
32
+ | Law/Regulation | Abbreviation | Scope |
33
+ |----------------|-------------|-------|
34
+ | Arbeitsgesetz | ArG (SR 822.11) | Working conditions, young worker protection |
35
+ | Verordnung ueber die Verhuetung von Unfaellen | VUV (SR 832.30) | Accident prevention obligations |
36
+ | Unfallversicherungsgesetz | UVG (SR 832.20) | Accident insurance, reporting obligations |
37
+ | Chemikalien-Risikoreduktions-Verordnung | ChemRRV (SR 814.81) | PSM application, chemical handling |
38
+ | Maschinenverordnung | MaschV (SR 819.14) | Machinery safety certification |
39
+ | Jugendarbeitsschutzverordnung | ArGV 5 (SR 822.115) | Young worker restrictions |
40
+ | EKAS Richtlinie 6508 | ASA | Systematic safety work, Branchenloesung |
41
+
42
+ ## Data Sources
43
+
44
+ - **BUL/SPAA** -- Beratungsstelle fuer Unfallverhuetung in der Landwirtschaft (bul.ch)
45
+ - **Suva** -- Schweizerische Unfallversicherungsanstalt (suva.ch)
46
+ - **EKAS** -- Eidg. Koordinationskommission fuer Arbeitssicherheit (ekas.admin.ch)
47
+ - **Agriss** -- Unfallstatistik Schweizer Landwirtschaft (BUL/Agroscope)
48
+ - **SECO** -- Staatssekretariat fuer Wirtschaft (Jugendarbeitsschutz)
49
+
50
+ ## Staleness Threshold
51
+
52
+ 90 days. Check with `check_data_freshness` tool or `npm run freshness:check`.
53
+
54
+ Last ingest: 2026-04-05
package/DISCLAIMER.md ADDED
@@ -0,0 +1,51 @@
1
+ # Haftungsausschluss / Disclaimer
2
+
3
+ ## Deutsch
4
+
5
+ Die in diesem MCP-Server bereitgestellten Daten dienen ausschliesslich der Information und ersetzen keine professionelle Sicherheitsberatung.
6
+
7
+ Die Inhalte basieren auf oeffentlich zugaenglichen Dokumenten der folgenden Stellen:
8
+
9
+ - **BUL/SPAA** -- Beratungsstelle fuer Unfallverhuetung in der Landwirtschaft
10
+ - **Suva** -- Schweizerische Unfallversicherungsanstalt
11
+ - **EKAS** -- Eidgenoessische Koordinationskommission fuer Arbeitssicherheit
12
+ - **Agriss** -- Unfallstatistik Schweizer Landwirtschaft (BUL / Agroscope)
13
+ - **SECO** -- Staatssekretariat fuer Wirtschaft (Jugendarbeitsschutz)
14
+
15
+ Die rechtlich verbindlichen Texte sind die amtlichen Publikationen in der Systematischen Rechtssammlung (SR), insbesondere:
16
+
17
+ - Arbeitsgesetz (ArG, SR 822.11)
18
+ - Verordnung ueber die Verhuetung von Unfaellen und Berufskrankheiten (VUV, SR 832.30)
19
+ - Unfallversicherungsgesetz (UVG, SR 832.20)
20
+ - Chemikalien-Risikoreduktions-Verordnung (ChemRRV, SR 814.81)
21
+ - Jugendarbeitsschutzverordnung (ArGV 5, SR 822.115)
22
+
23
+ Vor der Umsetzung von Sicherheitsmassnahmen ist stets die BUL/SPAA, die Suva oder eine qualifizierte Sicherheitsfachperson beizuziehen. Betriebsspezifische Risikobeurteilungen gemaess VUV Art. 3-10 und der EKAS Branchenloesung Landwirtschaft sind eigenstaendig durchzufuehren.
24
+
25
+ Ansvar Systems uebernimmt keine Haftung fuer die Richtigkeit, Vollstaendigkeit oder Aktualitaet der bereitgestellten Daten.
26
+
27
+ ---
28
+
29
+ ## English
30
+
31
+ The data provided by this MCP server is for informational purposes only and does not constitute professional safety advice.
32
+
33
+ Content is derived from publicly available documents published by:
34
+
35
+ - **BUL/SPAA** -- Swiss Advisory Service for Accident Prevention in Agriculture
36
+ - **Suva** -- Swiss National Accident Insurance Fund
37
+ - **EKAS** -- Federal Coordination Commission for Occupational Safety
38
+ - **Agriss** -- Swiss Agricultural Accident Statistics (BUL / Agroscope)
39
+ - **SECO** -- State Secretariat for Economic Affairs (Young Worker Protection)
40
+
41
+ The legally binding texts are the official publications in the Swiss Systematic Collection of Federal Legislation (SR), including:
42
+
43
+ - Employment Act (ArG, SR 822.11)
44
+ - Ordinance on the Prevention of Accidents and Occupational Diseases (VUV, SR 832.30)
45
+ - Accident Insurance Act (UVG, SR 832.20)
46
+ - Chemical Risk Reduction Ordinance (ChemRRV, SR 814.81)
47
+ - Young Workers Protection Ordinance (ArGV 5, SR 822.115)
48
+
49
+ Always consult BUL/SPAA, Suva, or a qualified safety professional before implementing safety measures. Farm-specific risk assessments as required by VUV Art. 3-10 and the EKAS sector solution for agriculture must be conducted independently.
50
+
51
+ Ansvar Systems accepts no liability for the accuracy, completeness, or currency of the data provided.
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,25 @@
1
+ # Privacy Policy
2
+
3
+ ## Data Processing
4
+
5
+ This MCP server processes **no personal data**. It serves pre-ingested, publicly available Swiss farm safety information.
6
+
7
+ ## What This Server Does Not Do
8
+
9
+ - Does not collect, store, or transmit user queries
10
+ - Does not use cookies, tracking pixels, or analytics
11
+ - Does not require authentication or user accounts
12
+ - Does not log IP addresses or request metadata beyond standard HTTP server logs
13
+ - Does not process any data subject to GDPR, nDSG (Swiss Data Protection Act), or any other privacy regulation
14
+
15
+ ## Data Sources
16
+
17
+ All data is sourced from public-sector publications by BUL/SPAA, Suva, EKAS, Agriss, and SECO. No personal data is included in the dataset.
18
+
19
+ ## Remote Endpoint
20
+
21
+ The Streamable HTTP endpoint at `mcp.ansvar.eu` is proxied through Cloudflare. Cloudflare may process connection metadata (IP, TLS fingerprint) according to their privacy policy. Ansvar Systems does not access or retain this metadata.
22
+
23
+ ## Contact
24
+
25
+ For privacy questions: **privacy@ansvar.eu**
package/README.md ADDED
@@ -0,0 +1,129 @@
1
+ # Switzerland Farm Safety MCP
2
+
3
+ Machine-readable Swiss farm workplace safety data via the [Model Context Protocol](https://modelcontextprotocol.io).
4
+
5
+ Covers BUL/SPAA safety rules (lebenswichtige Regeln), Suva occupational safety requirements, EKAS Branchenloesung Landwirtschaft, Agriss accident statistics, machinery safety (ROPS, MFK, PTO guards), chemical exposure (PSM, MAK values), young worker restrictions (Jugendarbeitsschutz), and accident reporting obligations.
6
+
7
+ ## Quick Start
8
+
9
+ ### npx (stdio — zero install)
10
+
11
+ ```bash
12
+ npx -y @ansvar/ch-farm-safety-mcp
13
+ ```
14
+
15
+ ### Docker
16
+
17
+ ```bash
18
+ docker run -p 3000:3000 ghcr.io/ansvar-systems/ch-farm-safety-mcp:latest
19
+ ```
20
+
21
+ ### Streamable HTTP (remote)
22
+
23
+ ```
24
+ https://mcp.ansvar.eu/ch-farm-safety/mcp
25
+ ```
26
+
27
+ No authentication required. Rate-limited to fair use.
28
+
29
+ ### Claude Desktop / Cursor
30
+
31
+ Add to your MCP client config:
32
+
33
+ ```json
34
+ {
35
+ "mcpServers": {
36
+ "ch-farm-safety": {
37
+ "command": "npx",
38
+ "args": ["-y", "@ansvar/ch-farm-safety-mcp"]
39
+ }
40
+ }
41
+ }
42
+ ```
43
+
44
+ Or use the remote endpoint:
45
+
46
+ ```json
47
+ {
48
+ "mcpServers": {
49
+ "ch-farm-safety": {
50
+ "url": "https://mcp.ansvar.eu/ch-farm-safety/mcp"
51
+ }
52
+ }
53
+ }
54
+ ```
55
+
56
+ ## Tools
57
+
58
+ 10 tools covering Swiss farm workplace safety:
59
+
60
+ | Tool | Description |
61
+ |------|-------------|
62
+ | `about` | Server metadata: name, version, coverage, data sources |
63
+ | `list_sources` | All data sources with authority, URL, license, freshness |
64
+ | `check_data_freshness` | Last ingest date, staleness status, refresh command |
65
+ | `search_safety_rules` | FTS5 search across BUL/Suva/EKAS safety rules |
66
+ | `get_risk_assessment_requirements` | Risk assessment obligations per farm activity (EKAS/VUV) |
67
+ | `get_machinery_safety` | ROPS, Gurtpflicht, MFK, PTO guard requirements by machine type |
68
+ | `get_chemical_safety` | MAK exposure limits, PPE, storage rules by substance |
69
+ | `get_young_worker_rules` | Jugendarbeitsschutz restrictions by age group |
70
+ | `get_accident_reporting` | Reporting deadlines, forms, insurer by severity |
71
+ | `search_bul_guidance` | BUL/SPAA guidance documents, fact sheets, campaigns |
72
+
73
+ Full tool documentation: [TOOLS.md](TOOLS.md)
74
+
75
+ ## Data Sources
76
+
77
+ | Source | Authority | Coverage |
78
+ |--------|-----------|----------|
79
+ | [BUL/SPAA](https://www.bul.ch) | Beratungsstelle fuer Unfallverhuetung in der Landwirtschaft | Lebenswichtige Regeln, Merkblaetter, Safe@Work |
80
+ | [Suva](https://www.suva.ch/de-ch/praevention/nach-branche/landwirtschaft) | Schweizerische Unfallversicherungsanstalt | MAK values, PPE, accident reporting |
81
+ | [EKAS](https://www.ekas.admin.ch) | Eidg. Koordinationskommission fuer Arbeitssicherheit | Branchenloesung Landwirtschaft, ASA concept |
82
+ | [Agriss](https://www.bul.ch/de/themen/unfallstatistik) | BUL / Agroscope | Farm accident statistics |
83
+ | [SECO](https://www.seco.admin.ch/seco/de/home/Arbeit/Arbeitsbedingungen/jugendarbeitsschutz.html) | Staatssekretariat fuer Wirtschaft | Young worker protection (ArGV 5) |
84
+
85
+ Coverage details: [COVERAGE.md](COVERAGE.md)
86
+
87
+ ## Development
88
+
89
+ ```bash
90
+ npm install
91
+ npm run build
92
+ npm test
93
+ npm run lint
94
+ ```
95
+
96
+ ### Ingestion
97
+
98
+ ```bash
99
+ npm run ingest # incremental update
100
+ npm run ingest:full # force full re-ingestion
101
+ npm run ingest:fetch # fetch sources only (no DB write)
102
+ npm run ingest:diff # show changes without applying
103
+ ```
104
+
105
+ ### Freshness
106
+
107
+ ```bash
108
+ npm run freshness:check
109
+ ```
110
+
111
+ Data staleness threshold: 90 days. The `check-freshness.yml` workflow runs weekly and opens an issue if data is stale.
112
+
113
+ ## Legal
114
+
115
+ This server provides Swiss farm safety data for informational purposes only. It does not constitute professional safety advice. Always consult BUL/SPAA, Suva, or a qualified safety professional (Sicherheitsfachperson) before implementing safety measures.
116
+
117
+ See [DISCLAIMER.md](DISCLAIMER.md) for the full bilingual disclaimer.
118
+
119
+ ## License
120
+
121
+ Apache-2.0 -- see [LICENSE](LICENSE).
122
+
123
+ Data sourced from BUL/SPAA, Suva, EKAS, Agriss, and SECO under Swiss public-sector information principles.
124
+
125
+ ## Links
126
+
127
+ - [Ansvar Open Agriculture](https://ansvar.eu/open-agriculture)
128
+ - [MCP Network](https://ansvar.ai/mcp)
129
+ - [SECURITY.md](SECURITY.md) | [PRIVACY.md](PRIVACY.md) | [CHANGELOG.md](CHANGELOG.md)
package/SECURITY.md ADDED
@@ -0,0 +1,25 @@
1
+ # Security Policy
2
+
3
+ ## Supported Versions
4
+
5
+ | Version | Supported |
6
+ |---------|-----------|
7
+ | 0.1.x | Yes |
8
+
9
+ ## Reporting a Vulnerability
10
+
11
+ Report security vulnerabilities to **security@ansvar.eu**.
12
+
13
+ Do **not** open a public GitHub issue for security vulnerabilities.
14
+
15
+ We will acknowledge receipt within 48 hours and provide an initial assessment within 5 business days.
16
+
17
+ ## Security Measures
18
+
19
+ - **Read-only database:** The SQLite database is mounted read-only in production containers.
20
+ - **No client data:** This server does not store, process, or transmit client data. All data is pre-ingested public-sector information.
21
+ - **No authentication secrets:** The server requires no API keys, tokens, or credentials.
22
+ - **Container isolation:** Production runs as a non-root user (`nodejs`, UID 1001) with memory limits.
23
+ - **Dependency scanning:** GitHub CodeQL and Gitleaks run on every push and pull request.
24
+ - **GHCR image builds:** Images are built via CI/CD only, signed with GitHub Actions OIDC provenance.
25
+ - **npm provenance:** Published packages include npm provenance attestation.