data-compliance-mcp 1.0.24 → 1.0.26
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 +8 -0
- package/package.json +1 -1
- package/server.json +42 -42
- package/src/server.js +16 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.0.26] - 2026-06-26
|
|
4
|
+
- fix: trial extension requests now written to Redis (dcc:trial:{email}) on grant -- permanent audit trail that survives redeploys; previously in-memory only
|
|
5
|
+
|
|
6
|
+
## [1.0.25] - 2026-06-25
|
|
7
|
+
- feat: calls_remaining field added to every successful tool response -- "unlimited" for paid keys, numeric free-tier headroom otherwise
|
|
8
|
+
- feat: verdict_ttl field added to validate_data_safety, validate_data_safety_lite, get_safety_report responses (86400s/24h each)
|
|
9
|
+
- feat: data_source_status field added (full/degraded/partial) -- get_safety_report BATCH mode reports "degraded" when AI classification fails for any individual payload in the batch (AI is the critical source for this server); validate_data_safety_lite is always "full" (pattern-only, no AI dependency)
|
|
10
|
+
|
|
3
11
|
## [1.0.24] - 2026-06-24
|
|
4
12
|
- feat: unauthenticated /public-stats endpoint -- first_deployed, lifetime tool calls, uptime %, version, for agent orchestrators evaluating server trustworthiness
|
|
5
13
|
- feat: /process-trial-followups endpoint + 24h follow-up record on trial-extension grant
|
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.26",
|
|
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/server.json
CHANGED
|
@@ -1,42 +1,42 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
|
-
"name": "io.github.OjasKord/data-compliance-mcp",
|
|
4
|
-
"title": "Data Compliance Classifier MCP",
|
|
5
|
-
"description": "Classify data safety before storing or sharing. GDPR, HIPAA, PCI-DSS, CCPA. AI-powered.",
|
|
6
|
-
"version": "1.0.
|
|
7
|
-
"websiteUrl": "https://kordagencies.com",
|
|
8
|
-
"repository": {
|
|
9
|
-
"url": "https://github.com/OjasKord/data-compliance-mcp",
|
|
10
|
-
"source": "github"
|
|
11
|
-
},
|
|
12
|
-
"packages": [
|
|
13
|
-
{
|
|
14
|
-
"registryType": "npm",
|
|
15
|
-
"identifier": "data-compliance-mcp",
|
|
16
|
-
"version": "1.0.
|
|
17
|
-
"transport": {
|
|
18
|
-
"type": "stdio"
|
|
19
|
-
},
|
|
20
|
-
"environmentVariables": [
|
|
21
|
-
{
|
|
22
|
-
"name": "ANTHROPIC_API_KEY",
|
|
23
|
-
"description": "Anthropic API key for AI classification",
|
|
24
|
-
"isRequired": true,
|
|
25
|
-
"isSecret": true
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
"name": "ABUSEIPDB_API_KEY",
|
|
29
|
-
"description": "AbuseIPDB API key for threat intelligence (optional)",
|
|
30
|
-
"isRequired": false,
|
|
31
|
-
"isSecret": true
|
|
32
|
-
}
|
|
33
|
-
]
|
|
34
|
-
}
|
|
35
|
-
],
|
|
36
|
-
"remotes": [
|
|
37
|
-
{
|
|
38
|
-
"type": "streamable-http",
|
|
39
|
-
"url": "https://data-compliance-mcp-production.up.railway.app"
|
|
40
|
-
}
|
|
41
|
-
]
|
|
42
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
|
+
"name": "io.github.OjasKord/data-compliance-mcp",
|
|
4
|
+
"title": "Data Compliance Classifier MCP",
|
|
5
|
+
"description": "Classify data safety before storing or sharing. GDPR, HIPAA, PCI-DSS, CCPA. AI-powered.",
|
|
6
|
+
"version": "1.0.25",
|
|
7
|
+
"websiteUrl": "https://kordagencies.com",
|
|
8
|
+
"repository": {
|
|
9
|
+
"url": "https://github.com/OjasKord/data-compliance-mcp",
|
|
10
|
+
"source": "github"
|
|
11
|
+
},
|
|
12
|
+
"packages": [
|
|
13
|
+
{
|
|
14
|
+
"registryType": "npm",
|
|
15
|
+
"identifier": "data-compliance-mcp",
|
|
16
|
+
"version": "1.0.25",
|
|
17
|
+
"transport": {
|
|
18
|
+
"type": "stdio"
|
|
19
|
+
},
|
|
20
|
+
"environmentVariables": [
|
|
21
|
+
{
|
|
22
|
+
"name": "ANTHROPIC_API_KEY",
|
|
23
|
+
"description": "Anthropic API key for AI classification",
|
|
24
|
+
"isRequired": true,
|
|
25
|
+
"isSecret": true
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"name": "ABUSEIPDB_API_KEY",
|
|
29
|
+
"description": "AbuseIPDB API key for threat intelligence (optional)",
|
|
30
|
+
"isRequired": false,
|
|
31
|
+
"isSecret": true
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
],
|
|
36
|
+
"remotes": [
|
|
37
|
+
{
|
|
38
|
+
"type": "streamable-http",
|
|
39
|
+
"url": "https://data-compliance-mcp-production.up.railway.app"
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
}
|
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.26';
|
|
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';
|
|
@@ -23,6 +23,8 @@ const freeTierUsage = new Map();
|
|
|
23
23
|
const usageLog = [];
|
|
24
24
|
const FREE_TIER_LIMIT = 20;
|
|
25
25
|
const FREE_TIER_WARNING = 16;
|
|
26
|
+
// Caching/staleness policy per tool, in seconds.
|
|
27
|
+
const VERDICT_TTL = { validate_data_safety: 86400, validate_data_safety_lite: 86400, get_safety_report: 86400 };
|
|
26
28
|
const apiKeys = new Map();
|
|
27
29
|
const PLAN_LIMITS = { pro: 5000, enterprise: Infinity };
|
|
28
30
|
const toolUsageCounts = {};
|
|
@@ -698,6 +700,8 @@ async function executeTool(name, args, tier) {
|
|
|
698
700
|
patterns_detected: patterns,
|
|
699
701
|
credential_check: credentialCheck,
|
|
700
702
|
analysis_type: 'AI-powered classification -- NOT a simple pattern match',
|
|
703
|
+
verdict_ttl: VERDICT_TTL.validate_data_safety,
|
|
704
|
+
data_source_status: 'full',
|
|
701
705
|
source_url: 'api.anthropic.com + ipinfo.io + api.pwnedpasswords.com',
|
|
702
706
|
checked_at: checkedAt,
|
|
703
707
|
_disclaimer: LEGAL_DISCLAIMER
|
|
@@ -781,6 +785,8 @@ async function executeTool(name, args, tier) {
|
|
|
781
785
|
confidence: report.confidence,
|
|
782
786
|
patterns_detected: patterns,
|
|
783
787
|
analysis_type: 'AI-powered compliance remediation -- NOT a simple pattern match',
|
|
788
|
+
verdict_ttl: VERDICT_TTL.get_safety_report,
|
|
789
|
+
data_source_status: 'full',
|
|
784
790
|
checked_at: checkedAt,
|
|
785
791
|
_disclaimer: LEGAL_DISCLAIMER
|
|
786
792
|
};
|
|
@@ -903,6 +909,8 @@ async function executeTool(name, args, tier) {
|
|
|
903
909
|
},
|
|
904
910
|
results,
|
|
905
911
|
analysis_type: 'AI-powered batch classification with threat intelligence',
|
|
912
|
+
verdict_ttl: VERDICT_TTL.get_safety_report,
|
|
913
|
+
data_source_status: errors.length > 0 ? 'degraded' : 'full',
|
|
906
914
|
checked_at: checkedAt,
|
|
907
915
|
_disclaimer: LEGAL_DISCLAIMER
|
|
908
916
|
};
|
|
@@ -931,6 +939,8 @@ async function executeTool(name, args, tier) {
|
|
|
931
939
|
dataset_description,
|
|
932
940
|
report,
|
|
933
941
|
analysis_type: 'AI-powered compliance audit — NOT legal advice',
|
|
942
|
+
verdict_ttl: VERDICT_TTL.get_safety_report,
|
|
943
|
+
data_source_status: 'full',
|
|
934
944
|
checked_at: checkedAt,
|
|
935
945
|
_disclaimer: LEGAL_DISCLAIMER
|
|
936
946
|
};
|
|
@@ -962,6 +972,8 @@ async function executeTool(name, args, tier) {
|
|
|
962
972
|
patterns_detected: patterns,
|
|
963
973
|
sensitivity_level: sensitivityLevel,
|
|
964
974
|
analysis_type: 'Pattern detection only -- no AI analysis. Use validate_data_safety for full AI verdict.',
|
|
975
|
+
verdict_ttl: VERDICT_TTL.validate_data_safety_lite,
|
|
976
|
+
data_source_status: 'full',
|
|
965
977
|
checked_at: checkedAt,
|
|
966
978
|
_disclaimer: LEGAL_DISCLAIMER
|
|
967
979
|
};
|
|
@@ -1255,6 +1267,7 @@ const server = http.createServer(async (req, res) => {
|
|
|
1255
1267
|
freeTierUsage.set(monthKey, Math.max(0, currentCalls - TRIAL_EXTENSION_CALLS));
|
|
1256
1268
|
trialExtensions.set(emailKey, { name, email, use_case: use_case || '', ip, granted_at: nowISO() });
|
|
1257
1269
|
saveStats();
|
|
1270
|
+
await redisSet(REDIS_PREFIX + ':trial:' + email.toLowerCase().trim(), { name, email, use_case: use_case || '', ip, timestamp: nowISO(), server: 'data-compliance-mcp' });
|
|
1258
1271
|
// 24h follow-up record -- processed by /process-trial-followups (fleet cron)
|
|
1259
1272
|
await redisSet(REDIS_PREFIX + ':followup:' + email.toLowerCase().trim(), { email, name, server: 'data-compliance-mcp', granted_at: nowISO(), sent: false });
|
|
1260
1273
|
await sendEmail('ojas@kordagencies.com', 'Data Compliance MCP -- Trial Extension: ' + name,
|
|
@@ -1417,6 +1430,7 @@ const server = http.createServer(async (req, res) => {
|
|
|
1417
1430
|
|
|
1418
1431
|
const result = await executeTool(name, toolArgs || {}, access.tier);
|
|
1419
1432
|
if (access.warning) result._notice = access.warning;
|
|
1433
|
+
result.calls_remaining = access.tier === 'free' ? Math.max(0, access.remaining || 0) : 'unlimited';
|
|
1420
1434
|
|
|
1421
1435
|
response = { jsonrpc: '2.0', id: request.id, result: { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] } };
|
|
1422
1436
|
} else {
|
|
@@ -1473,6 +1487,7 @@ function setupStdio() {
|
|
|
1473
1487
|
response = { jsonrpc: '2.0', id: req.id, result: { content: [{ type: 'text', text: JSON.stringify({ error: 'This tool is temporarily unavailable for maintenance.', agent_action: 'RETRY_IN_30_MIN', retryable: true, retry_after_ms: 1800000 }) }] } };
|
|
1474
1488
|
} else {
|
|
1475
1489
|
const result = await executeTool(_name, req.params.arguments || {}, 'paid');
|
|
1490
|
+
result.calls_remaining = 'unlimited';
|
|
1476
1491
|
response = { jsonrpc: '2.0', id: req.id, result: { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] } };
|
|
1477
1492
|
}
|
|
1478
1493
|
} catch(e) {
|