@vaultcompass/vault-guard-mcp 1.4.7 → 1.5.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 +24 -8
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -86,7 +86,7 @@ async function scanWorkspaceDirectory(root, scanner, concurrency = 10, configIgn
86
86
  }
87
87
 
88
88
  // src/server.ts
89
- var SERVER_VERSION = true ? "1.4.7" : "0.0.0-dev";
89
+ var SERVER_VERSION = true ? "1.5.0" : "0.0.0-dev";
90
90
  function loadMcpConfig(workspaceRoot) {
91
91
  let cfg;
92
92
  try {
@@ -107,6 +107,7 @@ function loadMcpConfig(workspaceRoot) {
107
107
  function makeScanner(config) {
108
108
  return new import_vault_guard_core2.SecretScanner(config);
109
109
  }
110
+ var MAX_SCAN_BYTES = 10 * 1024 * 1024;
110
111
  function toolPayload(obj) {
111
112
  return {
112
113
  content: [{ type: "text", text: JSON.stringify(obj, null, 2) }]
@@ -247,9 +248,12 @@ function createMcpServer(options = {}) {
247
248
  if (!import_fs2.default.existsSync(fp) || !import_fs2.default.statSync(fp).isFile()) {
248
249
  return toolPayload({ error: "not_a_file", path: fp });
249
250
  }
251
+ const st = import_fs2.default.statSync(fp);
252
+ if (st.size > MAX_SCAN_BYTES) {
253
+ return toolPayload({ error: "file_too_large", path: fp, bytes: st.size, max_bytes: MAX_SCAN_BYTES });
254
+ }
250
255
  const t0 = Date.now();
251
256
  const matches = scanner.scan(fp);
252
- const st = import_fs2.default.statSync(fp);
253
257
  const run = {
254
258
  duration_ms: Date.now() - t0,
255
259
  files_scanned: 1,
@@ -275,12 +279,15 @@ function createMcpServer(options = {}) {
275
279
  }
276
280
  },
277
281
  async ({ text, virtual_path }) => {
282
+ const bytes = Buffer.byteLength(text, "utf8");
283
+ if (bytes > MAX_SCAN_BYTES) {
284
+ return toolPayload({ error: "text_too_large", bytes, max_bytes: MAX_SCAN_BYTES });
285
+ }
278
286
  const scanner = makeScanner(loadMcpConfig(workspaceRoot));
279
287
  const t0 = Date.now();
280
288
  const matches = scanner.scanContent(text);
281
289
  const label = virtual_path ?? "inline://snippet";
282
290
  const results = matches.length ? [{ file: label, matches }] : [];
283
- const bytes = Buffer.byteLength(text, "utf8");
284
291
  const run = {
285
292
  duration_ms: Date.now() - t0,
286
293
  files_scanned: 1,
@@ -308,16 +315,20 @@ function createMcpServer(options = {}) {
308
315
  const targets = paths && paths.length > 0 ? paths : ["."];
309
316
  let total = 0;
310
317
  const breakdown = {};
318
+ const visited = /* @__PURE__ */ new Set();
311
319
  const walkFile = (file) => {
312
320
  try {
313
- if (!import_fs2.default.existsSync(file)) return;
314
- const st = import_fs2.default.statSync(file);
315
- if (st.isFile()) {
321
+ const lst = import_fs2.default.lstatSync(file);
322
+ if (lst.isSymbolicLink()) return;
323
+ if (lst.isFile()) {
316
324
  const n = tokenCounter.countTokensInFile(file);
317
325
  total += n;
318
326
  const ext = import_path2.default.extname(file) || "(no-ext)";
319
327
  breakdown[ext] = (breakdown[ext] ?? 0) + n;
320
- } else if (st.isDirectory()) {
328
+ } else if (lst.isDirectory()) {
329
+ const real = import_fs2.default.realpathSync(file);
330
+ if (visited.has(real)) return;
331
+ visited.add(real);
321
332
  const entries = import_fs2.default.readdirSync(file, { withFileTypes: true });
322
333
  for (const e of entries) {
323
334
  if (e.name === "node_modules" || e.name === ".git") continue;
@@ -332,7 +343,12 @@ function createMcpServer(options = {}) {
332
343
  if (!resolved.ok) {
333
344
  return toolPayload({ error: resolved.error, path: resolved.path });
334
345
  }
335
- walkFile(resolved.path);
346
+ let start = resolved.path;
347
+ try {
348
+ start = import_fs2.default.realpathSync(resolved.path);
349
+ } catch {
350
+ }
351
+ walkFile(start);
336
352
  }
337
353
  const estCostAnthropic = tokenCounter.calculateCost("anthropic", total, 0);
338
354
  return toolPayload({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaultcompass/vault-guard-mcp",
3
- "version": "1.4.7",
3
+ "version": "1.5.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.4.7",
30
- "@vaultcompass/vault-guard-telemetry": "1.4.7"
29
+ "@vaultcompass/vault-guard-core": "1.5.0",
30
+ "@vaultcompass/vault-guard-telemetry": "1.5.0"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@types/jest": "^30.0.0",