@cognium-ai/mcp-server 0.1.1 → 0.2.1
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/dist/server.d.ts.map +1 -1
- package/dist/server.js +5 -1
- package/dist/server.js.map +1 -1
- package/dist/tools/check-license-compliance.d.ts +11 -0
- package/dist/tools/check-license-compliance.d.ts.map +1 -0
- package/dist/tools/check-license-compliance.js +125 -0
- package/dist/tools/check-license-compliance.js.map +1 -0
- package/dist/tools/find-credential-exposure.d.ts +17 -0
- package/dist/tools/find-credential-exposure.d.ts.map +1 -0
- package/dist/tools/find-credential-exposure.js +172 -0
- package/dist/tools/find-credential-exposure.js.map +1 -0
- package/package.json +2 -2
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAOpE,wBAAgB,WAAW,IAAI,SAAS,CAavC"}
|
package/dist/server.js
CHANGED
|
@@ -5,14 +5,18 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
5
5
|
import { registerVerifySpecConformance } from './tools/verify-spec-conformance.js';
|
|
6
6
|
import { registerFindSpecDrift } from './tools/find-spec-drift.js';
|
|
7
7
|
import { registerFindPattern } from './tools/find-pattern.js';
|
|
8
|
+
import { registerFindCredentialExposure } from './tools/find-credential-exposure.js';
|
|
9
|
+
import { registerCheckLicenseCompliance } from './tools/check-license-compliance.js';
|
|
8
10
|
export function buildServer() {
|
|
9
11
|
const server = new McpServer({
|
|
10
12
|
name: 'cognium-mcp',
|
|
11
|
-
version: '0.
|
|
13
|
+
version: '0.2.1',
|
|
12
14
|
});
|
|
13
15
|
registerVerifySpecConformance(server);
|
|
14
16
|
registerFindSpecDrift(server);
|
|
15
17
|
registerFindPattern(server);
|
|
18
|
+
registerFindCredentialExposure(server);
|
|
19
|
+
registerCheckLicenseCompliance(server);
|
|
16
20
|
return server;
|
|
17
21
|
}
|
|
18
22
|
//# sourceMappingURL=server.js.map
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,6BAA6B,EAAE,MAAM,oCAAoC,CAAC;AACnF,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,6BAA6B,EAAE,MAAM,oCAAoC,CAAC;AACnF,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,8BAA8B,EAAE,MAAM,qCAAqC,CAAC;AACrF,OAAO,EAAE,8BAA8B,EAAE,MAAM,qCAAqC,CAAC;AAErF,MAAM,UAAU,WAAW;IACzB,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,6BAA6B,CAAC,MAAM,CAAC,CAAC;IACtC,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC9B,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC5B,8BAA8B,CAAC,MAAM,CAAC,CAAC;IACvC,8BAA8B,CAAC,MAAM,CAAC,CAAC;IAEvC,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* check_license_compliance MCP tool (Pillar I, Workflow #2).
|
|
3
|
+
*
|
|
4
|
+
* Scans a code root for copyleft/restrictive license issues in dependencies.
|
|
5
|
+
* Supports Node.js (package.json) and Rust (Cargo.toml) ecosystems.
|
|
6
|
+
*
|
|
7
|
+
* @see https://github.com/cogniumhq/cognium-ai/issues/79
|
|
8
|
+
*/
|
|
9
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
10
|
+
export declare function registerCheckLicenseCompliance(server: McpServer): void;
|
|
11
|
+
//# sourceMappingURL=check-license-compliance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-license-compliance.d.ts","sourceRoot":"","sources":["../../src/tools/check-license-compliance.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA0HzE,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAsDtE"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* check_license_compliance MCP tool (Pillar I, Workflow #2).
|
|
3
|
+
*
|
|
4
|
+
* Scans a code root for copyleft/restrictive license issues in dependencies.
|
|
5
|
+
* Supports Node.js (package.json) and Rust (Cargo.toml) ecosystems.
|
|
6
|
+
*
|
|
7
|
+
* @see https://github.com/cogniumhq/cognium-ai/issues/79
|
|
8
|
+
*/
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
import { scanLicenseCompliance, COPYLEFT_SEVERITY, } from 'circle-ir-ai';
|
|
11
|
+
const MAX_FINDINGS = 500;
|
|
12
|
+
const inputSchema = {
|
|
13
|
+
code_root: z.string().describe('Absolute path to the code root to scan'),
|
|
14
|
+
include_dev_deps: z.boolean().optional().default(false).describe('Include devDependencies (default: false)'),
|
|
15
|
+
severity_floor: z.enum(['info', 'low', 'medium', 'high', 'critical']).optional().default('low').describe('Minimum severity to report (default: low)'),
|
|
16
|
+
};
|
|
17
|
+
const findingSchema = z.object({
|
|
18
|
+
kind: z.literal('LICENSE_VIOLATION'),
|
|
19
|
+
severity: z.enum(['low', 'medium', 'high', 'critical']),
|
|
20
|
+
location: z.object({
|
|
21
|
+
file: z.string(),
|
|
22
|
+
span: z.tuple([z.number(), z.number()]),
|
|
23
|
+
}),
|
|
24
|
+
evidence: z.object({
|
|
25
|
+
rule_id: z.string(),
|
|
26
|
+
dependency: z.string(),
|
|
27
|
+
license: z.string(),
|
|
28
|
+
confidence: z.number(),
|
|
29
|
+
}),
|
|
30
|
+
suggested_action: z.string(),
|
|
31
|
+
});
|
|
32
|
+
const outputSchema = {
|
|
33
|
+
findings: z.array(findingSchema),
|
|
34
|
+
summary: z.object({
|
|
35
|
+
total: z.number(),
|
|
36
|
+
by_severity: z.object({
|
|
37
|
+
critical: z.number(),
|
|
38
|
+
high: z.number(),
|
|
39
|
+
medium: z.number(),
|
|
40
|
+
low: z.number(),
|
|
41
|
+
}),
|
|
42
|
+
by_ecosystem: z.object({
|
|
43
|
+
nodejs: z.number(),
|
|
44
|
+
rust: z.number(),
|
|
45
|
+
}),
|
|
46
|
+
truncated: z.boolean(),
|
|
47
|
+
}),
|
|
48
|
+
copyleft_reference: z.record(z.string(), z.string()).describe('Reference table: license to severity'),
|
|
49
|
+
};
|
|
50
|
+
const SEVERITY_ORDER = {
|
|
51
|
+
info: 0,
|
|
52
|
+
low: 1,
|
|
53
|
+
medium: 2,
|
|
54
|
+
high: 3,
|
|
55
|
+
critical: 4,
|
|
56
|
+
};
|
|
57
|
+
function licenseToFinding(finding) {
|
|
58
|
+
return {
|
|
59
|
+
kind: 'LICENSE_VIOLATION',
|
|
60
|
+
severity: finding.severity === 'info' ? 'low' : finding.severity,
|
|
61
|
+
location: {
|
|
62
|
+
file: finding.file,
|
|
63
|
+
span: [finding.line ?? 1, finding.line ?? 1],
|
|
64
|
+
},
|
|
65
|
+
evidence: {
|
|
66
|
+
rule_id: finding.ruleId,
|
|
67
|
+
dependency: finding.dependency,
|
|
68
|
+
license: finding.license,
|
|
69
|
+
confidence: finding.confidence,
|
|
70
|
+
},
|
|
71
|
+
suggested_action: finding.suggestedAction,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function buildCopyleftReference() {
|
|
75
|
+
const ref = {};
|
|
76
|
+
for (const [license, severity] of Object.entries(COPYLEFT_SEVERITY)) {
|
|
77
|
+
ref[license] = severity;
|
|
78
|
+
}
|
|
79
|
+
return ref;
|
|
80
|
+
}
|
|
81
|
+
export function registerCheckLicenseCompliance(server) {
|
|
82
|
+
server.registerTool('check_license_compliance', {
|
|
83
|
+
title: 'Check License Compliance',
|
|
84
|
+
description: 'Scan a code root for copyleft/restrictive license issues in dependencies. ' +
|
|
85
|
+
'Supports Node.js (package.json) and Rust (Cargo.toml). ' +
|
|
86
|
+
'Flags AGPL, GPL, LGPL, MPL, and other copyleft licenses with severity classification. ' +
|
|
87
|
+
'Returns findings with dependency info, license SPDX, and remediation guidance.',
|
|
88
|
+
inputSchema,
|
|
89
|
+
outputSchema,
|
|
90
|
+
}, async ({ code_root, include_dev_deps, severity_floor }) => {
|
|
91
|
+
const scanResult = await scanLicenseCompliance(code_root, {
|
|
92
|
+
includeDevDeps: include_dev_deps,
|
|
93
|
+
minSeverity: severity_floor,
|
|
94
|
+
});
|
|
95
|
+
const floorValue = SEVERITY_ORDER[severity_floor ?? 'low'];
|
|
96
|
+
const filteredFindings = scanResult.findings.filter((f) => SEVERITY_ORDER[f.severity] >= floorValue);
|
|
97
|
+
const truncated = filteredFindings.length > MAX_FINDINGS;
|
|
98
|
+
const findings = filteredFindings
|
|
99
|
+
.slice(0, MAX_FINDINGS)
|
|
100
|
+
.map(licenseToFinding);
|
|
101
|
+
const result = {
|
|
102
|
+
findings,
|
|
103
|
+
summary: {
|
|
104
|
+
total: filteredFindings.length,
|
|
105
|
+
by_severity: {
|
|
106
|
+
critical: filteredFindings.filter((f) => f.severity === 'critical').length,
|
|
107
|
+
high: filteredFindings.filter((f) => f.severity === 'high').length,
|
|
108
|
+
medium: filteredFindings.filter((f) => f.severity === 'medium').length,
|
|
109
|
+
low: filteredFindings.filter((f) => f.severity === 'low').length,
|
|
110
|
+
},
|
|
111
|
+
by_ecosystem: {
|
|
112
|
+
nodejs: filteredFindings.filter((f) => f.ecosystem === 'nodejs').length,
|
|
113
|
+
rust: filteredFindings.filter((f) => f.ecosystem === 'rust').length,
|
|
114
|
+
},
|
|
115
|
+
truncated,
|
|
116
|
+
},
|
|
117
|
+
copyleft_reference: buildCopyleftReference(),
|
|
118
|
+
};
|
|
119
|
+
return {
|
|
120
|
+
content: [{ type: 'text', text: JSON.stringify(result) }],
|
|
121
|
+
structuredContent: result,
|
|
122
|
+
};
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=check-license-compliance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-license-compliance.js","sourceRoot":"","sources":["../../src/tools/check-license-compliance.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `find_credential_exposure` MCP tool (Pillar I, Workflow #1).
|
|
3
|
+
*
|
|
4
|
+
* Scans a code root for hardcoded credentials (API keys, tokens, passwords,
|
|
5
|
+
* private keys) using circle-ir's ScanSecretsPass for SAST detection and
|
|
6
|
+
* circle-ir-ai's secret scanner for git history scanning.
|
|
7
|
+
*
|
|
8
|
+
* Architecture:
|
|
9
|
+
* - SAST detection: Delegated to circle-ir's ScanSecretsPass (no duplication)
|
|
10
|
+
* - Git history: circle-ir-ai scans commits (cross-commit analysis)
|
|
11
|
+
* - Output: Common Pillar I findings envelope for cognium-code integration
|
|
12
|
+
*
|
|
13
|
+
* @see https://github.com/cogniumhq/cognium-ai/issues/78
|
|
14
|
+
*/
|
|
15
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
16
|
+
export declare function registerFindCredentialExposure(server: McpServer): void;
|
|
17
|
+
//# sourceMappingURL=find-credential-exposure.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find-credential-exposure.d.ts","sourceRoot":"","sources":["../../src/tools/find-credential-exposure.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAuJzE,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA4DtE"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `find_credential_exposure` MCP tool (Pillar I, Workflow #1).
|
|
3
|
+
*
|
|
4
|
+
* Scans a code root for hardcoded credentials (API keys, tokens, passwords,
|
|
5
|
+
* private keys) using circle-ir's ScanSecretsPass for SAST detection and
|
|
6
|
+
* circle-ir-ai's secret scanner for git history scanning.
|
|
7
|
+
*
|
|
8
|
+
* Architecture:
|
|
9
|
+
* - SAST detection: Delegated to circle-ir's ScanSecretsPass (no duplication)
|
|
10
|
+
* - Git history: circle-ir-ai scans commits (cross-commit analysis)
|
|
11
|
+
* - Output: Common Pillar I findings envelope for cognium-code integration
|
|
12
|
+
*
|
|
13
|
+
* @see https://github.com/cogniumhq/cognium-ai/issues/78
|
|
14
|
+
*/
|
|
15
|
+
import { z } from 'zod';
|
|
16
|
+
import { scanForSecrets } from 'circle-ir-ai';
|
|
17
|
+
/** Hard cap on findings returned. */
|
|
18
|
+
const MAX_FINDINGS = 500;
|
|
19
|
+
const inputSchema = {
|
|
20
|
+
code_root: z.string().describe('Absolute path to the code root to scan'),
|
|
21
|
+
include_git_history: z.boolean().optional().default(false).describe('Scan git history for secrets (default: false)'),
|
|
22
|
+
severity_floor: z.enum(['info', 'low', 'medium', 'high', 'critical']).optional().default('low').describe('Minimum severity to report (default: low)'),
|
|
23
|
+
};
|
|
24
|
+
const findingSchema = z.object({
|
|
25
|
+
kind: z.literal('CREDENTIAL_EXPOSURE'),
|
|
26
|
+
severity: z.enum(['low', 'medium', 'high', 'critical']),
|
|
27
|
+
location: z.object({
|
|
28
|
+
file: z.string(),
|
|
29
|
+
span: z.tuple([z.number(), z.number()]),
|
|
30
|
+
}),
|
|
31
|
+
evidence: z.object({
|
|
32
|
+
rule_id: z.string(),
|
|
33
|
+
match_snippet: z.string(),
|
|
34
|
+
confidence: z.number(),
|
|
35
|
+
}),
|
|
36
|
+
suggested_action: z.string(),
|
|
37
|
+
});
|
|
38
|
+
const outputSchema = {
|
|
39
|
+
findings: z.array(findingSchema),
|
|
40
|
+
summary: z.object({
|
|
41
|
+
total: z.number(),
|
|
42
|
+
by_severity: z.object({
|
|
43
|
+
critical: z.number(),
|
|
44
|
+
high: z.number(),
|
|
45
|
+
medium: z.number(),
|
|
46
|
+
low: z.number(),
|
|
47
|
+
}),
|
|
48
|
+
truncated: z.boolean(),
|
|
49
|
+
}),
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Map severity to suggested action
|
|
53
|
+
*/
|
|
54
|
+
function getSuggestedAction(secret) {
|
|
55
|
+
const category = secret.category.toLowerCase();
|
|
56
|
+
const isActive = secret.presentInHead;
|
|
57
|
+
if (!isActive) {
|
|
58
|
+
return 'Secret found in git history only. Consider rotating and cleaning history with git-filter-repo or BFG.';
|
|
59
|
+
}
|
|
60
|
+
switch (category) {
|
|
61
|
+
case 'aws':
|
|
62
|
+
return 'Rotate the AWS access key immediately via IAM console and move to AWS Secrets Manager or environment variables.';
|
|
63
|
+
case 'github':
|
|
64
|
+
return 'Revoke the token at https://github.com/settings/tokens and use GITHUB_TOKEN or repository secrets instead.';
|
|
65
|
+
case 'openai':
|
|
66
|
+
return 'Revoke the key at https://platform.openai.com/api-keys and load from environment variables.';
|
|
67
|
+
case 'anthropic':
|
|
68
|
+
return 'Revoke the key in the Anthropic Console and load from environment variables.';
|
|
69
|
+
case 'stripe':
|
|
70
|
+
return 'Rotate in the Stripe Dashboard and use environment variables or a secrets manager.';
|
|
71
|
+
case 'slack':
|
|
72
|
+
return 'Revoke the token in Slack workspace settings and use environment variables.';
|
|
73
|
+
case 'gcp':
|
|
74
|
+
return 'Restrict or revoke in Google Cloud Console and use service account keys or Workload Identity.';
|
|
75
|
+
case 'private-key':
|
|
76
|
+
return 'Remove immediately, rotate the keypair, and never commit private keys to source control.';
|
|
77
|
+
case 'jwt':
|
|
78
|
+
return 'JWTs carry whatever scope they were minted with. Rotate signing keys and remove the token.';
|
|
79
|
+
case 'npm':
|
|
80
|
+
return 'Revoke at https://www.npmjs.com/settings/<user>/tokens and use NPM_TOKEN environment variable.';
|
|
81
|
+
case 'high-entropy':
|
|
82
|
+
return 'If this is a credential, move to environment variables or a secrets manager. If sample data, add to .gitignore.';
|
|
83
|
+
default:
|
|
84
|
+
return 'Rotate this credential immediately and move to environment variables or a secrets manager.';
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Map severity order for filtering
|
|
89
|
+
*/
|
|
90
|
+
const SEVERITY_ORDER = {
|
|
91
|
+
info: 0,
|
|
92
|
+
low: 1,
|
|
93
|
+
medium: 2,
|
|
94
|
+
high: 3,
|
|
95
|
+
critical: 4,
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Convert DetectedSecret to CredentialFinding
|
|
99
|
+
*/
|
|
100
|
+
function secretToFinding(secret, codeRoot) {
|
|
101
|
+
// Make file path relative to code_root
|
|
102
|
+
let relativePath = secret.file;
|
|
103
|
+
if (relativePath.startsWith(codeRoot)) {
|
|
104
|
+
relativePath = relativePath.slice(codeRoot.length);
|
|
105
|
+
if (relativePath.startsWith('/')) {
|
|
106
|
+
relativePath = relativePath.slice(1);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
kind: 'CREDENTIAL_EXPOSURE',
|
|
111
|
+
severity: secret.severity === 'low' ? 'low' : secret.severity,
|
|
112
|
+
location: {
|
|
113
|
+
file: relativePath,
|
|
114
|
+
span: [secret.line, secret.line], // Single line span
|
|
115
|
+
},
|
|
116
|
+
evidence: {
|
|
117
|
+
rule_id: secret.patternId,
|
|
118
|
+
match_snippet: secret.match, // Already redacted by scanner
|
|
119
|
+
confidence: secret.llmConfidence ?? (secret.category === 'high-entropy' ? 0.7 : 0.95),
|
|
120
|
+
},
|
|
121
|
+
suggested_action: getSuggestedAction(secret),
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
export function registerFindCredentialExposure(server) {
|
|
125
|
+
server.registerTool('find_credential_exposure', {
|
|
126
|
+
title: 'Find Credential Exposure',
|
|
127
|
+
description: 'Scan a code root for hardcoded credentials (API keys, tokens, passwords, ' +
|
|
128
|
+
'private keys). Uses SAST pattern matching and optional git history scanning. ' +
|
|
129
|
+
'Returns findings with severity, location, and remediation guidance.',
|
|
130
|
+
inputSchema,
|
|
131
|
+
outputSchema,
|
|
132
|
+
}, async ({ code_root, include_git_history, severity_floor }) => {
|
|
133
|
+
// Map severity_floor to scanner's minSeverity
|
|
134
|
+
const minSeverity = severity_floor === 'info' ? undefined :
|
|
135
|
+
severity_floor === 'low' ? 'low' :
|
|
136
|
+
severity_floor === 'medium' ? 'medium' :
|
|
137
|
+
severity_floor === 'high' ? 'high' :
|
|
138
|
+
severity_floor === 'critical' ? 'critical' :
|
|
139
|
+
'low';
|
|
140
|
+
const scanResult = await scanForSecrets(code_root, {
|
|
141
|
+
scanHistory: include_git_history,
|
|
142
|
+
minSeverity,
|
|
143
|
+
maxCommits: 100, // Reasonable limit for git history
|
|
144
|
+
});
|
|
145
|
+
// Filter by severity floor and convert to findings
|
|
146
|
+
const floorValue = SEVERITY_ORDER[severity_floor ?? 'low'];
|
|
147
|
+
const filteredSecrets = scanResult.secrets.filter((s) => SEVERITY_ORDER[s.severity] >= floorValue);
|
|
148
|
+
// Convert to findings format, respecting MAX_FINDINGS
|
|
149
|
+
const truncated = filteredSecrets.length > MAX_FINDINGS;
|
|
150
|
+
const findings = filteredSecrets
|
|
151
|
+
.slice(0, MAX_FINDINGS)
|
|
152
|
+
.map((s) => secretToFinding(s, code_root));
|
|
153
|
+
const result = {
|
|
154
|
+
findings,
|
|
155
|
+
summary: {
|
|
156
|
+
total: filteredSecrets.length,
|
|
157
|
+
by_severity: {
|
|
158
|
+
critical: filteredSecrets.filter((s) => s.severity === 'critical').length,
|
|
159
|
+
high: filteredSecrets.filter((s) => s.severity === 'high').length,
|
|
160
|
+
medium: filteredSecrets.filter((s) => s.severity === 'medium').length,
|
|
161
|
+
low: filteredSecrets.filter((s) => s.severity === 'low').length,
|
|
162
|
+
},
|
|
163
|
+
truncated,
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
return {
|
|
167
|
+
content: [{ type: 'text', text: JSON.stringify(result) }],
|
|
168
|
+
structuredContent: result,
|
|
169
|
+
};
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=find-credential-exposure.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find-credential-exposure.js","sourceRoot":"","sources":["../../src/tools/find-credential-exposure.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cognium-ai/mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "MCP server exposing Cognium spec-conformance, spec-drift, and pattern-search tools over stdio",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
48
48
|
"circle-ir": "^3.23.3",
|
|
49
|
-
"circle-ir-ai": "^2.
|
|
49
|
+
"circle-ir-ai": "^2.8.0",
|
|
50
50
|
"minimatch": "^10.2.5",
|
|
51
51
|
"zod": "^3.25.0"
|
|
52
52
|
},
|