@paretools/security 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Dave London
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { registerAllTools } from "./tools/index.js";
5
+ const server = new McpServer({ name: "@paretools/security", version: "0.1.0" }, {
6
+ instructions: "Structured security scanning operations (trivy, semgrep, gitleaks). Returns typed JSON with vulnerability and finding data. Use instead of running trivy, semgrep, or gitleaks in the terminal.",
7
+ });
8
+ registerAllTools(server);
9
+ const transport = new StdioServerTransport();
10
+ await server.connect(transport);
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B,EAAE,IAAI,EAAE,qBAAqB,EAAE,OAAO,EAAE,OAAO,EAAE,EACjD;IACE,YAAY,EACV,iMAAiM;CACpM,CACF,CAAC;AAEF,gBAAgB,CAAC,MAAM,CAAC,CAAC;AAEzB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC"}
@@ -0,0 +1,44 @@
1
+ import type { TrivyScanResult, SemgrepScanResult, GitleaksScanResult } from "../schemas/index.js";
2
+ /** Formats a Trivy scan result into human-readable text. */
3
+ export declare function formatTrivyScan(data: TrivyScanResult): string;
4
+ /** Compact scan result: summary and total only, no individual vulnerabilities. */
5
+ export interface TrivyScanCompact {
6
+ [key: string]: unknown;
7
+ target: string;
8
+ scanType: "image" | "fs" | "config";
9
+ totalVulnerabilities: number;
10
+ summary: {
11
+ critical: number;
12
+ high: number;
13
+ medium: number;
14
+ low: number;
15
+ unknown: number;
16
+ };
17
+ }
18
+ export declare function compactTrivyScanMap(data: TrivyScanResult): TrivyScanCompact;
19
+ export declare function formatTrivyScanCompact(data: TrivyScanCompact): string;
20
+ /** Formats a Semgrep scan result into human-readable text. */
21
+ export declare function formatSemgrepScan(data: SemgrepScanResult): string;
22
+ /** Compact scan result: summary and total only, no individual findings. */
23
+ export interface SemgrepScanCompact {
24
+ [key: string]: unknown;
25
+ totalFindings: number;
26
+ summary: {
27
+ error: number;
28
+ warning: number;
29
+ info: number;
30
+ };
31
+ config: string;
32
+ }
33
+ export declare function compactSemgrepScanMap(data: SemgrepScanResult): SemgrepScanCompact;
34
+ export declare function formatSemgrepScanCompact(data: SemgrepScanCompact): string;
35
+ /** Formats a Gitleaks scan result into human-readable text. */
36
+ export declare function formatGitleaksScan(data: GitleaksScanResult): string;
37
+ /** Compact scan result: summary and total only, no individual findings. */
38
+ export interface GitleaksScanCompact {
39
+ [key: string]: unknown;
40
+ totalFindings: number;
41
+ }
42
+ export declare function compactGitleaksScanMap(data: GitleaksScanResult): GitleaksScanCompact;
43
+ export declare function formatGitleaksScanCompact(data: GitleaksScanCompact): string;
44
+ //# sourceMappingURL=formatters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatters.d.ts","sourceRoot":"","sources":["../../src/lib/formatters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAIlG,4DAA4D;AAC5D,wBAAgB,eAAe,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAqB7D;AAID,kFAAkF;AAClF,MAAM,WAAW,gBAAgB;IAC/B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,GAAG,IAAI,GAAG,QAAQ,CAAC;IACpC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,OAAO,EAAE;QACP,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,eAAe,GAAG,gBAAgB,CAO3E;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,CAMrE;AAID,8DAA8D;AAC9D,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAoBjE;AAID,2EAA2E;AAC3E,MAAM,WAAW,kBAAkB;IACjC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,iBAAiB,GAAG,kBAAkB,CAMjF;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAMzE;AAID,+DAA+D;AAC/D,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAgBnE;AAID,2EAA2E;AAC3E,MAAM,WAAW,mBAAmB;IAClC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,kBAAkB,GAAG,mBAAmB,CAIpF;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,mBAAmB,GAAG,MAAM,CAE3E"}
@@ -0,0 +1,87 @@
1
+ // -- Full formatters ----------------------------------------------------------
2
+ /** Formats a Trivy scan result into human-readable text. */
3
+ export function formatTrivyScan(data) {
4
+ const lines = [];
5
+ lines.push(`Trivy ${data.scanType} scan: ${data.target}`);
6
+ lines.push(`Found ${data.totalVulnerabilities} vulnerabilities: ` +
7
+ `${data.summary.critical} critical, ${data.summary.high} high, ` +
8
+ `${data.summary.medium} medium, ${data.summary.low} low, ` +
9
+ `${data.summary.unknown} unknown`);
10
+ if (data.vulnerabilities.length > 0) {
11
+ lines.push("");
12
+ for (const v of data.vulnerabilities) {
13
+ const fixed = v.fixedVersion ? ` -> ${v.fixedVersion}` : "";
14
+ const title = v.title ? ` - ${v.title}` : "";
15
+ lines.push(` [${v.severity}] ${v.id}: ${v.package}@${v.installedVersion}${fixed}${title}`);
16
+ }
17
+ }
18
+ return lines.join("\n");
19
+ }
20
+ export function compactTrivyScanMap(data) {
21
+ return {
22
+ target: data.target,
23
+ scanType: data.scanType,
24
+ totalVulnerabilities: data.totalVulnerabilities,
25
+ summary: data.summary,
26
+ };
27
+ }
28
+ export function formatTrivyScanCompact(data) {
29
+ return (`Trivy ${data.scanType} scan: ${data.target} -- ` +
30
+ `${data.totalVulnerabilities} vulnerabilities ` +
31
+ `(${data.summary.critical}C/${data.summary.high}H/${data.summary.medium}M/${data.summary.low}L)`);
32
+ }
33
+ // -- Semgrep formatters -------------------------------------------------------
34
+ /** Formats a Semgrep scan result into human-readable text. */
35
+ export function formatSemgrepScan(data) {
36
+ const lines = [];
37
+ lines.push(`Semgrep scan (config: ${data.config})`);
38
+ lines.push(`Found ${data.totalFindings} findings: ` +
39
+ `${data.summary.error} error, ${data.summary.warning} warning, ` +
40
+ `${data.summary.info} info`);
41
+ if (data.findings.length > 0) {
42
+ lines.push("");
43
+ for (const f of data.findings) {
44
+ const category = f.category ? ` [${f.category}]` : "";
45
+ lines.push(` [${f.severity}] ${f.ruleId}: ${f.path}:${f.startLine}-${f.endLine}${category}`);
46
+ lines.push(` ${f.message}`);
47
+ }
48
+ }
49
+ return lines.join("\n");
50
+ }
51
+ export function compactSemgrepScanMap(data) {
52
+ return {
53
+ totalFindings: data.totalFindings,
54
+ summary: data.summary,
55
+ config: data.config,
56
+ };
57
+ }
58
+ export function formatSemgrepScanCompact(data) {
59
+ return (`Semgrep scan (config: ${data.config}) -- ` +
60
+ `${data.totalFindings} findings ` +
61
+ `(${data.summary.error}E/${data.summary.warning}W/${data.summary.info}I)`);
62
+ }
63
+ // -- Gitleaks formatters ------------------------------------------------------
64
+ /** Formats a Gitleaks scan result into human-readable text. */
65
+ export function formatGitleaksScan(data) {
66
+ const lines = [];
67
+ lines.push(`Gitleaks secret detection scan`);
68
+ lines.push(`Found ${data.totalFindings} secret(s)`);
69
+ if (data.findings.length > 0) {
70
+ lines.push("");
71
+ for (const f of data.findings) {
72
+ const commit = f.commit ? ` (commit: ${f.commit.slice(0, 8)})` : "";
73
+ lines.push(` [${f.ruleID}] ${f.file}:${f.startLine}-${f.endLine}${commit}`);
74
+ lines.push(` ${f.description} -- secret: ${f.secret}`);
75
+ }
76
+ }
77
+ return lines.join("\n");
78
+ }
79
+ export function compactGitleaksScanMap(data) {
80
+ return {
81
+ totalFindings: data.totalFindings,
82
+ };
83
+ }
84
+ export function formatGitleaksScanCompact(data) {
85
+ return `Gitleaks scan -- ${data.totalFindings} secret(s) detected`;
86
+ }
87
+ //# sourceMappingURL=formatters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatters.js","sourceRoot":"","sources":["../../src/lib/formatters.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import type { TrivyScanResult, SemgrepScanResult, GitleaksScanResult } from "../schemas/index.js";
2
+ /**
3
+ * Parses raw Trivy JSON output into a structured TrivyScanResult.
4
+ *
5
+ * Trivy's JSON output has a `Results` array, each entry containing
6
+ * a `Target` and `Vulnerabilities` array. We flatten all vulnerabilities
7
+ * across all results into a single list.
8
+ */
9
+ export declare function parseTrivyJson(jsonStr: string, target: string, scanType: "image" | "fs" | "config"): TrivyScanResult;
10
+ /**
11
+ * Parses raw Semgrep JSON output into a structured SemgrepScanResult.
12
+ *
13
+ * Semgrep's JSON output has a `results` array containing findings,
14
+ * each with check_id, path, start/end positions, and extra metadata.
15
+ */
16
+ export declare function parseSemgrepJson(jsonStr: string, config: string): SemgrepScanResult;
17
+ /**
18
+ * Parses raw Gitleaks JSON output into a structured GitleaksScanResult.
19
+ *
20
+ * Gitleaks outputs a JSON array of findings. Each finding contains
21
+ * RuleID, Description, Match, Secret, File, StartLine, EndLine,
22
+ * Commit, Author, and Date fields.
23
+ */
24
+ export declare function parseGitleaksJson(jsonStr: string): GitleaksScanResult;
25
+ //# sourceMappingURL=parsers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parsers.d.ts","sourceRoot":"","sources":["../../src/lib/parsers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EAGf,iBAAiB,EAGjB,kBAAkB,EAEnB,MAAM,qBAAqB,CAAC;AAiC7B;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,OAAO,GAAG,IAAI,GAAG,QAAQ,GAClC,eAAe,CAyDjB;AA4DD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,iBAAiB,CAqCnF;AA2DD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,kBAAkB,CAkCrE"}
@@ -0,0 +1,217 @@
1
+ /**
2
+ * Parses raw Trivy JSON output into a structured TrivyScanResult.
3
+ *
4
+ * Trivy's JSON output has a `Results` array, each entry containing
5
+ * a `Target` and `Vulnerabilities` array. We flatten all vulnerabilities
6
+ * across all results into a single list.
7
+ */
8
+ export function parseTrivyJson(jsonStr, target, scanType) {
9
+ let parsed;
10
+ try {
11
+ parsed = JSON.parse(jsonStr);
12
+ }
13
+ catch {
14
+ return {
15
+ target,
16
+ scanType,
17
+ vulnerabilities: [],
18
+ summary: { critical: 0, high: 0, medium: 0, low: 0, unknown: 0 },
19
+ totalVulnerabilities: 0,
20
+ };
21
+ }
22
+ const vulnerabilities = [];
23
+ if (parsed.Results) {
24
+ for (const result of parsed.Results) {
25
+ // Handle regular vulnerabilities
26
+ if (result.Vulnerabilities) {
27
+ for (const v of result.Vulnerabilities) {
28
+ vulnerabilities.push({
29
+ id: v.VulnerabilityID || "UNKNOWN",
30
+ severity: normalizeSeverity(v.Severity),
31
+ package: v.PkgName || "unknown",
32
+ installedVersion: v.InstalledVersion || "unknown",
33
+ fixedVersion: v.FixedVersion || undefined,
34
+ title: v.Title || undefined,
35
+ });
36
+ }
37
+ }
38
+ // Handle misconfigurations (config scans)
39
+ if (result.Misconfigurations) {
40
+ for (const m of result.Misconfigurations) {
41
+ vulnerabilities.push({
42
+ id: m.ID || "UNKNOWN",
43
+ severity: normalizeSeverity(m.Severity),
44
+ package: m.Type || "config",
45
+ installedVersion: "N/A",
46
+ fixedVersion: undefined,
47
+ title: m.Title || m.Message || undefined,
48
+ });
49
+ }
50
+ }
51
+ }
52
+ }
53
+ const summary = computeSummary(vulnerabilities);
54
+ return {
55
+ target,
56
+ scanType,
57
+ vulnerabilities,
58
+ summary,
59
+ totalVulnerabilities: vulnerabilities.length,
60
+ };
61
+ }
62
+ /** Normalizes Trivy severity strings to a consistent uppercase form. */
63
+ function normalizeSeverity(severity) {
64
+ if (!severity)
65
+ return "UNKNOWN";
66
+ const upper = severity.toUpperCase();
67
+ if (["CRITICAL", "HIGH", "MEDIUM", "LOW", "UNKNOWN"].includes(upper))
68
+ return upper;
69
+ return upper;
70
+ }
71
+ /** Computes severity summary counts from a list of vulnerabilities. */
72
+ function computeSummary(vulnerabilities) {
73
+ const summary = { critical: 0, high: 0, medium: 0, low: 0, unknown: 0 };
74
+ for (const v of vulnerabilities) {
75
+ switch (v.severity) {
76
+ case "CRITICAL":
77
+ summary.critical++;
78
+ break;
79
+ case "HIGH":
80
+ summary.high++;
81
+ break;
82
+ case "MEDIUM":
83
+ summary.medium++;
84
+ break;
85
+ case "LOW":
86
+ summary.low++;
87
+ break;
88
+ default:
89
+ summary.unknown++;
90
+ break;
91
+ }
92
+ }
93
+ return summary;
94
+ }
95
+ /**
96
+ * Parses raw Semgrep JSON output into a structured SemgrepScanResult.
97
+ *
98
+ * Semgrep's JSON output has a `results` array containing findings,
99
+ * each with check_id, path, start/end positions, and extra metadata.
100
+ */
101
+ export function parseSemgrepJson(jsonStr, config) {
102
+ let parsed;
103
+ try {
104
+ parsed = JSON.parse(jsonStr);
105
+ }
106
+ catch {
107
+ return {
108
+ totalFindings: 0,
109
+ findings: [],
110
+ summary: { error: 0, warning: 0, info: 0 },
111
+ config,
112
+ };
113
+ }
114
+ const findings = [];
115
+ if (parsed.results) {
116
+ for (const r of parsed.results) {
117
+ findings.push({
118
+ ruleId: r.check_id || "unknown",
119
+ path: r.path || "unknown",
120
+ startLine: r.start?.line ?? 0,
121
+ endLine: r.end?.line ?? 0,
122
+ message: r.extra?.message || "",
123
+ severity: normalizeSemgrepSeverity(r.extra?.severity),
124
+ category: r.extra?.metadata?.category || undefined,
125
+ });
126
+ }
127
+ }
128
+ const summary = computeSemgrepSummary(findings);
129
+ return {
130
+ totalFindings: findings.length,
131
+ findings,
132
+ summary,
133
+ config,
134
+ };
135
+ }
136
+ /** Normalizes Semgrep severity strings to a consistent uppercase form. */
137
+ function normalizeSemgrepSeverity(severity) {
138
+ if (!severity)
139
+ return "INFO";
140
+ const upper = severity.toUpperCase();
141
+ if (["ERROR", "WARNING", "INFO"].includes(upper))
142
+ return upper;
143
+ return upper;
144
+ }
145
+ /** Computes severity summary counts from a list of Semgrep findings. */
146
+ function computeSemgrepSummary(findings) {
147
+ const summary = { error: 0, warning: 0, info: 0 };
148
+ for (const f of findings) {
149
+ switch (f.severity) {
150
+ case "ERROR":
151
+ summary.error++;
152
+ break;
153
+ case "WARNING":
154
+ summary.warning++;
155
+ break;
156
+ case "INFO":
157
+ summary.info++;
158
+ break;
159
+ default:
160
+ // Map unknown severities to info
161
+ summary.info++;
162
+ break;
163
+ }
164
+ }
165
+ return summary;
166
+ }
167
+ /**
168
+ * Redacts a secret string, keeping only the first 3 and last 3 characters
169
+ * and replacing the rest with asterisks. Secrets 8 chars or shorter are fully
170
+ * redacted.
171
+ */
172
+ function redactSecret(secret) {
173
+ if (secret.length <= 8)
174
+ return "***";
175
+ return secret.slice(0, 3) + "***" + secret.slice(-3);
176
+ }
177
+ /**
178
+ * Parses raw Gitleaks JSON output into a structured GitleaksScanResult.
179
+ *
180
+ * Gitleaks outputs a JSON array of findings. Each finding contains
181
+ * RuleID, Description, Match, Secret, File, StartLine, EndLine,
182
+ * Commit, Author, and Date fields.
183
+ */
184
+ export function parseGitleaksJson(jsonStr) {
185
+ let parsed;
186
+ try {
187
+ const raw = JSON.parse(jsonStr);
188
+ if (!Array.isArray(raw)) {
189
+ return { totalFindings: 0, findings: [], summary: { totalFindings: 0 } };
190
+ }
191
+ parsed = raw;
192
+ }
193
+ catch {
194
+ return { totalFindings: 0, findings: [], summary: { totalFindings: 0 } };
195
+ }
196
+ const findings = [];
197
+ for (const f of parsed) {
198
+ findings.push({
199
+ ruleID: f.RuleID || "unknown",
200
+ description: f.Description || "",
201
+ match: f.Match || "",
202
+ secret: redactSecret(f.Secret || ""),
203
+ file: f.File || "unknown",
204
+ startLine: f.StartLine ?? 0,
205
+ endLine: f.EndLine ?? 0,
206
+ commit: f.Commit || "",
207
+ author: f.Author || "",
208
+ date: f.Date || "",
209
+ });
210
+ }
211
+ return {
212
+ totalFindings: findings.length,
213
+ findings,
214
+ summary: { totalFindings: findings.length },
215
+ };
216
+ }
217
+ //# sourceMappingURL=parsers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parsers.js","sourceRoot":"","sources":["../../src/lib/parsers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,124 @@
1
+ import { z } from "zod";
2
+ /** Zod schema for a single vulnerability entry from Trivy output. */
3
+ export declare const TrivyVulnerabilitySchema: z.ZodObject<{
4
+ id: z.ZodString;
5
+ severity: z.ZodString;
6
+ package: z.ZodString;
7
+ installedVersion: z.ZodString;
8
+ fixedVersion: z.ZodOptional<z.ZodString>;
9
+ title: z.ZodOptional<z.ZodString>;
10
+ }, z.core.$strip>;
11
+ export type TrivyVulnerability = z.infer<typeof TrivyVulnerabilitySchema>;
12
+ /** Zod schema for severity summary counts. */
13
+ export declare const TrivySeveritySummarySchema: z.ZodObject<{
14
+ critical: z.ZodNumber;
15
+ high: z.ZodNumber;
16
+ medium: z.ZodNumber;
17
+ low: z.ZodNumber;
18
+ unknown: z.ZodNumber;
19
+ }, z.core.$strip>;
20
+ export type TrivySeveritySummary = z.infer<typeof TrivySeveritySummarySchema>;
21
+ /** Zod schema for the structured Trivy scan result. */
22
+ export declare const TrivyScanResultSchema: z.ZodObject<{
23
+ target: z.ZodString;
24
+ scanType: z.ZodEnum<{
25
+ image: "image";
26
+ fs: "fs";
27
+ config: "config";
28
+ }>;
29
+ vulnerabilities: z.ZodArray<z.ZodObject<{
30
+ id: z.ZodString;
31
+ severity: z.ZodString;
32
+ package: z.ZodString;
33
+ installedVersion: z.ZodString;
34
+ fixedVersion: z.ZodOptional<z.ZodString>;
35
+ title: z.ZodOptional<z.ZodString>;
36
+ }, z.core.$strip>>;
37
+ summary: z.ZodObject<{
38
+ critical: z.ZodNumber;
39
+ high: z.ZodNumber;
40
+ medium: z.ZodNumber;
41
+ low: z.ZodNumber;
42
+ unknown: z.ZodNumber;
43
+ }, z.core.$strip>;
44
+ totalVulnerabilities: z.ZodNumber;
45
+ }, z.core.$strip>;
46
+ export type TrivyScanResult = z.infer<typeof TrivyScanResultSchema>;
47
+ /** Zod schema for a single Semgrep finding. */
48
+ export declare const SemgrepFindingSchema: z.ZodObject<{
49
+ ruleId: z.ZodString;
50
+ path: z.ZodString;
51
+ startLine: z.ZodNumber;
52
+ endLine: z.ZodNumber;
53
+ message: z.ZodString;
54
+ severity: z.ZodString;
55
+ category: z.ZodOptional<z.ZodString>;
56
+ }, z.core.$strip>;
57
+ export type SemgrepFinding = z.infer<typeof SemgrepFindingSchema>;
58
+ /** Zod schema for Semgrep severity summary counts. */
59
+ export declare const SemgrepSeveritySummarySchema: z.ZodObject<{
60
+ error: z.ZodNumber;
61
+ warning: z.ZodNumber;
62
+ info: z.ZodNumber;
63
+ }, z.core.$strip>;
64
+ export type SemgrepSeveritySummary = z.infer<typeof SemgrepSeveritySummarySchema>;
65
+ /** Zod schema for the structured Semgrep scan result. */
66
+ export declare const SemgrepScanResultSchema: z.ZodObject<{
67
+ totalFindings: z.ZodNumber;
68
+ findings: z.ZodArray<z.ZodObject<{
69
+ ruleId: z.ZodString;
70
+ path: z.ZodString;
71
+ startLine: z.ZodNumber;
72
+ endLine: z.ZodNumber;
73
+ message: z.ZodString;
74
+ severity: z.ZodString;
75
+ category: z.ZodOptional<z.ZodString>;
76
+ }, z.core.$strip>>;
77
+ summary: z.ZodObject<{
78
+ error: z.ZodNumber;
79
+ warning: z.ZodNumber;
80
+ info: z.ZodNumber;
81
+ }, z.core.$strip>;
82
+ config: z.ZodString;
83
+ }, z.core.$strip>;
84
+ export type SemgrepScanResult = z.infer<typeof SemgrepScanResultSchema>;
85
+ /** Zod schema for a single Gitleaks finding. */
86
+ export declare const GitleaksFindingSchema: z.ZodObject<{
87
+ ruleID: z.ZodString;
88
+ description: z.ZodString;
89
+ match: z.ZodString;
90
+ secret: z.ZodString;
91
+ file: z.ZodString;
92
+ startLine: z.ZodNumber;
93
+ endLine: z.ZodNumber;
94
+ commit: z.ZodString;
95
+ author: z.ZodString;
96
+ date: z.ZodString;
97
+ }, z.core.$strip>;
98
+ export type GitleaksFinding = z.infer<typeof GitleaksFindingSchema>;
99
+ /** Zod schema for Gitleaks summary. */
100
+ export declare const GitleaksSummarySchema: z.ZodObject<{
101
+ totalFindings: z.ZodNumber;
102
+ }, z.core.$strip>;
103
+ export type GitleaksSummary = z.infer<typeof GitleaksSummarySchema>;
104
+ /** Zod schema for the structured Gitleaks scan result. */
105
+ export declare const GitleaksScanResultSchema: z.ZodObject<{
106
+ totalFindings: z.ZodNumber;
107
+ findings: z.ZodArray<z.ZodObject<{
108
+ ruleID: z.ZodString;
109
+ description: z.ZodString;
110
+ match: z.ZodString;
111
+ secret: z.ZodString;
112
+ file: z.ZodString;
113
+ startLine: z.ZodNumber;
114
+ endLine: z.ZodNumber;
115
+ commit: z.ZodString;
116
+ author: z.ZodString;
117
+ date: z.ZodString;
118
+ }, z.core.$strip>>;
119
+ summary: z.ZodObject<{
120
+ totalFindings: z.ZodNumber;
121
+ }, z.core.$strip>;
122
+ }, z.core.$strip>;
123
+ export type GitleaksScanResult = z.infer<typeof GitleaksScanResultSchema>;
124
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/schemas/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,qEAAqE;AACrE,eAAO,MAAM,wBAAwB;;;;;;;iBAOnC,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,8CAA8C;AAC9C,eAAO,MAAM,0BAA0B;;;;;;iBAMrC,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAE9E,uDAAuD;AACvD,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;iBAMhC,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAIpE,+CAA+C;AAC/C,eAAO,MAAM,oBAAoB;;;;;;;;iBAQ/B,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,sDAAsD;AACtD,eAAO,MAAM,4BAA4B;;;;iBAIvC,CAAC;AAEH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAElF,yDAAyD;AACzD,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;iBAKlC,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAIxE,gDAAgD;AAChD,eAAO,MAAM,qBAAqB;;;;;;;;;;;iBAWhC,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,uCAAuC;AACvC,eAAO,MAAM,qBAAqB;;iBAEhC,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,0DAA0D;AAC1D,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;iBAInC,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC"}
@@ -0,0 +1,75 @@
1
+ import { z } from "zod";
2
+ /** Zod schema for a single vulnerability entry from Trivy output. */
3
+ export const TrivyVulnerabilitySchema = z.object({
4
+ id: z.string(),
5
+ severity: z.string(),
6
+ package: z.string(),
7
+ installedVersion: z.string(),
8
+ fixedVersion: z.string().optional(),
9
+ title: z.string().optional(),
10
+ });
11
+ /** Zod schema for severity summary counts. */
12
+ export const TrivySeveritySummarySchema = z.object({
13
+ critical: z.number(),
14
+ high: z.number(),
15
+ medium: z.number(),
16
+ low: z.number(),
17
+ unknown: z.number(),
18
+ });
19
+ /** Zod schema for the structured Trivy scan result. */
20
+ export const TrivyScanResultSchema = z.object({
21
+ target: z.string(),
22
+ scanType: z.enum(["image", "fs", "config"]),
23
+ vulnerabilities: z.array(TrivyVulnerabilitySchema),
24
+ summary: TrivySeveritySummarySchema,
25
+ totalVulnerabilities: z.number(),
26
+ });
27
+ // -- Semgrep schemas ----------------------------------------------------------
28
+ /** Zod schema for a single Semgrep finding. */
29
+ export const SemgrepFindingSchema = z.object({
30
+ ruleId: z.string(),
31
+ path: z.string(),
32
+ startLine: z.number(),
33
+ endLine: z.number(),
34
+ message: z.string(),
35
+ severity: z.string(),
36
+ category: z.string().optional(),
37
+ });
38
+ /** Zod schema for Semgrep severity summary counts. */
39
+ export const SemgrepSeveritySummarySchema = z.object({
40
+ error: z.number(),
41
+ warning: z.number(),
42
+ info: z.number(),
43
+ });
44
+ /** Zod schema for the structured Semgrep scan result. */
45
+ export const SemgrepScanResultSchema = z.object({
46
+ totalFindings: z.number(),
47
+ findings: z.array(SemgrepFindingSchema),
48
+ summary: SemgrepSeveritySummarySchema,
49
+ config: z.string(),
50
+ });
51
+ // -- Gitleaks schemas ---------------------------------------------------------
52
+ /** Zod schema for a single Gitleaks finding. */
53
+ export const GitleaksFindingSchema = z.object({
54
+ ruleID: z.string(),
55
+ description: z.string(),
56
+ match: z.string(),
57
+ secret: z.string(),
58
+ file: z.string(),
59
+ startLine: z.number(),
60
+ endLine: z.number(),
61
+ commit: z.string(),
62
+ author: z.string(),
63
+ date: z.string(),
64
+ });
65
+ /** Zod schema for Gitleaks summary. */
66
+ export const GitleaksSummarySchema = z.object({
67
+ totalFindings: z.number(),
68
+ });
69
+ /** Zod schema for the structured Gitleaks scan result. */
70
+ export const GitleaksScanResultSchema = z.object({
71
+ totalFindings: z.number(),
72
+ findings: z.array(GitleaksFindingSchema),
73
+ summary: GitleaksSummarySchema,
74
+ });
75
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/schemas/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,qEAAqE;AACrE,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/C,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE;IAC5B,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACnC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC7B,CAAC,CAAC;AAIH,8CAA8C;AAC9C,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC;IACjD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;CACpB,CAAC,CAAC;AAIH,uDAAuD;AACvD,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC3C,eAAe,EAAE,CAAC,CAAC,KAAK,CAAC,wBAAwB,CAAC;IAClD,OAAO,EAAE,0BAA0B;IACnC,oBAAoB,EAAE,CAAC,CAAC,MAAM,EAAE;CACjC,CAAC,CAAC;AAIH,gFAAgF;AAEhF,+CAA+C;AAC/C,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAChC,CAAC,CAAC;AAIH,sDAAsD;AACtD,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,CAAC,MAAM,CAAC;IACnD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;CACjB,CAAC,CAAC;AAIH,yDAAyD;AACzD,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE;IACzB,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,oBAAoB,CAAC;IACvC,OAAO,EAAE,4BAA4B;IACrC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;CACnB,CAAC,CAAC;AAIH,gFAAgF;AAEhF,gDAAgD;AAChD,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;CACjB,CAAC,CAAC;AAIH,uCAAuC;AACvC,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE;CAC1B,CAAC,CAAC;AAIH,0DAA0D;AAC1D,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/C,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE;IACzB,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,qBAAqB,CAAC;IACxC,OAAO,EAAE,qBAAqB;CAC/B,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerGitleaksTool(server: McpServer): void;
3
+ //# sourceMappingURL=gitleaks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitleaks.d.ts","sourceRoot":"","sources":["../../src/tools/gitleaks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAUzE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,QAkErD"}
@@ -0,0 +1,50 @@
1
+ import { z } from "zod";
2
+ import { compactDualOutput, run, INPUT_LIMITS } from "@paretools/shared";
3
+ import { parseGitleaksJson } from "../lib/parsers.js";
4
+ import { formatGitleaksScan, compactGitleaksScanMap, formatGitleaksScanCompact, } from "../lib/formatters.js";
5
+ import { GitleaksScanResultSchema } from "../schemas/index.js";
6
+ export function registerGitleaksTool(server) {
7
+ server.registerTool("gitleaks", {
8
+ title: "Gitleaks Secret Detection",
9
+ description: "Runs Gitleaks to detect hardcoded secrets in git repositories. Returns structured finding data with redacted secrets. Use instead of running `gitleaks` in the terminal.",
10
+ inputSchema: {
11
+ path: z
12
+ .string()
13
+ .max(INPUT_LIMITS.PATH_MAX)
14
+ .optional()
15
+ .describe("Repository path to scan (default: cwd)"),
16
+ noGit: z
17
+ .boolean()
18
+ .optional()
19
+ .default(false)
20
+ .describe("Scan files without git history (--no-git). Useful for scanning non-git directories."),
21
+ verbose: z
22
+ .boolean()
23
+ .optional()
24
+ .default(false)
25
+ .describe("Enable verbose output from gitleaks"),
26
+ compact: z
27
+ .boolean()
28
+ .optional()
29
+ .default(true)
30
+ .describe("Auto-compact when structured output exceeds raw CLI tokens. Set false to always get full schema."),
31
+ },
32
+ outputSchema: GitleaksScanResultSchema,
33
+ }, async ({ path, noGit, verbose, compact }) => {
34
+ const cwd = path || process.cwd();
35
+ const args = ["detect", "--report-format", "json", "--report-path", "/dev/stdout"];
36
+ if (noGit) {
37
+ args.push("--no-git");
38
+ }
39
+ if (verbose) {
40
+ args.push("--verbose");
41
+ }
42
+ args.push("--source", cwd);
43
+ // gitleaks exits with code 1 when findings are detected, which is not an error
44
+ const result = await run("gitleaks", args, { cwd, timeout: 300_000 });
45
+ const data = parseGitleaksJson(result.stdout);
46
+ const rawOutput = (result.stdout + "\n" + result.stderr).trim();
47
+ return compactDualOutput(data, rawOutput, formatGitleaksScan, compactGitleaksScanMap, formatGitleaksScanCompact, compact === false);
48
+ });
49
+ }
50
+ //# sourceMappingURL=gitleaks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitleaks.js","sourceRoot":"","sources":["../../src/tools/gitleaks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,iBAAiB,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,yBAAyB,GAC1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAE/D,MAAM,UAAU,oBAAoB,CAAC,MAAiB;IACpD,MAAM,CAAC,YAAY,CACjB,UAAU,EACV;QACE,KAAK,EAAE,2BAA2B;QAClC,WAAW,EACT,0KAA0K;QAC5K,WAAW,EAAE;YACX,IAAI,EAAE,CAAC;iBACJ,MAAM,EAAE;iBACR,GAAG,CAAC,YAAY,CAAC,QAAQ,CAAC;iBAC1B,QAAQ,EAAE;iBACV,QAAQ,CAAC,wCAAwC,CAAC;YACrD,KAAK,EAAE,CAAC;iBACL,OAAO,EAAE;iBACT,QAAQ,EAAE;iBACV,OAAO,CAAC,KAAK,CAAC;iBACd,QAAQ,CACP,qFAAqF,CACtF;YACH,OAAO,EAAE,CAAC;iBACP,OAAO,EAAE;iBACT,QAAQ,EAAE;iBACV,OAAO,CAAC,KAAK,CAAC;iBACd,QAAQ,CAAC,qCAAqC,CAAC;YAClD,OAAO,EAAE,CAAC;iBACP,OAAO,EAAE;iBACT,QAAQ,EAAE;iBACV,OAAO,CAAC,IAAI,CAAC;iBACb,QAAQ,CACP,kGAAkG,CACnG;SACJ;QACD,YAAY,EAAE,wBAAwB;KACvC,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE;QAC1C,MAAM,GAAG,GAAG,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QAElC,MAAM,IAAI,GAAa,CAAC,QAAQ,EAAE,iBAAiB,EAAE,MAAM,EAAE,eAAe,EAAE,aAAa,CAAC,CAAC;QAE7F,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACxB,CAAC;QAED,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACzB,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QAE3B,+EAA+E;QAC/E,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,UAAU,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;QAEtE,MAAM,IAAI,GAAG,iBAAiB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC9C,MAAM,SAAS,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QAEhE,OAAO,iBAAiB,CACtB,IAAI,EACJ,SAAS,EACT,kBAAkB,EAClB,sBAAsB,EACtB,yBAAyB,EACzB,OAAO,KAAK,KAAK,CAClB,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerAllTools(server: McpServer): void;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAMzE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,QAKjD"}
@@ -0,0 +1,14 @@
1
+ import { shouldRegisterTool } from "@paretools/shared";
2
+ import { registerTrivyTool } from "./trivy.js";
3
+ import { registerSemgrepTool } from "./semgrep.js";
4
+ import { registerGitleaksTool } from "./gitleaks.js";
5
+ export function registerAllTools(server) {
6
+ const s = (name) => shouldRegisterTool("security", name);
7
+ if (s("trivy"))
8
+ registerTrivyTool(server);
9
+ if (s("semgrep"))
10
+ registerSemgrepTool(server);
11
+ if (s("gitleaks"))
12
+ registerGitleaksTool(server);
13
+ }
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAErD,MAAM,UAAU,gBAAgB,CAAC,MAAiB;IAChD,MAAM,CAAC,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,kBAAkB,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IACjE,IAAI,CAAC,CAAC,OAAO,CAAC;QAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1C,IAAI,CAAC,CAAC,SAAS,CAAC;QAAE,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC9C,IAAI,CAAC,CAAC,UAAU,CAAC;QAAE,oBAAoB,CAAC,MAAM,CAAC,CAAC;AAClD,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerSemgrepTool(server: McpServer): void;
3
+ //# sourceMappingURL=semgrep.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semgrep.d.ts","sourceRoot":"","sources":["../../src/tools/semgrep.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAUzE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,QA0EpD"}
@@ -0,0 +1,56 @@
1
+ import { z } from "zod";
2
+ import { compactDualOutput, run, INPUT_LIMITS } from "@paretools/shared";
3
+ import { parseSemgrepJson } from "../lib/parsers.js";
4
+ import { formatSemgrepScan, compactSemgrepScanMap, formatSemgrepScanCompact, } from "../lib/formatters.js";
5
+ import { SemgrepScanResultSchema } from "../schemas/index.js";
6
+ export function registerSemgrepTool(server) {
7
+ server.registerTool("semgrep", {
8
+ title: "Semgrep Static Analysis",
9
+ description: "Runs Semgrep static analysis with structured rules and findings. Returns structured finding data with severity summary. Use instead of running `semgrep` in the terminal.",
10
+ inputSchema: {
11
+ patterns: z
12
+ .array(z.string().max(INPUT_LIMITS.PATH_MAX))
13
+ .max(INPUT_LIMITS.ARRAY_MAX)
14
+ .optional()
15
+ .default(["."])
16
+ .describe("File patterns or paths to scan (default: ['.'])"),
17
+ config: z
18
+ .string()
19
+ .max(INPUT_LIMITS.SHORT_STRING_MAX)
20
+ .optional()
21
+ .default("auto")
22
+ .describe('Semgrep config/ruleset (e.g. "auto", "p/security-audit", "p/owasp-top-ten"). Default: "auto"'),
23
+ severity: z
24
+ .string()
25
+ .max(INPUT_LIMITS.SHORT_STRING_MAX)
26
+ .optional()
27
+ .describe("Comma-separated severity filter (e.g. 'ERROR,WARNING'). Default: all severities"),
28
+ path: z
29
+ .string()
30
+ .max(INPUT_LIMITS.PATH_MAX)
31
+ .optional()
32
+ .describe("Working directory (default: cwd)"),
33
+ compact: z
34
+ .boolean()
35
+ .optional()
36
+ .default(true)
37
+ .describe("Auto-compact when structured output exceeds raw CLI tokens. Set false to always get full schema."),
38
+ },
39
+ outputSchema: SemgrepScanResultSchema,
40
+ }, async ({ patterns, config, severity, path, compact }) => {
41
+ const cwd = path || process.cwd();
42
+ const args = ["scan", "--json", "--quiet"];
43
+ if (config) {
44
+ args.push("--config", config);
45
+ }
46
+ if (severity) {
47
+ args.push("--severity", severity);
48
+ }
49
+ args.push(...patterns);
50
+ const result = await run("semgrep", args, { cwd, timeout: 300_000 });
51
+ const data = parseSemgrepJson(result.stdout, config);
52
+ const rawOutput = (result.stdout + "\n" + result.stderr).trim();
53
+ return compactDualOutput(data, rawOutput, formatSemgrepScan, compactSemgrepScanMap, formatSemgrepScanCompact, compact === false);
54
+ });
55
+ }
56
+ //# sourceMappingURL=semgrep.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semgrep.js","sourceRoot":"","sources":["../../src/tools/semgrep.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,iBAAiB,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAE9D,MAAM,UAAU,mBAAmB,CAAC,MAAiB;IACnD,MAAM,CAAC,YAAY,CACjB,SAAS,EACT;QACE,KAAK,EAAE,yBAAyB;QAChC,WAAW,EACT,2KAA2K;QAC7K,WAAW,EAAE;YACX,QAAQ,EAAE,CAAC;iBACR,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;iBAC5C,GAAG,CAAC,YAAY,CAAC,SAAS,CAAC;iBAC3B,QAAQ,EAAE;iBACV,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC;iBACd,QAAQ,CAAC,iDAAiD,CAAC;YAC9D,MAAM,EAAE,CAAC;iBACN,MAAM,EAAE;iBACR,GAAG,CAAC,YAAY,CAAC,gBAAgB,CAAC;iBAClC,QAAQ,EAAE;iBACV,OAAO,CAAC,MAAM,CAAC;iBACf,QAAQ,CACP,8FAA8F,CAC/F;YACH,QAAQ,EAAE,CAAC;iBACR,MAAM,EAAE;iBACR,GAAG,CAAC,YAAY,CAAC,gBAAgB,CAAC;iBAClC,QAAQ,EAAE;iBACV,QAAQ,CACP,iFAAiF,CAClF;YACH,IAAI,EAAE,CAAC;iBACJ,MAAM,EAAE;iBACR,GAAG,CAAC,YAAY,CAAC,QAAQ,CAAC;iBAC1B,QAAQ,EAAE;iBACV,QAAQ,CAAC,kCAAkC,CAAC;YAC/C,OAAO,EAAE,CAAC;iBACP,OAAO,EAAE;iBACT,QAAQ,EAAE;iBACV,OAAO,CAAC,IAAI,CAAC;iBACb,QAAQ,CACP,kGAAkG,CACnG;SACJ;QACD,YAAY,EAAE,uBAAuB;KACtC,EACD,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE;QACtD,MAAM,GAAG,GAAG,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QAElC,MAAM,IAAI,GAAa,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;QAErD,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAChC,CAAC;QAED,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;QACpC,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC;QAEvB,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,SAAS,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;QAErE,MAAM,IAAI,GAAG,gBAAgB,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACrD,MAAM,SAAS,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QAEhE,OAAO,iBAAiB,CACtB,IAAI,EACJ,SAAS,EACT,iBAAiB,EACjB,qBAAqB,EACrB,wBAAwB,EACxB,OAAO,KAAK,KAAK,CAClB,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerTrivyTool(server: McpServer): void;
3
+ //# sourceMappingURL=trivy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trivy.d.ts","sourceRoot":"","sources":["../../src/tools/trivy.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAMzE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,QA4ElD"}
@@ -0,0 +1,58 @@
1
+ import { z } from "zod";
2
+ import { compactDualOutput, run, INPUT_LIMITS } from "@paretools/shared";
3
+ import { parseTrivyJson } from "../lib/parsers.js";
4
+ import { formatTrivyScan, compactTrivyScanMap, formatTrivyScanCompact } from "../lib/formatters.js";
5
+ import { TrivyScanResultSchema } from "../schemas/index.js";
6
+ export function registerTrivyTool(server) {
7
+ server.registerTool("trivy", {
8
+ title: "Trivy Security Scanner",
9
+ description: "Runs Trivy vulnerability/misconfiguration scanner on container images, filesystems, or IaC configs. Returns structured vulnerability data with severity summary. Use instead of running `trivy` in the terminal.",
10
+ inputSchema: {
11
+ target: z
12
+ .string()
13
+ .max(INPUT_LIMITS.PATH_MAX)
14
+ .describe("Scan target: image name (e.g. 'alpine:3.18') or filesystem path"),
15
+ scanType: z
16
+ .enum(["image", "fs", "config"])
17
+ .optional()
18
+ .default("image")
19
+ .describe('Scan type: "image" for container images, "fs" for filesystem, "config" for IaC misconfigurations'),
20
+ severity: z
21
+ .string()
22
+ .max(INPUT_LIMITS.SHORT_STRING_MAX)
23
+ .optional()
24
+ .describe("Comma-separated severity filter (e.g. 'CRITICAL,HIGH'). Default: all severities"),
25
+ ignoreUnfixed: z
26
+ .boolean()
27
+ .optional()
28
+ .default(false)
29
+ .describe("Only show vulnerabilities with known fixes"),
30
+ path: z
31
+ .string()
32
+ .max(INPUT_LIMITS.PATH_MAX)
33
+ .optional()
34
+ .describe("Working directory (default: cwd)"),
35
+ compact: z
36
+ .boolean()
37
+ .optional()
38
+ .default(true)
39
+ .describe("Auto-compact when structured output exceeds raw CLI tokens. Set false to always get full schema."),
40
+ },
41
+ outputSchema: TrivyScanResultSchema,
42
+ }, async ({ target, scanType, severity, ignoreUnfixed, path, compact }) => {
43
+ const cwd = path || process.cwd();
44
+ const args = [scanType, "--format", "json", "--quiet"];
45
+ if (severity) {
46
+ args.push("--severity", severity);
47
+ }
48
+ if (ignoreUnfixed) {
49
+ args.push("--ignore-unfixed");
50
+ }
51
+ args.push(target);
52
+ const result = await run("trivy", args, { cwd, timeout: 300_000 });
53
+ const data = parseTrivyJson(result.stdout, target, scanType);
54
+ const rawOutput = (result.stdout + "\n" + result.stderr).trim();
55
+ return compactDualOutput(data, rawOutput, formatTrivyScan, compactTrivyScanMap, formatTrivyScanCompact, compact === false);
56
+ });
57
+ }
58
+ //# sourceMappingURL=trivy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trivy.js","sourceRoot":"","sources":["../../src/tools/trivy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,iBAAiB,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACpG,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAE5D,MAAM,UAAU,iBAAiB,CAAC,MAAiB;IACjD,MAAM,CAAC,YAAY,CACjB,OAAO,EACP;QACE,KAAK,EAAE,wBAAwB;QAC/B,WAAW,EACT,kNAAkN;QACpN,WAAW,EAAE;YACX,MAAM,EAAE,CAAC;iBACN,MAAM,EAAE;iBACR,GAAG,CAAC,YAAY,CAAC,QAAQ,CAAC;iBAC1B,QAAQ,CAAC,iEAAiE,CAAC;YAC9E,QAAQ,EAAE,CAAC;iBACR,IAAI,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;iBAC/B,QAAQ,EAAE;iBACV,OAAO,CAAC,OAAO,CAAC;iBAChB,QAAQ,CACP,kGAAkG,CACnG;YACH,QAAQ,EAAE,CAAC;iBACR,MAAM,EAAE;iBACR,GAAG,CAAC,YAAY,CAAC,gBAAgB,CAAC;iBAClC,QAAQ,EAAE;iBACV,QAAQ,CACP,iFAAiF,CAClF;YACH,aAAa,EAAE,CAAC;iBACb,OAAO,EAAE;iBACT,QAAQ,EAAE;iBACV,OAAO,CAAC,KAAK,CAAC;iBACd,QAAQ,CAAC,4CAA4C,CAAC;YACzD,IAAI,EAAE,CAAC;iBACJ,MAAM,EAAE;iBACR,GAAG,CAAC,YAAY,CAAC,QAAQ,CAAC;iBAC1B,QAAQ,EAAE;iBACV,QAAQ,CAAC,kCAAkC,CAAC;YAC/C,OAAO,EAAE,CAAC;iBACP,OAAO,EAAE;iBACT,QAAQ,EAAE;iBACV,OAAO,CAAC,IAAI,CAAC;iBACb,QAAQ,CACP,kGAAkG,CACnG;SACJ;QACD,YAAY,EAAE,qBAAqB;KACpC,EACD,KAAK,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE;QACrE,MAAM,GAAG,GAAG,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QAElC,MAAM,IAAI,GAAa,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;QAEjE,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;QACpC,CAAC;QAED,IAAI,aAAa,EAAE,CAAC;YAClB,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAChC,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAElB,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;QAEnE,MAAM,IAAI,GAAG,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC7D,MAAM,SAAS,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QAEhE,OAAO,iBAAiB,CACtB,IAAI,EACJ,SAAS,EACT,eAAe,EACf,mBAAmB,EACnB,sBAAsB,EACtB,OAAO,KAAK,KAAK,CAClB,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
package/package.json ADDED
@@ -0,0 +1,74 @@
1
+ {
2
+ "name": "@paretools/security",
3
+ "version": "0.1.0",
4
+ "mcpName": "io.github.Dave-London/pare-security",
5
+ "description": "MCP server for security scanning (Trivy, Semgrep, Gitleaks) with structured, token-efficient output",
6
+ "license": "MIT",
7
+ "keywords": [
8
+ "mcp",
9
+ "mcp-server",
10
+ "model-context-protocol",
11
+ "structured-output",
12
+ "ai",
13
+ "ai-agent",
14
+ "claude",
15
+ "cursor",
16
+ "copilot",
17
+ "token-efficient",
18
+ "devtools",
19
+ "cli",
20
+ "trivy",
21
+ "security",
22
+ "vulnerability",
23
+ "scanner",
24
+ "container",
25
+ "iac",
26
+ "semgrep",
27
+ "static-analysis",
28
+ "sast",
29
+ "gitleaks",
30
+ "secret-detection"
31
+ ],
32
+ "homepage": "https://github.com/Dave-London/Pare/tree/main/packages/server-security",
33
+ "engines": {
34
+ "node": ">=20"
35
+ },
36
+ "type": "module",
37
+ "bin": {
38
+ "pare-security": "./dist/index.js"
39
+ },
40
+ "exports": {
41
+ ".": {
42
+ "types": "./dist/index.d.ts",
43
+ "default": "./dist/index.js"
44
+ }
45
+ },
46
+ "publishConfig": {
47
+ "access": "public"
48
+ },
49
+ "repository": {
50
+ "type": "git",
51
+ "url": "https://github.com/Dave-London/Pare.git",
52
+ "directory": "packages/server-security"
53
+ },
54
+ "files": [
55
+ "dist"
56
+ ],
57
+ "dependencies": {
58
+ "@modelcontextprotocol/sdk": "^1.26.0",
59
+ "zod": "^4.3.6",
60
+ "@paretools/shared": "0.8.1"
61
+ },
62
+ "devDependencies": {
63
+ "@types/node": "^25.2.3",
64
+ "typescript": "^5.7.0",
65
+ "vitest": "^4.0.18",
66
+ "@paretools/tsconfig": "0.0.0"
67
+ },
68
+ "scripts": {
69
+ "build": "tsc",
70
+ "test": "vitest run",
71
+ "test:watch": "vitest",
72
+ "lint": "eslint src/"
73
+ }
74
+ }