couchloop-eq-mcp 1.0.3 → 1.0.5
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 +24 -11
- package/dist/clients/shrinkChatClient.js +1 -1
- package/dist/clients/shrinkChatClient.js.map +1 -1
- package/dist/developer/analyzers/bloat-detector.d.ts +89 -0
- package/dist/developer/analyzers/bloat-detector.d.ts.map +1 -0
- package/dist/developer/analyzers/bloat-detector.js +483 -0
- package/dist/developer/analyzers/bloat-detector.js.map +1 -0
- package/dist/developer/backup/auto-backup.d.ts +96 -0
- package/dist/developer/backup/auto-backup.d.ts.map +1 -0
- package/dist/developer/backup/auto-backup.js +346 -0
- package/dist/developer/backup/auto-backup.js.map +1 -0
- package/dist/developer/blockers/package-blocker.d.ts +33 -0
- package/dist/developer/blockers/package-blocker.d.ts.map +1 -0
- package/dist/developer/blockers/package-blocker.js +224 -0
- package/dist/developer/blockers/package-blocker.js.map +1 -0
- package/dist/developer/evaluators/ai-error-preventer.d.ts +54 -0
- package/dist/developer/evaluators/ai-error-preventer.d.ts.map +1 -0
- package/dist/developer/evaluators/ai-error-preventer.js +270 -0
- package/dist/developer/evaluators/ai-error-preventer.js.map +1 -0
- package/dist/developer/evaluators/build-context-detector.d.ts +44 -0
- package/dist/developer/evaluators/build-context-detector.d.ts.map +1 -0
- package/dist/developer/evaluators/build-context-detector.js +258 -0
- package/dist/developer/evaluators/build-context-detector.js.map +1 -0
- package/dist/developer/evaluators/package-evaluator.d.ts +37 -0
- package/dist/developer/evaluators/package-evaluator.d.ts.map +1 -0
- package/dist/developer/evaluators/package-evaluator.js +278 -0
- package/dist/developer/evaluators/package-evaluator.js.map +1 -0
- package/dist/developer/guards/file-guardian.d.ts +79 -0
- package/dist/developer/guards/file-guardian.d.ts.map +1 -0
- package/dist/developer/guards/file-guardian.js +309 -0
- package/dist/developer/guards/file-guardian.js.map +1 -0
- package/dist/developer/managers/context-manager.d.ts +61 -0
- package/dist/developer/managers/context-manager.d.ts.map +1 -0
- package/dist/developer/managers/context-manager.js +302 -0
- package/dist/developer/managers/context-manager.js.map +1 -0
- package/dist/developer/metrics/complexity-calculator.d.ts +52 -0
- package/dist/developer/metrics/complexity-calculator.d.ts.map +1 -0
- package/dist/developer/metrics/complexity-calculator.js +259 -0
- package/dist/developer/metrics/complexity-calculator.js.map +1 -0
- package/dist/developer/reports/review-summary.d.ts +49 -0
- package/dist/developer/reports/review-summary.d.ts.map +1 -0
- package/dist/developer/reports/review-summary.js +249 -0
- package/dist/developer/reports/review-summary.js.map +1 -0
- package/dist/developer/scanners/review-assistant.d.ts +41 -0
- package/dist/developer/scanners/review-assistant.d.ts.map +1 -0
- package/dist/developer/scanners/review-assistant.js +374 -0
- package/dist/developer/scanners/review-assistant.js.map +1 -0
- package/dist/developer/scanners/secret-scanner.d.ts +66 -0
- package/dist/developer/scanners/secret-scanner.d.ts.map +1 -0
- package/dist/developer/scanners/secret-scanner.js +287 -0
- package/dist/developer/scanners/secret-scanner.js.map +1 -0
- package/dist/developer/scanners/sql-injection-detector.d.ts +54 -0
- package/dist/developer/scanners/sql-injection-detector.d.ts.map +1 -0
- package/dist/developer/scanners/sql-injection-detector.js +174 -0
- package/dist/developer/scanners/sql-injection-detector.js.map +1 -0
- package/dist/developer/scanners/xss-detector.d.ts +60 -0
- package/dist/developer/scanners/xss-detector.d.ts.map +1 -0
- package/dist/developer/scanners/xss-detector.js +229 -0
- package/dist/developer/scanners/xss-detector.js.map +1 -0
- package/dist/developer/types/ai-errors.d.ts +34 -0
- package/dist/developer/types/ai-errors.d.ts.map +1 -0
- package/dist/developer/types/ai-errors.js +271 -0
- package/dist/developer/types/ai-errors.js.map +1 -0
- package/dist/developer/types/package.d.ts +32 -0
- package/dist/developer/types/package.d.ts.map +1 -0
- package/dist/developer/types/package.js +5 -0
- package/dist/developer/types/package.js.map +1 -0
- package/dist/developer/updaters/dependency-updater.d.ts +102 -0
- package/dist/developer/updaters/dependency-updater.d.ts.map +1 -0
- package/dist/developer/updaters/dependency-updater.js +472 -0
- package/dist/developer/updaters/dependency-updater.js.map +1 -0
- package/dist/developer/validators/cargo.d.ts +14 -0
- package/dist/developer/validators/cargo.d.ts.map +1 -0
- package/dist/developer/validators/cargo.js +132 -0
- package/dist/developer/validators/cargo.js.map +1 -0
- package/dist/developer/validators/gem.d.ts +14 -0
- package/dist/developer/validators/gem.d.ts.map +1 -0
- package/dist/developer/validators/gem.js +85 -0
- package/dist/developer/validators/gem.js.map +1 -0
- package/dist/developer/validators/go.d.ts +14 -0
- package/dist/developer/validators/go.d.ts.map +1 -0
- package/dist/developer/validators/go.js +138 -0
- package/dist/developer/validators/go.js.map +1 -0
- package/dist/developer/validators/maven.d.ts +14 -0
- package/dist/developer/validators/maven.d.ts.map +1 -0
- package/dist/developer/validators/maven.js +99 -0
- package/dist/developer/validators/maven.js.map +1 -0
- package/dist/developer/validators/npm.d.ts +14 -0
- package/dist/developer/validators/npm.d.ts.map +1 -0
- package/dist/developer/validators/npm.js +96 -0
- package/dist/developer/validators/npm.js.map +1 -0
- package/dist/developer/validators/nuget.d.ts +15 -0
- package/dist/developer/validators/nuget.d.ts.map +1 -0
- package/dist/developer/validators/nuget.js +107 -0
- package/dist/developer/validators/nuget.js.map +1 -0
- package/dist/developer/validators/pypi.d.ts +14 -0
- package/dist/developer/validators/pypi.d.ts.map +1 -0
- package/dist/developer/validators/pypi.js +118 -0
- package/dist/developer/validators/pypi.js.map +1 -0
- package/dist/developer/validators/registry-manager.d.ts +37 -0
- package/dist/developer/validators/registry-manager.d.ts.map +1 -0
- package/dist/developer/validators/registry-manager.js +89 -0
- package/dist/developer/validators/registry-manager.js.map +1 -0
- package/dist/developer/validators/version-checker.d.ts +145 -0
- package/dist/developer/validators/version-checker.d.ts.map +1 -0
- package/dist/developer/validators/version-checker.js +529 -0
- package/dist/developer/validators/version-checker.js.map +1 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/middleware/auth.d.ts +7 -9
- package/dist/server/middleware/auth.d.ts.map +1 -1
- package/dist/server/middleware/auth.js.map +1 -1
- package/dist/tools/check-versions.d.ts +100 -0
- package/dist/tools/check-versions.d.ts.map +1 -0
- package/dist/tools/check-versions.js +328 -0
- package/dist/tools/check-versions.js.map +1 -0
- package/dist/tools/detect-code-smell.d.ts +9 -0
- package/dist/tools/detect-code-smell.d.ts.map +1 -0
- package/dist/tools/detect-code-smell.js +231 -0
- package/dist/tools/detect-code-smell.js.map +1 -0
- package/dist/tools/index.d.ts +471 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +178 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/journey.js +1 -1
- package/dist/tools/journey.js.map +1 -1
- package/dist/tools/pre-review-code.d.ts +71 -0
- package/dist/tools/pre-review-code.d.ts.map +1 -0
- package/dist/tools/pre-review-code.js +159 -0
- package/dist/tools/pre-review-code.js.map +1 -0
- package/dist/tools/preserve-context.d.ts +27 -0
- package/dist/tools/preserve-context.d.ts.map +1 -0
- package/dist/tools/preserve-context.js +98 -0
- package/dist/tools/preserve-context.js.map +1 -0
- package/dist/tools/protect-files.d.ts +224 -0
- package/dist/tools/protect-files.d.ts.map +1 -0
- package/dist/tools/protect-files.js +286 -0
- package/dist/tools/protect-files.js.map +1 -0
- package/dist/tools/scan-security.d.ts +38 -0
- package/dist/tools/scan-security.d.ts.map +1 -0
- package/dist/tools/scan-security.js +237 -0
- package/dist/tools/scan-security.js.map +1 -0
- package/dist/tools/validate_packages.d.ts +8 -0
- package/dist/tools/validate_packages.d.ts.map +1 -0
- package/dist/tools/validate_packages.js +159 -0
- package/dist/tools/validate_packages.js.map +1 -0
- package/dist/types/auth.d.ts +18 -18
- package/dist/types/auth.d.ts.map +1 -1
- package/dist/types/auth.js +91 -36
- package/dist/types/auth.js.map +1 -1
- package/dist/types/context.d.ts +46 -0
- package/dist/types/context.d.ts.map +1 -0
- package/dist/types/context.js +17 -0
- package/dist/types/context.js.map +1 -0
- package/dist/types/file-protection.d.ts +50 -0
- package/dist/types/file-protection.d.ts.map +1 -0
- package/dist/types/file-protection.js +9 -0
- package/dist/types/file-protection.js.map +1 -0
- package/dist/utils/errorHandler.d.ts.map +1 -1
- package/dist/utils/errorHandler.js +2 -1
- package/dist/utils/errorHandler.js.map +1 -1
- package/package.json +23 -2
- package/dist/db/migrate.d.ts +0 -4
- package/dist/db/migrate.d.ts.map +0 -1
- package/dist/db/migrate.js +0 -34
- package/dist/db/migrate.js.map +0 -1
- package/dist/db/migrations/schema.d.ts +0 -1074
- package/dist/db/migrations/schema.d.ts.map +0 -1
- package/dist/db/migrations/schema.js +0 -160
- package/dist/db/migrations/schema.js.map +0 -1
- package/dist/db/schema.d.ts +0 -1576
- package/dist/db/schema.d.ts.map +0 -1
- package/dist/db/schema.js +0 -204
- package/dist/db/schema.js.map +0 -1
- package/dist/db/seed.d.ts +0 -4
- package/dist/db/seed.d.ts.map +0 -1
- package/dist/db/seed.js +0 -57
- package/dist/db/seed.js.map +0 -1
- package/dist/db/seedOAuth.d.ts +0 -4
- package/dist/db/seedOAuth.d.ts.map +0 -1
- package/dist/db/seedOAuth.js +0 -76
- package/dist/db/seedOAuth.js.map +0 -1
- package/dist/governance/config.d.ts +0 -66
- package/dist/governance/config.d.ts.map +0 -1
- package/dist/governance/config.js +0 -238
- package/dist/governance/config.js.map +0 -1
- package/dist/governance/detectors/hallucination.d.ts +0 -61
- package/dist/governance/detectors/hallucination.d.ts.map +0 -1
- package/dist/governance/detectors/hallucination.js +0 -338
- package/dist/governance/detectors/hallucination.js.map +0 -1
- package/dist/governance/detectors/inconsistency.d.ts +0 -99
- package/dist/governance/detectors/inconsistency.d.ts.map +0 -1
- package/dist/governance/detectors/inconsistency.js +0 -548
- package/dist/governance/detectors/inconsistency.js.map +0 -1
- package/dist/governance/detectors/toneDrift.d.ts +0 -63
- package/dist/governance/detectors/toneDrift.d.ts.map +0 -1
- package/dist/governance/detectors/toneDrift.js +0 -421
- package/dist/governance/detectors/toneDrift.js.map +0 -1
- package/dist/governance/detectors/unsafeReasoning.d.ts +0 -54
- package/dist/governance/detectors/unsafeReasoning.d.ts.map +0 -1
- package/dist/governance/detectors/unsafeReasoning.js +0 -473
- package/dist/governance/detectors/unsafeReasoning.js.map +0 -1
- package/dist/governance/evaluationEngine.d.ts +0 -112
- package/dist/governance/evaluationEngine.d.ts.map +0 -1
- package/dist/governance/evaluationEngine.js +0 -265
- package/dist/governance/evaluationEngine.js.map +0 -1
- package/dist/governance/intervention.d.ts +0 -81
- package/dist/governance/intervention.d.ts.map +0 -1
- package/dist/governance/intervention.js +0 -405
- package/dist/governance/intervention.js.map +0 -1
- package/dist/server/oauth/anomalyDetection.d.ts +0 -146
- package/dist/server/oauth/anomalyDetection.d.ts.map +0 -1
- package/dist/server/oauth/anomalyDetection.js +0 -405
- package/dist/server/oauth/anomalyDetection.js.map +0 -1
- package/dist/server/oauth/authServer.d.ts +0 -61
- package/dist/server/oauth/authServer.d.ts.map +0 -1
- package/dist/server/oauth/authServer.js +0 -283
- package/dist/server/oauth/authServer.js.map +0 -1
- package/dist/server/oauth/dpop.d.ts +0 -135
- package/dist/server/oauth/dpop.d.ts.map +0 -1
- package/dist/server/oauth/dpop.js +0 -338
- package/dist/server/oauth/dpop.js.map +0 -1
- package/dist/server/oauth/gdpr/consent.d.ts +0 -173
- package/dist/server/oauth/gdpr/consent.d.ts.map +0 -1
- package/dist/server/oauth/gdpr/consent.js +0 -388
- package/dist/server/oauth/gdpr/consent.js.map +0 -1
- package/dist/server/oauth/gdpr/dataPortability.d.ts +0 -214
- package/dist/server/oauth/gdpr/dataPortability.d.ts.map +0 -1
- package/dist/server/oauth/gdpr/dataPortability.js +0 -486
- package/dist/server/oauth/gdpr/dataPortability.js.map +0 -1
- package/dist/server/oauth/gdpr/index.d.ts +0 -103
- package/dist/server/oauth/gdpr/index.d.ts.map +0 -1
- package/dist/server/oauth/gdpr/index.js +0 -273
- package/dist/server/oauth/gdpr/index.js.map +0 -1
- package/dist/server/oauth/gdpr/rightToErasure.d.ts +0 -184
- package/dist/server/oauth/gdpr/rightToErasure.d.ts.map +0 -1
- package/dist/server/oauth/gdpr/rightToErasure.js +0 -527
- package/dist/server/oauth/gdpr/rightToErasure.js.map +0 -1
- package/dist/server/oauth/monitoring/securityMonitor.d.ts +0 -218
- package/dist/server/oauth/monitoring/securityMonitor.d.ts.map +0 -1
- package/dist/server/oauth/monitoring/securityMonitor.js +0 -615
- package/dist/server/oauth/monitoring/securityMonitor.js.map +0 -1
- package/dist/server/oauth/pkce.d.ts +0 -61
- package/dist/server/oauth/pkce.d.ts.map +0 -1
- package/dist/server/oauth/pkce.js +0 -157
- package/dist/server/oauth/pkce.js.map +0 -1
- package/dist/server/oauth/providers/base.d.ts +0 -147
- package/dist/server/oauth/providers/base.d.ts.map +0 -1
- package/dist/server/oauth/providers/base.js +0 -312
- package/dist/server/oauth/providers/base.js.map +0 -1
- package/dist/server/oauth/providers/github.d.ts +0 -55
- package/dist/server/oauth/providers/github.d.ts.map +0 -1
- package/dist/server/oauth/providers/github.js +0 -225
- package/dist/server/oauth/providers/github.js.map +0 -1
- package/dist/server/oauth/providers/google.d.ts +0 -49
- package/dist/server/oauth/providers/google.d.ts.map +0 -1
- package/dist/server/oauth/providers/google.js +0 -153
- package/dist/server/oauth/providers/google.js.map +0 -1
- package/dist/server/oauth/providers/index.d.ts +0 -9
- package/dist/server/oauth/providers/index.d.ts.map +0 -1
- package/dist/server/oauth/providers/index.js +0 -24
- package/dist/server/oauth/providers/index.js.map +0 -1
- package/dist/server/oauth/refreshTokenRotation.d.ts +0 -114
- package/dist/server/oauth/refreshTokenRotation.d.ts.map +0 -1
- package/dist/server/oauth/refreshTokenRotation.js +0 -344
- package/dist/server/oauth/refreshTokenRotation.js.map +0 -1
- package/dist/server/oauth/security.d.ts +0 -101
- package/dist/server/oauth/security.d.ts.map +0 -1
- package/dist/server/oauth/security.js +0 -268
- package/dist/server/oauth/security.js.map +0 -1
- package/dist/server/oauth/tokenEncryption.d.ts +0 -80
- package/dist/server/oauth/tokenEncryption.d.ts.map +0 -1
- package/dist/server/oauth/tokenEncryption.js +0 -218
- package/dist/server/oauth/tokenEncryption.js.map +0 -1
- package/dist/tools/sendMessage-complex-backup.d.ts +0 -6
- package/dist/tools/sendMessage-complex-backup.d.ts.map +0 -1
- package/dist/tools/sendMessage-complex-backup.js +0 -545
- package/dist/tools/sendMessage-complex-backup.js.map +0 -1
- package/dist/tools/sendMessage-revised.d.ts +0 -11
- package/dist/tools/sendMessage-revised.d.ts.map +0 -1
- package/dist/tools/sendMessage-revised.js +0 -429
- package/dist/tools/sendMessage-revised.js.map +0 -1
- package/dist/tools/sendMessage-truly-simple.d.ts +0 -8
- package/dist/tools/sendMessage-truly-simple.d.ts.map +0 -1
- package/dist/tools/sendMessage-truly-simple.js +0 -299
- package/dist/tools/sendMessage-truly-simple.js.map +0 -1
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool: scan_security
|
|
3
|
+
* Comprehensive security vulnerability scanner for AI-generated code
|
|
4
|
+
* Detects SQL injection, XSS, hardcoded secrets, and other security issues
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { SqlInjectionDetector } from '../developer/scanners/sql-injection-detector.js';
|
|
8
|
+
import { XssDetector } from '../developer/scanners/xss-detector.js';
|
|
9
|
+
import { SecretScanner } from '../developer/scanners/secret-scanner.js';
|
|
10
|
+
import { logger } from '../utils/logger.js';
|
|
11
|
+
const inputSchema = z.object({
|
|
12
|
+
code: z.string().describe('Code snippet to scan for security vulnerabilities'),
|
|
13
|
+
language: z.enum(['javascript', 'typescript', 'python', 'java', 'sql', 'html', 'unknown']).default('javascript').describe('Programming language of the code'),
|
|
14
|
+
scanType: z.enum(['quick', 'thorough']).default('thorough').describe('Scan depth: quick (essential) or thorough (comprehensive)'),
|
|
15
|
+
});
|
|
16
|
+
export const scanSecurityTool = {
|
|
17
|
+
name: 'scan_security',
|
|
18
|
+
description: 'Comprehensive security scanner for AI-generated code. Detects SQL injection, XSS, hardcoded secrets, and other vulnerabilities with CWE codes and secure alternatives.',
|
|
19
|
+
inputSchema: {
|
|
20
|
+
type: 'object',
|
|
21
|
+
properties: {
|
|
22
|
+
code: {
|
|
23
|
+
type: 'string',
|
|
24
|
+
description: 'Code snippet to scan for security vulnerabilities'
|
|
25
|
+
},
|
|
26
|
+
language: {
|
|
27
|
+
type: 'string',
|
|
28
|
+
enum: ['javascript', 'typescript', 'python', 'java', 'sql', 'html', 'unknown'],
|
|
29
|
+
default: 'javascript',
|
|
30
|
+
description: 'Programming language of the code'
|
|
31
|
+
},
|
|
32
|
+
scanType: {
|
|
33
|
+
type: 'string',
|
|
34
|
+
enum: ['quick', 'thorough'],
|
|
35
|
+
default: 'thorough',
|
|
36
|
+
description: 'Scan depth: quick (essential checks) or thorough (comprehensive)'
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
required: ['code']
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
export async function handleScanSecurity(input) {
|
|
43
|
+
try {
|
|
44
|
+
const params = inputSchema.parse(input);
|
|
45
|
+
logger.info(`Security scan requested for ${params.language} code (${params.scanType} mode)`);
|
|
46
|
+
const vulnerabilities = [];
|
|
47
|
+
// Run appropriate scanners based on language and scan type
|
|
48
|
+
if (params.scanType === 'thorough' || ['javascript', 'typescript', 'sql'].includes(params.language)) {
|
|
49
|
+
const sqlDetector = new SqlInjectionDetector();
|
|
50
|
+
const sqlVulns = sqlDetector.scan(params.code);
|
|
51
|
+
vulnerabilities.push(...formatVulnerabilities(sqlVulns, 'SQLInjectionDetector'));
|
|
52
|
+
}
|
|
53
|
+
if (params.scanType === 'thorough' || ['javascript', 'typescript', 'html', 'python', 'java'].includes(params.language)) {
|
|
54
|
+
const xssDetector = new XssDetector();
|
|
55
|
+
const xssVulns = xssDetector.scan(params.code);
|
|
56
|
+
vulnerabilities.push(...formatVulnerabilities(xssVulns, 'XssDetector'));
|
|
57
|
+
}
|
|
58
|
+
if (params.scanType === 'thorough' || ['javascript', 'typescript', 'python', 'java'].includes(params.language)) {
|
|
59
|
+
const secretScanner = new SecretScanner();
|
|
60
|
+
const secretVulns = secretScanner.scan(params.code);
|
|
61
|
+
vulnerabilities.push(...formatVulnerabilities(secretVulns, 'SecretScanner'));
|
|
62
|
+
}
|
|
63
|
+
// Sort by severity and line number
|
|
64
|
+
vulnerabilities.sort((a, b) => {
|
|
65
|
+
const severityOrder = { CRITICAL: 0, HIGH: 1, MEDIUM: 2, LOW: 3 };
|
|
66
|
+
const aSeverity = severityOrder[a.severity] ?? 4;
|
|
67
|
+
const bSeverity = severityOrder[b.severity] ?? 4;
|
|
68
|
+
if (aSeverity !== bSeverity)
|
|
69
|
+
return aSeverity - bSeverity;
|
|
70
|
+
return a.line - b.line;
|
|
71
|
+
});
|
|
72
|
+
// Calculate summary
|
|
73
|
+
const summary = calculateSummary(vulnerabilities, params.language, params.scanType);
|
|
74
|
+
// Generate recommendations
|
|
75
|
+
const recommendations = generateRecommendations(vulnerabilities);
|
|
76
|
+
// Generate developer notes
|
|
77
|
+
const developerNotes = generateDeveloperNotes(vulnerabilities, params.language);
|
|
78
|
+
// Determine overall risk level
|
|
79
|
+
const riskLevel = determineRiskLevel(summary);
|
|
80
|
+
const result = {
|
|
81
|
+
summary,
|
|
82
|
+
vulnerabilities,
|
|
83
|
+
riskLevel,
|
|
84
|
+
recommendations,
|
|
85
|
+
developerNotes,
|
|
86
|
+
};
|
|
87
|
+
logger.info(`Security scan completed: ${vulnerabilities.length} vulnerabilities found (${summary.critical} critical, ${summary.high} high)`);
|
|
88
|
+
return result;
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
logger.error('Error during security scan:', error);
|
|
92
|
+
if (error instanceof z.ZodError) {
|
|
93
|
+
return {
|
|
94
|
+
summary: {
|
|
95
|
+
totalVulnerabilities: 0,
|
|
96
|
+
critical: 0,
|
|
97
|
+
high: 0,
|
|
98
|
+
medium: 0,
|
|
99
|
+
low: 0,
|
|
100
|
+
language: 'unknown',
|
|
101
|
+
scanType: 'thorough',
|
|
102
|
+
},
|
|
103
|
+
vulnerabilities: [],
|
|
104
|
+
riskLevel: 'SAFE',
|
|
105
|
+
recommendations: ['Invalid input provided to security scanner'],
|
|
106
|
+
developerNotes: `Validation error: ${error.message}`,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
summary: {
|
|
111
|
+
totalVulnerabilities: 0,
|
|
112
|
+
critical: 0,
|
|
113
|
+
high: 0,
|
|
114
|
+
medium: 0,
|
|
115
|
+
low: 0,
|
|
116
|
+
language: 'unknown',
|
|
117
|
+
scanType: 'thorough',
|
|
118
|
+
},
|
|
119
|
+
vulnerabilities: [],
|
|
120
|
+
riskLevel: 'SAFE',
|
|
121
|
+
recommendations: ['An error occurred during scanning'],
|
|
122
|
+
developerNotes: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Format vulnerabilities from scanners to unified format
|
|
128
|
+
*/
|
|
129
|
+
function formatVulnerabilities(vulns, scannerName) {
|
|
130
|
+
return vulns.map(vuln => ({
|
|
131
|
+
...vuln,
|
|
132
|
+
scanner: scannerName,
|
|
133
|
+
}));
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Calculate vulnerability summary
|
|
137
|
+
*/
|
|
138
|
+
function calculateSummary(vulnerabilities, language, scanType) {
|
|
139
|
+
const counts = {
|
|
140
|
+
CRITICAL: 0,
|
|
141
|
+
HIGH: 0,
|
|
142
|
+
MEDIUM: 0,
|
|
143
|
+
LOW: 0,
|
|
144
|
+
};
|
|
145
|
+
for (const vuln of vulnerabilities) {
|
|
146
|
+
counts[vuln.severity]++;
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
totalVulnerabilities: vulnerabilities.length,
|
|
150
|
+
critical: counts.CRITICAL,
|
|
151
|
+
high: counts.HIGH,
|
|
152
|
+
medium: counts.MEDIUM,
|
|
153
|
+
low: counts.LOW,
|
|
154
|
+
language,
|
|
155
|
+
scanType,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Generate recommendations based on vulnerabilities found
|
|
160
|
+
*/
|
|
161
|
+
function generateRecommendations(vulnerabilities) {
|
|
162
|
+
const recommendations = new Set();
|
|
163
|
+
// Group vulnerabilities by type
|
|
164
|
+
const hasSQL = vulnerabilities.some(v => v.type === 'SQL_INJECTION' || v.type === 'UNPARAMETERIZED_QUERY');
|
|
165
|
+
const hasXSS = vulnerabilities.some(v => v.type?.includes('XSS') || v.type?.includes('INNERHTML'));
|
|
166
|
+
const hasSecrets = vulnerabilities.some(v => v.type === 'HARDCODED_API_KEY' || v.type === 'HARDCODED_PASSWORD');
|
|
167
|
+
if (hasSQL) {
|
|
168
|
+
recommendations.add('Use parameterized queries for all database operations. Never concatenate user input directly into SQL strings.');
|
|
169
|
+
recommendations.add('Consider using an ORM like Prisma, Drizzle, or TypeORM that handle SQL injection prevention automatically.');
|
|
170
|
+
recommendations.add('Validate and whitelist all dynamic table and column names using strict allowlists.');
|
|
171
|
+
}
|
|
172
|
+
if (hasXSS) {
|
|
173
|
+
recommendations.add('Use textContent instead of innerHTML for displaying user-provided text.');
|
|
174
|
+
recommendations.add('Always sanitize untrusted HTML using libraries like DOMPurify before rendering.');
|
|
175
|
+
recommendations.add('Use content security policies (CSP) to prevent inline script execution.');
|
|
176
|
+
recommendations.add('Never use eval() or Function() constructors with user input.');
|
|
177
|
+
recommendations.add('In React, prefer component composition over dangerouslySetInnerHTML.');
|
|
178
|
+
}
|
|
179
|
+
if (hasSecrets) {
|
|
180
|
+
recommendations.add('Move all secrets to environment variables (.env files, never commit these).');
|
|
181
|
+
recommendations.add('Use a secrets management system: AWS Secrets Manager, HashiCorp Vault, or cloud provider equivalents.');
|
|
182
|
+
recommendations.add('Rotate all exposed credentials immediately - they may be compromised.');
|
|
183
|
+
recommendations.add('Implement pre-commit hooks to prevent secrets from being committed.');
|
|
184
|
+
}
|
|
185
|
+
// General recommendations
|
|
186
|
+
recommendations.add('Enable OWASP dependency scanning in your CI/CD pipeline (npm audit, Snyk, etc.).');
|
|
187
|
+
recommendations.add('Implement automated security scanning in code review process.');
|
|
188
|
+
recommendations.add('Conduct regular security audits of AI-generated code before deployment.');
|
|
189
|
+
recommendations.add('Use security linters: ESLint security plugins, Semgrep, or SonarQube.');
|
|
190
|
+
return Array.from(recommendations);
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Generate developer-friendly notes
|
|
194
|
+
*/
|
|
195
|
+
function generateDeveloperNotes(vulnerabilities, language) {
|
|
196
|
+
const criticalCount = vulnerabilities.filter(v => v.severity === 'CRITICAL').length;
|
|
197
|
+
const highCount = vulnerabilities.filter(v => v.severity === 'HIGH').length;
|
|
198
|
+
if (vulnerabilities.length === 0) {
|
|
199
|
+
return `Good news! No security vulnerabilities detected in this ${language} code snippet during scanning. ✓`;
|
|
200
|
+
}
|
|
201
|
+
let notes = `Security scan found ${vulnerabilities.length} potential issue(s) in this ${language} code:\n`;
|
|
202
|
+
if (criticalCount > 0) {
|
|
203
|
+
notes += `\n🔴 CRITICAL (${criticalCount}): These vulnerabilities could lead to immediate security breaches. Fix these before any deployment.\n`;
|
|
204
|
+
}
|
|
205
|
+
if (highCount > 0) {
|
|
206
|
+
notes += `\n🟠 HIGH (${highCount}): Serious security issues that should be fixed as soon as possible.\n`;
|
|
207
|
+
}
|
|
208
|
+
const mediumCount = vulnerabilities.filter(v => v.severity === 'MEDIUM').length;
|
|
209
|
+
if (mediumCount > 0) {
|
|
210
|
+
notes += `\n🟡 MEDIUM (${mediumCount}): Important security improvements to make.\n`;
|
|
211
|
+
}
|
|
212
|
+
notes += `\n📋 Each vulnerability includes:
|
|
213
|
+
- The specific code location (line number)
|
|
214
|
+
- CWE code for security reference
|
|
215
|
+
- Clear explanation of the risk
|
|
216
|
+
- Secure code example for fixing
|
|
217
|
+
|
|
218
|
+
⚠️ Research Finding: 80% of AI-generated code contains security vulnerabilities. Developers are 3.5x more likely to think insecure code is secure. Always review AI-generated code with security in mind.`;
|
|
219
|
+
return notes;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Determine overall risk level
|
|
223
|
+
*/
|
|
224
|
+
function determineRiskLevel(summary) {
|
|
225
|
+
if (summary.critical > 0)
|
|
226
|
+
return 'CRITICAL';
|
|
227
|
+
if (summary.high >= 3)
|
|
228
|
+
return 'CRITICAL';
|
|
229
|
+
if (summary.high > 0)
|
|
230
|
+
return 'HIGH';
|
|
231
|
+
if (summary.medium >= 3)
|
|
232
|
+
return 'MEDIUM';
|
|
233
|
+
if (summary.medium > 0)
|
|
234
|
+
return 'LOW';
|
|
235
|
+
return 'SAFE';
|
|
236
|
+
}
|
|
237
|
+
//# sourceMappingURL=scan-security.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan-security.js","sourceRoot":"","sources":["../../src/tools/scan-security.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool: validate_packages
|
|
3
|
+
* Validates package dependencies and prevents hallucinated packages
|
|
4
|
+
*/
|
|
5
|
+
import { Tool } from '@modelcontextprotocol/sdk/types.js';
|
|
6
|
+
export declare const validatePackagesTool: Tool;
|
|
7
|
+
export declare function handleValidatePackages(input: unknown): Promise<object>;
|
|
8
|
+
//# sourceMappingURL=validate_packages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate_packages.d.ts","sourceRoot":"","sources":["../../src/tools/validate_packages.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAgB1D,eAAO,MAAM,oBAAoB,EAAE,IA0ClC,CAAC;AAEF,wBAAsB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CA2F5E"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool: validate_packages
|
|
3
|
+
* Validates package dependencies and prevents hallucinated packages
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { PackageBlocker } from '../developer/blockers/package-blocker.js';
|
|
7
|
+
import { PackageEvaluator } from '../developer/evaluators/package-evaluator.js';
|
|
8
|
+
const inputSchema = z.object({
|
|
9
|
+
code: z.string().optional().describe('Code snippet containing package imports/requires'),
|
|
10
|
+
command: z.string().optional().describe('Package manager command (npm install, pip install, etc.)'),
|
|
11
|
+
packages: z.array(z.object({
|
|
12
|
+
name: z.string(),
|
|
13
|
+
version: z.string().optional(),
|
|
14
|
+
registry: z.enum(['npm', 'pypi', 'maven']).optional()
|
|
15
|
+
})).optional().describe('Array of packages to validate'),
|
|
16
|
+
language: z.enum(['javascript', 'typescript', 'python', 'java', 'unknown']).default('unknown'),
|
|
17
|
+
autoFix: z.boolean().default(true).describe('Automatically fix package names when possible')
|
|
18
|
+
});
|
|
19
|
+
export const validatePackagesTool = {
|
|
20
|
+
name: 'validate_packages',
|
|
21
|
+
description: 'Validate package dependencies to prevent installation of non-existent or malicious packages',
|
|
22
|
+
inputSchema: {
|
|
23
|
+
type: 'object',
|
|
24
|
+
properties: {
|
|
25
|
+
code: {
|
|
26
|
+
type: 'string',
|
|
27
|
+
description: 'Code snippet containing package imports/requires'
|
|
28
|
+
},
|
|
29
|
+
command: {
|
|
30
|
+
type: 'string',
|
|
31
|
+
description: 'Package manager command (npm install, pip install, etc.)'
|
|
32
|
+
},
|
|
33
|
+
packages: {
|
|
34
|
+
type: 'array',
|
|
35
|
+
items: {
|
|
36
|
+
type: 'object',
|
|
37
|
+
properties: {
|
|
38
|
+
name: { type: 'string' },
|
|
39
|
+
version: { type: 'string' },
|
|
40
|
+
registry: {
|
|
41
|
+
type: 'string',
|
|
42
|
+
enum: ['npm', 'pypi', 'maven']
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
required: ['name']
|
|
46
|
+
},
|
|
47
|
+
description: 'Array of packages to validate'
|
|
48
|
+
},
|
|
49
|
+
language: {
|
|
50
|
+
type: 'string',
|
|
51
|
+
enum: ['javascript', 'typescript', 'python', 'java', 'unknown'],
|
|
52
|
+
default: 'unknown'
|
|
53
|
+
},
|
|
54
|
+
autoFix: {
|
|
55
|
+
type: 'boolean',
|
|
56
|
+
default: true,
|
|
57
|
+
description: 'Automatically fix package names when possible'
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
export async function handleValidatePackages(input) {
|
|
63
|
+
try {
|
|
64
|
+
const params = inputSchema.parse(input);
|
|
65
|
+
const blocker = new PackageBlocker(params.autoFix);
|
|
66
|
+
const evaluator = new PackageEvaluator();
|
|
67
|
+
// Handle code validation
|
|
68
|
+
if (params.code) {
|
|
69
|
+
const result = await blocker.interceptCode(params.code, params.language);
|
|
70
|
+
return {
|
|
71
|
+
type: 'code_validation',
|
|
72
|
+
allowed: result.allowed,
|
|
73
|
+
blockedPackages: result.blockedPackages,
|
|
74
|
+
warnings: result.warnings,
|
|
75
|
+
suggestions: result.suggestions,
|
|
76
|
+
modifiedCode: result.modified,
|
|
77
|
+
summary: generateSummary(result.blockedPackages, result.warnings)
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
// Handle command validation
|
|
81
|
+
if (params.command) {
|
|
82
|
+
const result = await blocker.interceptCommand(params.command);
|
|
83
|
+
return {
|
|
84
|
+
type: 'command_validation',
|
|
85
|
+
allowed: result.allowed,
|
|
86
|
+
blockedPackages: result.blockedPackages,
|
|
87
|
+
warnings: result.warnings,
|
|
88
|
+
suggestions: result.suggestions,
|
|
89
|
+
modifiedCommand: result.modified,
|
|
90
|
+
summary: generateSummary(result.blockedPackages, result.warnings)
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
// Handle direct package list validation
|
|
94
|
+
if (params.packages && params.packages.length > 0) {
|
|
95
|
+
const results = await Promise.all(params.packages.map(async (pkg) => {
|
|
96
|
+
const evaluation = await evaluator.evaluate(pkg.name, { language: params.language }, pkg.version);
|
|
97
|
+
return {
|
|
98
|
+
package: pkg.name,
|
|
99
|
+
version: pkg.version,
|
|
100
|
+
exists: evaluation.package.exists,
|
|
101
|
+
blocked: evaluation.blocked,
|
|
102
|
+
reason: evaluation.reason,
|
|
103
|
+
warnings: evaluation.warning,
|
|
104
|
+
suggestions: evaluation.suggestions,
|
|
105
|
+
latestVersion: evaluation.package.latestVersion,
|
|
106
|
+
deprecated: evaluation.package.deprecated,
|
|
107
|
+
securityIssues: evaluation.package.securityIssues
|
|
108
|
+
};
|
|
109
|
+
}));
|
|
110
|
+
const blockedCount = results.filter(r => r.blocked).length;
|
|
111
|
+
const warningCount = results.filter(r => r.warnings).length;
|
|
112
|
+
return {
|
|
113
|
+
type: 'package_validation',
|
|
114
|
+
packages: results,
|
|
115
|
+
summary: {
|
|
116
|
+
total: results.length,
|
|
117
|
+
valid: results.filter(r => r.exists && !r.blocked).length,
|
|
118
|
+
blocked: blockedCount,
|
|
119
|
+
warnings: warningCount,
|
|
120
|
+
message: blockedCount > 0
|
|
121
|
+
? `⚠️ ${blockedCount} package(s) blocked - they don't exist or have issues`
|
|
122
|
+
: warningCount > 0
|
|
123
|
+
? `✓ All packages exist but ${warningCount} have warnings`
|
|
124
|
+
: '✅ All packages validated successfully'
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
error: 'No input provided. Please provide code, command, or packages to validate.'
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
console.error('Package validation error:', error);
|
|
134
|
+
return {
|
|
135
|
+
error: error instanceof Error ? error.message : 'Failed to validate packages'
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
function generateSummary(blockedPackages, warnings) {
|
|
140
|
+
if (blockedPackages.length === 0 && warnings.length === 0) {
|
|
141
|
+
return {
|
|
142
|
+
status: 'success',
|
|
143
|
+
message: '✅ All packages validated successfully'
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
if (blockedPackages.length > 0) {
|
|
147
|
+
return {
|
|
148
|
+
status: 'blocked',
|
|
149
|
+
message: `❌ Blocked ${blockedPackages.length} non-existent/malicious package(s)`,
|
|
150
|
+
details: `Prevented installation of: ${blockedPackages.join(', ')}`
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
status: 'warning',
|
|
155
|
+
message: `⚠️ ${warnings.length} warning(s) found`,
|
|
156
|
+
details: warnings[0] // Show first warning
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=validate_packages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate_packages.js","sourceRoot":"","sources":["../../src/tools/validate_packages.ts"],"names":[],"mappings":"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"}
|
package/dist/types/auth.d.ts
CHANGED
|
@@ -4,25 +4,9 @@ import { z } from 'zod';
|
|
|
4
4
|
* This allows the AI agent to provide user authentication info
|
|
5
5
|
*/
|
|
6
6
|
export declare const AuthContextSchema: z.ZodObject<{
|
|
7
|
-
/**
|
|
8
|
-
* OAuth access token or session identifier
|
|
9
|
-
* This will be validated against the OAuth tokens table
|
|
10
|
-
*/
|
|
11
7
|
token: z.ZodOptional<z.ZodString>;
|
|
12
|
-
/**
|
|
13
|
-
* External user identifier (from OAuth provider)
|
|
14
|
-
* Used as a fallback if token validation fails
|
|
15
|
-
*/
|
|
16
8
|
user_id: z.ZodOptional<z.ZodString>;
|
|
17
|
-
/**
|
|
18
|
-
* Client identifier (ChatGPT, Claude, etc.)
|
|
19
|
-
* Helps track which AI agent is making the request
|
|
20
|
-
*/
|
|
21
9
|
client_id: z.ZodOptional<z.ZodString>;
|
|
22
|
-
/**
|
|
23
|
-
* Stable conversation identifier for user binding
|
|
24
|
-
* Used to generate persistent user IDs for MCP clients without OAuth
|
|
25
|
-
*/
|
|
26
10
|
conversation_id: z.ZodOptional<z.ZodString>;
|
|
27
11
|
}, "strip", z.ZodTypeAny, {
|
|
28
12
|
user_id?: string | undefined;
|
|
@@ -38,8 +22,24 @@ export declare const AuthContextSchema: z.ZodObject<{
|
|
|
38
22
|
export type AuthContext = z.infer<typeof AuthContextSchema>;
|
|
39
23
|
/**
|
|
40
24
|
* Extract user ID from authentication context
|
|
41
|
-
* Implements
|
|
42
|
-
*
|
|
25
|
+
* Implements tiered identity:
|
|
26
|
+
* - Priority 1: OAuth token validation (Pro tier - cross-device)
|
|
27
|
+
* - Priority 2: External user ID + client ID (ChatGPT OAuth)
|
|
28
|
+
* - Priority 3: Local file-based identity (Free tier - single machine)
|
|
29
|
+
* - Priority 4: Conversation-based ID (single window only)
|
|
30
|
+
* - Fallback: Ephemeral IDs (no persistence)
|
|
43
31
|
*/
|
|
44
32
|
export declare function extractUserFromContext(authContext?: AuthContext): Promise<string>;
|
|
33
|
+
/**
|
|
34
|
+
* Get user tier from identity prefix
|
|
35
|
+
*/
|
|
36
|
+
export declare function getUserTier(userId: string): 'pro' | 'free' | 'ephemeral';
|
|
37
|
+
/**
|
|
38
|
+
* Check if user has Pro tier features
|
|
39
|
+
*/
|
|
40
|
+
export declare function hasProFeatures(userId: string): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Get the local identity file path for debugging/support
|
|
43
|
+
*/
|
|
44
|
+
export declare function getIdentityFilePath(): string;
|
|
45
45
|
//# sourceMappingURL=auth.d.ts.map
|
package/dist/types/auth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/types/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/types/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB;;;GAGG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;EAK5B,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AA0D5D;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAAC,WAAW,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAwCvF;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,WAAW,CAMxE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C"}
|
package/dist/types/auth.js
CHANGED
|
@@ -1,71 +1,126 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { createHash } from 'crypto';
|
|
3
|
+
import { homedir, hostname } from 'os';
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
3
6
|
/**
|
|
4
7
|
* Authentication context that can be passed through MCP tool calls
|
|
5
8
|
* This allows the AI agent to provide user authentication info
|
|
6
9
|
*/
|
|
7
10
|
export const AuthContextSchema = z.object({
|
|
8
|
-
/**
|
|
9
|
-
* OAuth access token or session identifier
|
|
10
|
-
* This will be validated against the OAuth tokens table
|
|
11
|
-
*/
|
|
12
11
|
token: z.string().optional().describe('OAuth access token or session identifier'),
|
|
13
|
-
/**
|
|
14
|
-
* External user identifier (from OAuth provider)
|
|
15
|
-
* Used as a fallback if token validation fails
|
|
16
|
-
*/
|
|
17
12
|
user_id: z.string().optional().describe('External user identifier from OAuth provider'),
|
|
18
|
-
/**
|
|
19
|
-
* Client identifier (ChatGPT, Claude, etc.)
|
|
20
|
-
* Helps track which AI agent is making the request
|
|
21
|
-
*/
|
|
22
13
|
client_id: z.string().optional().describe('Client application identifier'),
|
|
23
|
-
/**
|
|
24
|
-
* Stable conversation identifier for user binding
|
|
25
|
-
* Used to generate persistent user IDs for MCP clients without OAuth
|
|
26
|
-
*/
|
|
27
14
|
conversation_id: z.string().optional().describe('Stable conversation identifier for user binding'),
|
|
28
15
|
});
|
|
16
|
+
const IDENTITY_DIR = join(homedir(), '.couchloop-mcp');
|
|
17
|
+
const IDENTITY_FILE = join(IDENTITY_DIR, 'identity.json');
|
|
18
|
+
/**
|
|
19
|
+
* Get or create local identity file for free tier users
|
|
20
|
+
* This provides single-machine persistence without requiring OAuth
|
|
21
|
+
*/
|
|
22
|
+
function getOrCreateLocalIdentity() {
|
|
23
|
+
try {
|
|
24
|
+
// Ensure directory exists
|
|
25
|
+
if (!existsSync(IDENTITY_DIR)) {
|
|
26
|
+
mkdirSync(IDENTITY_DIR, { recursive: true });
|
|
27
|
+
}
|
|
28
|
+
// Check if identity file exists
|
|
29
|
+
if (existsSync(IDENTITY_FILE)) {
|
|
30
|
+
const data = readFileSync(IDENTITY_FILE, 'utf-8');
|
|
31
|
+
const identity = JSON.parse(data);
|
|
32
|
+
if (identity.user_id && identity.user_id.startsWith('local_')) {
|
|
33
|
+
return identity.user_id;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// Create new local identity
|
|
37
|
+
const machineId = createHash('sha256')
|
|
38
|
+
.update(hostname() + ':' + homedir() + ':' + Date.now())
|
|
39
|
+
.digest('hex')
|
|
40
|
+
.substring(0, 24);
|
|
41
|
+
const newIdentity = {
|
|
42
|
+
user_id: 'local_' + machineId,
|
|
43
|
+
created_at: new Date().toISOString(),
|
|
44
|
+
machine: hostname(),
|
|
45
|
+
tier: 'free',
|
|
46
|
+
};
|
|
47
|
+
writeFileSync(IDENTITY_FILE, JSON.stringify(newIdentity, null, 2));
|
|
48
|
+
console.log('Created local identity: ' + newIdentity.user_id + ' at ' + IDENTITY_FILE);
|
|
49
|
+
return newIdentity.user_id;
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
console.warn('Failed to create/read local identity file:', error);
|
|
53
|
+
return '';
|
|
54
|
+
}
|
|
55
|
+
}
|
|
29
56
|
/**
|
|
30
57
|
* Extract user ID from authentication context
|
|
31
|
-
* Implements
|
|
32
|
-
*
|
|
58
|
+
* Implements tiered identity:
|
|
59
|
+
* - Priority 1: OAuth token validation (Pro tier - cross-device)
|
|
60
|
+
* - Priority 2: External user ID + client ID (ChatGPT OAuth)
|
|
61
|
+
* - Priority 3: Local file-based identity (Free tier - single machine)
|
|
62
|
+
* - Priority 4: Conversation-based ID (single window only)
|
|
63
|
+
* - Fallback: Ephemeral IDs (no persistence)
|
|
33
64
|
*/
|
|
34
65
|
export async function extractUserFromContext(authContext) {
|
|
35
|
-
// Priority 1:
|
|
66
|
+
// Priority 1: OAuth token validation (Pro tier - future)
|
|
67
|
+
if (authContext?.token) {
|
|
68
|
+
const hash = createHash('sha256').update(authContext.token).digest('hex');
|
|
69
|
+
return 'oauth_' + hash.substring(0, 24);
|
|
70
|
+
}
|
|
71
|
+
// Priority 2: Hash-based persistent ID from external user identifier
|
|
36
72
|
// For ChatGPT: this is the openai/subject that persists across all chat windows
|
|
37
|
-
// We hash it to avoid storing any external PII
|
|
38
73
|
if (authContext?.user_id && authContext?.client_id) {
|
|
39
74
|
const hash = createHash('sha256')
|
|
40
|
-
.update(
|
|
75
|
+
.update(authContext.client_id + ':' + authContext.user_id)
|
|
41
76
|
.digest('hex');
|
|
42
|
-
|
|
43
|
-
return `${authContext.client_id}_${hash.substring(0, 24)}`;
|
|
77
|
+
return authContext.client_id + '_' + hash.substring(0, 24);
|
|
44
78
|
}
|
|
45
|
-
// Priority
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return
|
|
79
|
+
// Priority 3: Local file-based identity (Free tier)
|
|
80
|
+
// Provides single-machine persistence for VS Code, Cursor, Claude Desktop, etc.
|
|
81
|
+
const localIdentity = getOrCreateLocalIdentity();
|
|
82
|
+
if (localIdentity) {
|
|
83
|
+
return localIdentity;
|
|
50
84
|
}
|
|
51
|
-
// Priority
|
|
52
|
-
// This is less ideal as it doesn't persist across windows
|
|
85
|
+
// Priority 4: Conversation-based ID (single chat window only)
|
|
53
86
|
if (authContext?.client_id && authContext?.conversation_id) {
|
|
54
87
|
const hash = createHash('sha256')
|
|
55
|
-
.update(
|
|
88
|
+
.update(authContext.client_id + ':conv:' + authContext.conversation_id)
|
|
56
89
|
.digest('hex');
|
|
57
|
-
|
|
58
|
-
return `conv_${hash.substring(0, 28)}`;
|
|
90
|
+
return 'conv_' + hash.substring(0, 28);
|
|
59
91
|
}
|
|
60
92
|
// Fallback: Create ephemeral user with warning
|
|
61
|
-
// These should be cleaned up periodically as they indicate missing context
|
|
62
93
|
console.warn('Creating ephemeral user - no stable identity provided', {
|
|
63
94
|
client_id: authContext?.client_id,
|
|
64
95
|
has_conversation_id: !!authContext?.conversation_id,
|
|
65
96
|
timestamp: new Date().toISOString()
|
|
66
97
|
});
|
|
67
98
|
const { nanoid } = await import('nanoid');
|
|
68
|
-
|
|
69
|
-
|
|
99
|
+
return 'ephemeral_' + nanoid(12);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Get user tier from identity prefix
|
|
103
|
+
*/
|
|
104
|
+
export function getUserTier(userId) {
|
|
105
|
+
if (userId.startsWith('oauth_'))
|
|
106
|
+
return 'pro';
|
|
107
|
+
if (userId.startsWith('local_'))
|
|
108
|
+
return 'free';
|
|
109
|
+
if (userId.startsWith('ephemeral_'))
|
|
110
|
+
return 'ephemeral';
|
|
111
|
+
// Client-based IDs (chatgpt_, claude_, etc.) could be either
|
|
112
|
+
return 'free';
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Check if user has Pro tier features
|
|
116
|
+
*/
|
|
117
|
+
export function hasProFeatures(userId) {
|
|
118
|
+
return getUserTier(userId) === 'pro';
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Get the local identity file path for debugging/support
|
|
122
|
+
*/
|
|
123
|
+
export function getIdentityFilePath() {
|
|
124
|
+
return IDENTITY_FILE;
|
|
70
125
|
}
|
|
71
126
|
//# sourceMappingURL=auth.js.map
|