@vaultcompass/vault-guard-mcp 1.5.0 → 1.6.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.
Files changed (2) hide show
  1. package/dist/index.js +26 -7
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -59,9 +59,11 @@ var BINARY_EXTENSIONS = /* @__PURE__ */ new Set([
59
59
  function isBinaryFile(filePath) {
60
60
  return BINARY_EXTENSIONS.has(import_path.default.extname(filePath).toLowerCase());
61
61
  }
62
- async function scanWorkspaceDirectory(root, scanner, concurrency = 10, configIgnorePatterns2 = []) {
62
+ var MCP_SCAN_BUDGET_MS = 5e3;
63
+ async function scanWorkspaceDirectory(root, scanner, concurrency = 10, configIgnorePatterns2 = [], scanBudgetMs = MCP_SCAN_BUDGET_MS) {
63
64
  const files = await (0, import_vault_guard_core.getFilesToScanAsync)(root, false, void 0, configIgnorePatterns2);
64
65
  const results = [];
66
+ const overBudget = [];
65
67
  let filesScanned = 0;
66
68
  let bytesScanned = 0;
67
69
  const scanOne = async (file) => {
@@ -71,10 +73,15 @@ async function scanWorkspaceDirectory(root, scanner, concurrency = 10, configIgn
71
73
  if (!st.isFile()) return;
72
74
  filesScanned += 1;
73
75
  bytesScanned += st.size;
76
+ const t0 = Date.now();
74
77
  const matches = await (0, import_vault_guard_core.scanTextFileAsync)(scanner, file, { maxFileBytes: MAX_FILE_SIZE });
78
+ const elapsed = Date.now() - t0;
75
79
  if (matches.length > 0) {
76
80
  results.push({ file, matches });
77
81
  }
82
+ if (elapsed > scanBudgetMs) {
83
+ overBudget.push({ file, elapsed_ms: elapsed, budget_ms: scanBudgetMs });
84
+ }
78
85
  } catch {
79
86
  }
80
87
  };
@@ -82,11 +89,11 @@ async function scanWorkspaceDirectory(root, scanner, concurrency = 10, configIgn
82
89
  const batch = files.slice(i, i + concurrency);
83
90
  await Promise.all(batch.map(scanOne));
84
91
  }
85
- return { results, filesScanned, bytesScanned };
92
+ return { results, filesScanned, bytesScanned, overBudget };
86
93
  }
87
94
 
88
95
  // src/server.ts
89
- var SERVER_VERSION = true ? "1.5.0" : "0.0.0-dev";
96
+ var SERVER_VERSION = true ? "1.6.0" : "0.0.0-dev";
90
97
  function loadMcpConfig(workspaceRoot) {
91
98
  let cfg;
92
99
  try {
@@ -205,7 +212,7 @@ function createMcpServer(options = {}) {
205
212
  }
206
213
  const dir = resolved.path;
207
214
  const t0 = Date.now();
208
- const { results, filesScanned, bytesScanned } = await scanWorkspaceDirectory(
215
+ const { results, filesScanned, bytesScanned, overBudget } = await scanWorkspaceDirectory(
209
216
  dir,
210
217
  scanner,
211
218
  10,
@@ -220,8 +227,13 @@ function createMcpServer(options = {}) {
220
227
  return toolPayload({
221
228
  summary: {
222
229
  files_with_secrets: results.length,
223
- total_matches: results.reduce((n, r) => n + r.matches.length, 0)
230
+ total_matches: results.reduce((n, r) => n + r.matches.length, 0),
231
+ // Post-hoc: these files WERE scanned, but took long enough that the
232
+ // result is not trusted. Surfaced so an agent is not handed a silent
233
+ // "clean" for a file whose scan behaved pathologically.
234
+ ...overBudget.length > 0 ? { files_over_scan_budget: overBudget.length } : {}
224
235
  },
236
+ ...overBudget.length > 0 ? { over_budget: overBudget } : {},
225
237
  json: JSON.parse((0, import_vault_guard_core2.formatJson)(results, { cwd: dir, run })),
226
238
  sarif: (0, import_vault_guard_core2.formatSarif)(results, { cwd: dir, run }),
227
239
  results
@@ -254,15 +266,22 @@ function createMcpServer(options = {}) {
254
266
  }
255
267
  const t0 = Date.now();
256
268
  const matches = scanner.scan(fp);
269
+ const elapsed = Date.now() - t0;
257
270
  const run = {
258
- duration_ms: Date.now() - t0,
271
+ duration_ms: elapsed,
259
272
  files_scanned: 1,
260
273
  bytes_scanned: st.size,
261
274
  patterns_active: scanner.getActivePatternCount()
262
275
  };
263
276
  const results = matches.length ? [{ file: fp, matches }] : [];
277
+ const overBudget = elapsed > MCP_SCAN_BUDGET_MS;
264
278
  return toolPayload({
265
- summary: { files_with_secrets: results.length, total_matches: matches.length },
279
+ summary: {
280
+ files_with_secrets: results.length,
281
+ total_matches: matches.length,
282
+ ...overBudget ? { over_scan_budget: true } : {}
283
+ },
284
+ ...overBudget ? { over_budget: [{ file: fp, elapsed_ms: elapsed, budget_ms: MCP_SCAN_BUDGET_MS }] } : {},
266
285
  json: JSON.parse((0, import_vault_guard_core2.formatJson)(results, { cwd: workspaceRoot, run })),
267
286
  sarif: (0, import_vault_guard_core2.formatSarif)(results, { cwd: workspaceRoot, run })
268
287
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaultcompass/vault-guard-mcp",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "Let Cursor and Claude scan AI-proposed edits for secrets before applying. Local MCP server.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -26,8 +26,8 @@
26
26
  "dependencies": {
27
27
  "@modelcontextprotocol/sdk": "^1.30.0",
28
28
  "zod": "^4.4.3",
29
- "@vaultcompass/vault-guard-core": "1.5.0",
30
- "@vaultcompass/vault-guard-telemetry": "1.5.0"
29
+ "@vaultcompass/vault-guard-core": "1.6.0",
30
+ "@vaultcompass/vault-guard-telemetry": "1.6.0"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@types/jest": "^30.0.0",