@runsec/mcp 1.0.85 → 1.0.87

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 +69 -21
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -6129,7 +6129,8 @@ function buildHubComplianceBlock(result) {
6129
6129
  // src/telemetryClient.ts
6130
6130
  var HUB_UPLOAD_TIMEOUT_MS = 12e4;
6131
6131
  var HUB_UPLOAD_MAX_RETRIES = 4;
6132
- var HUB_HTTPS_AGENT = new import_node_https.default.Agent({ keepAlive: true, maxSockets: 4, timeout: HUB_UPLOAD_TIMEOUT_MS });
6132
+ var HUB_WRITE_CHUNK_BYTES = 16 * 1024;
6133
+ var HUB_HTTPS_AGENT = new import_node_https.default.Agent({ keepAlive: false, maxSockets: 2, timeout: HUB_UPLOAD_TIMEOUT_MS });
6133
6134
  function sleepMs(ms) {
6134
6135
  return new Promise((resolve) => setTimeout(resolve, ms));
6135
6136
  }
@@ -6206,13 +6207,51 @@ function slimFindingForHubUpload(finding) {
6206
6207
  file_path: finding.file_path,
6207
6208
  line: finding.line,
6208
6209
  detector_name: finding.detector_name,
6209
- description: finding.description?.slice(0, 240),
6210
- match_text: finding.match_text?.slice(0, 120),
6210
+ description: finding.description?.slice(0, 160),
6211
6211
  confidence_score: finding.confidence_score,
6212
6212
  suppressed: finding.suppressed,
6213
6213
  suppression_reason: finding.suppression_reason
6214
6214
  };
6215
6215
  }
6216
+ function buildSuppressedSummaryForHub(findings) {
6217
+ const byReason = {};
6218
+ const locations = [];
6219
+ for (const f of findings) {
6220
+ const reason = String(f.suppression_reason ?? "cognitive_suppressed");
6221
+ byReason[reason] = (byReason[reason] ?? 0) + 1;
6222
+ locations.push({
6223
+ file_path: f.file_path,
6224
+ line: f.line ?? 0,
6225
+ rule_id: f.rule_id,
6226
+ detector_name: f.detector_name,
6227
+ suppression_reason: reason,
6228
+ severity: f.severity
6229
+ });
6230
+ }
6231
+ return { total: findings.length, by_reason: byReason, locations };
6232
+ }
6233
+ function slimEngineSummaryForHub(engineSummary) {
6234
+ if (!engineSummary) return void 0;
6235
+ const pick = (row) => row ? {
6236
+ engine: row.engine,
6237
+ status: row.status,
6238
+ finding_count: row.finding_count,
6239
+ duration_ms: row.duration_ms
6240
+ } : void 0;
6241
+ return {
6242
+ concurrent_duration_ms: engineSummary.concurrent_duration_ms,
6243
+ semgrep: pick(engineSummary.semgrep),
6244
+ trufflehog: pick(engineSummary.trufflehog),
6245
+ syft: pick(engineSummary.syft)
6246
+ };
6247
+ }
6248
+ function slimReportMetricsForHub(reportMetrics) {
6249
+ const { findings_suppressed: _fs, raw_engines: _raw, engine_summary, ...rest } = reportMetrics;
6250
+ return {
6251
+ ...rest,
6252
+ engine_summary: slimEngineSummaryForHub(engine_summary)
6253
+ };
6254
+ }
6216
6255
  function slimRunsecJsonForHubUpload(result, reportMetrics, workspacePath, verdict, metrics, compliance, complianceASVS) {
6217
6256
  return {
6218
6257
  source: "runsec_mcp",
@@ -6222,14 +6261,15 @@ function slimRunsecJsonForHubUpload(result, reportMetrics, workspacePath, verdic
6222
6261
  metrics,
6223
6262
  compliance,
6224
6263
  complianceASVS,
6225
- report_metrics: reportMetrics,
6264
+ report_metrics: slimReportMetricsForHub(reportMetrics),
6226
6265
  findings: result.findings.map(slimFindingForHubUpload),
6227
- findings_suppressed: result.findings_suppressed.map(slimFindingForHubUpload),
6266
+ findings_suppressed_summary: buildSuppressedSummaryForHub(result.findings_suppressed),
6267
+ findings_suppressed_count: result.findings_suppressed.length,
6228
6268
  duration_ms: result.duration_ms,
6229
6269
  findings_count: result.findings_count,
6230
6270
  cognitive_suppressed_count: result.cognitive_suppressed_count,
6231
6271
  engines: result.engines,
6232
- engine_summary: result.engine_summary,
6272
+ engine_summary: slimEngineSummaryForHub(result.engine_summary),
6233
6273
  cognitive: result.cognitive,
6234
6274
  verdict_detail: result.verdict
6235
6275
  };
@@ -6250,9 +6290,11 @@ function postHubUploadNodeHttp(url, apiKey, payload) {
6250
6290
  reject(err);
6251
6291
  return;
6252
6292
  }
6293
+ const bodyBuffer = Buffer.from(body, "utf8");
6253
6294
  const headers = {
6254
6295
  ...hubAuthHeaders(apiKey),
6255
- "Content-Length": String(Buffer.byteLength(body))
6296
+ "Content-Length": String(bodyBuffer.length),
6297
+ Connection: "close"
6256
6298
  };
6257
6299
  const lib = parsed.protocol === "https:" ? import_node_https.default : import_node_http.default;
6258
6300
  const port = parsed.port !== "" ? Number(parsed.port) : parsed.protocol === "https:" ? 443 : 80;
@@ -6287,27 +6329,33 @@ function postHubUploadNodeHttp(url, apiKey, payload) {
6287
6329
  req.destroy();
6288
6330
  reject(Object.assign(new Error("Hub upload request timeout"), { code: "ETIMEDOUT" }));
6289
6331
  });
6290
- req.write(body);
6332
+ for (let offset = 0; offset < bodyBuffer.length; offset += HUB_WRITE_CHUNK_BYTES) {
6333
+ req.write(bodyBuffer.subarray(offset, offset + HUB_WRITE_CHUNK_BYTES));
6334
+ }
6291
6335
  req.end();
6292
6336
  });
6293
6337
  }
6294
- function preferNodeHttpUpload() {
6295
- if (process.env.VITEST === "true" || process.env.RUNSEC_HUB_USE_FETCH === "1") return false;
6296
- if (process.env.RUNSEC_HUB_USE_NODE_HTTP === "1") return true;
6297
- if (process.platform === "win32") return true;
6298
- return false;
6338
+ async function postHubUploadFetch(url, apiKey, payload) {
6339
+ return await fetch(url, {
6340
+ method: "POST",
6341
+ headers: hubAuthHeaders(apiKey),
6342
+ body: JSON.stringify(payload),
6343
+ signal: AbortSignal.timeout(HUB_UPLOAD_TIMEOUT_MS)
6344
+ });
6299
6345
  }
6300
6346
  async function postHubUploadOnce(url, apiKey, payload) {
6301
- if (preferNodeHttpUpload()) {
6302
- return postHubUploadNodeHttp(url, apiKey, payload);
6347
+ const useNodeFirst = process.env.RUNSEC_HUB_USE_NODE_HTTP === "1";
6348
+ if (useNodeFirst) {
6349
+ try {
6350
+ return await postHubUploadNodeHttp(url, apiKey, payload);
6351
+ } catch (nodeError) {
6352
+ console.error("[runsec] node:http(s) upload failed \u2014 retrying with fetch()");
6353
+ dumpHubNetworkError(nodeError, url);
6354
+ return postHubUploadFetch(url, apiKey, payload);
6355
+ }
6303
6356
  }
6304
6357
  try {
6305
- return await fetch(url, {
6306
- method: "POST",
6307
- headers: hubAuthHeaders(apiKey),
6308
- body: JSON.stringify(payload),
6309
- signal: AbortSignal.timeout(HUB_UPLOAD_TIMEOUT_MS)
6310
- });
6358
+ return await postHubUploadFetch(url, apiKey, payload);
6311
6359
  } catch (fetchError) {
6312
6360
  console.error("[runsec] fetch() failed \u2014 retrying Hub upload via node:http(s)");
6313
6361
  dumpHubNetworkError(fetchError, url);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runsec/mcp",
3
- "version": "1.0.85",
3
+ "version": "1.0.87",
4
4
  "main": "dist/index.js",
5
5
  "files": [
6
6
  "package.json",