@costrinity/vigil-compliance-mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,105 @@
1
+ # @costrinity/vigil-compliance-mcp
2
+
3
+ **MCP server exposing VIGIL's compliance fabric as tools your LLM agents can call.**
4
+
5
+ Pair with [`@costrinity/vigil-mcp`](https://www.npmjs.com/package/@costrinity/vigil-mcp) (the JSON-RPC observer): the observer captures what your agent does, this server gives your agent compliance superpowers before it acts.
6
+
7
+ ## What it gives your agent
8
+
9
+ | Tool | Purpose |
10
+ |---|---|
11
+ | `consent_check` | Is processing allowed for this principal + purpose? (pre-flight gate) |
12
+ | `breach_classify` | Is this incident reportable? Per-jurisdiction decision support |
13
+ | `ai_act_classify` | EU AI Act risk tier classification |
14
+ | `dpia_threshold_check` | Is a DPIA mandatory before this processing? |
15
+ | `us_sectoral_check` | HIPAA / GLBA / COPPA / FERPA / FCRA / SOX applicability |
16
+ | `india_sectoral_check` | RBI / SEBI / IRDAI / TRAI / PFRDA applicability |
17
+ | `india_cross_border_status` | DPDP §16 status for a destination country |
18
+ | `japan_cross_border_status` | APPI Art 28 status for a destination country |
19
+ | `us_state_breach_deadline` | US state breach window + AG recipient |
20
+ | `aadhaar_mask` / `pan_classify` / `gstin_validate` / `cpf_validate` / `sin_validate` / `iban_validate` | Identifier validators with masking + reference token |
21
+ | `pii_test` | Dry-run threat detection on a sample event |
22
+ | `privacy_notice_get` | Generate operator's jurisdiction-templated privacy notice |
23
+ | `sub_processors_register` | Sub-processor disclosure register |
24
+ | `global_compliance_map` | 28+ regimes VIGIL has fabric for |
25
+ | `india_regulators_directory` | Indian regulators + sectoral filter |
26
+
27
+ ## Install
28
+
29
+ ```bash
30
+ npm install -g @costrinity/vigil-compliance-mcp
31
+ ```
32
+
33
+ Or use directly via `npx`.
34
+
35
+ ## Configure your MCP client
36
+
37
+ ### Claude Desktop / Code / Cursor (`mcp.json`)
38
+
39
+ ```json
40
+ {
41
+ "mcpServers": {
42
+ "vigil-compliance": {
43
+ "command": "npx",
44
+ "args": ["@costrinity/vigil-compliance-mcp"],
45
+ "env": {
46
+ "VIGIL_OWNER_ID": "<your-owner-uuid>",
47
+ "VIGIL_API_KEY": "vigil_<your-key>",
48
+ "VIGIL_BASE_URL": "https://vigil.costrinity.xyz"
49
+ }
50
+ }
51
+ }
52
+ }
53
+ ```
54
+
55
+ ### What the env vars do
56
+
57
+ - `VIGIL_OWNER_ID` — your operator UUID. Required; every tool call carries this. Get it from your VIGIL dashboard's URL.
58
+ - `VIGIL_API_KEY` — optional but recommended. Authenticates the tool calls.
59
+ - `VIGIL_BASE_URL` — defaults to `https://vigil.costrinity.xyz`. Point at your own VIGIL instance if self-hosted.
60
+
61
+ ## Example agent interactions
62
+
63
+ **Agent considering cross-border transfer:**
64
+
65
+ > User: Move this Indian user's profile to our US analytics warehouse.
66
+
67
+ > Agent: Let me check DPDP §16 status first.
68
+ > *Calls `india_cross_border_status({ country: "US" })`*
69
+ > Result: `permitted, but RBI Digital Lending Guidelines require India-only storage for fintech lending data`.
70
+ >
71
+ > Agent: This transfer is permitted under DPDP §16 (US is not on India's negative list). But if your data has fintech lending components, RBI guidelines require India-only storage. Do you want me to filter those fields out first?
72
+
73
+ **Agent reviewing a new AI use case:**
74
+
75
+ > User: We're building an AI tool to evaluate job applicants.
76
+
77
+ > Agent: *Calls `ai_act_classify({ use_case: "AI evaluation of job applicants", sectors: ["employment"], automated_decisions: true })`*
78
+ > Result: `high-risk, Art 35(3)(a) + Annex III, requires conformity assessment + human oversight + bias monitoring`.
79
+ >
80
+ > Agent: This is a **high-risk** AI system under the EU AI Act Annex III (employment / HR). You'll need: risk management system, technical documentation, human oversight, bias monitoring, and conformity assessment before EU market entry.
81
+
82
+ **Agent handling a breach:**
83
+
84
+ > User: We just discovered 1200 user records were exposed.
85
+
86
+ > Agent: *Calls `breach_classify({ affected_count: 1200, data_categories: ["email", "phone"], sensitivity: "medium", recovery_state: "exposed" })`*
87
+ > Result: `reportable=true, window_hours=72, deadline=..., recipient="Data Protection Board of India"`.
88
+ >
89
+ > Agent: This is reportable to the Data Protection Board of India within 72 hours (deadline: 2026-06-05). Should I prepare the §8 notification draft?
90
+
91
+ ## Why this exists
92
+
93
+ Compliance lives in the operator's runtime, not their planning stage. An agent about to:
94
+ - Send a user record cross-border
95
+ - Decide on a high-risk action affecting an individual
96
+ - Classify a breach for severity
97
+ - Validate an identifier before storing it
98
+
99
+ ...should be able to **ask** VIGIL whether that's allowed *at request time*, not in a yearly DPIA.
100
+
101
+ MCP turns VIGIL from "a dashboard the operator visits" into "a synchronous decision-support layer the agent calls."
102
+
103
+ ## License
104
+
105
+ MIT © COSTRINITY (Indigenous-owned software studio, Regina, Saskatchewan, Treaty 4 territory)
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * VIGIL Compliance MCP server.
4
+ *
5
+ * Exposes VIGIL's compliance fabric as MCP tools so LLM agents can:
6
+ * - Check if processing is allowed under any active consent
7
+ * - Classify whether an incident is reportable per jurisdiction
8
+ * - Classify an AI system under the EU AI Act
9
+ * - Validate identifiers (Aadhaar / CPF / SIN / etc.) with masking
10
+ * - Generate cross-border transfer notices
11
+ * - Look up sub-processor disclosures, US state laws, breach deadlines
12
+ * - Run DPIA + ROPA + SCC Annex II + privacy notice generators
13
+ *
14
+ * Why this exists
15
+ * Compliance lives in the operator's runtime, not their planning stage.
16
+ * An agent that's about to send a user record cross-border should be
17
+ * able to ASK whether that's allowed — at request time, not in a
18
+ * yearly DPIA. MCP turns VIGIL from a dashboard the operator visits
19
+ * into a synchronous decision-support layer the agent calls.
20
+ *
21
+ * Pair with `@costrinity/vigil-mcp` (the proxy/observer) for full
22
+ * coverage: the observer captures what the agent does, this server
23
+ * gives the agent compliance superpowers before it acts.
24
+ *
25
+ * Transport
26
+ * stdio JSON-RPC 2.0 — same as every other MCP server. Add to your
27
+ * client config:
28
+ *
29
+ * {
30
+ * "mcpServers": {
31
+ * "vigil-compliance": {
32
+ * "command": "npx",
33
+ * "args": ["@costrinity/vigil-compliance-mcp"],
34
+ * "env": {
35
+ * "VIGIL_OWNER_ID": "<your-owner-uuid>",
36
+ * "VIGIL_API_KEY": "vigil_<your-key>",
37
+ * "VIGIL_BASE_URL": "https://vigil.costrinity.xyz"
38
+ * }
39
+ * }
40
+ * }
41
+ * }
42
+ *
43
+ * Tool catalogue
44
+ * The MCP `tools/list` response enumerates each tool with its input
45
+ * schema. Keep the catalogue stable across versions; add new tools
46
+ * rather than mutating signatures.
47
+ */
48
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,400 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * VIGIL Compliance MCP server.
5
+ *
6
+ * Exposes VIGIL's compliance fabric as MCP tools so LLM agents can:
7
+ * - Check if processing is allowed under any active consent
8
+ * - Classify whether an incident is reportable per jurisdiction
9
+ * - Classify an AI system under the EU AI Act
10
+ * - Validate identifiers (Aadhaar / CPF / SIN / etc.) with masking
11
+ * - Generate cross-border transfer notices
12
+ * - Look up sub-processor disclosures, US state laws, breach deadlines
13
+ * - Run DPIA + ROPA + SCC Annex II + privacy notice generators
14
+ *
15
+ * Why this exists
16
+ * Compliance lives in the operator's runtime, not their planning stage.
17
+ * An agent that's about to send a user record cross-border should be
18
+ * able to ASK whether that's allowed — at request time, not in a
19
+ * yearly DPIA. MCP turns VIGIL from a dashboard the operator visits
20
+ * into a synchronous decision-support layer the agent calls.
21
+ *
22
+ * Pair with `@costrinity/vigil-mcp` (the proxy/observer) for full
23
+ * coverage: the observer captures what the agent does, this server
24
+ * gives the agent compliance superpowers before it acts.
25
+ *
26
+ * Transport
27
+ * stdio JSON-RPC 2.0 — same as every other MCP server. Add to your
28
+ * client config:
29
+ *
30
+ * {
31
+ * "mcpServers": {
32
+ * "vigil-compliance": {
33
+ * "command": "npx",
34
+ * "args": ["@costrinity/vigil-compliance-mcp"],
35
+ * "env": {
36
+ * "VIGIL_OWNER_ID": "<your-owner-uuid>",
37
+ * "VIGIL_API_KEY": "vigil_<your-key>",
38
+ * "VIGIL_BASE_URL": "https://vigil.costrinity.xyz"
39
+ * }
40
+ * }
41
+ * }
42
+ * }
43
+ *
44
+ * Tool catalogue
45
+ * The MCP `tools/list` response enumerates each tool with its input
46
+ * schema. Keep the catalogue stable across versions; add new tools
47
+ * rather than mutating signatures.
48
+ */
49
+ Object.defineProperty(exports, "__esModule", { value: true });
50
+ const node_readline_1 = require("node:readline");
51
+ const VIGIL_BASE_URL = process.env.VIGIL_BASE_URL ?? 'https://vigil.costrinity.xyz';
52
+ const VIGIL_OWNER_ID = process.env.VIGIL_OWNER_ID ?? '';
53
+ const VIGIL_API_KEY = process.env.VIGIL_API_KEY ?? '';
54
+ const SERVER_NAME = 'vigil-compliance';
55
+ const SERVER_VERSION = '0.1.0';
56
+ const TOOLS = [
57
+ // ─── Consent + processing gate ───────────────────────────────────
58
+ {
59
+ name: 'consent_check',
60
+ description: "Pre-flight check: is processing allowed for this data principal + purpose? Returns { allowed, reason, matching_consent_id, principal_id }. Call this BEFORE processing data on behalf of a principal.",
61
+ inputSchema: {
62
+ type: 'object',
63
+ required: ['purpose'],
64
+ properties: {
65
+ principal_id: { type: 'string', description: 'UUID of the data principal (if known).' },
66
+ principal_ref: { type: 'string', description: 'Operator-side identifier; will be SHA-256-hashed.' },
67
+ purpose: { type: 'string', description: "Purpose code (e.g. 'operational_observability')." },
68
+ category: { type: 'string', description: 'Optional permitted-category check.' },
69
+ },
70
+ },
71
+ call: (input) => ({
72
+ method: 'POST',
73
+ path: '/api/consent/check',
74
+ body: input,
75
+ }),
76
+ },
77
+ // ─── Breach + incident classification ────────────────────────────
78
+ {
79
+ name: 'breach_classify',
80
+ description: 'Decide whether an incident is reportable per the operator\'s jurisdiction (DPDP §8, GDPR Art 33, CPRA §1798.82, LGPD Art 48, PDPA §26B, US-FED sectoral). Returns reportability + reasoning + deadline + recipient.',
81
+ inputSchema: {
82
+ type: 'object',
83
+ required: ['affected_count', 'data_categories', 'sensitivity', 'recovery_state'],
84
+ properties: {
85
+ affected_count: { type: 'integer' },
86
+ data_categories: { type: 'array', items: { type: 'string' } },
87
+ processing_purpose: { type: 'string' },
88
+ sensitivity: { type: 'string', enum: ['low', 'medium', 'high', 'special'] },
89
+ recovery_state: { type: 'string', enum: ['lost', 'exposed', 'altered', 'destroyed', 'contained'] },
90
+ jurisdiction: { type: 'string' },
91
+ },
92
+ },
93
+ call: (input) => ({ method: 'POST', path: '/api/compliance/breach-classify', body: input }),
94
+ },
95
+ // ─── EU AI Act risk classifier ────────────────────────────────────
96
+ {
97
+ name: 'ai_act_classify',
98
+ description: "Classify an AI use case under the EU AI Act (Regulation 2024/1689). Returns risk tier (prohibited / high-risk / limited-risk / minimal-risk) + GPAI obligations + per-tier remediation obligations.",
99
+ inputSchema: {
100
+ type: 'object',
101
+ required: ['use_case'],
102
+ properties: {
103
+ use_case: { type: 'string' },
104
+ data_categories: { type: 'array', items: { type: 'string' } },
105
+ sectors: { type: 'array', items: { type: 'string' } },
106
+ automated_decisions: { type: 'boolean' },
107
+ biometric: { type: 'boolean' },
108
+ remote_identification: { type: 'boolean' },
109
+ social_scoring: { type: 'boolean' },
110
+ general_purpose_ai: { type: 'boolean' },
111
+ },
112
+ },
113
+ call: (input) => ({ method: 'POST', path: '/api/compliance/ai-act-classify', body: input }),
114
+ },
115
+ // ─── DPIA threshold check ─────────────────────────────────────────
116
+ {
117
+ name: 'dpia_threshold_check',
118
+ description: 'Decide if a DPIA is mandatory before processing under GDPR Art 35 / DPDP §10 / LGPD Art 38. Returns dpia_required + 9-criterion WP29 analysis + jurisdiction-specific guidance.',
119
+ inputSchema: {
120
+ type: 'object',
121
+ required: ['processing_purpose', 'data_categories'],
122
+ properties: {
123
+ processing_purpose: { type: 'string' },
124
+ data_categories: { type: 'array', items: { type: 'string' } },
125
+ scale: { type: 'string', enum: ['small', 'medium', 'large', 'mass'] },
126
+ automated_decision: { type: 'boolean' },
127
+ systematic_monitoring: { type: 'boolean' },
128
+ cross_border: { type: 'boolean' },
129
+ vulnerable_subjects: { type: 'boolean' },
130
+ jurisdiction: { type: 'string' },
131
+ },
132
+ },
133
+ call: (input) => ({ method: 'POST', path: '/api/compliance/dpia-threshold-check', body: input }),
134
+ },
135
+ // ─── US sectoral analysis ─────────────────────────────────────────
136
+ {
137
+ name: 'us_sectoral_check',
138
+ description: 'Determine which US sectoral laws apply (HIPAA, GLBA, COPPA, FERPA, FCRA, SOX) given a processing profile.',
139
+ inputSchema: {
140
+ type: 'object',
141
+ required: ['processing_purpose', 'data_categories'],
142
+ properties: {
143
+ processing_purpose: { type: 'string' },
144
+ data_categories: { type: 'array', items: { type: 'string' } },
145
+ counterparty_types: { type: 'array', items: { type: 'string' } },
146
+ ai_decisions: { type: 'boolean' },
147
+ has_revenue_threshold: { type: 'boolean' },
148
+ },
149
+ },
150
+ call: (input) => ({ method: 'POST', path: '/api/compliance/sectoral-check', body: input }),
151
+ },
152
+ // ─── Indian sectoral analysis ─────────────────────────────────────
153
+ {
154
+ name: 'india_sectoral_check',
155
+ description: 'Determine which Indian sectoral regulators apply (RBI / SEBI / IRDAI / TRAI / DoT / PFRDA) given a processing profile.',
156
+ inputSchema: {
157
+ type: 'object',
158
+ required: ['processing_purpose', 'data_categories'],
159
+ properties: {
160
+ processing_purpose: { type: 'string' },
161
+ data_categories: { type: 'array', items: { type: 'string' } },
162
+ counterparty_types: { type: 'array', items: { type: 'string' } },
163
+ sector_hint: { type: 'string' },
164
+ },
165
+ },
166
+ call: (input) => ({ method: 'POST', path: '/api/compliance/india-sectoral-check', body: input }),
167
+ },
168
+ // ─── Cross-border lookups ─────────────────────────────────────────
169
+ {
170
+ name: 'india_cross_border_status',
171
+ description: 'Look up DPDP §16 cross-border transfer status for a destination country. Returns permitted / restricted / sectoral_restricted + RBI/SEBI/IRDAI caveats.',
172
+ inputSchema: {
173
+ type: 'object',
174
+ required: ['country'],
175
+ properties: { country: { type: 'string', description: 'ISO-3166 alpha-2 (e.g. US).' } },
176
+ },
177
+ call: (input) => ({
178
+ method: 'GET',
179
+ path: `/api/compliance/india-cross-border-countries?country=${encodeURIComponent(String(input.country ?? ''))}`,
180
+ }),
181
+ },
182
+ {
183
+ name: 'japan_cross_border_status',
184
+ description: 'Look up Japan APPI Art 28 cross-border status for a destination country (adequacy / standard basis / high scrutiny).',
185
+ inputSchema: {
186
+ type: 'object',
187
+ required: ['country'],
188
+ properties: { country: { type: 'string', description: 'ISO-3166 alpha-2.' } },
189
+ },
190
+ call: (input) => ({
191
+ method: 'GET',
192
+ path: `/api/compliance/japan-cross-border?country=${encodeURIComponent(String(input.country ?? ''))}`,
193
+ }),
194
+ },
195
+ // ─── US state breach deadlines ────────────────────────────────────
196
+ {
197
+ name: 'us_state_breach_deadline',
198
+ description: "Look up a US state's breach-notification window + AG recipient + threshold (e.g. 'CA' → 500 residents → CA AG → expedient).",
199
+ inputSchema: {
200
+ type: 'object',
201
+ required: ['state'],
202
+ properties: { state: { type: 'string', description: 'US 2-letter state code (CA, NY, TX, ...).' } },
203
+ },
204
+ call: (input) => ({
205
+ method: 'GET',
206
+ path: `/api/compliance/state-breach-deadlines?state=${encodeURIComponent(String(input.state ?? ''))}`,
207
+ }),
208
+ },
209
+ // ─── Identifier validators (all auth-gated; pass owner_id) ───────
210
+ {
211
+ name: 'aadhaar_mask',
212
+ description: "Mask + Verhoeff-validate an Aadhaar number. Returns masked form, validity, and an owner-scoped reference token. No persistence of the raw value.",
213
+ inputSchema: {
214
+ type: 'object',
215
+ required: ['aadhaar'],
216
+ properties: { aadhaar: { type: 'string' } },
217
+ },
218
+ call: (input) => ({ method: 'POST', path: '/api/india/aadhaar-mask', body: input }),
219
+ },
220
+ {
221
+ name: 'pan_classify',
222
+ description: 'Classify a PAN entity type from the 4th character (P=Person, C=Company, H=HUF, F=Firm, ...).',
223
+ inputSchema: { type: 'object', required: ['pan'], properties: { pan: { type: 'string' } } },
224
+ call: (input) => ({ method: 'POST', path: '/api/india/pan-classify', body: input }),
225
+ },
226
+ {
227
+ name: 'gstin_validate',
228
+ description: 'Validate a GSTIN format + mod-36 check digit; returns state code lookup.',
229
+ inputSchema: { type: 'object', required: ['gstin'], properties: { gstin: { type: 'string' } } },
230
+ call: (input) => ({ method: 'POST', path: '/api/india/gstn-validate', body: input }),
231
+ },
232
+ {
233
+ name: 'cpf_validate',
234
+ description: 'Validate a Brazilian CPF (mod-11 check digits, rejects all-same).',
235
+ inputSchema: { type: 'object', required: ['cpf'], properties: { cpf: { type: 'string' } } },
236
+ call: (input) => ({ method: 'POST', path: '/api/brazil/cpf-validate', body: input }),
237
+ },
238
+ {
239
+ name: 'sin_validate',
240
+ description: 'Validate a Canadian SIN (Luhn checksum); returns series region + masked form.',
241
+ inputSchema: { type: 'object', required: ['sin'], properties: { sin: { type: 'string' } } },
242
+ call: (input) => ({ method: 'POST', path: '/api/canada/sin-validate', body: input }),
243
+ },
244
+ {
245
+ name: 'iban_validate',
246
+ description: 'Validate an IBAN format + ISO 7064 mod-97 check digit; supports 66 countries.',
247
+ inputSchema: { type: 'object', required: ['iban'], properties: { iban: { type: 'string' } } },
248
+ call: (input) => ({ method: 'POST', path: '/api/eu/iban-validate', body: input }),
249
+ },
250
+ {
251
+ name: 'pii_test',
252
+ description: "Dry-run PII / threat detection against a sample event. Returns what would be tagged, redacted preview, and whether severity would be escalated. No persistence.",
253
+ inputSchema: {
254
+ type: 'object',
255
+ required: ['sample_event'],
256
+ properties: {
257
+ sample_event: { type: 'object', description: 'event_type / message / payload fields.' },
258
+ jurisdiction: { type: 'string' },
259
+ },
260
+ },
261
+ call: (input) => ({ method: 'POST', path: '/api/compliance/pii-test', body: input }),
262
+ },
263
+ // ─── Read-only generators ─────────────────────────────────────────
264
+ {
265
+ name: 'privacy_notice_get',
266
+ description: "Generate the operator's jurisdiction-templated privacy notice. Returns markdown or JSON.",
267
+ inputSchema: {
268
+ type: 'object',
269
+ properties: { format: { type: 'string', enum: ['md', 'json'] } },
270
+ },
271
+ call: (input) => ({
272
+ method: 'GET',
273
+ path: `/api/compliance/privacy-notice?format=${input.format ?? 'md'}`,
274
+ }),
275
+ },
276
+ {
277
+ name: 'sub_processors_register',
278
+ description: "Return the public sub-processor register (Supabase, Vercel, Resend, etc.).",
279
+ inputSchema: { type: 'object', properties: {} },
280
+ call: () => ({ method: 'GET', path: '/api/compliance/sub-processors?format=json' }),
281
+ },
282
+ {
283
+ name: 'global_compliance_map',
284
+ description: "Master catalogue of every privacy/security/sectoral regime VIGIL has fabric for (28+ regimes).",
285
+ inputSchema: { type: 'object', properties: {} },
286
+ call: () => ({ method: 'GET', path: '/api/compliance/global-status' }),
287
+ },
288
+ {
289
+ name: 'india_regulators_directory',
290
+ description: "Directory of Indian regulators (DPB, RBI, SEBI, IRDAI, TRAI, DoT, PFRDA, MeitY, MCA) with sectoral filter.",
291
+ inputSchema: {
292
+ type: 'object',
293
+ properties: { sector: { type: 'string' } },
294
+ },
295
+ call: (input) => ({
296
+ method: 'GET',
297
+ path: input.sector
298
+ ? `/api/india/regulators?sector=${encodeURIComponent(String(input.sector))}`
299
+ : '/api/india/regulators',
300
+ }),
301
+ },
302
+ ];
303
+ // ─── HTTP transport ────────────────────────────────────────────────
304
+ async function callVigil(method, path, body) {
305
+ const url = `${VIGIL_BASE_URL}${path}${path.includes('?') ? '&' : '?'}owner_id=${encodeURIComponent(VIGIL_OWNER_ID)}`;
306
+ const headers = {
307
+ 'Content-Type': 'application/json',
308
+ 'User-Agent': `vigil-compliance-mcp/${SERVER_VERSION}`,
309
+ };
310
+ if (VIGIL_API_KEY) {
311
+ headers['Authorization'] = `Bearer ${VIGIL_API_KEY}`;
312
+ headers['x-vigil-key'] = VIGIL_API_KEY;
313
+ }
314
+ const res = await fetch(url, {
315
+ method,
316
+ headers,
317
+ body: body !== undefined ? JSON.stringify(body) : undefined,
318
+ });
319
+ const text = await res.text();
320
+ try {
321
+ return JSON.parse(text);
322
+ }
323
+ catch {
324
+ return { _raw: text, _status: res.status };
325
+ }
326
+ }
327
+ function send(resp) {
328
+ process.stdout.write(JSON.stringify(resp) + '\n');
329
+ }
330
+ function ok(id, result) {
331
+ send({ jsonrpc: '2.0', id, result });
332
+ }
333
+ function err(id, code, message, data) {
334
+ send({ jsonrpc: '2.0', id, error: { code, message, data } });
335
+ }
336
+ async function handle(req) {
337
+ const id = req.id ?? null;
338
+ try {
339
+ switch (req.method) {
340
+ case 'initialize':
341
+ ok(id, {
342
+ protocolVersion: '2024-11-05',
343
+ capabilities: { tools: {} },
344
+ serverInfo: { name: SERVER_NAME, version: SERVER_VERSION },
345
+ });
346
+ return;
347
+ case 'tools/list':
348
+ ok(id, {
349
+ tools: TOOLS.map((t) => ({
350
+ name: t.name,
351
+ description: t.description,
352
+ inputSchema: t.inputSchema,
353
+ })),
354
+ });
355
+ return;
356
+ case 'tools/call': {
357
+ const params = (req.params ?? {});
358
+ const tool = TOOLS.find((t) => t.name === params.name);
359
+ if (!tool) {
360
+ err(id, -32602, `unknown tool: ${params.name}`);
361
+ return;
362
+ }
363
+ const { method, path, body } = tool.call(params.arguments ?? {});
364
+ const result = await callVigil(method, path, body);
365
+ ok(id, {
366
+ content: [
367
+ { type: 'text', text: JSON.stringify(result, null, 2) },
368
+ ],
369
+ });
370
+ return;
371
+ }
372
+ case 'notifications/initialized':
373
+ // Spec-required notification; no response.
374
+ return;
375
+ default:
376
+ err(id, -32601, `method not found: ${req.method}`);
377
+ return;
378
+ }
379
+ }
380
+ catch (e) {
381
+ err(id, -32603, e instanceof Error ? e.message : 'internal error');
382
+ }
383
+ }
384
+ // ─── Main loop ─────────────────────────────────────────────────────
385
+ if (!VIGIL_OWNER_ID) {
386
+ console.error('[vigil-compliance-mcp] VIGIL_OWNER_ID not set — every tool call will 401. ' +
387
+ 'Set this to your operator UUID before adding the server to your MCP client.');
388
+ }
389
+ const rl = (0, node_readline_1.createInterface)({ input: process.stdin });
390
+ rl.on('line', (line) => {
391
+ if (!line.trim())
392
+ return;
393
+ try {
394
+ const req = JSON.parse(line);
395
+ void handle(req);
396
+ }
397
+ catch {
398
+ // Malformed — ignore. MCP protocol assumes line-delimited valid JSON.
399
+ }
400
+ });
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@costrinity/vigil-compliance-mcp",
3
+ "version": "0.1.0",
4
+ "description": "MCP server exposing VIGIL's compliance fabric — consent / breach / DPIA / AI Act / identifier validators / cross-border — as tools LLM agents can call mid-task. 13 jurisdictions, 28+ regulatory regimes.",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "bin": {
8
+ "vigil-compliance-mcp": "dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "dev": "tsc --watch",
13
+ "start": "node dist/index.js",
14
+ "prepublishOnly": "tsc"
15
+ },
16
+ "keywords": [
17
+ "mcp",
18
+ "model-context-protocol",
19
+ "compliance",
20
+ "dpdp",
21
+ "gdpr",
22
+ "ai-act",
23
+ "privacy",
24
+ "ai-agents",
25
+ "vigil",
26
+ "costrinity",
27
+ "indigenous-owned"
28
+ ],
29
+ "engines": {
30
+ "node": ">=18"
31
+ },
32
+ "author": "COSTRINITY (Indigenous-owned software studio, Regina, Saskatchewan, Treaty 4 territory)",
33
+ "license": "MIT",
34
+ "homepage": "https://vigil.costrinity.xyz/why-vigil",
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "git+https://github.com/COSTRINITY/costrinity-api.git",
38
+ "directory": "vigil/packages/vigil-compliance-mcp"
39
+ },
40
+ "bugs": {
41
+ "url": "https://github.com/COSTRINITY/costrinity-api/issues"
42
+ },
43
+ "files": [
44
+ "dist",
45
+ "README.md"
46
+ ],
47
+ "publishConfig": {
48
+ "access": "public"
49
+ }
50
+ }