@ansvar/ch-farm-grants-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 +18 -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 +28 -0
- package/.github/workflows/publish.yml +24 -0
- package/CHANGELOG.md +22 -0
- package/CODEOWNERS +1 -0
- package/COVERAGE.md +45 -0
- package/DISCLAIMER.md +39 -0
- package/Dockerfile +26 -0
- package/LICENSE +17 -0
- package/PRIVACY.md +36 -0
- package/README.md +80 -0
- package/SECURITY.md +31 -0
- package/TOOLS.md +154 -0
- package/data/coverage.json +19 -0
- package/data/database.db +0 -0
- package/data/sources.yml +29 -0
- package/dist/db.d.ts +25 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +167 -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 +261 -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 +207 -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 +28 -0
- package/dist/tools/about.js.map +1 -0
- package/dist/tools/check-eligibility.d.ts +31 -0
- package/dist/tools/check-eligibility.d.ts.map +1 -0
- package/dist/tools/check-eligibility.js +57 -0
- package/dist/tools/check-eligibility.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-application-deadlines.d.ts +27 -0
- package/dist/tools/get-application-deadlines.d.ts.map +1 -0
- package/dist/tools/get-application-deadlines.js +40 -0
- package/dist/tools/get-application-deadlines.js.map +1 -0
- package/dist/tools/get-grant-details.d.ts +42 -0
- package/dist/tools/get-grant-details.d.ts.map +1 -0
- package/dist/tools/get-grant-details.js +24 -0
- package/dist/tools/get-grant-details.js.map +1 -0
- package/dist/tools/get-payment-rates.d.ts +49 -0
- package/dist/tools/get-payment-rates.d.ts.map +1 -0
- package/dist/tools/get-payment-rates.js +37 -0
- package/dist/tools/get-payment-rates.js.map +1 -0
- package/dist/tools/list-grant-options.d.ts +56 -0
- package/dist/tools/list-grant-options.d.ts.map +1 -0
- package/dist/tools/list-grant-options.js +39 -0
- package/dist/tools/list-grant-options.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 +51 -0
- package/dist/tools/list-sources.js.map +1 -0
- package/dist/tools/search-application-guidance.d.ts +36 -0
- package/dist/tools/search-application-guidance.d.ts.map +1 -0
- package/dist/tools/search-application-guidance.js +52 -0
- package/dist/tools/search-application-guidance.js.map +1 -0
- package/dist/tools/search-grants.d.ts +25 -0
- package/dist/tools/search-grants.d.ts.map +1 -0
- package/dist/tools/search-grants.js +26 -0
- package/dist/tools/search-grants.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 +742 -0
- package/server.json +41 -0
- package/src/db.ts +208 -0
- package/src/http-server.ts +293 -0
- package/src/jurisdiction.ts +30 -0
- package/src/metadata.ts +32 -0
- package/src/server.ts +230 -0
- package/src/tools/about.ts +29 -0
- package/src/tools/check-eligibility.ts +81 -0
- package/src/tools/check-freshness.ts +42 -0
- package/src/tools/get-application-deadlines.ts +55 -0
- package/src/tools/get-grant-details.ts +51 -0
- package/src/tools/get-payment-rates.ts +60 -0
- package/src/tools/list-grant-options.ts +63 -0
- package/src/tools/list-sources.ts +65 -0
- package/src/tools/search-application-guidance.ts +59 -0
- package/src/tools/search-grants.ts +35 -0
- package/tests/db.test.ts +69 -0
- package/tests/helpers/seed-db.ts +188 -0
- package/tests/jurisdiction.test.ts +35 -0
- package/tests/tools/about.test.ts +23 -0
- package/tests/tools/check-freshness.test.ts +53 -0
- package/tests/tools/list-sources.test.ts +47 -0
- package/tests/tools/search-grants.test.ts +57 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
name: Check Data Freshness
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
schedule:
|
|
5
|
+
- cron: "0 8 * * *" # Daily at 08:00 UTC
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
freshness:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v4
|
|
13
|
+
- uses: actions/setup-node@v4
|
|
14
|
+
with:
|
|
15
|
+
node-version: "20"
|
|
16
|
+
cache: npm
|
|
17
|
+
- run: npm ci
|
|
18
|
+
- run: npm run freshness:check
|
|
@@ -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-farm-grants-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,28 @@
|
|
|
1
|
+
name: Re-ingest Data
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
schedule:
|
|
5
|
+
- cron: "0 4 1 * *" # Monthly, 1st at 04:00 UTC
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
ingest:
|
|
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
|
+
cache: npm
|
|
20
|
+
- run: npm ci
|
|
21
|
+
- run: npm run ingest
|
|
22
|
+
- name: Commit updated database
|
|
23
|
+
run: |
|
|
24
|
+
git config user.name "github-actions[bot]"
|
|
25
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
26
|
+
git add data/database.db data/coverage.json data/sources.yml
|
|
27
|
+
git diff --staged --quiet || git commit -m "chore: re-ingest data $(date +%Y-%m-%d)"
|
|
28
|
+
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,22 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to the Switzerland Farm Grants MCP will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## [0.1.0] - 2026-04-05 - Initial Release
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- 10 tools: `about`, `list_sources`, `check_data_freshness`, `search_grants`, `get_grant_details`, `get_payment_rates`, `check_eligibility`, `list_grant_options`, `get_application_deadlines`, `search_application_guidance`
|
|
14
|
+
- 25 grant programmes covering Investitionskredite, Beitraege, Meliorationen, PRE, Ressourcenprogramme, Gewaesserschutz, Starthilfe
|
|
15
|
+
- 29 eligibility rules by farm type, investment type, and altitude zone
|
|
16
|
+
- 23 grant sub-options (Massnahmen)
|
|
17
|
+
- 20 application deadlines (federal and cantonal)
|
|
18
|
+
- FTS5 full-text search with 6-tier fallback (phrase, AND, prefix, stemmed, OR, LIKE)
|
|
19
|
+
- Dual transport: stdio (npx) and Streamable HTTP (Docker)
|
|
20
|
+
- Golden standard documentation: README, TOOLS.md, COVERAGE.md, DISCLAIMER.md, SECURITY.md, PRIVACY.md
|
|
21
|
+
- CI/CD: CodeQL, Gitleaks, ingest workflow, freshness check, GHCR build, npm publish
|
|
22
|
+
- Test suite: db, jurisdiction, and tool-level tests with seeded test database
|
package/CODEOWNERS
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
* @ansvar-systems/engineering
|
package/COVERAGE.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Coverage -- Switzerland Farm Grants MCP
|
|
2
|
+
|
|
3
|
+
## Data Summary
|
|
4
|
+
|
|
5
|
+
| Table | Records | Description |
|
|
6
|
+
|-------|---------|-------------|
|
|
7
|
+
| `grants` | 25 | Grant programmes (Investitionskredite, Beitraege, Meliorationen, PRE, Ressourcenprogramme, Gewaesserschutz, Starthilfe) |
|
|
8
|
+
| `grant_options` | 23 | Sub-options / Massnahmen within grant programmes |
|
|
9
|
+
| `eligibility_rules` | 29 | Eligibility criteria by farm type, investment type, and altitude zone |
|
|
10
|
+
| `application_deadlines` | 20 | Federal and cantonal application deadlines |
|
|
11
|
+
|
|
12
|
+
**Jurisdiction:** Switzerland (CH)
|
|
13
|
+
**Language:** German (primary), English (search supported)
|
|
14
|
+
**Currency:** CHF
|
|
15
|
+
**Last ingestion:** 2026-04-05
|
|
16
|
+
|
|
17
|
+
## Grant Types Covered
|
|
18
|
+
|
|
19
|
+
| Grant Type | Description |
|
|
20
|
+
|------------|-------------|
|
|
21
|
+
| `investitionskredit` | Interest-free federal loans for agricultural buildings and infrastructure (SVV Art. 44 ff.) |
|
|
22
|
+
| `beitrag` | Capital grants (non-repayable) for structural improvements (SVV Art. 18 ff.) |
|
|
23
|
+
| `meliorationsbeitrag` | Land improvement grants: drainage, irrigation, access roads (SVV Art. 14 ff.) |
|
|
24
|
+
| `pre` | Projekte zur regionalen Entwicklung -- regional development projects (SVV Art. 93 ff.) |
|
|
25
|
+
| `ressourcenprogramm` | Resource efficiency programmes under LwG Art. 77a/77b |
|
|
26
|
+
| `gewaesserschutz` | Water protection projects under GSchG Art. 62a |
|
|
27
|
+
| `starthilfe` | Start-up assistance for young farmers (SVV Art. 86 ff.) |
|
|
28
|
+
|
|
29
|
+
## Data Sources
|
|
30
|
+
|
|
31
|
+
| Source | Authority | Update Frequency |
|
|
32
|
+
|--------|-----------|-----------------|
|
|
33
|
+
| Strukturverbesserungsverordnung (SVV, SR 913.1) | BLW | Annual (with ordinance updates) |
|
|
34
|
+
| BLW Weisungen Investitionskredite und Beitraege | BLW | Annual |
|
|
35
|
+
| Kantonale Landwirtschaftsaemter | 26 cantonal offices | Variable per canton |
|
|
36
|
+
| AGRIDEA Beratungsunterlagen | AGRIDEA | Periodic |
|
|
37
|
+
|
|
38
|
+
## Limitations
|
|
39
|
+
|
|
40
|
+
- **Cantonal programmes:** Only major cantons covered. Some smaller cantons have additional programmes not yet ingested.
|
|
41
|
+
- **Historical rates:** Only current rates. Historical contribution rates are not tracked.
|
|
42
|
+
- **Cantonal deadlines:** Not all cantons have published fixed deadlines. Some cantons accept applications year-round.
|
|
43
|
+
- **French/Italian:** Data is primarily in German. French- and Italian-speaking canton specifics may be incomplete.
|
|
44
|
+
- **PRE projects:** Regional development project data covers federal-level rules. Specific approved PRE regions are not individually listed.
|
|
45
|
+
- **Private co-funding:** Schweizer Berghilfe and other private funding sources are referenced in guidance but not tracked as separate grant programmes.
|
package/DISCLAIMER.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Haftungsausschluss / Disclaimer
|
|
2
|
+
|
|
3
|
+
## Keine Rechtsberatung / Not Legal or Financial Advice
|
|
4
|
+
|
|
5
|
+
**DE:** Dieser MCP-Server liefert Informationen zu Schweizer Strukturverbesserungsmassnahmen in der Landwirtschaft. Die Daten basieren auf der Strukturverbesserungsverordnung (SVV, SR 913.1), den Weisungen des Bundesamts fuer Landwirtschaft (BLW) zu Investitionskrediten und Beitraegen sowie kantonalen Ausfuehrungsbestimmungen. **Nichts in diesem Server stellt eine Rechts-, Finanz- oder Foerderberatung dar.** Foerderentscheide liegen ausschliesslich bei den zustaendigen kantonalen Landwirtschaftsaemtern und dem BLW.
|
|
6
|
+
|
|
7
|
+
**EN:** This MCP server provides information about Swiss agricultural structural improvement grants. Data is sourced from the Structural Improvements Ordinance (SVV, SR 913.1), Federal Office for Agriculture (BLW) investment credit guidelines, and cantonal implementation rules. **Nothing in this server constitutes legal, financial, or grant application advice.** Funding decisions are made exclusively by the competent cantonal agricultural offices and the BLW.
|
|
8
|
+
|
|
9
|
+
## Keine Garantie fuer Foerderberechtigung / No Guarantee of Eligibility
|
|
10
|
+
|
|
11
|
+
**DE:** Die Ergebnisse der Berechtigungspruefung (`check_eligibility`) und der Beitragssaetze (`get_payment_rates`) sind informativ. Tatsaechliche Beitragssaetze, Kreditlimiten und Berechtigungskriterien koennen je nach Kanton, Projektbewertung und Verfuegbarkeit der Bundesmittel abweichen. Vor der Einreichung eines Gesuchs ist stets die kantonale Fachstelle oder AGRIDEA zu konsultieren.
|
|
12
|
+
|
|
13
|
+
**EN:** Eligibility checks and payment rate information are indicative only. Actual contribution rates, credit limits, and eligibility criteria may differ by canton, project evaluation, and availability of federal funds. Always consult the cantonal agricultural office or AGRIDEA before submitting an application.
|
|
14
|
+
|
|
15
|
+
## Keine Gewaehrleistung / No Warranty
|
|
16
|
+
|
|
17
|
+
THE SOFTWARE AND DATA ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT.
|
|
18
|
+
|
|
19
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
20
|
+
|
|
21
|
+
## Haftungsbeschraenkung / Limitation of Liability
|
|
22
|
+
|
|
23
|
+
**DE:** Die Autoren, Mitwirkenden und Ansvar Systems uebernehmen keine Haftung fuer:
|
|
24
|
+
|
|
25
|
+
- Fehler, Auslassungen oder Ungenauigkeiten in den Foerderdaten
|
|
26
|
+
- Entscheidungen, die auf Informationen aus diesem Server beruhen
|
|
27
|
+
- Finanzielle, rechtliche oder sonstige Verluste durch Nutzung dieser Software
|
|
28
|
+
- Aenderungen der Gesetzgebung oder Verordnungen, die noch nicht abgebildet sind
|
|
29
|
+
|
|
30
|
+
**EN:** The authors, contributors, and Ansvar Systems accept no liability for:
|
|
31
|
+
|
|
32
|
+
- Errors, omissions, or inaccuracies in the grant data
|
|
33
|
+
- Decisions made based on information from this server
|
|
34
|
+
- Financial, legal, or other losses arising from use of this software
|
|
35
|
+
- Changes in legislation or ordinances not yet reflected in the database
|
|
36
|
+
|
|
37
|
+
## Open Source
|
|
38
|
+
|
|
39
|
+
Apache License 2.0. See [LICENSE](LICENSE).
|
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,36 @@
|
|
|
1
|
+
# Privacy Policy
|
|
2
|
+
|
|
3
|
+
## Data Collection
|
|
4
|
+
|
|
5
|
+
**This MCP server collects no data.**
|
|
6
|
+
|
|
7
|
+
- No user data is stored
|
|
8
|
+
- No telemetry is sent
|
|
9
|
+
- No tracking or analytics
|
|
10
|
+
- No cookies or session data
|
|
11
|
+
- No network calls at runtime
|
|
12
|
+
|
|
13
|
+
## Architecture
|
|
14
|
+
|
|
15
|
+
This MCP server is a **read-only knowledge base**. It serves pre-built data from a local SQLite database. No user queries, inputs, or interactions are logged or persisted by the MCP server itself.
|
|
16
|
+
|
|
17
|
+
## Data Sources
|
|
18
|
+
|
|
19
|
+
All data in this knowledge base is sourced from **publicly available** Swiss federal and cantonal agricultural publications: Strukturverbesserungsverordnung (SVV, SR 913.1), BLW investment credit guidelines, cantonal agricultural office publications, and AGRIDEA advisory materials.
|
|
20
|
+
|
|
21
|
+
## Host Environment
|
|
22
|
+
|
|
23
|
+
When this MCP server runs inside a host application (Claude Desktop, Cursor, VS Code, etc.), the **host application's** privacy policy governs how your interactions are processed. This MCP server itself has no visibility into or control over the host's data practices.
|
|
24
|
+
|
|
25
|
+
## npm Package
|
|
26
|
+
|
|
27
|
+
The published npm package contains only:
|
|
28
|
+
- Static SQLite database (grant data)
|
|
29
|
+
- Server code (TypeScript/JavaScript)
|
|
30
|
+
- Configuration files
|
|
31
|
+
|
|
32
|
+
No user data is included in or collected by the package.
|
|
33
|
+
|
|
34
|
+
## Contact
|
|
35
|
+
|
|
36
|
+
For privacy questions about this MCP server: [Ansvar Systems](https://ansvar.eu)
|
package/README.md
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Switzerland Farm Grants MCP
|
|
2
|
+
|
|
3
|
+
[](https://github.com/ansvar-systems/ch-farm-grants-mcp/actions/workflows/ci.yml)
|
|
4
|
+
[](https://github.com/ansvar-systems/ch-farm-grants-mcp/actions/workflows/ghcr-build.yml)
|
|
5
|
+
[](https://opensource.org/licenses/Apache-2.0)
|
|
6
|
+
|
|
7
|
+
Swiss agricultural structural improvement grants via the [Model Context Protocol](https://modelcontextprotocol.io). Query Investitionskredite (interest-free loans), Beitraege (capital grants), Meliorationen, PRE, Ressourcenprogramme, Gewaesserschutzprojekte, and Starthilfe Junglandwirte -- 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 farmers, advisors, and cantonal agricultural offices need fast access to structural improvement grant rules when planning investments. The data is spread across federal ordinances (SVV, SR 913.1), BLW guidelines, cantonal implementation rules, and AGRIDEA advisory materials. This MCP server puts it all behind a single tool interface so AI assistants can answer grant eligibility, payment rates, and application process questions with cited Swiss data instead of guessing from training data.
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
### Claude Desktop
|
|
18
|
+
|
|
19
|
+
Add to your `claude_desktop_config.json`:
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"mcpServers": {
|
|
24
|
+
"ch-farm-grants": {
|
|
25
|
+
"command": "npx",
|
|
26
|
+
"args": ["-y", "@ansvar/ch-farm-grants-mcp"]
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Claude Code
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
claude mcp add ch-farm-grants -- npx -y @ansvar/ch-farm-grants-mcp
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Streamable HTTP (remote)
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
https://mcp.ansvar.eu/ch-farm-grants/mcp
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
No authentication required.
|
|
45
|
+
|
|
46
|
+
### Docker (self-hosted)
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
docker run -p 3000:3000 ghcr.io/ansvar-systems/ch-farm-grants-mcp:latest
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Tools
|
|
53
|
+
|
|
54
|
+
| Tool | Description |
|
|
55
|
+
|------|-------------|
|
|
56
|
+
| `about` | Server metadata: name, version, coverage, data sources, and links. |
|
|
57
|
+
| `list_sources` | All data sources with authority, URL, license, and freshness info. |
|
|
58
|
+
| `check_data_freshness` | When data was last ingested, staleness status, how to trigger a refresh. |
|
|
59
|
+
| `search_grants` | Search grants by free text (German or English), filter by grant type. |
|
|
60
|
+
| `get_grant_details` | Full details for a grant programme: objectives, rates, conditions, eligibility, sub-options. |
|
|
61
|
+
| `get_payment_rates` | Federal and cantonal contribution rates, zone-specific bonuses (Berggebiet, Huegelzone). |
|
|
62
|
+
| `check_eligibility` | Check which grants a farm is eligible for by farm type, investment, and altitude zone. |
|
|
63
|
+
| `list_grant_options` | List sub-options (Massnahmen) within a grant programme, or list all grants with option counts. |
|
|
64
|
+
| `get_application_deadlines` | Application deadlines for grants, optionally filtered by canton. |
|
|
65
|
+
| `search_application_guidance` | How to apply: required documents, cantonal contacts, AGRIDEA advisory support. |
|
|
66
|
+
|
|
67
|
+
See [TOOLS.md](TOOLS.md) for full parameter documentation.
|
|
68
|
+
|
|
69
|
+
## Data Sources
|
|
70
|
+
|
|
71
|
+
- **Strukturverbesserungsverordnung (SVV, SR 913.1)** -- federal structural improvement rules
|
|
72
|
+
- **BLW Weisungen Investitionskredite und Beitraege** -- federal investment credit guidelines
|
|
73
|
+
- **Kantonale Landwirtschaftsaemter** -- cantonal contribution rates, deadlines, additional programmes
|
|
74
|
+
- **AGRIDEA Beratungsunterlagen** -- project planning guidance, application procedures
|
|
75
|
+
|
|
76
|
+
See [COVERAGE.md](COVERAGE.md) for data counts and limitations.
|
|
77
|
+
|
|
78
|
+
## License
|
|
79
|
+
|
|
80
|
+
Apache-2.0. See [LICENSE](LICENSE).
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported Versions
|
|
4
|
+
|
|
5
|
+
| Version | Supported |
|
|
6
|
+
| ------- | ------------------ |
|
|
7
|
+
| 0.x | :white_check_mark: |
|
|
8
|
+
|
|
9
|
+
## Reporting a Vulnerability
|
|
10
|
+
|
|
11
|
+
If you discover a security vulnerability in this MCP server, please report it responsibly:
|
|
12
|
+
|
|
13
|
+
1. **Do NOT open a public issue**
|
|
14
|
+
2. Email: security@ansvar.eu
|
|
15
|
+
3. Include: description, reproduction steps, potential impact
|
|
16
|
+
|
|
17
|
+
We aim to acknowledge reports within 48 hours and provide a fix within 7 days for critical issues.
|
|
18
|
+
|
|
19
|
+
## Security Architecture
|
|
20
|
+
|
|
21
|
+
- **Read-only**: No write operations to the database at runtime
|
|
22
|
+
- **No network calls**: All data served from local SQLite
|
|
23
|
+
- **No authentication**: Public reference data only
|
|
24
|
+
- **No secrets**: No API keys or credentials required
|
|
25
|
+
- **Input validation**: All inputs validated with Zod schemas before processing
|
|
26
|
+
- **SQL injection prevention**: Parameterized queries throughout, FTS5 input sanitized
|
|
27
|
+
- **FTS5 hardening**: User input is stripped of special characters before FTS5 queries
|
|
28
|
+
|
|
29
|
+
## Dependencies
|
|
30
|
+
|
|
31
|
+
Dependencies are monitored via GitHub Dependabot and updated regularly. Security scanning is enabled via GitHub Advanced Security (CodeQL + secret scanning).
|
package/TOOLS.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# Tools -- Switzerland Farm Grants MCP
|
|
2
|
+
|
|
3
|
+
All tools return JSON with a `_meta` object containing disclaimer, data age, and source URL.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## `about`
|
|
8
|
+
|
|
9
|
+
Server metadata: name, version, coverage, data sources, and links.
|
|
10
|
+
|
|
11
|
+
**Parameters:** None.
|
|
12
|
+
|
|
13
|
+
**Returns:** `name`, `description`, `version`, `jurisdiction`, `data_sources`, `tools_count`, `links`, `_meta`.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## `list_sources`
|
|
18
|
+
|
|
19
|
+
All data sources with authority, official URL, retrieval method, update frequency, license, and coverage scope.
|
|
20
|
+
|
|
21
|
+
**Parameters:** None.
|
|
22
|
+
|
|
23
|
+
**Returns:** `sources[]` array with one entry per data source; `_meta`.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## `check_data_freshness`
|
|
28
|
+
|
|
29
|
+
When data was last ingested, staleness status, and how to trigger a refresh.
|
|
30
|
+
|
|
31
|
+
**Parameters:** None.
|
|
32
|
+
|
|
33
|
+
**Returns:**
|
|
34
|
+
|
|
35
|
+
| Field | Type | Description |
|
|
36
|
+
|-------|------|-------------|
|
|
37
|
+
| `status` | `fresh \| stale \| unknown` | Whether data is within the 90-day threshold |
|
|
38
|
+
| `last_ingest` | `string \| null` | ISO date of last ingestion |
|
|
39
|
+
| `days_since_ingest` | `number \| null` | Days elapsed since last ingestion |
|
|
40
|
+
| `staleness_threshold_days` | `number` | Threshold used (90) |
|
|
41
|
+
| `refresh_command` | `string` | CLI command to trigger re-ingestion |
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## `search_grants`
|
|
46
|
+
|
|
47
|
+
Search grants via FTS5 full-text index. Supports German and English queries with tiered fallback (exact phrase, AND, prefix, stemmed, OR, LIKE).
|
|
48
|
+
|
|
49
|
+
**Parameters:**
|
|
50
|
+
|
|
51
|
+
| Param | Type | Required | Description |
|
|
52
|
+
|-------|------|----------|-------------|
|
|
53
|
+
| `query` | `string` | Yes | Free-text search query |
|
|
54
|
+
| `grant_type` | `string` | No | Filter: `investitionskredit`, `beitrag`, `meliorationsbeitrag`, `pre`, `ressourcenprogramm`, `gewaesserschutz`, `starthilfe` |
|
|
55
|
+
| `jurisdiction` | `string` | No | ISO 3166-1 alpha-2 (default: `CH`) |
|
|
56
|
+
| `limit` | `number` | No | Max results (default: 20, max: 50) |
|
|
57
|
+
|
|
58
|
+
**Returns:** `query`, `jurisdiction`, `results_count`, `results[]` with `title`, `body`, `grant_type`, `relevance_rank`; `_meta`.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## `get_grant_details`
|
|
63
|
+
|
|
64
|
+
Full details for a specific grant programme.
|
|
65
|
+
|
|
66
|
+
**Parameters:**
|
|
67
|
+
|
|
68
|
+
| Param | Type | Required | Description |
|
|
69
|
+
|-------|------|----------|-------------|
|
|
70
|
+
| `grant_id` | `string` | Yes | Grant ID or name (e.g. `ik-oekonomiegebaeude`) |
|
|
71
|
+
| `jurisdiction` | `string` | No | ISO 3166-1 alpha-2 (default: `CH`) |
|
|
72
|
+
|
|
73
|
+
**Returns:** All grant fields (`id`, `name`, `grant_type`, `description`, `federal_rate_pct`, `max_amount`, `duration_years`, `zone_bonus`, `legal_basis`, `language`, `jurisdiction`), plus `options[]` and `eligibility_rules[]`; `_meta`.
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## `get_payment_rates`
|
|
78
|
+
|
|
79
|
+
Federal and cantonal contribution rates for a grant programme, with zone-specific bonuses.
|
|
80
|
+
|
|
81
|
+
**Parameters:**
|
|
82
|
+
|
|
83
|
+
| Param | Type | Required | Description |
|
|
84
|
+
|-------|------|----------|-------------|
|
|
85
|
+
| `grant_id` | `string` | Yes | Grant ID or name |
|
|
86
|
+
| `zone` | `string` | No | Altitude zone: `talzone`, `huegelzone`, `bergzone_i`, `bergzone_ii`, `bergzone_iii`, `bergzone_iv`, `soemmerungsgebiet` |
|
|
87
|
+
| `jurisdiction` | `string` | No | ISO 3166-1 alpha-2 (default: `CH`) |
|
|
88
|
+
|
|
89
|
+
**Returns:** `grant_id`, `grant_name`, `grant_type`, `federal_rate_pct`, `max_amount_chf`, `duration_years`, `zone_requested`, `zone_bonus`, `all_zone_bonuses`, `rate_options[]`, `currency` (`CHF`); `_meta`.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## `check_eligibility`
|
|
94
|
+
|
|
95
|
+
Check which grants a farm is eligible for based on farm characteristics.
|
|
96
|
+
|
|
97
|
+
**Parameters:**
|
|
98
|
+
|
|
99
|
+
| Param | Type | Required | Description |
|
|
100
|
+
|-------|------|----------|-------------|
|
|
101
|
+
| `farm_type` | `string` | Yes | `milchwirtschaft`, `ackerbau`, `mutterkuhhaltung`, `bergbetrieb`, `alpwirtschaft`, `gemischt`, `gemeinschaft`, `junglandwirt` |
|
|
102
|
+
| `investment_type` | `string` | No | `stallbau`, `hofduengerlager`, `wohnhaus`, `diversifikation`, `alpgebaeude`, `wegebau`, `wasserversorgung`, `biogasanlage`, `kaeserei` |
|
|
103
|
+
| `zone` | `string` | No | Altitude zone |
|
|
104
|
+
| `jurisdiction` | `string` | No | ISO 3166-1 alpha-2 (default: `CH`) |
|
|
105
|
+
|
|
106
|
+
**Returns:** `farm_type`, `investment_type`, `zone`, `jurisdiction`, `eligible_grants_count`, `eligible_grants[]` with grant details and `requirements[]`; `_meta`.
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## `list_grant_options`
|
|
111
|
+
|
|
112
|
+
List sub-options (Massnahmen) within a grant programme, or list all grants with option counts.
|
|
113
|
+
|
|
114
|
+
**Parameters:**
|
|
115
|
+
|
|
116
|
+
| Param | Type | Required | Description |
|
|
117
|
+
|-------|------|----------|-------------|
|
|
118
|
+
| `grant_id` | `string` | No | Grant ID. If omitted, lists all grants with option counts. |
|
|
119
|
+
| `jurisdiction` | `string` | No | ISO 3166-1 alpha-2 (default: `CH`) |
|
|
120
|
+
|
|
121
|
+
**Returns (with grant_id):** `grant_id`, `grant_name`, `options_count`, `options[]` with `option_name`, `description`, `rate`, `conditions`; `_meta`.
|
|
122
|
+
|
|
123
|
+
**Returns (without grant_id):** `grants_count`, `grants[]` with `id`, `name`, `grant_type`, `option_count`; `_meta`.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## `get_application_deadlines`
|
|
128
|
+
|
|
129
|
+
Application deadlines for grants, optionally filtered by canton.
|
|
130
|
+
|
|
131
|
+
**Parameters:**
|
|
132
|
+
|
|
133
|
+
| Param | Type | Required | Description |
|
|
134
|
+
|-------|------|----------|-------------|
|
|
135
|
+
| `grant_id` | `string` | No | Grant ID to check deadlines for |
|
|
136
|
+
| `canton` | `string` | No | Canton 2-letter code: `ZH`, `BE`, `LU`, `SG`, `GR`, `VS`, `TI`, etc. |
|
|
137
|
+
| `jurisdiction` | `string` | No | ISO 3166-1 alpha-2 (default: `CH`) |
|
|
138
|
+
|
|
139
|
+
**Returns:** `grant_id`, `canton`, `jurisdiction`, `deadlines_count`, `deadlines[]` with `grant_id`, `grant_name`, `grant_type`, `canton`, `deadline_date`, `notes`; `_meta`.
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## `search_application_guidance`
|
|
144
|
+
|
|
145
|
+
How to apply for Swiss farm grants. Returns FTS search results plus general application guidance.
|
|
146
|
+
|
|
147
|
+
**Parameters:**
|
|
148
|
+
|
|
149
|
+
| Param | Type | Required | Description |
|
|
150
|
+
|-------|------|----------|-------------|
|
|
151
|
+
| `query` | `string` | Yes | Free-text query about the application process |
|
|
152
|
+
| `jurisdiction` | `string` | No | ISO 3166-1 alpha-2 (default: `CH`) |
|
|
153
|
+
|
|
154
|
+
**Returns:** `query`, `jurisdiction`, `search_results_count`, `search_results[]`, plus `application_guidance` with `general_process[]`, `required_documents[]`, and `contact_points[]`; `_meta`.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"server": "ch-farm-grants-mcp",
|
|
3
|
+
"jurisdiction": "CH",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"last_ingest": "2026-04-05",
|
|
6
|
+
"data": {
|
|
7
|
+
"grants": 25,
|
|
8
|
+
"grant_options": 23,
|
|
9
|
+
"eligibility_rules": 29,
|
|
10
|
+
"application_deadlines": 20
|
|
11
|
+
},
|
|
12
|
+
"tools": 10,
|
|
13
|
+
"sources": [
|
|
14
|
+
"Strukturverbesserungsverordnung (SVV, SR 913.1)",
|
|
15
|
+
"BLW Weisungen Investitionskredite und Beitraege",
|
|
16
|
+
"Kantonale Landwirtschaftsaemter",
|
|
17
|
+
"AGRIDEA Beratungsunterlagen"
|
|
18
|
+
]
|
|
19
|
+
}
|
package/data/database.db
ADDED
|
Binary file
|