@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 +105 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.js +400 -0
- package/package.json +50 -0
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)
|
package/dist/index.d.ts
ADDED
|
@@ -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
|
+
}
|