data-compliance-mcp 1.0.27 → 1.0.30
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/CHANGELOG.md +11 -0
- package/glama.json +19 -8
- package/package.json +1 -1
- package/src/server.js +20 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.0.29] - 2026-06-29
|
|
4
|
+
- feat: add GET /.well-known/glama.json ownership endpoint for Glama registry verification
|
|
5
|
+
|
|
6
|
+
## [1.0.28] - 2026-06-28
|
|
7
|
+
- fix: gate email dedup — notifyGateHit now writes dcc:gate_email:{ip} to Redis with 1-hour TTL; retries within the hour suppressed
|
|
8
|
+
- fix: 402 gate response agent_action changed to HALT_WORKFLOW; added retryable: false, retry_after_ms: null
|
|
9
|
+
- fix: trial_extension structured field added explicitly to 402 gate response
|
|
10
|
+
|
|
11
|
+
## [1.0.27] - 2026-06-28
|
|
12
|
+
- feat: owner key bypass (OWNER_KEY env var) — fleet owner bypasses free tier and paid-only gates; usage logged to dcc:owner_calls:YYYY-MM in Redis
|
|
13
|
+
|
|
3
14
|
## [1.0.26] - 2026-06-26
|
|
4
15
|
- fix: trial extension requests now written to Redis (dcc:trial:{email}) on grant -- permanent audit trail that survives redeploys; previously in-memory only
|
|
5
16
|
|
package/glama.json
CHANGED
|
@@ -1,22 +1,33 @@
|
|
|
1
1
|
{
|
|
2
|
+
"$schema": "https://glama.ai/mcp/servers/schema.json",
|
|
2
3
|
"name": "Data Compliance Classifier MCP",
|
|
3
4
|
"description": "Classify data safety before your agent stores or shares it. GDPR, HIPAA, PCI-DSS, CCPA. AI-powered with jurisdiction detection, credential breach checking, and threat intelligence. Free tier: 20/month.",
|
|
4
|
-
"url": "https://data-compliance-mcp-production.up.railway.app",
|
|
5
|
-
"homepage": "https://kordagencies.com",
|
|
6
5
|
"license": "UNLICENSED",
|
|
7
|
-
"categories": [
|
|
6
|
+
"categories": [
|
|
7
|
+
"legal-and-compliance",
|
|
8
|
+
"security",
|
|
9
|
+
"data-privacy"
|
|
10
|
+
],
|
|
11
|
+
"remote": {
|
|
12
|
+
"transport": "sse",
|
|
13
|
+
"url": "https://data-compliance-mcp-production.up.railway.app/sse"
|
|
14
|
+
},
|
|
8
15
|
"tools": [
|
|
9
16
|
{
|
|
10
17
|
"name": "validate_data_safety",
|
|
11
18
|
"description": "Classify a data payload before storing or transmitting. Returns SAFE_TO_PROCESS, REDACT_BEFORE_PASSING, DO_NOT_STORE, or ESCALATE with applicable regulations."
|
|
12
19
|
},
|
|
13
|
-
{
|
|
14
|
-
"name": "get_safety_report",
|
|
15
|
-
"description": "Batch classify up to 50 payloads or generate an audit-ready compliance report. Paid tier."
|
|
16
|
-
},
|
|
17
20
|
{
|
|
18
21
|
"name": "validate_data_safety_lite",
|
|
19
22
|
"description": "Pattern-only screening for high-volume payload batches -- no AI, no IP check, no jurisdiction lookup. Returns SAFE_TO_PROCESS/REVIEW_REQUIRED in under 100ms."
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"name": "get_safety_report",
|
|
26
|
+
"description": "Batch classify up to 50 payloads or generate an audit-ready compliance report. Paid tier."
|
|
20
27
|
}
|
|
21
|
-
]
|
|
28
|
+
],
|
|
29
|
+
"links": {
|
|
30
|
+
"homepage": "https://kordagencies.com",
|
|
31
|
+
"npm": "https://www.npmjs.com/package/data-compliance-mcp"
|
|
32
|
+
}
|
|
22
33
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "data-compliance-mcp",
|
|
3
3
|
"mcpName": "io.github.OjasKord/data-compliance-mcp",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.30",
|
|
5
5
|
"description": "Data safety classifier for AI agents. GDPR, HIPAA, PCI-DSS compliance before your agent stores or shares any payload. SAFE/ESCALATE verdict in one call.",
|
|
6
6
|
"main": "src/server.js",
|
|
7
7
|
"scripts": {
|
package/src/server.js
CHANGED
|
@@ -3,7 +3,7 @@ const https = require('https');
|
|
|
3
3
|
const crypto = require('crypto');
|
|
4
4
|
const fs = require('fs');
|
|
5
5
|
|
|
6
|
-
const VERSION = '1.0.
|
|
6
|
+
const VERSION = '1.0.29';
|
|
7
7
|
const FIRST_DEPLOYED = '2026-04-21T09:53:12Z';
|
|
8
8
|
const LIFETIME_CALLS_REDIS_KEY = 'dcc:lifetime_calls';
|
|
9
9
|
const UPTIME_HEARTBEAT_KEY = 'dcc:uptime:heartbeat_count';
|
|
@@ -1017,7 +1017,7 @@ async function checkAccess(req, toolName) {
|
|
|
1017
1017
|
const monthKey = getMonthKey(ip);
|
|
1018
1018
|
const calls = freeTierUsage.get(monthKey) || 0;
|
|
1019
1019
|
if (calls >= FREE_TIER_LIMIT) {
|
|
1020
|
-
notifyGateHit('Data Compliance Classifier', ip, toolName, calls, STRIPE_PRO_URL);
|
|
1020
|
+
notifyGateHit('Data Compliance Classifier', ip, toolName, calls, STRIPE_PRO_URL).catch(() => {});
|
|
1021
1021
|
recordFleetGateHit(ip).catch(() => {});
|
|
1022
1022
|
const crossServerNote = await buildCrossServerNote(ip);
|
|
1023
1023
|
return {
|
|
@@ -1069,10 +1069,17 @@ function truncateIp(ip) {
|
|
|
1069
1069
|
return parts.length === 4 ? parts.slice(0, 3).join('.') + '.0' : ip;
|
|
1070
1070
|
}
|
|
1071
1071
|
|
|
1072
|
-
function notifyGateHit(serverName, ip, toolName, totalCalls, stripeUrl) {
|
|
1073
|
-
const
|
|
1074
|
-
const
|
|
1075
|
-
|
|
1072
|
+
async function notifyGateHit(serverName, ip, toolName, totalCalls, stripeUrl) {
|
|
1073
|
+
const ip24 = truncateIp(ip);
|
|
1074
|
+
const dedupKey = REDIS_PREFIX + ':gate_email:' + ip24;
|
|
1075
|
+
try {
|
|
1076
|
+
const recent = await redisGet(dedupKey);
|
|
1077
|
+
if (recent) { console.log('[GateNotify] suppressed duplicate for ' + ip24); return; }
|
|
1078
|
+
await redisSet(dedupKey, new Date().toISOString());
|
|
1079
|
+
await redisExpire(dedupKey, 3600);
|
|
1080
|
+
} catch(e) { /* Redis unavailable — fall through and send */ }
|
|
1081
|
+
const html = '<p>Server: ' + serverName + '</p><p>IP: ' + ip24 + '</p><p>Tool: ' + (toolName || 'unknown') + '</p><p>Calls this month: ' + totalCalls + '</p><p>Time: ' + new Date().toISOString() + '</p><p>Upgrade: ' + stripeUrl + '</p>';
|
|
1082
|
+
sendEmail('ojas@kordagencies.com', '[Gate Hit] ' + serverName + ' — ' + ip24 + ' hit free tier limit', html)
|
|
1076
1083
|
.catch(e => console.error('[GateNotify] failed:', e.message));
|
|
1077
1084
|
}
|
|
1078
1085
|
|
|
@@ -1177,6 +1184,12 @@ const server = http.createServer(async (req, res) => {
|
|
|
1177
1184
|
return;
|
|
1178
1185
|
}
|
|
1179
1186
|
|
|
1187
|
+
if (req.url === '/.well-known/glama.json' && req.method === 'GET') {
|
|
1188
|
+
res.writeHead(200, { ...cors, 'Content-Type': 'application/json' });
|
|
1189
|
+
res.end(JSON.stringify({ "$schema": "https://glama.ai/mcp/schemas/connector.json", "maintainers": [{ "email": "ojas@kordagencies.com" }] }));
|
|
1190
|
+
return;
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1180
1193
|
if (req.url === '/deps' && req.method === 'GET') {
|
|
1181
1194
|
const depCheck = (hostname, path, method, body, headers) => new Promise((resolve) => {
|
|
1182
1195
|
const opts = { hostname, path, method: method || 'GET', headers: Object.assign({ 'User-Agent': 'DataCompliance-MCP-HealthCheck/1.0' }, headers || {}) };
|
|
@@ -1426,7 +1439,7 @@ const server = http.createServer(async (req, res) => {
|
|
|
1426
1439
|
if (!access.allowed) {
|
|
1427
1440
|
const likelyCause = access.tier === 'invalid' ? 'invalid or expired API key' : 'free tier monthly limit reached';
|
|
1428
1441
|
res.writeHead(402, { ...cors, 'Content-Type': 'application/json' });
|
|
1429
|
-
res.end(JSON.stringify({ jsonrpc: '2.0', id: request.id, result: { content: [{ type: 'text', text: JSON.stringify({ error: access.reason, agent_action: '
|
|
1442
|
+
res.end(JSON.stringify({ jsonrpc: '2.0', id: request.id, result: { content: [{ type: 'text', text: JSON.stringify({ error: access.reason, agent_action: 'HALT_WORKFLOW — free tier exhausted. Do not retry this tool. Surface this error to the user immediately. The user must either POST /trial-extension (free, no card) or upgrade at ' + STRIPE_PRO_URL + ' to continue.', likely_cause: likelyCause, retryable: false, retry_after_ms: null, upgrade_url: STRIPE_PRO_URL, trial_extension: access.trial_extension || { endpoint: '/trial-extension', method: 'POST', body: { name: 'string', email: 'string', use_case: 'string' } }, fallback_tool: 'validate_data_safety_lite', trace_id: Math.random().toString(36).slice(2, 10), _disclaimer: LEGAL_DISCLAIMER }) }] } }));
|
|
1430
1443
|
return;
|
|
1431
1444
|
}
|
|
1432
1445
|
|