@ansvar/zimbabwe-law-mcp 1.0.1

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 (104) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/LICENSE +110 -0
  3. package/README.md +151 -0
  4. package/data/.gitkeep +0 -0
  5. package/data/database.db +0 -0
  6. package/data/seed/zw-access-information-privacy.json +1087 -0
  7. package/data/seed/zw-broadcasting-services.json +1150 -0
  8. package/data/seed/zw-companies-business-entities.json +4128 -0
  9. package/data/seed/zw-constitution-2013.json +2783 -0
  10. package/data/seed/zw-criminal-law-codification.json +2857 -0
  11. package/data/seed/zw-cyber-data-protection-2021.json +389 -0
  12. package/data/seed/zw-freedom-of-information-2020.json +382 -0
  13. package/data/seed/zw-interception-communications-2007.json +335 -0
  14. package/data/seed/zw-money-laundering-proceeds-crime.json +1432 -0
  15. package/data/seed/zw-postal-telecommunications.json +1361 -0
  16. package/dist/capabilities.d.ts +16 -0
  17. package/dist/capabilities.d.ts.map +1 -0
  18. package/dist/capabilities.js +43 -0
  19. package/dist/capabilities.js.map +1 -0
  20. package/dist/constants.d.ts +7 -0
  21. package/dist/constants.d.ts.map +1 -0
  22. package/dist/constants.js +7 -0
  23. package/dist/constants.js.map +1 -0
  24. package/dist/index.d.ts +8 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +80 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/tools/about.d.ts +37 -0
  29. package/dist/tools/about.d.ts.map +1 -0
  30. package/dist/tools/about.js +46 -0
  31. package/dist/tools/about.js.map +1 -0
  32. package/dist/tools/build-legal-stance.d.ts +21 -0
  33. package/dist/tools/build-legal-stance.d.ts.map +1 -0
  34. package/dist/tools/build-legal-stance.js +46 -0
  35. package/dist/tools/build-legal-stance.js.map +1 -0
  36. package/dist/tools/check-currency.d.ts +20 -0
  37. package/dist/tools/check-currency.d.ts.map +1 -0
  38. package/dist/tools/check-currency.js +41 -0
  39. package/dist/tools/check-currency.js.map +1 -0
  40. package/dist/tools/format-citation.d.ts +19 -0
  41. package/dist/tools/format-citation.d.ts.map +1 -0
  42. package/dist/tools/format-citation.js +33 -0
  43. package/dist/tools/format-citation.js.map +1 -0
  44. package/dist/tools/get-eu-basis.d.ts +25 -0
  45. package/dist/tools/get-eu-basis.d.ts.map +1 -0
  46. package/dist/tools/get-eu-basis.js +56 -0
  47. package/dist/tools/get-eu-basis.js.map +1 -0
  48. package/dist/tools/get-provision-eu-basis.d.ts +20 -0
  49. package/dist/tools/get-provision-eu-basis.d.ts.map +1 -0
  50. package/dist/tools/get-provision-eu-basis.js +45 -0
  51. package/dist/tools/get-provision-eu-basis.js.map +1 -0
  52. package/dist/tools/get-provision.d.ts +24 -0
  53. package/dist/tools/get-provision.d.ts.map +1 -0
  54. package/dist/tools/get-provision.js +80 -0
  55. package/dist/tools/get-provision.js.map +1 -0
  56. package/dist/tools/get-zimbabwean-implementations.d.ts +27 -0
  57. package/dist/tools/get-zimbabwean-implementations.d.ts.map +1 -0
  58. package/dist/tools/get-zimbabwean-implementations.js +48 -0
  59. package/dist/tools/get-zimbabwean-implementations.js.map +1 -0
  60. package/dist/tools/list-sources.d.ts +25 -0
  61. package/dist/tools/list-sources.d.ts.map +1 -0
  62. package/dist/tools/list-sources.js +44 -0
  63. package/dist/tools/list-sources.js.map +1 -0
  64. package/dist/tools/registry.d.ts +13 -0
  65. package/dist/tools/registry.d.ts.map +1 -0
  66. package/dist/tools/registry.js +365 -0
  67. package/dist/tools/registry.js.map +1 -0
  68. package/dist/tools/search-eu-implementations.d.ts +25 -0
  69. package/dist/tools/search-eu-implementations.d.ts.map +1 -0
  70. package/dist/tools/search-eu-implementations.js +59 -0
  71. package/dist/tools/search-eu-implementations.js.map +1 -0
  72. package/dist/tools/search-legislation.d.ts +24 -0
  73. package/dist/tools/search-legislation.d.ts.map +1 -0
  74. package/dist/tools/search-legislation.js +54 -0
  75. package/dist/tools/search-legislation.js.map +1 -0
  76. package/dist/tools/validate-citation.d.ts +26 -0
  77. package/dist/tools/validate-citation.d.ts.map +1 -0
  78. package/dist/tools/validate-citation.js +118 -0
  79. package/dist/tools/validate-citation.js.map +1 -0
  80. package/dist/tools/validate-eu-compliance.d.ts +20 -0
  81. package/dist/tools/validate-eu-compliance.d.ts.map +1 -0
  82. package/dist/tools/validate-eu-compliance.js +98 -0
  83. package/dist/tools/validate-eu-compliance.js.map +1 -0
  84. package/dist/utils/as-of-date.d.ts +9 -0
  85. package/dist/utils/as-of-date.d.ts.map +1 -0
  86. package/dist/utils/as-of-date.js +25 -0
  87. package/dist/utils/as-of-date.js.map +1 -0
  88. package/dist/utils/fts-query.d.ts +19 -0
  89. package/dist/utils/fts-query.d.ts.map +1 -0
  90. package/dist/utils/fts-query.js +47 -0
  91. package/dist/utils/fts-query.js.map +1 -0
  92. package/dist/utils/metadata.d.ts +16 -0
  93. package/dist/utils/metadata.d.ts.map +1 -0
  94. package/dist/utils/metadata.js +23 -0
  95. package/dist/utils/metadata.js.map +1 -0
  96. package/dist/utils/statute-id.d.ts +15 -0
  97. package/dist/utils/statute-id.d.ts.map +1 -0
  98. package/dist/utils/statute-id.js +39 -0
  99. package/dist/utils/statute-id.js.map +1 -0
  100. package/fixtures/golden-hashes.json +56 -0
  101. package/fixtures/golden-tests.json +180 -0
  102. package/package.json +77 -0
  103. package/server.json +22 -0
  104. package/sources.yml +64 -0
@@ -0,0 +1,118 @@
1
+ /**
2
+ * validate_citation — Validate a Zimbabwean legal citation against the database.
3
+ *
4
+ * Supports citation formats:
5
+ * - "Section N, [Act Title Year]" (e.g., "Section 29, Cyber and Data Protection Act 2021")
6
+ * - "s N" shorthand (e.g., "s 29 CDPA")
7
+ * - "Chapter N:NN" (e.g., "Chapter 9:23")
8
+ * - "[Act Title], Section N"
9
+ */
10
+ import { resolveDocumentId } from '../utils/statute-id.js';
11
+ import { generateResponseMetadata } from '../utils/metadata.js';
12
+ /**
13
+ * Parse a Zimbabwean legal citation.
14
+ * Supports:
15
+ * - "Section N, Act Title Year" / "Section N Act Title"
16
+ * - "s N Act Title"
17
+ * - "Act Title, Section N" / "Act Title Section N"
18
+ * - "Chapter N:NN"
19
+ * - Just a document reference
20
+ */
21
+ function parseCitation(citation) {
22
+ const trimmed = citation.trim();
23
+ // "Section N, Act Title" or "Section N Act Title"
24
+ const sectionFirst = trimmed.match(/^(?:Section|s\.?)\s+(\d+[A-Za-z]*)\s*[,;]?\s+(.+)$/i);
25
+ if (sectionFirst) {
26
+ return { documentRef: sectionFirst[2].trim(), sectionRef: sectionFirst[1] };
27
+ }
28
+ // "Act Title, Section N" or "Act Title Section N"
29
+ const sectionLast = trimmed.match(/^(.+?)[,;]?\s+(?:Section|s\.?)\s+(\d+[A-Za-z]*)$/i);
30
+ if (sectionLast) {
31
+ return { documentRef: sectionLast[1].trim(), sectionRef: sectionLast[2] };
32
+ }
33
+ // "Chapter N:NN, Section N"
34
+ const chapterWithSection = trimmed.match(/^(Chapter\s+\d+:\d+)\s*[,;]?\s*(?:Section|s\.?)\s+(\d+[A-Za-z]*)$/i);
35
+ if (chapterWithSection) {
36
+ return { documentRef: chapterWithSection[1], sectionRef: chapterWithSection[2] };
37
+ }
38
+ // "Chapter N:NN" alone
39
+ const chapterOnly = trimmed.match(/^Chapter\s+(\d+:\d+)$/i);
40
+ if (chapterOnly) {
41
+ return { documentRef: trimmed };
42
+ }
43
+ // Just a document reference
44
+ return { documentRef: trimmed };
45
+ }
46
+ export async function validateCitationTool(db, input) {
47
+ const warnings = [];
48
+ const parsed = parseCitation(input.citation);
49
+ if (!parsed) {
50
+ return {
51
+ results: {
52
+ valid: false,
53
+ citation: input.citation,
54
+ warnings: ['Could not parse citation format'],
55
+ },
56
+ _metadata: generateResponseMetadata(db),
57
+ };
58
+ }
59
+ const docId = resolveDocumentId(db, parsed.documentRef);
60
+ if (!docId) {
61
+ return {
62
+ results: {
63
+ valid: false,
64
+ citation: input.citation,
65
+ warnings: [`Document not found: "${parsed.documentRef}"`],
66
+ },
67
+ _metadata: generateResponseMetadata(db),
68
+ };
69
+ }
70
+ const doc = db.prepare('SELECT id, title, status FROM legal_documents WHERE id = ?').get(docId);
71
+ if (doc.status === 'repealed') {
72
+ warnings.push(`WARNING: This statute has been repealed.`);
73
+ }
74
+ else if (doc.status === 'amended') {
75
+ warnings.push(`Note: This statute has been amended. Verify you are referencing the current version.`);
76
+ }
77
+ if (parsed.sectionRef) {
78
+ const provision = db.prepare("SELECT provision_ref FROM legal_provisions WHERE document_id = ? AND (provision_ref = ? OR provision_ref = ? OR section = ?)").get(docId, parsed.sectionRef, `s${parsed.sectionRef}`, parsed.sectionRef);
79
+ if (!provision) {
80
+ return {
81
+ results: {
82
+ valid: false,
83
+ citation: input.citation,
84
+ document_id: docId,
85
+ document_title: doc.title,
86
+ warnings: [...warnings, `Provision "${parsed.sectionRef}" not found in ${doc.title}`],
87
+ },
88
+ _metadata: generateResponseMetadata(db),
89
+ };
90
+ }
91
+ return {
92
+ results: {
93
+ valid: true,
94
+ citation: input.citation,
95
+ normalized: `Section ${parsed.sectionRef}, ${doc.title}`,
96
+ document_id: docId,
97
+ document_title: doc.title,
98
+ provision_ref: provision.provision_ref,
99
+ status: doc.status,
100
+ warnings,
101
+ },
102
+ _metadata: generateResponseMetadata(db),
103
+ };
104
+ }
105
+ return {
106
+ results: {
107
+ valid: true,
108
+ citation: input.citation,
109
+ normalized: doc.title,
110
+ document_id: docId,
111
+ document_title: doc.title,
112
+ status: doc.status,
113
+ warnings,
114
+ },
115
+ _metadata: generateResponseMetadata(db),
116
+ };
117
+ }
118
+ //# sourceMappingURL=validate-citation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-citation.js","sourceRoot":"","sources":["../../src/tools/validate-citation.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,wBAAwB,EAAqB,MAAM,sBAAsB,CAAC;AAiBnF;;;;;;;;GAQG;AACH,SAAS,aAAa,CAAC,QAAgB;IACrC,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;IAEhC,kDAAkD;IAClD,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,qDAAqD,CAAC,CAAC;IAC1F,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9E,CAAC;IAED,kDAAkD;IAClD,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvF,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5E,CAAC;IAED,4BAA4B;IAC5B,MAAM,kBAAkB,GAAG,OAAO,CAAC,KAAK,CAAC,oEAAoE,CAAC,CAAC;IAC/G,IAAI,kBAAkB,EAAE,CAAC;QACvB,OAAO,EAAE,WAAW,EAAE,kBAAkB,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC;IACnF,CAAC;IAED,uBAAuB;IACvB,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC5D,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC;IAClC,CAAC;IAED,4BAA4B;IAC5B,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC;AAClC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,EAAiC,EACjC,KAA4B;IAE5B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAE7C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO;YACL,OAAO,EAAE;gBACP,KAAK,EAAE,KAAK;gBACZ,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,QAAQ,EAAE,CAAC,iCAAiC,CAAC;aAC9C;YACD,SAAS,EAAE,wBAAwB,CAAC,EAAE,CAAC;SACxC,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,iBAAiB,CAAC,EAAE,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;IACxD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO;YACL,OAAO,EAAE;gBACP,KAAK,EAAE,KAAK;gBACZ,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,QAAQ,EAAE,CAAC,wBAAwB,MAAM,CAAC,WAAW,GAAG,CAAC;aAC1D;YACD,SAAS,EAAE,wBAAwB,CAAC,EAAE,CAAC;SACxC,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CACpB,4DAA4D,CAC7D,CAAC,GAAG,CAAC,KAAK,CAAkD,CAAC;IAE9D,IAAI,GAAG,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QAC9B,QAAQ,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;IAC5D,CAAC;SAAM,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACpC,QAAQ,CAAC,IAAI,CAAC,sFAAsF,CAAC,CAAC;IACxG,CAAC;IAED,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACtB,MAAM,SAAS,GAAG,EAAE,CAAC,OAAO,CAC1B,8HAA8H,CAC/H,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,UAAU,EAAE,IAAI,MAAM,CAAC,UAAU,EAAE,EAAE,MAAM,CAAC,UAAU,CAA0C,CAAC;QAErH,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO;gBACL,OAAO,EAAE;oBACP,KAAK,EAAE,KAAK;oBACZ,QAAQ,EAAE,KAAK,CAAC,QAAQ;oBACxB,WAAW,EAAE,KAAK;oBAClB,cAAc,EAAE,GAAG,CAAC,KAAK;oBACzB,QAAQ,EAAE,CAAC,GAAG,QAAQ,EAAE,cAAc,MAAM,CAAC,UAAU,kBAAkB,GAAG,CAAC,KAAK,EAAE,CAAC;iBACtF;gBACD,SAAS,EAAE,wBAAwB,CAAC,EAAE,CAAC;aACxC,CAAC;QACJ,CAAC;QAED,OAAO;YACL,OAAO,EAAE;gBACP,KAAK,EAAE,IAAI;gBACX,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,UAAU,EAAE,WAAW,MAAM,CAAC,UAAU,KAAK,GAAG,CAAC,KAAK,EAAE;gBACxD,WAAW,EAAE,KAAK;gBAClB,cAAc,EAAE,GAAG,CAAC,KAAK;gBACzB,aAAa,EAAE,SAAS,CAAC,aAAa;gBACtC,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,QAAQ;aACT;YACD,SAAS,EAAE,wBAAwB,CAAC,EAAE,CAAC;SACxC,CAAC;IACJ,CAAC;IAED,OAAO;QACL,OAAO,EAAE;YACP,KAAK,EAAE,IAAI;YACX,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,UAAU,EAAE,GAAG,CAAC,KAAK;YACrB,WAAW,EAAE,KAAK;YAClB,cAAc,EAAE,GAAG,CAAC,KAAK;YACzB,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,QAAQ;SACT;QACD,SAAS,EAAE,wBAAwB,CAAC,EAAE,CAAC;KACxC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * validate_eu_compliance — Check international/EU alignment status for a Zimbabwean statute.
3
+ */
4
+ import type Database from '@ansvar/mcp-sqlite';
5
+ import { type ToolResponse } from '../utils/metadata.js';
6
+ export interface ValidateEUComplianceInput {
7
+ document_id: string;
8
+ provision_ref?: string;
9
+ eu_document_id?: string;
10
+ }
11
+ export interface EUComplianceResult {
12
+ document_id: string;
13
+ document_title: string;
14
+ compliance_status: 'compliant' | 'partial' | 'unclear' | 'not_applicable';
15
+ eu_references_found: number;
16
+ warnings: string[];
17
+ recommendations: string[];
18
+ }
19
+ export declare function validateEUCompliance(db: InstanceType<typeof Database>, input: ValidateEUComplianceInput): Promise<ToolResponse<EUComplianceResult>>;
20
+ //# sourceMappingURL=validate-eu-compliance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-eu-compliance.d.ts","sourceRoot":"","sources":["../../src/tools/validate-eu-compliance.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,QAAQ,MAAM,oBAAoB,CAAC;AAE/C,OAAO,EAA4B,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEnF,MAAM,WAAW,yBAAyB;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,gBAAgB,CAAC;IAC1E,mBAAmB,EAAE,MAAM,CAAC;IAC5B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,YAAY,CAAC,OAAO,QAAQ,CAAC,EACjC,KAAK,EAAE,yBAAyB,GAC/B,OAAO,CAAC,YAAY,CAAC,kBAAkB,CAAC,CAAC,CAuG3C"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * validate_eu_compliance — Check international/EU alignment status for a Zimbabwean statute.
3
+ */
4
+ import { resolveDocumentId } from '../utils/statute-id.js';
5
+ import { generateResponseMetadata } from '../utils/metadata.js';
6
+ export async function validateEUCompliance(db, input) {
7
+ const resolvedId = resolveDocumentId(db, input.document_id);
8
+ if (!resolvedId) {
9
+ return {
10
+ results: {
11
+ document_id: input.document_id,
12
+ document_title: 'Unknown',
13
+ compliance_status: 'not_applicable',
14
+ eu_references_found: 0,
15
+ warnings: [`Document not found: "${input.document_id}"`],
16
+ recommendations: [],
17
+ },
18
+ _metadata: generateResponseMetadata(db),
19
+ };
20
+ }
21
+ const doc = db.prepare('SELECT id, title, status FROM legal_documents WHERE id = ?').get(resolvedId);
22
+ const warnings = [];
23
+ const recommendations = [];
24
+ // Check if EU reference tables exist
25
+ let euRefCount = 0;
26
+ try {
27
+ let sql = 'SELECT COUNT(*) as count FROM eu_references WHERE document_id = ?';
28
+ const params = [resolvedId];
29
+ if (input.eu_document_id) {
30
+ sql += ' AND eu_document_id = ?';
31
+ params.push(input.eu_document_id);
32
+ }
33
+ const row = db.prepare(sql).get(...params);
34
+ euRefCount = row.count;
35
+ }
36
+ catch {
37
+ return {
38
+ results: {
39
+ document_id: resolvedId,
40
+ document_title: doc.title,
41
+ compliance_status: 'not_applicable',
42
+ eu_references_found: 0,
43
+ warnings: ['EU/international references not available in this database tier'],
44
+ recommendations: [],
45
+ },
46
+ _metadata: generateResponseMetadata(db),
47
+ };
48
+ }
49
+ if (euRefCount === 0) {
50
+ return {
51
+ results: {
52
+ document_id: resolvedId,
53
+ document_title: doc.title,
54
+ compliance_status: 'not_applicable',
55
+ eu_references_found: 0,
56
+ warnings: [],
57
+ recommendations: ['No international cross-references found for this statute. This may be a purely domestic law.'],
58
+ },
59
+ _metadata: generateResponseMetadata(db),
60
+ };
61
+ }
62
+ if (doc.status === 'repealed') {
63
+ warnings.push('This statute has been repealed.');
64
+ recommendations.push('Check for replacement legislation.');
65
+ }
66
+ // Check implementation status
67
+ const statuses = db.prepare('SELECT implementation_status, COUNT(*) as count FROM eu_references WHERE document_id = ? GROUP BY implementation_status').all(resolvedId);
68
+ const statusMap = new Map(statuses.map(s => [s.implementation_status, s.count]));
69
+ const completeCount = statusMap.get('complete') ?? 0;
70
+ const partialCount = statusMap.get('partial') ?? 0;
71
+ const unknownCount = statusMap.get('unknown') ?? 0;
72
+ let compliance_status;
73
+ if (completeCount > 0 && partialCount === 0 && unknownCount === 0) {
74
+ compliance_status = 'compliant';
75
+ }
76
+ else if (partialCount > 0) {
77
+ compliance_status = 'partial';
78
+ warnings.push(`${partialCount} international reference(s) have partial implementation status.`);
79
+ }
80
+ else {
81
+ compliance_status = 'unclear';
82
+ if (unknownCount > 0) {
83
+ recommendations.push(`${unknownCount} international reference(s) have unknown implementation status. Manual review recommended.`);
84
+ }
85
+ }
86
+ return {
87
+ results: {
88
+ document_id: resolvedId,
89
+ document_title: doc.title,
90
+ compliance_status,
91
+ eu_references_found: euRefCount,
92
+ warnings,
93
+ recommendations,
94
+ },
95
+ _metadata: generateResponseMetadata(db),
96
+ };
97
+ }
98
+ //# sourceMappingURL=validate-eu-compliance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-eu-compliance.js","sourceRoot":"","sources":["../../src/tools/validate-eu-compliance.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Date normalization for temporal queries.
3
+ */
4
+ /**
5
+ * Normalize an as-of date string to ISO 8601 format.
6
+ * Returns null if the input is not a valid date.
7
+ */
8
+ export declare function normalizeAsOfDate(input?: string): string | null;
9
+ //# sourceMappingURL=as-of-date.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"as-of-date.d.ts","sourceRoot":"","sources":["../../src/utils/as-of-date.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkB/D"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Date normalization for temporal queries.
3
+ */
4
+ /**
5
+ * Normalize an as-of date string to ISO 8601 format.
6
+ * Returns null if the input is not a valid date.
7
+ */
8
+ export function normalizeAsOfDate(input) {
9
+ if (!input || input.trim().length === 0)
10
+ return null;
11
+ const trimmed = input.trim();
12
+ // Already ISO 8601
13
+ if (/^\d{4}-\d{2}-\d{2}$/.test(trimmed)) {
14
+ const date = new Date(trimmed);
15
+ if (!isNaN(date.getTime()))
16
+ return trimmed;
17
+ }
18
+ // Try parsing as a general date
19
+ const date = new Date(trimmed);
20
+ if (!isNaN(date.getTime())) {
21
+ return date.toISOString().slice(0, 10);
22
+ }
23
+ return null;
24
+ }
25
+ //# sourceMappingURL=as-of-date.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"as-of-date.js","sourceRoot":"","sources":["../../src/utils/as-of-date.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAErD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAE7B,mBAAmB;IACnB,IAAI,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC;QAC/B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAAE,OAAO,OAAO,CAAC;IAC7C,CAAC;IAED,gCAAgC;IAChC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC;IAC/B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * FTS5 query helpers for Zimbabwe Law MCP.
3
+ *
4
+ * Handles query sanitization and variant generation for SQLite FTS5.
5
+ */
6
+ /**
7
+ * Sanitize user input for safe FTS5 queries.
8
+ * Removes characters that have special meaning in FTS5 syntax.
9
+ */
10
+ export declare function sanitizeFtsInput(input: string): string;
11
+ /**
12
+ * Build FTS5 query variants for a search term.
13
+ * Returns variants in order of specificity (most specific first):
14
+ * 1. Exact phrase match
15
+ * 2. All terms required (AND)
16
+ * 3. Prefix match on last term
17
+ */
18
+ export declare function buildFtsQueryVariants(sanitized: string): string[];
19
+ //# sourceMappingURL=fts-query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fts-query.d.ts","sourceRoot":"","sources":["../../src/utils/fts-query.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKtD;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CA2BjE"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * FTS5 query helpers for Zimbabwe Law MCP.
3
+ *
4
+ * Handles query sanitization and variant generation for SQLite FTS5.
5
+ */
6
+ /**
7
+ * Sanitize user input for safe FTS5 queries.
8
+ * Removes characters that have special meaning in FTS5 syntax.
9
+ */
10
+ export function sanitizeFtsInput(input) {
11
+ return input
12
+ .replace(/['"(){}[\]^~*:]/g, ' ')
13
+ .replace(/\s+/g, ' ')
14
+ .trim();
15
+ }
16
+ /**
17
+ * Build FTS5 query variants for a search term.
18
+ * Returns variants in order of specificity (most specific first):
19
+ * 1. Exact phrase match
20
+ * 2. All terms required (AND)
21
+ * 3. Prefix match on last term
22
+ */
23
+ export function buildFtsQueryVariants(sanitized) {
24
+ if (!sanitized || sanitized.trim().length === 0) {
25
+ return [];
26
+ }
27
+ const terms = sanitized.split(/\s+/).filter(t => t.length > 0);
28
+ if (terms.length === 0)
29
+ return [];
30
+ const variants = [];
31
+ // Exact phrase
32
+ if (terms.length > 1) {
33
+ variants.push(`"${terms.join(' ')}"`);
34
+ }
35
+ // AND query
36
+ variants.push(terms.join(' AND '));
37
+ // Prefix match on last term (for autocomplete-like behavior)
38
+ if (terms.length === 1 && terms[0].length >= 3) {
39
+ variants.push(`${terms[0]}*`);
40
+ }
41
+ else if (terms.length > 1) {
42
+ const prefix = [...terms.slice(0, -1), `${terms[terms.length - 1]}*`];
43
+ variants.push(prefix.join(' AND '));
44
+ }
45
+ return variants;
46
+ }
47
+ //# sourceMappingURL=fts-query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fts-query.js","sourceRoot":"","sources":["../../src/utils/fts-query.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,OAAO,KAAK;SACT,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC;SAChC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,IAAI,EAAE,CAAC;AACZ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,SAAiB;IACrD,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChD,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC/D,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAElC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,eAAe;IACf,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACxC,CAAC;IAED,YAAY;IACZ,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAEnC,6DAA6D;IAC7D,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QAC/C,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;SAAM,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QACtE,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IACtC,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Response metadata utilities for Zimbabwe Law MCP.
3
+ */
4
+ import type Database from '@ansvar/mcp-sqlite';
5
+ export interface ResponseMetadata {
6
+ data_source: string;
7
+ jurisdiction: string;
8
+ disclaimer: string;
9
+ freshness?: string;
10
+ }
11
+ export interface ToolResponse<T> {
12
+ results: T;
13
+ _metadata: ResponseMetadata;
14
+ }
15
+ export declare function generateResponseMetadata(db: InstanceType<typeof Database>): ResponseMetadata;
16
+ //# sourceMappingURL=metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/utils/metadata.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,QAAQ,MAAM,oBAAoB,CAAC;AAE/C,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,OAAO,EAAE,CAAC,CAAC;IACX,SAAS,EAAE,gBAAgB,CAAC;CAC7B;AAED,wBAAgB,wBAAwB,CACtC,EAAE,EAAE,YAAY,CAAC,OAAO,QAAQ,CAAC,GAChC,gBAAgB,CAoBlB"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Response metadata utilities for Zimbabwe Law MCP.
3
+ */
4
+ export function generateResponseMetadata(db) {
5
+ let freshness;
6
+ try {
7
+ const row = db.prepare("SELECT value FROM db_metadata WHERE key = 'built_at'").get();
8
+ if (row)
9
+ freshness = row.value;
10
+ }
11
+ catch {
12
+ // Ignore
13
+ }
14
+ return {
15
+ data_source: 'ZimLII (zimlii.org) — Zimbabwe Legal Information Institute, hosted by AfricanLII',
16
+ jurisdiction: 'ZW',
17
+ disclaimer: 'This data is sourced from ZimLII under free access principles. ' +
18
+ 'Government legislation is public domain under Zimbabwean law. ' +
19
+ 'Always verify with the official Zimbabwe Government Gazette or Parliament of Zimbabwe portal.',
20
+ freshness,
21
+ };
22
+ }
23
+ //# sourceMappingURL=metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/utils/metadata.ts"],"names":[],"mappings":"AAAA;;GAEG;AAgBH,MAAM,UAAU,wBAAwB,CACtC,EAAiC;IAEjC,IAAI,SAA6B,CAAC;IAClC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CACpB,sDAAsD,CACvD,CAAC,GAAG,EAAmC,CAAC;QACzC,IAAI,GAAG;YAAE,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,SAAS;IACX,CAAC;IAED,OAAO;QACL,WAAW,EAAE,kFAAkF;QAC/F,YAAY,EAAE,IAAI;QAClB,UAAU,EACR,iEAAiE;YACjE,gEAAgE;YAChE,+FAA+F;QACjG,SAAS;KACV,CAAC;AACJ,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Statute ID resolution for Zimbabwe Law MCP.
3
+ *
4
+ * Resolves fuzzy document references (titles, chapter numbers) to database document IDs.
5
+ */
6
+ import type Database from '@ansvar/mcp-sqlite';
7
+ /**
8
+ * Resolve a document identifier to a database document ID.
9
+ * Supports:
10
+ * - Direct ID match (e.g., "zw-cyber-data-protection-2021")
11
+ * - Chapter number match (e.g., "Chapter 9:23", "9:23")
12
+ * - Title substring match (e.g., "Cyber and Data Protection", "CDPA")
13
+ */
14
+ export declare function resolveDocumentId(db: InstanceType<typeof Database>, input: string): string | null;
15
+ //# sourceMappingURL=statute-id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"statute-id.d.ts","sourceRoot":"","sources":["../../src/utils/statute-id.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,QAAQ,MAAM,oBAAoB,CAAC;AAE/C;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,EAAE,EAAE,YAAY,CAAC,OAAO,QAAQ,CAAC,EACjC,KAAK,EAAE,MAAM,GACZ,MAAM,GAAG,IAAI,CAiCf"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Statute ID resolution for Zimbabwe Law MCP.
3
+ *
4
+ * Resolves fuzzy document references (titles, chapter numbers) to database document IDs.
5
+ */
6
+ /**
7
+ * Resolve a document identifier to a database document ID.
8
+ * Supports:
9
+ * - Direct ID match (e.g., "zw-cyber-data-protection-2021")
10
+ * - Chapter number match (e.g., "Chapter 9:23", "9:23")
11
+ * - Title substring match (e.g., "Cyber and Data Protection", "CDPA")
12
+ */
13
+ export function resolveDocumentId(db, input) {
14
+ const trimmed = input.trim();
15
+ if (!trimmed)
16
+ return null;
17
+ // Direct ID match
18
+ const directMatch = db.prepare('SELECT id FROM legal_documents WHERE id = ?').get(trimmed);
19
+ if (directMatch)
20
+ return directMatch.id;
21
+ // Chapter number match (e.g., "Chapter 9:23" or just "9:23")
22
+ const chapterMatch = trimmed.match(/(?:Chapter\s+)?(\d+:\d+)/i);
23
+ if (chapterMatch) {
24
+ const chapterNum = chapterMatch[1];
25
+ const chResult = db.prepare("SELECT id FROM legal_documents WHERE short_name LIKE ? OR title LIKE ? LIMIT 1").get(`%${chapterNum}%`, `%${chapterNum}%`);
26
+ if (chResult)
27
+ return chResult.id;
28
+ }
29
+ // Title/short_name fuzzy match
30
+ const titleResult = db.prepare("SELECT id FROM legal_documents WHERE title LIKE ? OR short_name LIKE ? OR title_en LIKE ? LIMIT 1").get(`%${trimmed}%`, `%${trimmed}%`, `%${trimmed}%`);
31
+ if (titleResult)
32
+ return titleResult.id;
33
+ // Case-insensitive fallback
34
+ const lowerResult = db.prepare("SELECT id FROM legal_documents WHERE LOWER(title) LIKE LOWER(?) OR LOWER(short_name) LIKE LOWER(?) OR LOWER(title_en) LIKE LOWER(?) LIMIT 1").get(`%${trimmed}%`, `%${trimmed}%`, `%${trimmed}%`);
35
+ if (lowerResult)
36
+ return lowerResult.id;
37
+ return null;
38
+ }
39
+ //# sourceMappingURL=statute-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"statute-id.js","sourceRoot":"","sources":["../../src/utils/statute-id.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,EAAiC,EACjC,KAAa;IAEb,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAE1B,kBAAkB;IAClB,MAAM,WAAW,GAAG,EAAE,CAAC,OAAO,CAC5B,6CAA6C,CAC9C,CAAC,GAAG,CAAC,OAAO,CAA+B,CAAC;IAC7C,IAAI,WAAW;QAAE,OAAO,WAAW,CAAC,EAAE,CAAC;IAEvC,6DAA6D;IAC7D,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAChE,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,UAAU,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;QACnC,MAAM,QAAQ,GAAG,EAAE,CAAC,OAAO,CACzB,gFAAgF,CACjF,CAAC,GAAG,CAAC,IAAI,UAAU,GAAG,EAAE,IAAI,UAAU,GAAG,CAA+B,CAAC;QAC1E,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAC,EAAE,CAAC;IACnC,CAAC;IAED,+BAA+B;IAC/B,MAAM,WAAW,GAAG,EAAE,CAAC,OAAO,CAC5B,mGAAmG,CACpG,CAAC,GAAG,CAAC,IAAI,OAAO,GAAG,EAAE,IAAI,OAAO,GAAG,EAAE,IAAI,OAAO,GAAG,CAA+B,CAAC;IACpF,IAAI,WAAW;QAAE,OAAO,WAAW,CAAC,EAAE,CAAC;IAEvC,4BAA4B;IAC5B,MAAM,WAAW,GAAG,EAAE,CAAC,OAAO,CAC5B,6IAA6I,CAC9I,CAAC,GAAG,CAAC,IAAI,OAAO,GAAG,EAAE,IAAI,OAAO,GAAG,EAAE,IAAI,OAAO,GAAG,CAA+B,CAAC;IACpF,IAAI,WAAW;QAAE,OAAO,WAAW,CAAC,EAAE,CAAC;IAEvC,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,56 @@
1
+ {
2
+ "$schema": "./golden-hashes.schema.json",
3
+ "version": "1.0",
4
+ "mcp_name": "Zimbabwe Law MCP",
5
+ "jurisdiction": "ZW",
6
+ "provisions": [
7
+ {
8
+ "id": "zw-hash-001",
9
+ "description": "Constitution of Zimbabwe (2013), Section 1 — Republic of Zimbabwe (stable constitutional anchor)",
10
+ "upstream_url": "https://zimlii.org/zw/legislation/act/2013/amendment-no-20/eng",
11
+ "selector_hint": "Section 1",
12
+ "expected_sha256": "COMPUTE_ON_FIRST_INGEST",
13
+ "expected_snippet": "Republic of Zimbabwe"
14
+ },
15
+ {
16
+ "id": "zw-hash-002",
17
+ "description": "Cyber and Data Protection Act 2021, Section 2 — interpretation and definitions",
18
+ "upstream_url": "https://zimlii.org/zw/legislation/act/2021/5/eng",
19
+ "selector_hint": "Section 2",
20
+ "expected_sha256": "COMPUTE_ON_FIRST_INGEST",
21
+ "expected_snippet": "interpretation"
22
+ },
23
+ {
24
+ "id": "zw-hash-003",
25
+ "description": "Cyber and Data Protection Act 2021, Section 3 — objects of Act (data protection and cybersecurity purposes)",
26
+ "upstream_url": "https://zimlii.org/zw/legislation/act/2021/5/eng",
27
+ "selector_hint": "Section 3",
28
+ "expected_sha256": "COMPUTE_ON_FIRST_INGEST",
29
+ "expected_snippet": "objects"
30
+ },
31
+ {
32
+ "id": "zw-hash-004",
33
+ "description": "Access to Information and Protection of Privacy Act (AIPPA), Section 1 — short title",
34
+ "upstream_url": "https://zimlii.org/zw/legislation/act/2002/5/eng",
35
+ "selector_hint": "Section 1",
36
+ "expected_sha256": "COMPUTE_ON_FIRST_INGEST",
37
+ "expected_snippet": "Access to Information and Protection of Privacy"
38
+ },
39
+ {
40
+ "id": "zw-hash-005",
41
+ "description": "Criminal Law (Codification and Reform) Act (Chapter 9:23), Section 1 — short title and commencement",
42
+ "upstream_url": "https://zimlii.org/zw/legislation/act/2004/23/eng",
43
+ "selector_hint": "Section 1",
44
+ "expected_sha256": "COMPUTE_ON_FIRST_INGEST",
45
+ "expected_snippet": "Criminal Law"
46
+ },
47
+ {
48
+ "id": "zw-hash-006",
49
+ "description": "Postal and Telecommunications Act (Chapter 12:05), Section 1 — short title",
50
+ "upstream_url": "https://zimlii.org/zw/legislation/act/2000/4/eng",
51
+ "selector_hint": "Section 1",
52
+ "expected_sha256": "COMPUTE_ON_FIRST_INGEST",
53
+ "expected_snippet": "Postal and Telecommunications"
54
+ }
55
+ ]
56
+ }