@ansvar/ch-pest-management-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 (108) 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 +16 -0
  9. package/CODEOWNERS +1 -0
  10. package/COVERAGE.md +66 -0
  11. package/DISCLAIMER.md +39 -0
  12. package/Dockerfile +26 -0
  13. package/LICENSE +17 -0
  14. package/PRIVACY.md +23 -0
  15. package/README.md +98 -0
  16. package/SECURITY.md +26 -0
  17. package/TOOLS.md +202 -0
  18. package/data/coverage.json +34 -0
  19. package/data/database.db +0 -0
  20. package/data/sources.yml +57 -0
  21. package/dist/db.d.ts +26 -0
  22. package/dist/db.d.ts.map +1 -0
  23. package/dist/db.js +189 -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 +270 -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 +21 -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 +216 -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-approved-products.d.ts +38 -0
  50. package/dist/tools/get-approved-products.d.ts.map +1 -0
  51. package/dist/tools/get-approved-products.js +49 -0
  52. package/dist/tools/get-approved-products.js.map +1 -0
  53. package/dist/tools/get-ipm-guidance.d.ts +42 -0
  54. package/dist/tools/get-ipm-guidance.d.ts.map +1 -0
  55. package/dist/tools/get-ipm-guidance.js +40 -0
  56. package/dist/tools/get-ipm-guidance.js.map +1 -0
  57. package/dist/tools/get-pest-details.d.ts +43 -0
  58. package/dist/tools/get-pest-details.d.ts.map +1 -0
  59. package/dist/tools/get-pest-details.js +20 -0
  60. package/dist/tools/get-pest-details.js.map +1 -0
  61. package/dist/tools/get-treatments.d.ts +46 -0
  62. package/dist/tools/get-treatments.d.ts.map +1 -0
  63. package/dist/tools/get-treatments.js +41 -0
  64. package/dist/tools/get-treatments.js.map +1 -0
  65. package/dist/tools/identify-from-symptoms.d.ts +31 -0
  66. package/dist/tools/identify-from-symptoms.d.ts.map +1 -0
  67. package/dist/tools/identify-from-symptoms.js +49 -0
  68. package/dist/tools/identify-from-symptoms.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-crop-threats.d.ts +36 -0
  74. package/dist/tools/search-crop-threats.d.ts.map +1 -0
  75. package/dist/tools/search-crop-threats.js +48 -0
  76. package/dist/tools/search-crop-threats.js.map +1 -0
  77. package/dist/tools/search-pests.d.ts +31 -0
  78. package/dist/tools/search-pests.d.ts.map +1 -0
  79. package/dist/tools/search-pests.js +36 -0
  80. package/dist/tools/search-pests.js.map +1 -0
  81. package/docker-compose.yml +12 -0
  82. package/eslint.config.js +23 -0
  83. package/package.json +54 -0
  84. package/scripts/ingest.ts +1037 -0
  85. package/server.json +71 -0
  86. package/src/db.ts +230 -0
  87. package/src/http-server.ts +302 -0
  88. package/src/jurisdiction.ts +30 -0
  89. package/src/metadata.ts +31 -0
  90. package/src/server.ts +239 -0
  91. package/src/tools/about.ts +28 -0
  92. package/src/tools/check-freshness.ts +42 -0
  93. package/src/tools/get-approved-products.ts +68 -0
  94. package/src/tools/get-ipm-guidance.ts +56 -0
  95. package/src/tools/get-pest-details.ts +44 -0
  96. package/src/tools/get-treatments.ts +61 -0
  97. package/src/tools/identify-from-symptoms.ts +64 -0
  98. package/src/tools/list-sources.ts +65 -0
  99. package/src/tools/search-crop-threats.ts +74 -0
  100. package/src/tools/search-pests.ts +49 -0
  101. package/tests/db.test.ts +82 -0
  102. package/tests/helpers/seed-db.ts +187 -0
  103. package/tests/jurisdiction.test.ts +35 -0
  104. package/tests/tools/about.test.ts +27 -0
  105. package/tests/tools/check-freshness.test.ts +58 -0
  106. package/tests/tools/list-sources.test.ts +57 -0
  107. package/tests/tools/search-pests.test.ts +64 -0
  108. package/tsconfig.json +19 -0
@@ -0,0 +1,36 @@
1
+ import type { Database } from '../db.js';
2
+ interface SearchCropThreatsArgs {
3
+ crop: string;
4
+ growth_stage?: string;
5
+ jurisdiction?: string;
6
+ }
7
+ export declare function handleSearchCropThreats(db: Database, args: SearchCropThreatsArgs): {
8
+ error: string;
9
+ supported: readonly string[];
10
+ message: string;
11
+ } | {
12
+ crop: string;
13
+ growth_stage: string | null;
14
+ jurisdiction: "CH";
15
+ total_threats: number;
16
+ by_type: {
17
+ insects: number;
18
+ diseases: number;
19
+ weeds: number;
20
+ };
21
+ threats: {
22
+ pest_id: string;
23
+ name: string;
24
+ pest_type: string;
25
+ scientific_name: string;
26
+ crop_category: string;
27
+ damage: string;
28
+ identification: string;
29
+ threshold: string | null;
30
+ monitoring: string | null;
31
+ prognose_system: string | null;
32
+ }[];
33
+ _meta: import("../metadata.js").Meta;
34
+ };
35
+ export {};
36
+ //# sourceMappingURL=search-crop-threats.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-crop-threats.d.ts","sourceRoot":"","sources":["../../src/tools/search-crop-threats.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,UAAU,qBAAqB;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+DhF"}
@@ -0,0 +1,48 @@
1
+ import { buildMeta } from '../metadata.js';
2
+ import { validateJurisdiction } from '../jurisdiction.js';
3
+ export function handleSearchCropThreats(db, args) {
4
+ const jv = validateJurisdiction(args.jurisdiction);
5
+ if (!jv.valid)
6
+ return jv.error;
7
+ const cropLower = args.crop.toLowerCase();
8
+ // Find all pests that affect this crop
9
+ const pests = db.all(`SELECT * FROM pests WHERE LOWER(crops_affected) LIKE ? AND jurisdiction = ? ORDER BY pest_type, name`, [`%${cropLower}%`, jv.jurisdiction]);
10
+ // Get IPM guidance for this crop
11
+ const ipmGuidance = db.all('SELECT pest_id, threshold, monitoring_method, prognose_system FROM ipm_guidance WHERE LOWER(crop) = ? AND jurisdiction = ?', [cropLower, jv.jurisdiction]);
12
+ const ipmMap = new Map(ipmGuidance.map(g => [g.pest_id, g]));
13
+ const threats = pests.map(p => {
14
+ const ipm = ipmMap.get(p.id);
15
+ return {
16
+ pest_id: p.id,
17
+ name: p.name,
18
+ pest_type: p.pest_type,
19
+ scientific_name: p.scientific_name,
20
+ crop_category: p.crop_category,
21
+ damage: p.damage_description,
22
+ identification: p.identification,
23
+ threshold: ipm?.threshold ?? null,
24
+ monitoring: ipm?.monitoring_method ?? null,
25
+ prognose_system: ipm?.prognose_system ?? null,
26
+ };
27
+ });
28
+ // Group by pest type
29
+ const byType = {
30
+ insects: threats.filter(t => t.pest_type === 'insect'),
31
+ diseases: threats.filter(t => t.pest_type === 'disease'),
32
+ weeds: threats.filter(t => t.pest_type === 'weed'),
33
+ };
34
+ return {
35
+ crop: args.crop,
36
+ growth_stage: args.growth_stage ?? null,
37
+ jurisdiction: jv.jurisdiction,
38
+ total_threats: threats.length,
39
+ by_type: {
40
+ insects: byType.insects.length,
41
+ diseases: byType.diseases.length,
42
+ weeds: byType.weeds.length,
43
+ },
44
+ threats,
45
+ _meta: buildMeta(),
46
+ };
47
+ }
48
+ //# sourceMappingURL=search-crop-threats.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-crop-threats.js","sourceRoot":"","sources":["../../src/tools/search-crop-threats.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAS1D,MAAM,UAAU,uBAAuB,CAAC,EAAY,EAAE,IAA2B;IAC/E,MAAM,EAAE,GAAG,oBAAoB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACnD,IAAI,CAAC,EAAE,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC,KAAK,CAAC;IAE/B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;IAE1C,uCAAuC;IACvC,MAAM,KAAK,GAAG,EAAE,CAAC,GAAG,CAKlB,sGAAsG,EACtG,CAAC,IAAI,SAAS,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,CACpC,CAAC;IAEF,iCAAiC;IACjC,MAAM,WAAW,GAAG,EAAE,CAAC,GAAG,CAIxB,4HAA4H,EAC5H,CAAC,SAAS,EAAE,EAAE,CAAC,YAAY,CAAC,CAC7B,CAAC;IAEF,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAE7D,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;QAC5B,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC7B,OAAO;YACL,OAAO,EAAE,CAAC,CAAC,EAAE;YACb,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,eAAe,EAAE,CAAC,CAAC,eAAe;YAClC,aAAa,EAAE,CAAC,CAAC,aAAa;YAC9B,MAAM,EAAE,CAAC,CAAC,kBAAkB;YAC5B,cAAc,EAAE,CAAC,CAAC,cAAc;YAChC,SAAS,EAAE,GAAG,EAAE,SAAS,IAAI,IAAI;YACjC,UAAU,EAAE,GAAG,EAAE,iBAAiB,IAAI,IAAI;YAC1C,eAAe,EAAE,GAAG,EAAE,eAAe,IAAI,IAAI;SAC9C,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,qBAAqB;IACrB,MAAM,MAAM,GAAG;QACb,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,QAAQ,CAAC;QACtD,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,SAAS,CAAC;QACxD,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,MAAM,CAAC;KACnD,CAAC;IAEF,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,YAAY,EAAE,IAAI,CAAC,YAAY,IAAI,IAAI;QACvC,YAAY,EAAE,EAAE,CAAC,YAAY;QAC7B,aAAa,EAAE,OAAO,CAAC,MAAM;QAC7B,OAAO,EAAE;YACP,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM;YAC9B,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM;YAChC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM;SAC3B;QACD,OAAO;QACP,KAAK,EAAE,SAAS,EAAE;KACnB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { type Database } from '../db.js';
2
+ interface SearchPestsArgs {
3
+ query: string;
4
+ pest_type?: string;
5
+ crop?: string;
6
+ jurisdiction?: string;
7
+ limit?: number;
8
+ }
9
+ export declare function handleSearchPests(db: Database, args: SearchPestsArgs): {
10
+ error: string;
11
+ supported: readonly string[];
12
+ message: string;
13
+ } | {
14
+ query: string;
15
+ jurisdiction: "CH";
16
+ filters: {
17
+ pest_type: string | null;
18
+ crop: string | null;
19
+ };
20
+ results_count: number;
21
+ results: {
22
+ title: string;
23
+ body: string;
24
+ pest_type: string;
25
+ crop_category: string;
26
+ relevance_rank: number;
27
+ }[];
28
+ _meta: import("../metadata.js").Meta;
29
+ };
30
+ export {};
31
+ //# sourceMappingURL=search-pests.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-pests.d.ts","sourceRoot":"","sources":["../../src/tools/search-pests.ts"],"names":[],"mappings":"AAEA,OAAO,EAAa,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpD,UAAU,eAAe;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,eAAe;;;;;;;;;;;;;;;;;;;;EAoCpE"}
@@ -0,0 +1,36 @@
1
+ import { buildMeta } from '../metadata.js';
2
+ import { validateJurisdiction } from '../jurisdiction.js';
3
+ import { ftsSearch } from '../db.js';
4
+ export function handleSearchPests(db, args) {
5
+ const jv = validateJurisdiction(args.jurisdiction);
6
+ if (!jv.valid)
7
+ return jv.error;
8
+ const limit = Math.min(args.limit ?? 20, 50);
9
+ let results = ftsSearch(db, args.query, limit);
10
+ if (args.pest_type) {
11
+ results = results.filter(r => r.pest_type.toLowerCase() === args.pest_type.toLowerCase());
12
+ }
13
+ if (args.crop) {
14
+ const cropLower = args.crop.toLowerCase();
15
+ results = results.filter(r => r.body.toLowerCase().includes(cropLower) ||
16
+ r.crop_category?.toLowerCase().includes(cropLower));
17
+ }
18
+ return {
19
+ query: args.query,
20
+ jurisdiction: jv.jurisdiction,
21
+ filters: {
22
+ pest_type: args.pest_type ?? null,
23
+ crop: args.crop ?? null,
24
+ },
25
+ results_count: results.length,
26
+ results: results.map(r => ({
27
+ title: r.title,
28
+ body: r.body,
29
+ pest_type: r.pest_type,
30
+ crop_category: r.crop_category,
31
+ relevance_rank: r.rank,
32
+ })),
33
+ _meta: buildMeta(),
34
+ };
35
+ }
36
+ //# sourceMappingURL=search-pests.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-pests.js","sourceRoot":"","sources":["../../src/tools/search-pests.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAiB,MAAM,UAAU,CAAC;AAUpD,MAAM,UAAU,iBAAiB,CAAC,EAAY,EAAE,IAAqB;IACnE,MAAM,EAAE,GAAG,oBAAoB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACnD,IAAI,CAAC,EAAE,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC,KAAK,CAAC;IAE/B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IAC7C,IAAI,OAAO,GAAG,SAAS,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAE/C,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,SAAU,CAAC,WAAW,EAAE,CAAC,CAAC;IAC7F,CAAC;IAED,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QAC1C,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAC3B,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC;YACxC,CAAC,CAAC,aAAa,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CACnD,CAAC;IACJ,CAAC;IAED,OAAO;QACL,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,YAAY,EAAE,EAAE,CAAC,YAAY;QAC7B,OAAO,EAAE;YACP,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,IAAI;YACjC,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,IAAI;SACxB;QACD,aAAa,EAAE,OAAO,CAAC,MAAM;QAC7B,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACzB,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,aAAa,EAAE,CAAC,CAAC,aAAa;YAC9B,cAAc,EAAE,CAAC,CAAC,IAAI;SACvB,CAAC,CAAC;QACH,KAAK,EAAE,SAAS,EAAE;KACnB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ services:
2
+ ch-crop-nutrients-mcp:
3
+ build: .
4
+ ports:
5
+ - "3000:3000"
6
+ environment:
7
+ - NODE_ENV=production
8
+ - PORT=3000
9
+ read_only: false
10
+ mem_limit: 128m
11
+ cpus: 0.5
12
+ restart: unless-stopped
@@ -0,0 +1,23 @@
1
+ import tseslint from '@typescript-eslint/eslint-plugin';
2
+ import tsparser from '@typescript-eslint/parser';
3
+
4
+ export default [
5
+ {
6
+ files: ['src/**/*.ts', 'tests/**/*.ts'],
7
+ languageOptions: {
8
+ parser: tsparser,
9
+ parserOptions: {
10
+ ecmaVersion: 2022,
11
+ sourceType: 'module',
12
+ },
13
+ },
14
+ plugins: {
15
+ '@typescript-eslint': tseslint,
16
+ },
17
+ rules: {
18
+ ...tseslint.configs.recommended.rules,
19
+ '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
20
+ 'no-console': 'off',
21
+ },
22
+ },
23
+ ];
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@ansvar/ch-pest-management-mcp",
3
+ "mcpName": "io.github.ansvar-systems/ch-pest-management-mcp",
4
+ "version": "0.1.0",
5
+ "description": "Swiss pest management and crop protection via MCP -- Pflanzenschutzmittelverzeichnis, IPM",
6
+ "type": "module",
7
+ "main": "dist/server.js",
8
+ "bin": {
9
+ "ch-pest-management-mcp": "dist/server.js"
10
+ },
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "dev": "tsx watch src/server.ts",
14
+ "start": "node dist/server.js",
15
+ "start:http": "node dist/http-server.js",
16
+ "test": "vitest run",
17
+ "test:watch": "vitest",
18
+ "lint": "eslint src/ tests/",
19
+ "typecheck": "tsc --noEmit",
20
+ "ingest": "tsx scripts/ingest.ts",
21
+ "ingest:fetch": "tsx scripts/ingest.ts --fetch-only",
22
+ "ingest:diff": "tsx scripts/ingest.ts --diff-only",
23
+ "ingest:full": "tsx scripts/ingest.ts --force",
24
+ "build:db": "tsx scripts/build-db.ts",
25
+ "freshness:check": "tsx scripts/check-freshness.ts",
26
+ "coverage:update": "tsx scripts/update-coverage.ts"
27
+ },
28
+ "keywords": ["mcp", "agriculture", "pest-management", "pflanzenschutz", "ipm", "farming", "switzerland"],
29
+ "author": "Ansvar Systems <info@ansvar.eu>",
30
+ "license": "Apache-2.0",
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "https://github.com/Ansvar-Systems/ch-pest-management-mcp"
34
+ },
35
+ "homepage": "https://ansvar.eu/open-agriculture",
36
+ "engines": {
37
+ "node": ">=20"
38
+ },
39
+ "dependencies": {
40
+ "@modelcontextprotocol/sdk": "^1.12.0",
41
+ "better-sqlite3": "^11.0.0",
42
+ "zod": "^3.23.0"
43
+ },
44
+ "devDependencies": {
45
+ "@types/better-sqlite3": "^7.6.0",
46
+ "@types/node": "^20.0.0",
47
+ "@typescript-eslint/eslint-plugin": "^8.0.0",
48
+ "@typescript-eslint/parser": "^8.0.0",
49
+ "eslint": "^9.0.0",
50
+ "tsx": "^4.0.0",
51
+ "typescript": "^5.5.0",
52
+ "vitest": "^2.0.0"
53
+ }
54
+ }