codeql-development-mcp-server 2.25.1-next.3 → 2.25.2-next.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.
@@ -3600,49 +3600,49 @@ var require_fast_uri = __commonJS({
3600
3600
  schemelessOptions.skipEscape = true;
3601
3601
  return serialize(resolved, schemelessOptions);
3602
3602
  }
3603
- function resolveComponent(base, relative3, options, skipNormalization) {
3603
+ function resolveComponent(base, relative4, options, skipNormalization) {
3604
3604
  const target = {};
3605
3605
  if (!skipNormalization) {
3606
3606
  base = parse4(serialize(base, options), options);
3607
- relative3 = parse4(serialize(relative3, options), options);
3607
+ relative4 = parse4(serialize(relative4, options), options);
3608
3608
  }
3609
3609
  options = options || {};
3610
- if (!options.tolerant && relative3.scheme) {
3611
- target.scheme = relative3.scheme;
3612
- target.userinfo = relative3.userinfo;
3613
- target.host = relative3.host;
3614
- target.port = relative3.port;
3615
- target.path = removeDotSegments(relative3.path || "");
3616
- target.query = relative3.query;
3610
+ if (!options.tolerant && relative4.scheme) {
3611
+ target.scheme = relative4.scheme;
3612
+ target.userinfo = relative4.userinfo;
3613
+ target.host = relative4.host;
3614
+ target.port = relative4.port;
3615
+ target.path = removeDotSegments(relative4.path || "");
3616
+ target.query = relative4.query;
3617
3617
  } else {
3618
- if (relative3.userinfo !== void 0 || relative3.host !== void 0 || relative3.port !== void 0) {
3619
- target.userinfo = relative3.userinfo;
3620
- target.host = relative3.host;
3621
- target.port = relative3.port;
3622
- target.path = removeDotSegments(relative3.path || "");
3623
- target.query = relative3.query;
3618
+ if (relative4.userinfo !== void 0 || relative4.host !== void 0 || relative4.port !== void 0) {
3619
+ target.userinfo = relative4.userinfo;
3620
+ target.host = relative4.host;
3621
+ target.port = relative4.port;
3622
+ target.path = removeDotSegments(relative4.path || "");
3623
+ target.query = relative4.query;
3624
3624
  } else {
3625
- if (!relative3.path) {
3625
+ if (!relative4.path) {
3626
3626
  target.path = base.path;
3627
- if (relative3.query !== void 0) {
3628
- target.query = relative3.query;
3627
+ if (relative4.query !== void 0) {
3628
+ target.query = relative4.query;
3629
3629
  } else {
3630
3630
  target.query = base.query;
3631
3631
  }
3632
3632
  } else {
3633
- if (relative3.path[0] === "/") {
3634
- target.path = removeDotSegments(relative3.path);
3633
+ if (relative4.path[0] === "/") {
3634
+ target.path = removeDotSegments(relative4.path);
3635
3635
  } else {
3636
3636
  if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) {
3637
- target.path = "/" + relative3.path;
3637
+ target.path = "/" + relative4.path;
3638
3638
  } else if (!base.path) {
3639
- target.path = relative3.path;
3639
+ target.path = relative4.path;
3640
3640
  } else {
3641
- target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative3.path;
3641
+ target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative4.path;
3642
3642
  }
3643
3643
  target.path = removeDotSegments(target.path);
3644
3644
  }
3645
- target.query = relative3.query;
3645
+ target.query = relative4.query;
3646
3646
  }
3647
3647
  target.userinfo = base.userinfo;
3648
3648
  target.host = base.host;
@@ -3650,7 +3650,7 @@ var require_fast_uri = __commonJS({
3650
3650
  }
3651
3651
  target.scheme = base.scheme;
3652
3652
  }
3653
- target.fragment = relative3.fragment;
3653
+ target.fragment = relative4.fragment;
3654
3654
  return target;
3655
3655
  }
3656
3656
  function equal(uriA, uriB, options) {
@@ -13305,7 +13305,7 @@ var require_src = __commonJS({
13305
13305
  // ../node_modules/depd/index.js
13306
13306
  var require_depd = __commonJS({
13307
13307
  "../node_modules/depd/index.js"(exports, module) {
13308
- var relative3 = __require("path").relative;
13308
+ var relative4 = __require("path").relative;
13309
13309
  module.exports = depd;
13310
13310
  var basePath = process.cwd();
13311
13311
  function containsNamespace(str2, namespace) {
@@ -13497,7 +13497,7 @@ var require_depd = __commonJS({
13497
13497
  return formatted;
13498
13498
  }
13499
13499
  function formatLocation(callSite) {
13500
- return relative3(basePath, callSite[0]) + ":" + callSite[1] + ":" + callSite[2];
13500
+ return relative4(basePath, callSite[0]) + ":" + callSite[1] + ":" + callSite[2];
13501
13501
  }
13502
13502
  function getStack() {
13503
13503
  var limit = Error.stackTraceLimit;
@@ -32676,9 +32676,8 @@ var require_side_channel_list = __commonJS({
32676
32676
  }
32677
32677
  },
32678
32678
  "delete": function(key) {
32679
- var root = $o && $o.next;
32680
32679
  var deletedNode = listDelete($o, key);
32681
- if (deletedNode && root && root === deletedNode) {
32680
+ if (deletedNode && $o && !$o.next) {
32682
32681
  $o = void 0;
32683
32682
  }
32684
32683
  return !!deletedNode;
@@ -34321,9 +34320,9 @@ var require_parse = __commonJS({
34321
34320
  var limit = options.parameterLimit === Infinity ? void 0 : options.parameterLimit;
34322
34321
  var parts = cleanStr.split(
34323
34322
  options.delimiter,
34324
- options.throwOnLimitExceeded ? limit + 1 : limit
34323
+ options.throwOnLimitExceeded && typeof limit !== "undefined" ? limit + 1 : limit
34325
34324
  );
34326
- if (options.throwOnLimitExceeded && parts.length > limit) {
34325
+ if (options.throwOnLimitExceeded && typeof limit !== "undefined" && parts.length > limit) {
34327
34326
  throw new RangeError("Parameter limit exceeded. Only " + limit + " parameter" + (limit === 1 ? "" : "s") + " allowed.");
34328
34327
  }
34329
34328
  var skipIndex = -1;
@@ -35004,7 +35003,7 @@ var require_view = __commonJS({
35004
35003
  var path3 = __require("node:path");
35005
35004
  var fs3 = __require("node:fs");
35006
35005
  var dirname10 = path3.dirname;
35007
- var basename10 = path3.basename;
35006
+ var basename11 = path3.basename;
35008
35007
  var extname3 = path3.extname;
35009
35008
  var join23 = path3.join;
35010
35009
  var resolve15 = path3.resolve;
@@ -35043,7 +35042,7 @@ var require_view = __commonJS({
35043
35042
  var root = roots[i];
35044
35043
  var loc = resolve15(root, name);
35045
35044
  var dir = dirname10(loc);
35046
- var file = basename10(loc);
35045
+ var file = basename11(loc);
35047
35046
  path4 = this.resolve(dir, file);
35048
35047
  }
35049
35048
  return path4;
@@ -35073,7 +35072,7 @@ var require_view = __commonJS({
35073
35072
  if (stat && stat.isFile()) {
35074
35073
  return path4;
35075
35074
  }
35076
- path4 = join23(dir, basename10(file, ext), "index" + ext);
35075
+ path4 = join23(dir, basename11(file, ext), "index" + ext);
35077
35076
  stat = tryStat(path4);
35078
35077
  if (stat && stat.isFile()) {
35079
35078
  return path4;
@@ -38371,10 +38370,8 @@ var require_content_disposition = __commonJS({
38371
38370
  "use strict";
38372
38371
  module.exports = contentDisposition;
38373
38372
  module.exports.parse = parse4;
38374
- var basename10 = __require("path").basename;
38373
+ var utf8Decoder = new TextDecoder("utf-8");
38375
38374
  var ENCODE_URL_ATTR_CHAR_REGEXP = /[\x00-\x20"'()*,/:;<=>?@[\\\]{}\x7f]/g;
38376
- var HEX_ESCAPE_REGEXP = /%[0-9A-Fa-f]{2}/;
38377
- var HEX_ESCAPE_REPLACE_REGEXP = /%([0-9A-Fa-f]{2})/g;
38378
38375
  var NON_LATIN1_REGEXP = /[^\x20-\x7e\xa0-\xff]/g;
38379
38376
  var QESC_REGEXP = /\\([\u0000-\u007f])/g;
38380
38377
  var QUOTE_REGEXP = /([\\"])/g;
@@ -38406,11 +38403,11 @@ var require_content_disposition = __commonJS({
38406
38403
  if (typeof fallback === "string" && NON_LATIN1_REGEXP.test(fallback)) {
38407
38404
  throw new TypeError("fallback must be ISO-8859-1 string");
38408
38405
  }
38409
- var name = basename10(filename);
38406
+ var name = basename11(filename);
38410
38407
  var isQuotedString = TEXT_REGEXP.test(name);
38411
- var fallbackName = typeof fallback !== "string" ? fallback && getlatin1(name) : basename10(fallback);
38408
+ var fallbackName = typeof fallback !== "string" ? fallback && getlatin1(name) : basename11(fallback);
38412
38409
  var hasFallback = typeof fallbackName === "string" && fallbackName !== name;
38413
- if (hasFallback || !isQuotedString || HEX_ESCAPE_REGEXP.test(name)) {
38410
+ if (hasFallback || !isQuotedString || hasHexEscape(name)) {
38414
38411
  params["filename*"] = name;
38415
38412
  }
38416
38413
  if (isQuotedString || hasFallback) {
@@ -38437,26 +38434,32 @@ var require_content_disposition = __commonJS({
38437
38434
  return string3;
38438
38435
  }
38439
38436
  function decodefield(str2) {
38440
- var match = EXT_VALUE_REGEXP.exec(str2);
38437
+ const match = EXT_VALUE_REGEXP.exec(str2);
38441
38438
  if (!match) {
38442
38439
  throw new TypeError("invalid extended field value");
38443
38440
  }
38444
- var charset = match[1].toLowerCase();
38445
- var encoded = match[2];
38446
- var value;
38447
- var binary2 = encoded.replace(HEX_ESCAPE_REPLACE_REGEXP, pdecode);
38441
+ const charset = match[1].toLowerCase();
38442
+ const encoded = match[2];
38448
38443
  switch (charset) {
38449
- case "iso-8859-1":
38450
- value = getlatin1(binary2);
38451
- break;
38444
+ case "iso-8859-1": {
38445
+ const binary2 = decodeHexEscapes(encoded);
38446
+ return getlatin1(binary2);
38447
+ }
38452
38448
  case "utf-8":
38453
- case "utf8":
38454
- value = Buffer.from(binary2, "binary").toString("utf8");
38455
- break;
38456
- default:
38457
- throw new TypeError("unsupported charset in extended field");
38449
+ case "utf8": {
38450
+ try {
38451
+ return decodeURIComponent(encoded);
38452
+ } catch {
38453
+ const binary2 = decodeHexEscapes(encoded);
38454
+ const bytes = new Uint8Array(binary2.length);
38455
+ for (let idx = 0; idx < binary2.length; idx++) {
38456
+ bytes[idx] = binary2.charCodeAt(idx);
38457
+ }
38458
+ return utf8Decoder.decode(bytes);
38459
+ }
38460
+ }
38458
38461
  }
38459
- return value;
38462
+ throw new TypeError("unsupported charset in extended field");
38460
38463
  }
38461
38464
  function getlatin1(val) {
38462
38465
  return String(val).replace(NON_LATIN1_REGEXP, "?");
@@ -38506,9 +38509,6 @@ var require_content_disposition = __commonJS({
38506
38509
  }
38507
38510
  return new ContentDisposition(type2, params);
38508
38511
  }
38509
- function pdecode(str2, hex) {
38510
- return String.fromCharCode(parseInt(hex, 16));
38511
- }
38512
38512
  function pencode(char) {
38513
38513
  return "%" + String(char).charCodeAt(0).toString(16).toUpperCase();
38514
38514
  }
@@ -38525,6 +38525,51 @@ var require_content_disposition = __commonJS({
38525
38525
  this.type = type2;
38526
38526
  this.parameters = parameters;
38527
38527
  }
38528
+ function basename11(path3) {
38529
+ const normalized = path3.replaceAll("\\", "/");
38530
+ let end = normalized.length;
38531
+ while (end > 0 && normalized[end - 1] === "/") {
38532
+ end--;
38533
+ }
38534
+ if (end === 0) {
38535
+ return "";
38536
+ }
38537
+ let start = end - 1;
38538
+ while (start >= 0 && normalized[start] !== "/") {
38539
+ start--;
38540
+ }
38541
+ return normalized.slice(start + 1, end);
38542
+ }
38543
+ function isHexDigit(char) {
38544
+ const code = char.charCodeAt(0);
38545
+ return code >= 48 && code <= 57 || // 0-9
38546
+ code >= 65 && code <= 70 || // A-F
38547
+ code >= 97 && code <= 102;
38548
+ }
38549
+ function hasHexEscape(str2) {
38550
+ const maxIndex = str2.length - 3;
38551
+ let lastIndex = -1;
38552
+ while ((lastIndex = str2.indexOf("%", lastIndex + 1)) !== -1 && lastIndex <= maxIndex) {
38553
+ if (isHexDigit(str2[lastIndex + 1]) && isHexDigit(str2[lastIndex + 2])) {
38554
+ return true;
38555
+ }
38556
+ }
38557
+ return false;
38558
+ }
38559
+ function decodeHexEscapes(str2) {
38560
+ const firstEscape = str2.indexOf("%");
38561
+ if (firstEscape === -1) return str2;
38562
+ let result = str2.slice(0, firstEscape);
38563
+ for (let idx = firstEscape; idx < str2.length; idx++) {
38564
+ if (str2[idx] === "%" && idx + 2 < str2.length && isHexDigit(str2[idx + 1]) && isHexDigit(str2[idx + 2])) {
38565
+ result += String.fromCharCode(Number.parseInt(str2[idx + 1] + str2[idx + 2], 16));
38566
+ idx += 2;
38567
+ } else {
38568
+ result += str2[idx];
38569
+ }
38570
+ }
38571
+ return result;
38572
+ }
38528
38573
  }
38529
38574
  });
38530
38575
 
@@ -38735,7 +38780,7 @@ var require_send = __commonJS({
38735
38780
  var join23 = path3.join;
38736
38781
  var normalize2 = path3.normalize;
38737
38782
  var resolve15 = path3.resolve;
38738
- var sep4 = path3.sep;
38783
+ var sep5 = path3.sep;
38739
38784
  var BYTES_RANGE_REGEXP = /^ *bytes=/;
38740
38785
  var MAX_MAXAGE = 60 * 60 * 24 * 365 * 1e3;
38741
38786
  var UP_PATH_REGEXP = /(?:^|[\\/])\.\.(?:[\\/]|$)/;
@@ -38896,14 +38941,14 @@ var require_send = __commonJS({
38896
38941
  var parts;
38897
38942
  if (root !== null) {
38898
38943
  if (path4) {
38899
- path4 = normalize2("." + sep4 + path4);
38944
+ path4 = normalize2("." + sep5 + path4);
38900
38945
  }
38901
38946
  if (UP_PATH_REGEXP.test(path4)) {
38902
38947
  debug('malicious path "%s"', path4);
38903
38948
  this.error(403);
38904
38949
  return res;
38905
38950
  }
38906
- parts = path4.split(sep4);
38951
+ parts = path4.split(sep5);
38907
38952
  path4 = normalize2(join23(root, path4));
38908
38953
  } else {
38909
38954
  if (UP_PATH_REGEXP.test(path4)) {
@@ -38911,7 +38956,7 @@ var require_send = __commonJS({
38911
38956
  this.error(403);
38912
38957
  return res;
38913
38958
  }
38914
- parts = normalize2(path4).split(sep4);
38959
+ parts = normalize2(path4).split(sep5);
38915
38960
  path4 = resolve15(path4);
38916
38961
  }
38917
38962
  if (containsDotFile(parts)) {
@@ -39005,7 +39050,7 @@ var require_send = __commonJS({
39005
39050
  var self2 = this;
39006
39051
  debug('stat "%s"', path4);
39007
39052
  fs3.stat(path4, function onstat(err, stat) {
39008
- var pathEndsWithSep = path4[path4.length - 1] === sep4;
39053
+ var pathEndsWithSep = path4[path4.length - 1] === sep5;
39009
39054
  if (err && err.code === "ENOENT" && !extname3(path4) && !pathEndsWithSep) {
39010
39055
  return next(err);
39011
39056
  }
@@ -40383,8 +40428,8 @@ var require_main = __commonJS({
40383
40428
  const shortPaths = [];
40384
40429
  for (const filePath of optionPaths) {
40385
40430
  try {
40386
- const relative3 = path3.relative(process.cwd(), filePath);
40387
- shortPaths.push(relative3);
40431
+ const relative4 = path3.relative(process.cwd(), filePath);
40432
+ shortPaths.push(relative4);
40388
40433
  } catch (e) {
40389
40434
  if (debug) {
40390
40435
  _debug(`failed to load ${filePath} ${e.message}`);
@@ -40392,7 +40437,7 @@ var require_main = __commonJS({
40392
40437
  lastError = e;
40393
40438
  }
40394
40439
  }
40395
- _log(`injecting env (${keysCount}) from ${shortPaths.join(",")} ${dim(`// tip: ${_getRandomTip()}`)}`);
40440
+ _log(`injected env (${keysCount}) from ${shortPaths.join(",")} ${dim(`// tip: ${_getRandomTip()}`)}`);
40396
40441
  }
40397
40442
  if (lastError) {
40398
40443
  return { parsed: parsedAll, error: lastError };
@@ -172214,8 +172259,8 @@ var require_adm_zip = __commonJS({
172214
172259
  return null;
172215
172260
  }
172216
172261
  function fixPath(zipPath) {
172217
- const { join: join23, normalize: normalize2, sep: sep4 } = pth.posix;
172218
- return join23(pth.isAbsolute(zipPath) ? "/" : ".", normalize2(sep4 + zipPath.split("\\").join(sep4) + sep4));
172262
+ const { join: join23, normalize: normalize2, sep: sep5 } = pth.posix;
172263
+ return join23(pth.isAbsolute(zipPath) ? "/" : ".", normalize2(sep5 + zipPath.split("\\").join(sep5) + sep5));
172219
172264
  }
172220
172265
  function filenameFilter(filterfn) {
172221
172266
  if (filterfn instanceof RegExp) {
@@ -187313,6 +187358,17 @@ var requestPrototype = {
187313
187358
  }
187314
187359
  });
187315
187360
  });
187361
+ Object.defineProperty(requestPrototype, /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom"), {
187362
+ value: function(depth, options, inspectFn) {
187363
+ const props = {
187364
+ method: this.method,
187365
+ url: this.url,
187366
+ headers: this.headers,
187367
+ nativeRequest: this[requestCache]
187368
+ };
187369
+ return `Request (lightweight) ${inspectFn(props, { ...options, depth: depth == null ? null : depth - 1 })}`;
187370
+ }
187371
+ });
187316
187372
  Object.setPrototypeOf(requestPrototype, Request.prototype);
187317
187373
  var newRequest = (incoming, defaultHostname) => {
187318
187374
  const req = Object.create(requestPrototype);
@@ -187417,6 +187473,17 @@ var Response2 = class _Response {
187417
187473
  }
187418
187474
  });
187419
187475
  });
187476
+ Object.defineProperty(Response2.prototype, /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom"), {
187477
+ value: function(depth, options, inspectFn) {
187478
+ const props = {
187479
+ status: this.status,
187480
+ headers: this.headers,
187481
+ ok: this.ok,
187482
+ nativeResponse: this[responseCache]
187483
+ };
187484
+ return `Response (lightweight) ${inspectFn(props, { ...options, depth: depth == null ? null : depth - 1 })}`;
187485
+ }
187486
+ });
187420
187487
  Object.setPrototypeOf(Response2, GlobalResponse);
187421
187488
  Object.setPrototypeOf(Response2.prototype, GlobalResponse.prototype);
187422
187489
  async function readWithoutBlocking(readPromise) {
@@ -188563,12 +188630,13 @@ init_logger();
188563
188630
  // src/lib/log-directory-manager.ts
188564
188631
  init_temp_dir();
188565
188632
  import { mkdirSync as mkdirSync3, existsSync as existsSync5 } from "fs";
188566
- import { join as join7, resolve as resolve3 } from "path";
188633
+ import { join as join7, resolve as resolve3, sep, relative } from "path";
188567
188634
  import { randomBytes } from "crypto";
188568
188635
  function ensurePathWithinBase(baseDir, targetPath) {
188569
188636
  const absBase = resolve3(baseDir);
188570
188637
  const absTarget = resolve3(targetPath);
188571
- if (!absTarget.startsWith(absBase + "/") && absTarget !== absBase) {
188638
+ const rel = relative(absBase, absTarget);
188639
+ if (rel === ".." || rel.startsWith(".." + sep)) {
188572
188640
  throw new Error(`Provided log directory is outside the allowed base directory: ${absBase}`);
188573
188641
  }
188574
188642
  return absTarget;
@@ -189374,10 +189442,43 @@ function diffSarifRules(sarifA, sarifB) {
189374
189442
  unchangedRules
189375
189443
  };
189376
189444
  }
189445
+ function computeFingerprintOverlap(resultA, resultB) {
189446
+ const fpA = resultA.partialFingerprints;
189447
+ const fpB = resultB.partialFingerprints;
189448
+ if (!fpA || !fpB || Object.keys(fpA).length === 0 || Object.keys(fpB).length === 0) {
189449
+ return {
189450
+ fingerprintMatch: false,
189451
+ overlaps: false,
189452
+ overlapMode: "fingerprint",
189453
+ sharedLocations: []
189454
+ };
189455
+ }
189456
+ const matchedFingerprints = {};
189457
+ for (const key of Object.keys(fpA)) {
189458
+ if (key in fpB && fpA[key] === fpB[key]) {
189459
+ matchedFingerprints[key] = fpA[key];
189460
+ }
189461
+ }
189462
+ const hasMatch = Object.keys(matchedFingerprints).length > 0;
189463
+ return {
189464
+ fingerprintMatch: hasMatch,
189465
+ matchedFingerprints: hasMatch ? matchedFingerprints : void 0,
189466
+ overlaps: hasMatch,
189467
+ overlapMode: "fingerprint",
189468
+ sharedLocations: []
189469
+ };
189470
+ }
189377
189471
  function computeLocationOverlap(resultA, resultB, mode = "sink") {
189378
189472
  let locsA;
189379
189473
  let locsB;
189380
189474
  switch (mode) {
189475
+ case "fingerprint": {
189476
+ const fpResult = computeFingerprintOverlap(resultA, resultB);
189477
+ if (fpResult.fingerprintMatch) {
189478
+ return fpResult;
189479
+ }
189480
+ return computeLocationOverlap(resultA, resultB, "full-path");
189481
+ }
189381
189482
  case "sink":
189382
189483
  locsA = extractPrimaryLocations(resultA);
189383
189484
  locsB = extractPrimaryLocations(resultB);
@@ -189417,6 +189518,99 @@ function computeLocationOverlap(resultA, resultB, mode = "sink") {
189417
189518
  sharedLocations: shared
189418
189519
  };
189419
189520
  }
189521
+ function findOverlappingAlerts(resultsA, ruleA, resultsB, ruleB, mode = "sink") {
189522
+ const overlaps = [];
189523
+ for (let i = 0; i < resultsA.length; i++) {
189524
+ for (let j = 0; j < resultsB.length; j++) {
189525
+ const overlapDetails = computeLocationOverlap(resultsA[i], resultsB[j], mode);
189526
+ if (overlapDetails.overlaps) {
189527
+ overlaps.push({
189528
+ overlapDetails,
189529
+ resultA: resultsA[i],
189530
+ resultAIndex: i,
189531
+ resultB: resultsB[j],
189532
+ resultBIndex: j,
189533
+ ruleIdA: ruleA.id,
189534
+ ruleIdB: ruleB.id
189535
+ });
189536
+ }
189537
+ }
189538
+ }
189539
+ return overlaps;
189540
+ }
189541
+ function lineInHunks(line, hunks) {
189542
+ for (const hunk of hunks) {
189543
+ const hunkEnd = hunk.startLine + Math.max(hunk.lineCount - 1, 0);
189544
+ if (line >= hunk.startLine && line <= hunkEnd) {
189545
+ return true;
189546
+ }
189547
+ }
189548
+ return false;
189549
+ }
189550
+ function diffSarifByCommits(sarif, diffFiles, refRange, granularity = "file") {
189551
+ const results = sarif.runs[0]?.results ?? [];
189552
+ const newResults = [];
189553
+ const preExistingResults = [];
189554
+ const normalizedDiffEntries = diffFiles.map((df) => ({
189555
+ entry: df,
189556
+ normalized: normalizeUri(df.path)
189557
+ }));
189558
+ for (let i = 0; i < results.length; i++) {
189559
+ const result = results[i];
189560
+ const primaryLoc = result.locations?.[0]?.physicalLocation;
189561
+ const uri = primaryLoc?.artifactLocation?.uri;
189562
+ if (!uri) {
189563
+ preExistingResults.push({
189564
+ file: "<unknown>",
189565
+ resultIndex: i,
189566
+ ruleId: result.ruleId
189567
+ });
189568
+ continue;
189569
+ }
189570
+ const startLine = primaryLoc?.region?.startLine;
189571
+ const normalizedUri = normalizeUri(uri);
189572
+ let matchingDiff;
189573
+ for (const { entry, normalized } of normalizedDiffEntries) {
189574
+ if (normalized === normalizedUri || normalized.endsWith(normalizedUri) || normalizedUri.endsWith(normalized)) {
189575
+ matchingDiff = entry;
189576
+ break;
189577
+ }
189578
+ }
189579
+ let isNew = false;
189580
+ if (matchingDiff) {
189581
+ if (granularity === "file") {
189582
+ isNew = true;
189583
+ } else if (startLine !== void 0 && matchingDiff.hunks.length > 0) {
189584
+ isNew = lineInHunks(startLine, matchingDiff.hunks);
189585
+ } else if (matchingDiff.hunks.length === 0 && !matchingDiff.hunksParsed) {
189586
+ isNew = true;
189587
+ }
189588
+ }
189589
+ const classified = {
189590
+ file: matchingDiff ? matchingDiff.path : normalizedUri,
189591
+ line: startLine,
189592
+ resultIndex: i,
189593
+ ruleId: result.ruleId
189594
+ };
189595
+ if (isNew) {
189596
+ newResults.push(classified);
189597
+ } else {
189598
+ preExistingResults.push(classified);
189599
+ }
189600
+ }
189601
+ return {
189602
+ granularity,
189603
+ newResults,
189604
+ preExistingResults,
189605
+ summary: {
189606
+ diffFileCount: diffFiles.length,
189607
+ refRange,
189608
+ totalNew: newResults.length,
189609
+ totalPreExisting: preExistingResults.length,
189610
+ totalResults: results.length
189611
+ }
189612
+ };
189613
+ }
189420
189614
 
189421
189615
  // src/lib/session-data-manager.ts
189422
189616
  init_temp_dir();
@@ -190292,8 +190486,8 @@ var MonitoringConfigSchema = external_exports.object({
190292
190486
  enableRecommendations: external_exports.boolean().default(true),
190293
190487
  enableMonitoringTools: external_exports.boolean().default(false),
190294
190488
  // Opt-in: session_* tools disabled by default for end-users
190295
- enableAnnotationTools: external_exports.boolean().default(false)
190296
- // Opt-in: annotation_* and audit_* tools disabled by default
190489
+ enableAnnotationTools: external_exports.boolean().default(true)
190490
+ // Controls auto-caching behaviour in result-processor; tools are always registered
190297
190491
  });
190298
190492
 
190299
190493
  // src/lib/session-data-manager.ts
@@ -190580,7 +190774,7 @@ function parseBoolEnv(envVar, defaultValue) {
190580
190774
  var sessionDataManager = new SessionDataManager({
190581
190775
  storageLocation: process.env.MONITORING_STORAGE_LOCATION || join9(getProjectTmpBase(), ".ql-mcp-tracking"),
190582
190776
  enableMonitoringTools: parseBoolEnv(process.env.ENABLE_MONITORING_TOOLS, false),
190583
- enableAnnotationTools: parseBoolEnv(process.env.ENABLE_ANNOTATION_TOOLS, false)
190777
+ enableAnnotationTools: parseBoolEnv(process.env.ENABLE_ANNOTATION_TOOLS, true)
190584
190778
  });
190585
190779
 
190586
190780
  // src/lib/result-processor.ts
@@ -190910,7 +191104,7 @@ function cacheDatabaseAnalyzeResults(params, logger2) {
190910
191104
  // src/lib/cli-tool-registry.ts
190911
191105
  init_package_paths();
190912
191106
  import { existsSync as existsSync6, mkdirSync as mkdirSync8, realpathSync, rmSync, writeFileSync as writeFileSync4 } from "fs";
190913
- import { delimiter as delimiter5, dirname as dirname5, isAbsolute as isAbsolute4, join as join10, resolve as resolve4 } from "path";
191107
+ import { basename as basename5, delimiter as delimiter5, dirname as dirname5, isAbsolute as isAbsolute4, join as join10, resolve as resolve4 } from "path";
190914
191108
 
190915
191109
  // ../node_modules/js-yaml/dist/js-yaml.mjs
190916
191110
  function isNothing(subject) {
@@ -193814,6 +194008,19 @@ function registerCLITool(server, definition) {
193814
194008
  break;
193815
194009
  }
193816
194010
  case "codeql_query_compile":
194011
+ if (query) {
194012
+ positionalArgs = [...positionalArgs, query];
194013
+ }
194014
+ if (options["dump-dil"] === void 0) {
194015
+ const pending = Array.isArray(options.additionalArgs) ? options.additionalArgs : [];
194016
+ const hasDilOverride = pending.some(
194017
+ (arg) => arg === "--no-dump-dil" || arg === "--dump-dil"
194018
+ );
194019
+ if (!hasDilOverride) {
194020
+ options["dump-dil"] = true;
194021
+ }
194022
+ }
194023
+ break;
193817
194024
  case "codeql_resolve_metadata":
193818
194025
  if (query) {
193819
194026
  positionalArgs = [...positionalArgs, query];
@@ -193863,8 +194070,25 @@ function registerCLITool(server, definition) {
193863
194070
  mkdirSync8(outputDir, { recursive: true });
193864
194071
  }
193865
194072
  }
193866
- const rawAdditionalArgs = Array.isArray(options.additionalArgs) ? options.additionalArgs : [];
194073
+ let effectiveDumpDilEnabled = false;
194074
+ let rawAdditionalArgs = Array.isArray(options.additionalArgs) ? options.additionalArgs : [];
193867
194075
  delete options.additionalArgs;
194076
+ if (name === "codeql_query_compile") {
194077
+ const lastDumpDilFlag = [...rawAdditionalArgs].reverse().find(
194078
+ (arg) => arg === "--dump-dil" || arg === "--no-dump-dil"
194079
+ );
194080
+ if (lastDumpDilFlag === "--dump-dil") {
194081
+ options["dump-dil"] = true;
194082
+ } else if (lastDumpDilFlag === "--no-dump-dil") {
194083
+ options["dump-dil"] = false;
194084
+ }
194085
+ if (lastDumpDilFlag !== void 0) {
194086
+ rawAdditionalArgs = rawAdditionalArgs.filter(
194087
+ (arg) => arg !== "--dump-dil" && arg !== "--no-dump-dil"
194088
+ );
194089
+ }
194090
+ effectiveDumpDilEnabled = options["dump-dil"] !== false;
194091
+ }
193868
194092
  const managedFlagNames = /* @__PURE__ */ new Set([
193869
194093
  "evaluator-log",
193870
194094
  "logdir",
@@ -193958,7 +194182,26 @@ function registerCLITool(server, definition) {
193958
194182
  const resolvedDb = typeof params.database === "string" ? resolveDatabasePath(params.database) : params.database;
193959
194183
  cacheDatabaseAnalyzeResults({ ...params, database: resolvedDb, output: options.output, format: options.format }, logger);
193960
194184
  }
193961
- const processedResult = resultProcessor(result, params);
194185
+ let dilFilePath;
194186
+ if (name === "codeql_query_compile" && result.success && effectiveDumpDilEnabled && result.stdout) {
194187
+ try {
194188
+ const compileLogDir = getOrCreateLogDirectory(customLogDir);
194189
+ logger.info(`Using log directory for ${name}: ${compileLogDir}`);
194190
+ const queryBaseName = query ? basename5(query, ".ql") : "query";
194191
+ dilFilePath = join10(compileLogDir, `${queryBaseName}.dil`);
194192
+ writeFileSync4(dilFilePath, result.stdout, "utf8");
194193
+ logger.info(`Saved DIL output to ${dilFilePath}`);
194194
+ } catch (dilError) {
194195
+ logger.warn(`Failed to save DIL output: ${dilError}`);
194196
+ dilFilePath = void 0;
194197
+ }
194198
+ }
194199
+ let processedResult = resultProcessor(result, params);
194200
+ if (dilFilePath) {
194201
+ processedResult += `
194202
+
194203
+ DIL file: ${dilFilePath}`;
194204
+ }
193962
194205
  return {
193963
194206
  content: [{
193964
194207
  type: "text",
@@ -195230,7 +195473,7 @@ var codeqlPackLsTool = {
195230
195473
 
195231
195474
  // src/tools/codeql/profile-codeql-query-from-logs.ts
195232
195475
  import { existsSync as existsSync11, mkdirSync as mkdirSync9, writeFileSync as writeFileSync5 } from "fs";
195233
- import { basename as basename6, dirname as dirname7, join as join15 } from "path";
195476
+ import { basename as basename7, dirname as dirname7, join as join15 } from "path";
195234
195477
 
195235
195478
  // src/lib/evaluator-log-parser.ts
195236
195479
  init_logger();
@@ -195562,7 +195805,7 @@ function buildDetailFile(profile, topN) {
195562
195805
  lines.push("");
195563
195806
  for (let qIdx = 0; qIdx < profile.queries.length; qIdx++) {
195564
195807
  const query = profile.queries[qIdx];
195565
- const qName = basename6(query.queryName);
195808
+ const qName = basename7(query.queryName);
195566
195809
  lines.push(`== Query: ${qName} ==`);
195567
195810
  lines.push(` Total: ${query.totalDurationMs.toFixed(2)}ms | Predicates evaluated: ${query.predicateCount} | Cache hits: ${query.cacheHits}`);
195568
195811
  lines.push("");
@@ -195721,7 +195964,7 @@ init_cli_executor();
195721
195964
  init_logger();
195722
195965
  import { writeFileSync as writeFileSync6, existsSync as existsSync12 } from "fs";
195723
195966
  import { createReadStream as createReadStream2 } from "fs";
195724
- import { join as join16, dirname as dirname8, basename as basename7 } from "path";
195967
+ import { join as join16, dirname as dirname8, basename as basename8 } from "path";
195725
195968
  import { mkdirSync as mkdirSync10 } from "fs";
195726
195969
  import { createInterface as createInterface2 } from "readline";
195727
195970
  async function parseEvaluatorLog2(logPath) {
@@ -195847,7 +196090,7 @@ function formatAsMermaid(profile) {
195847
196090
  lines.push("```mermaid");
195848
196091
  lines.push("graph TD");
195849
196092
  lines.push("");
195850
- lines.push(` QUERY["${basename7(profile.queryName)}<br/>Total: ${profile.totalDuration.toFixed(2)}ms"]`);
196093
+ lines.push(` QUERY["${basename8(profile.queryName)}<br/>Total: ${profile.totalDuration.toFixed(2)}ms"]`);
195851
196094
  lines.push("");
195852
196095
  profile.pipelines.forEach((pipeline) => {
195853
196096
  const nodeId = `P${pipeline.eventId}`;
@@ -195978,7 +196221,7 @@ function registerProfileCodeQLQueryTool(server) {
195978
196221
  ...outputFiles.map((f) => ` - ${f}`),
195979
196222
  "",
195980
196223
  "Profile Summary:",
195981
- ` - Query: ${basename7(profile.queryName)}`,
196224
+ ` - Query: ${basename8(profile.queryName)}`,
195982
196225
  ` - Total Duration: ${profile.totalDuration.toFixed(2)} ms`,
195983
196226
  ` - Total Pipelines: ${profile.pipelines.length}`,
195984
196227
  ` - Total Events: ${profile.totalEvents}`,
@@ -196015,13 +196258,15 @@ function registerProfileCodeQLQueryTool(server) {
196015
196258
  // src/tools/codeql/query-compile.ts
196016
196259
  var codeqlQueryCompileTool = {
196017
196260
  name: "codeql_query_compile",
196018
- description: "Compile and validate CodeQL queries",
196261
+ description: "Compile and validate CodeQL queries. By default, produces a .dil file containing the optimized DIL intermediate representation alongside the compilation output.",
196019
196262
  command: "codeql",
196020
196263
  subcommand: "query compile",
196021
196264
  inputSchema: {
196022
196265
  query: external_exports.string().describe("Path to the CodeQL query file (.ql)"),
196023
196266
  database: external_exports.string().optional().describe("Path to the CodeQL database"),
196267
+ "dump-dil": external_exports.boolean().optional().describe("Print the optimized DIL intermediate representation to standard output while compiling. Enabled by default; pass false or --no-dump-dil to disable."),
196024
196268
  library: external_exports.string().optional().describe("Path to query library"),
196269
+ logDir: external_exports.string().optional().describe("Custom directory for compilation DIL output (overrides CODEQL_QUERY_LOG_DIR environment variable). If not provided, uses CODEQL_QUERY_LOG_DIR or defaults to .tmp/query-logs/<unique-id>"),
196025
196270
  output: external_exports.string().optional().describe("Output file path"),
196026
196271
  warnings: external_exports.enum(["hide", "show", "error"]).optional().describe("How to handle compilation warnings"),
196027
196272
  verbose: external_exports.boolean().optional().describe("Enable verbose output"),
@@ -196029,6 +196274,7 @@ var codeqlQueryCompileTool = {
196029
196274
  },
196030
196275
  examples: [
196031
196276
  "codeql query compile --database=/path/to/db MyQuery.ql",
196277
+ "codeql query compile --dump-dil --database=/path/to/db MyQuery.ql",
196032
196278
  "codeql query compile --library=/path/to/lib --output=compiled.qlo MyQuery.ql"
196033
196279
  ]
196034
196280
  };
@@ -196677,7 +196923,7 @@ var codeqlResolveTestsTool = {
196677
196923
 
196678
196924
  // src/tools/codeql/search-ql-code.ts
196679
196925
  import { closeSync as closeSync2, createReadStream as createReadStream3, fstatSync as fstatSync2, lstatSync, openSync as openSync2, readdirSync as readdirSync8, readFileSync as readFileSync12, realpathSync as realpathSync2 } from "fs";
196680
- import { basename as basename8, extname as extname2, join as join19, resolve as resolve9 } from "path";
196926
+ import { basename as basename9, extname as extname2, join as join19, resolve as resolve9 } from "path";
196681
196927
  import { createInterface as createInterface3 } from "readline";
196682
196928
 
196683
196929
  // src/lib/scan-exclude.ts
@@ -196725,10 +196971,13 @@ var MAX_FILE_SIZE_BYTES = 5 * 1024 * 1024;
196725
196971
  var MAX_FILES_TRAVERSED = 1e4;
196726
196972
  var MAX_CONTEXT_LINES = 50;
196727
196973
  var MAX_MAX_RESULTS = 1e4;
196728
- var SKIP_DIRS2 = getScanExcludeDirs();
196974
+ function getSkipDirs() {
196975
+ return getScanExcludeDirs();
196976
+ }
196729
196977
  function collectFiles(paths, extensions, fileCount) {
196730
196978
  const files = [];
196731
196979
  const visitedDirs = /* @__PURE__ */ new Set();
196980
+ const skipDirs = getSkipDirs();
196732
196981
  function walk(p) {
196733
196982
  if (fileCount.value >= MAX_FILES_TRAVERSED) return;
196734
196983
  let stat;
@@ -196744,7 +196993,7 @@ function collectFiles(paths, extensions, fileCount) {
196744
196993
  }
196745
196994
  fileCount.value++;
196746
196995
  } else if (stat.isDirectory()) {
196747
- if (SKIP_DIRS2.has(basename8(p))) return;
196996
+ if (skipDirs.has(basename9(p))) return;
196748
196997
  let realPath;
196749
196998
  try {
196750
196999
  realPath = realpathSync2(p);
@@ -197288,7 +197537,7 @@ var server_prompts_default = "# MCP Server Prompts\n\nThis resource provides a c
197288
197537
  var server_queries_default = '# MCP Server Bundled Queries\n\nThis resource describes the tools queries bundled with the CodeQL Development MCP Server. These queries run via `codeql_query_run` and provide structural insight into how source code is represented in a CodeQL database. Use them to understand code structure before writing detection queries.\n\nFor general QL query writing guidance (syntax, metadata, `from`/`where`/`select`, testing conventions), see `codeql://learning/query-basics`.\n\n## Bundled Tools Queries\n\nThe server bundles five tools queries that operate on CodeQL databases:\n\n| Query | Purpose | Output Format |\n| ----------------- | ------------------------------------------------------- | ------------------------- |\n| `PrintAST` | Visualize the Abstract Syntax Tree of source code | `@kind graph` (graphtext) |\n| `PrintCFG` | Visualize the Control Flow Graph of a function | `@kind graph` (graphtext) |\n| `CallGraphFrom` | Show all functions called FROM a given function | `@kind graph` (graphtext) |\n| `CallGraphTo` | Show all call sites that call TO a given function | `@kind graph` (graphtext) |\n| `CallGraphFromTo` | Show calls FROM one function TO another (bidirectional) | `@kind graph` (graphtext) |\n\nAll five queries use `@kind graph` metadata and produce output in graphtext format.\n\n## PrintAST\n\n**Purpose**: Outputs a hierarchical representation of the Abstract Syntax Tree showing parent-child relationships between declarations, statements, and expressions.\n\n**When to use**: Before writing any CodeQL query, run `PrintAST` on your test source code to understand which QL classes represent which source constructs and which predicates are available for matching.\n\n**How to run**:\n\n```text\nTool: codeql_query_run\nParameters:\n queryName: "PrintAST"\n queryLanguage: "<language>"\n database: "<path-to-database>"\n sourceFiles: "<comma-separated-filenames>" (optional \u2014 filter to specific files)\n format: "graphtext"\n interpretedOutput: "<output-directory>"\n```\n\n**Output**: A tree showing each AST node with its QL class name, properties, and position in the hierarchy. This reveals exactly which QL classes and predicates to use in `from`/`where`/`select` clauses.\n\n## PrintCFG\n\n**Purpose**: Produces a Control Flow Graph representation showing the order in which statements and expressions execute, including branching paths.\n\n**When to use**: When writing queries that reason about execution order, reachability, or branching logic (e.g., "is this check always performed before this call?").\n\n**How to run**:\n\n```text\nTool: codeql_query_run\nParameters:\n queryName: "PrintCFG"\n queryLanguage: "<language>"\n database: "<path-to-database>"\n sourceFunction: "<function-name>" (optional \u2014 target a specific function)\n format: "graphtext"\n interpretedOutput: "<output-directory>"\n```\n\n**Output**: Nodes representing CFG basic blocks and edges representing possible execution transitions (successor relationships).\n\n## CallGraphFrom\n\n**Purpose**: Shows all functions called FROM a specified source function \u2014 the outbound call dependencies.\n\n**When to use**: When analyzing what a function does by tracing the functions it invokes. Useful for understanding call chains and identifying potential data flow paths.\n\n**How to run**:\n\n```text\nTool: codeql_query_run\nParameters:\n queryName: "CallGraphFrom"\n queryLanguage: "<language>"\n database: "<path-to-database>"\n sourceFunction: "<function-name>"\n format: "graphtext"\n interpretedOutput: "<output-directory>"\n```\n\n**Output**: A graph showing each call site within the source function and the target function being called.\n\n## CallGraphTo\n\n**Purpose**: Shows all call sites that invoke a specified target function \u2014 the inbound callers.\n\n**When to use**: When performing impact analysis to understand where a function is used, or when identifying all locations that pass data to a particular sink function.\n\n**How to run**:\n\n```text\nTool: codeql_query_run\nParameters:\n queryName: "CallGraphTo"\n queryLanguage: "<language>"\n database: "<path-to-database>"\n targetFunction: "<function-name>"\n format: "graphtext"\n interpretedOutput: "<output-directory>"\n```\n\n**Output**: A graph showing each caller function and the specific call site where the target function is invoked.\n\n## CallGraphFromTo\n\n**Purpose**: Shows the call relationship between two specific functions \u2014 whether function A calls function B (directly or transitively) and what the call path looks like.\n\n**When to use**: When investigating whether a specific source function can reach a specific sink function through the call graph. Useful for validating dataflow hypotheses before writing taint-tracking queries.\n\n**How to run**:\n\n```text\nTool: codeql_query_run\nParameters:\n queryName: "CallGraphFromTo"\n queryLanguage: "<language>"\n database: "<path-to-database>"\n sourceFunction: "<calling-function-name>"\n targetFunction: "<called-function-name>"\n format: "graphtext"\n interpretedOutput: "<output-directory>"\n```\n\n**Output**: A graph showing the call path from the source function to the target function, including intermediate call sites.\n\n## Language Support\n\n| Language | PrintAST | PrintCFG | CallGraphFrom | CallGraphTo | CallGraphFromTo |\n| ---------- | :------: | :------: | :-----------: | :---------: | :-------------: |\n| actions | \u2713 | \u2713 | | | |\n| cpp | \u2713 | \u2713 | \u2713 | \u2713 | \u2713 |\n| csharp | \u2713 | \u2713 | \u2713 | \u2713 | \u2713 |\n| go | \u2713 | \u2713 | \u2713 | \u2713 | \u2713 |\n| java | \u2713 | \u2713 | \u2713 | \u2713 | \u2713 |\n| javascript | \u2713 | \u2713 | \u2713 | \u2713 | \u2713 |\n| python | \u2713 | \u2713 | \u2713 | \u2713 | \u2713 |\n| ruby | \u2713 | \u2713 | \u2713 | \u2713 | \u2713 |\n| rust | \u2713 | \u2713 | \u2713 | \u2713 | \u2713 |\n| swift | \u2713 | \u2713 | \u2713 | \u2713 | \u2713 |\n\nNote: The `actions` language supports PrintAST and PrintCFG only (no call graph queries).\n\n## Recommended Workflow\n\nUse the `tools_query_workflow` prompt for a guided step-by-step workflow:\n\n1. **Identify or create a database**: Use `list_codeql_databases` or `codeql_database_create`\n2. **Run PrintAST**: Understand how the source code maps to QL classes\n3. **Run PrintCFG**: Understand control flow for the functions of interest\n4. **Run CallGraphFrom / CallGraphTo**: Trace call relationships to identify sources and sinks\n5. **Run CallGraphFromTo**: Verify specific source-to-sink call paths\n6. **Write detection queries**: Use the insights from steps 2\u20135 to select the right QL classes and predicates\n\n## Related Resources\n\n- `codeql://learning/query-basics` \u2014 QL query writing reference (syntax, metadata, patterns, testing)\n- `codeql://server/overview` \u2014 MCP server orientation guide\n- `codeql://server/tools` \u2014 Complete tool reference\n- `codeql://learning/test-driven-development` \u2014 TDD workflow for CodeQL queries\n- `codeql://languages/{language}/ast` \u2014 Language-specific AST class reference\n';
197289
197538
 
197290
197539
  // src/resources/server-tools.md
197291
- var server_tools_default = '# MCP Server Tools\n\nThis resource provides a complete reference of the default tools exposed by the CodeQL Development MCP Server. These tools wrap the CodeQL CLI and supporting utilities, enabling an LLM to develop, test, and analyze CodeQL queries programmatically.\n\n## CodeQL CLI Tools\n\n| Tool | Description |\n| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |\n| `codeql_bqrs_decode` | Decode BQRS result files to human-readable formats (text, csv, json). Supports `--result-set` and `--rows` for pagination |\n| `codeql_bqrs_info` | Get metadata about BQRS result files: result sets, column types, row counts |\n| `codeql_bqrs_interpret` | Interpret BQRS result files according to query metadata and generate output in specified formats (CSV, SARIF, graph formats) |\n| `codeql_database_analyze` | Run queries or query suites against CodeQL databases. Produces evaluator logs, BQRS, and SARIF output |\n| `codeql_database_create` | Create a CodeQL database from source code |\n| `codeql_generate_log-summary` | Create a summary of a structured JSON evaluator event log file |\n| `codeql_generate_query-help` | Generate query help documentation from QLDoc comments |\n| `codeql_pack_install` | Install CodeQL pack dependencies |\n| `codeql_pack_ls` | List CodeQL packs under a local directory path |\n| `codeql_query_compile` | Compile and validate CodeQL queries |\n| `codeql_query_format` | Automatically format CodeQL source code files |\n| `codeql_query_run` | Execute a CodeQL query against a database |\n| `codeql_resolve_database` | Resolve database path and validate database structure |\n| `codeql_resolve_files` | Find files in a directory tree, filtered by extension and glob patterns. Useful for discovering QL library files |\n| `codeql_resolve_languages` | List installed CodeQL extractor packs |\n| `codeql_resolve_library-path` | Resolve library path for CodeQL queries and libraries |\n| `codeql_resolve_metadata` | Resolve and return key-value metadata pairs from a CodeQL query source file |\n| `codeql_resolve_qlref` | Resolve `.qlref` files to their corresponding query files |\n| `codeql_resolve_queries` | List available CodeQL queries found on the local filesystem |\n| `codeql_resolve_tests` | Resolve the local filesystem paths of unit tests and/or queries under a base directory |\n| `codeql_test_accept` | Accept new test results as the expected baseline |\n| `codeql_test_extract` | Extract test databases for CodeQL query tests |\n| `codeql_test_run` | Run CodeQL query tests |\n\n## Language Server Protocol (LSP) Tools\n\n| Tool | Description |\n| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `codeql_lsp_completion` | Get code completions at a cursor position in a CodeQL file |\n| `codeql_lsp_definition` | Go to the definition of a CodeQL symbol at a given position |\n| `codeql_lsp_diagnostics` | Syntax and semantic validation of CodeQL code via the Language Server. Note: inline `ql_code` cannot resolve pack imports; use `codeql_query_compile` for files with imports |\n| `codeql_lsp_references` | Find all references to a CodeQL symbol at a given position |\n\n## Query Development Tools\n\n| Tool | Description |\n| -------------------------------- | ------------------------------------------------------------------------------------------------------------ |\n| `create_codeql_query` | Create directory structure and files for a new CodeQL query with tests |\n| `find_class_position` | Find the start/end line and column of a class for quick evaluation |\n| `find_codeql_query_files` | Find and track all files and directories related to a CodeQL query, including resolved metadata |\n| `find_predicate_position` | Find the start/end line and column of a predicate for quick evaluation |\n| `list_codeql_databases` | List CodeQL databases discovered in configured base directories |\n| `list_mrva_run_results` | List MRVA (Multi-Repository Variant Analysis) run results with per-repo details |\n| `list_query_run_results` | List query run result directories with artifact inventory. Filter by `queryName`, `language`, or `queryPath` |\n| `profile_codeql_query` | Profile the performance of a CodeQL query run against a specific database by analyzing the evaluator log |\n| `profile_codeql_query_from_logs` | Parse evaluator logs into a compact profile with line-indexed detail file for targeted read_file access |\n| `quick_evaluate` | Quick evaluate either a class or a predicate in a CodeQL query for debugging |\n| `read_database_source` | Read source file contents from a CodeQL database source archive. Omit `filePath` to list all files |\n| `register_database` | Register a CodeQL database given a local path to the database directory |\n| `search_ql_code` | Search QL source files for text or regex patterns with structured results (replaces grep for QL code) |\n| `validate_codeql_query` | Quick heuristic validation for CodeQL query structure (does not compile the query) |\n\n## SARIF Analysis Tools\n\n| Tool | Description |\n| ------------------------ | ---------------------------------------------------------------------------------------------------- |\n| `sarif_extract_rule` | Extract all data for a specific rule from multi-rule SARIF. Returns a valid SARIF JSON subset |\n| `sarif_list_rules` | List all rules in a SARIF file with result counts, severity, precision, and tags |\n| `sarif_rule_to_markdown` | Convert per-rule SARIF data to markdown with Mermaid dataflow diagrams |\n| `sarif_compare_alerts` | Compare code locations of two SARIF alerts for overlap (sink, source, any-location, full-path modes) |\n| `sarif_diff_runs` | Diff two SARIF files to find added, removed, and changed rules/results across analysis runs |\n\n### `sarif_list_rules` Response Format\n\nReturns a JSON object with per-rule result counts and metadata:\n\n```json\n{\n "totalRules": 3,\n "totalResults": 15,\n "rules": [\n {\n "ruleId": "js/sql-injection",\n "resultCount": 8,\n "name": "Database query built from user-controlled sources",\n "kind": "path-problem",\n "precision": "high",\n "severity": "8.8",\n "tags": ["security", "external/cwe/cwe-089"],\n "tool": "CodeQL",\n "toolVersion": "2.20.4"\n }\n ]\n}\n```\n\n| Field | Type | Description |\n| -------------- | ------ | ------------------------------------------------ |\n| `totalRules` | number | Total number of distinct rules in the SARIF file |\n| `totalResults` | number | Sum of `resultCount` across all rules |\n| `rules[]` | array | Per-rule summaries (see below) |\n\nEach rule object:\n\n| Field | Type | Required | Description |\n| ------------- | -------- | -------- | ---------------------------------------------------------------------------- |\n| `ruleId` | string | yes | Rule identifier (matches the CodeQL query `@id`) |\n| `resultCount` | number | yes | Number of results (findings) for this rule; `0` if defined but not triggered |\n| `name` | string | no | Display name (from `shortDescription.text`, `name`, or `id`) |\n| `kind` | string | no | Query kind (`path-problem`, `problem`, etc.) |\n| `precision` | string | no | Precision level (`high`, `medium`, `low`, `very-high`) |\n| `severity` | string | no | Security severity score (from `security-severity` property) |\n| `tags` | string[] | no | Rule tags (e.g., `security`, `external/cwe/cwe-089`) |\n| `tool` | string | no | Tool driver name (e.g., `CodeQL`) |\n| `toolVersion` | string | no | Tool driver version |\n\n## Common Tool Workflows\n\n### Create and Test a Query\n\n1. `create_codeql_query` \u2014 scaffold files\n2. `codeql_pack_install` \u2014 install dependencies\n3. `codeql_query_compile` \u2014 validate syntax\n4. `codeql_test_run` \u2014 run tests\n5. `codeql_test_accept` \u2014 accept correct results\n\n### Understand Code Structure\n\n1. `codeql_query_run` with `queryName="PrintAST"` \u2014 visualize the AST\n2. `codeql_query_run` with `queryName="PrintCFG"` \u2014 visualize control flow\n3. `codeql_query_run` with `queryName="CallGraphFrom"` / `"CallGraphTo"` \u2014 trace call relationships\n4. `codeql_query_run` with `queryName="CallGraphFromTo"` \u2014 verify source-to-sink call paths\n\n### Profile Query Performance\n\n1. `codeql_query_run` with `evaluationOutput` \u2014 run query and capture evaluator logs\n2. `profile_codeql_query_from_logs` \u2014 analyze evaluator logs: slowest predicates, RA operations, tuple count progressions, dependencies\n\n### Discover and Search QL Code\n\n1. `codeql_resolve_files` \u2014 find QL files by extension and glob patterns in library packs\n2. `search_ql_code` \u2014 search QL source files for classes, predicates, or patterns by text/regex\n3. `codeql_lsp_definition` \u2014 navigate to the definition of a discovered symbol\n4. `codeql_lsp_references` \u2014 find all usages of a symbol across a pack\n\n### Interactive Development\n\n1. `codeql_lsp_completion` \u2014 get QL code completions\n2. `codeql_lsp_definition` \u2014 navigate to definitions\n3. `codeql_lsp_references` \u2014 find all references\n4. `codeql_lsp_diagnostics` \u2014 real-time validation\n\n### Analyze and Compare Results\n\n1. `codeql_database_analyze` \u2014 run query packs and produce SARIF\n2. `sarif_list_rules` \u2014 discover rules and result counts in the SARIF\n3. `query_results_cache_lookup` with `ruleId` \u2014 find cached results by CodeQL query `@id`\n4. `sarif_extract_rule` \u2014 extract results for a specific rule from multi-rule SARIF\n5. `sarif_rule_to_markdown` \u2014 generate markdown report with Mermaid dataflow diagrams\n6. `sarif_compare_alerts` \u2014 compare two alerts for location overlap\n7. `sarif_diff_runs` \u2014 diff two SARIF files to detect behavioral changes across runs\n8. `query_results_cache_compare` with `ruleId` \u2014 compare results across databases\n\n## Tool Input Conventions\n\n- **LSP tools** use **0-based** line and column positions for input. Output uses 1-based `startLine`/`endLine`.\n- **`find_predicate_position`** and **`find_class_position`** return **1-based** positions.\n- **`workspace_uri`** for LSP tools must be a **plain directory path** to the pack root containing `codeql-pack.yml`, not a `file://` URI.\n\n## Related Resources\n\n- `codeql://server/overview` \u2014 MCP server orientation guide\n- `codeql://server/prompts` \u2014 Complete prompt reference\n- `codeql://learning/query-basics` \u2014 Query writing reference\n- `codeql://patterns/performance` \u2014 Performance profiling guide\n';
197540
+ var server_tools_default = '# MCP Server Tools\n\nThis resource provides a complete reference of the default tools exposed by the CodeQL Development MCP Server. These tools wrap the CodeQL CLI and supporting utilities, enabling an LLM to develop, test, and analyze CodeQL queries programmatically.\n\n## CodeQL CLI Tools\n\n| Tool | Description |\n| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |\n| `codeql_bqrs_decode` | Decode BQRS result files to human-readable formats (text, csv, json). Supports `--result-set` and `--rows` for pagination |\n| `codeql_bqrs_info` | Get metadata about BQRS result files: result sets, column types, row counts |\n| `codeql_bqrs_interpret` | Interpret BQRS result files according to query metadata and generate output in specified formats (CSV, SARIF, graph formats) |\n| `codeql_database_analyze` | Run queries or query suites against CodeQL databases. Produces evaluator logs, BQRS, and SARIF output |\n| `codeql_database_create` | Create a CodeQL database from source code |\n| `codeql_generate_log-summary` | Create a summary of a structured JSON evaluator event log file |\n| `codeql_generate_query-help` | Generate query help documentation from QLDoc comments |\n| `codeql_pack_install` | Install CodeQL pack dependencies |\n| `codeql_pack_ls` | List CodeQL packs under a local directory path |\n| `codeql_query_compile` | Compile and validate CodeQL queries |\n| `codeql_query_format` | Automatically format CodeQL source code files |\n| `codeql_query_run` | Execute a CodeQL query against a database |\n| `codeql_resolve_database` | Resolve database path and validate database structure |\n| `codeql_resolve_files` | Find files in a directory tree, filtered by extension and glob patterns. Useful for discovering QL library files |\n| `codeql_resolve_languages` | List installed CodeQL extractor packs |\n| `codeql_resolve_library-path` | Resolve library path for CodeQL queries and libraries |\n| `codeql_resolve_metadata` | Resolve and return key-value metadata pairs from a CodeQL query source file |\n| `codeql_resolve_qlref` | Resolve `.qlref` files to their corresponding query files |\n| `codeql_resolve_queries` | List available CodeQL queries found on the local filesystem |\n| `codeql_resolve_tests` | Resolve the local filesystem paths of unit tests and/or queries under a base directory |\n| `codeql_test_accept` | Accept new test results as the expected baseline |\n| `codeql_test_extract` | Extract test databases for CodeQL query tests |\n| `codeql_test_run` | Run CodeQL query tests |\n\n## Language Server Protocol (LSP) Tools\n\n| Tool | Description |\n| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `codeql_lsp_completion` | Get code completions at a cursor position in a CodeQL file |\n| `codeql_lsp_definition` | Go to the definition of a CodeQL symbol at a given position |\n| `codeql_lsp_diagnostics` | Syntax and semantic validation of CodeQL code via the Language Server. Note: inline `ql_code` cannot resolve pack imports; use `codeql_query_compile` for files with imports |\n| `codeql_lsp_references` | Find all references to a CodeQL symbol at a given position |\n\n## Query Development Tools\n\n| Tool | Description |\n| -------------------------------- | ------------------------------------------------------------------------------------------------------------ |\n| `create_codeql_query` | Create directory structure and files for a new CodeQL query with tests |\n| `find_class_position` | Find the start/end line and column of a class for quick evaluation |\n| `find_codeql_query_files` | Find and track all files and directories related to a CodeQL query, including resolved metadata |\n| `find_predicate_position` | Find the start/end line and column of a predicate for quick evaluation |\n| `list_codeql_databases` | List CodeQL databases discovered in configured base directories |\n| `list_mrva_run_results` | List MRVA (Multi-Repository Variant Analysis) run results with per-repo details |\n| `list_query_run_results` | List query run result directories with artifact inventory. Filter by `queryName`, `language`, or `queryPath` |\n| `profile_codeql_query` | Profile the performance of a CodeQL query run against a specific database by analyzing the evaluator log |\n| `profile_codeql_query_from_logs` | Parse evaluator logs into a compact profile with line-indexed detail file for targeted read_file access |\n| `quick_evaluate` | Quick evaluate either a class or a predicate in a CodeQL query for debugging |\n| `read_database_source` | Read source file contents from a CodeQL database source archive. Omit `filePath` to list all files |\n| `register_database` | Register a CodeQL database given a local path to the database directory |\n| `search_ql_code` | Search QL source files for text or regex patterns with structured results (replaces grep for QL code) |\n| `validate_codeql_query` | Quick heuristic validation for CodeQL query structure (does not compile the query) |\n\n## SARIF Analysis Tools\n\n| Tool | Description |\n| ------------------------- | ---------------------------------------------------------------------------------------------------- |\n| `sarif_compare_alerts` | Compare code locations of two SARIF alerts for overlap (sink, source, any-location, full-path modes) |\n| `sarif_deduplicate_rules` | Find duplicate rules across two SARIF files using fingerprint-first, full-path-fallback overlap |\n| `sarif_diff_by_commits` | Correlate SARIF results with a git diff to classify findings as "new" or "pre-existing" |\n| `sarif_diff_runs` | Diff two SARIF files to find added, removed, and changed rules/results across analysis runs |\n| `sarif_extract_rule` | Extract all data for a specific rule from multi-rule SARIF. Returns a valid SARIF JSON subset |\n| `sarif_list_rules` | List all rules in a SARIF file with result counts, severity, precision, and tags |\n| `sarif_rule_to_markdown` | Convert per-rule SARIF data to markdown with Mermaid dataflow diagrams |\n| `sarif_store` | Cache SARIF content in the session store and return a cache key for use by downstream SARIF tools |\n\n### `sarif_list_rules` Response Format\n\nReturns a JSON object with per-rule result counts and metadata:\n\n```json\n{\n "totalRules": 3,\n "totalResults": 15,\n "rules": [\n {\n "ruleId": "js/sql-injection",\n "resultCount": 8,\n "name": "Database query built from user-controlled sources",\n "kind": "path-problem",\n "precision": "high",\n "severity": "8.8",\n "tags": ["security", "external/cwe/cwe-089"],\n "tool": "CodeQL",\n "toolVersion": "2.20.4"\n }\n ]\n}\n```\n\n| Field | Type | Description |\n| -------------- | ------ | ------------------------------------------------ |\n| `totalRules` | number | Total number of distinct rules in the SARIF file |\n| `totalResults` | number | Sum of `resultCount` across all rules |\n| `rules[]` | array | Per-rule summaries (see below) |\n\nEach rule object:\n\n| Field | Type | Required | Description |\n| ------------- | -------- | -------- | ---------------------------------------------------------------------------- |\n| `ruleId` | string | yes | Rule identifier (matches the CodeQL query `@id`) |\n| `resultCount` | number | yes | Number of results (findings) for this rule; `0` if defined but not triggered |\n| `name` | string | no | Display name (from `shortDescription.text`, `name`, or `id`) |\n| `kind` | string | no | Query kind (`path-problem`, `problem`, etc.) |\n| `precision` | string | no | Precision level (`high`, `medium`, `low`, `very-high`) |\n| `severity` | string | no | Security severity score (from `security-severity` property) |\n| `tags` | string[] | no | Rule tags (e.g., `security`, `external/cwe/cwe-089`) |\n| `tool` | string | no | Tool driver name (e.g., `CodeQL`) |\n| `toolVersion` | string | no | Tool driver version |\n\n## Common Tool Workflows\n\n### Create and Test a Query\n\n1. `create_codeql_query` \u2014 scaffold files\n2. `codeql_pack_install` \u2014 install dependencies\n3. `codeql_query_compile` \u2014 validate syntax\n4. `codeql_test_run` \u2014 run tests\n5. `codeql_test_accept` \u2014 accept correct results\n\n### Understand Code Structure\n\n1. `codeql_query_run` with `queryName="PrintAST"` \u2014 visualize the AST\n2. `codeql_query_run` with `queryName="PrintCFG"` \u2014 visualize control flow\n3. `codeql_query_run` with `queryName="CallGraphFrom"` / `"CallGraphTo"` \u2014 trace call relationships\n4. `codeql_query_run` with `queryName="CallGraphFromTo"` \u2014 verify source-to-sink call paths\n\n### Profile Query Performance\n\n1. `codeql_query_run` with `evaluationOutput` \u2014 run query and capture evaluator logs\n2. `profile_codeql_query_from_logs` \u2014 analyze evaluator logs: slowest predicates, RA operations, tuple count progressions, dependencies\n\n### Discover and Search QL Code\n\n1. `codeql_resolve_files` \u2014 find QL files by extension and glob patterns in library packs\n2. `search_ql_code` \u2014 search QL source files for classes, predicates, or patterns by text/regex\n3. `codeql_lsp_definition` \u2014 navigate to the definition of a discovered symbol\n4. `codeql_lsp_references` \u2014 find all usages of a symbol across a pack\n\n### Interactive Development\n\n1. `codeql_lsp_completion` \u2014 get QL code completions\n2. `codeql_lsp_definition` \u2014 navigate to definitions\n3. `codeql_lsp_references` \u2014 find all references\n4. `codeql_lsp_diagnostics` \u2014 real-time validation\n\n### Analyze and Compare Results\n\n1. `codeql_database_analyze` \u2014 run query packs and produce SARIF\n2. `sarif_list_rules` \u2014 discover rules and result counts in the SARIF\n3. `query_results_cache_lookup` with `ruleId` \u2014 find cached results by CodeQL query `@id`\n4. `sarif_extract_rule` \u2014 extract results for a specific rule from multi-rule SARIF\n5. `sarif_rule_to_markdown` \u2014 generate markdown report with Mermaid dataflow diagrams\n6. `sarif_compare_alerts` \u2014 compare two alerts for location overlap\n7. `sarif_diff_runs` \u2014 diff two SARIF files to detect behavioral changes across runs\n8. `sarif_diff_by_commits` \u2014 correlate SARIF results with git diff to triage new vs pre-existing\n9. `query_results_cache_compare` with `ruleId` \u2014 compare results across databases\n\n## Tool Input Conventions\n\n- **LSP tools** use **0-based** line and column positions for input. Output uses 1-based `startLine`/`endLine`.\n- **`find_predicate_position`** and **`find_class_position`** return **1-based** positions.\n- **`workspace_uri`** for LSP tools must be a **plain directory path** to the pack root containing `codeql-pack.yml`, not a `file://` URI.\n\n## Related Resources\n\n- `codeql://server/overview` \u2014 MCP server orientation guide\n- `codeql://server/prompts` \u2014 Complete prompt reference\n- `codeql://learning/query-basics` \u2014 Query writing reference\n- `codeql://patterns/performance` \u2014 Performance profiling guide\n';
197292
197541
 
197293
197542
  // src/lib/resources.ts
197294
197543
  function getLearningQueryBasics() {
@@ -198145,7 +198394,7 @@ function registerLanguageResources(server) {
198145
198394
 
198146
198395
  // src/prompts/workflow-prompts.ts
198147
198396
  import { access as access2 } from "fs/promises";
198148
- import { basename as basename9, isAbsolute as isAbsolute7, normalize, relative as relative2, resolve as resolve13, sep as sep3 } from "path";
198397
+ import { basename as basename10, isAbsolute as isAbsolute7, normalize, relative as relative3, resolve as resolve13, sep as sep4 } from "path";
198149
198398
  import { fileURLToPath as fileURLToPath3 } from "url";
198150
198399
 
198151
198400
  // src/prompts/constants.ts
@@ -198165,13 +198414,13 @@ var SUPPORTED_LANGUAGES = [
198165
198414
  // src/prompts/prompt-completions.ts
198166
198415
  import { readdir, readFile as readFile4 } from "fs/promises";
198167
198416
  import { homedir as homedir2 } from "os";
198168
- import { dirname as dirname9, join as join22, relative, sep as sep2 } from "path";
198417
+ import { dirname as dirname9, join as join22, relative as relative2, sep as sep3 } from "path";
198169
198418
  init_logger();
198170
198419
  init_package_paths();
198171
198420
  var MAX_FILE_COMPLETIONS = 50;
198172
198421
  var MAX_SCAN_DEPTH = 8;
198173
198422
  var CACHE_TTL_MS = 5e3;
198174
- var SKIP_DIRS3 = getScanExcludeDirs();
198423
+ var SKIP_DIRS2 = getScanExcludeDirs();
198175
198424
  var scanCache = /* @__PURE__ */ new Map();
198176
198425
  function getCachedResults(cacheKey2) {
198177
198426
  const entry = scanCache.get(cacheKey2);
@@ -198199,14 +198448,14 @@ async function findFilesByExtension(dir, baseDir, extensions, maxDepth, results)
198199
198448
  if (results.length >= MAX_FILE_COMPLETIONS) break;
198200
198449
  const fullPath = join22(dir, entry.name);
198201
198450
  if (entry.isDirectory()) {
198202
- if (SKIP_DIRS3.has(entry.name)) {
198451
+ if (SKIP_DIRS2.has(entry.name)) {
198203
198452
  continue;
198204
198453
  }
198205
198454
  await findFilesByExtension(fullPath, baseDir, extensions, maxDepth - 1, results);
198206
198455
  } else if (entry.isFile()) {
198207
198456
  const lower = entry.name.toLowerCase();
198208
198457
  if (extensions.some((ext) => lower.endsWith(ext))) {
198209
- results.push(relative(baseDir, fullPath));
198458
+ results.push(relative2(baseDir, fullPath));
198210
198459
  }
198211
198460
  }
198212
198461
  }
@@ -198290,7 +198539,7 @@ async function completeDatabasePath(value) {
198290
198539
  }
198291
198540
  const lower = (value || "").toLowerCase();
198292
198541
  const filtered = allResults.filter((p) => {
198293
- const lastSeg = p.split(sep2).pop() ?? "";
198542
+ const lastSeg = p.split(sep3).pop() ?? "";
198294
198543
  return p.toLowerCase().includes(lower) || lastSeg.toLowerCase().includes(lower);
198295
198544
  }).sort();
198296
198545
  return filtered.slice(0, MAX_FILE_COMPLETIONS);
@@ -198312,7 +198561,7 @@ async function findDatabaseDirs(dir, _baseDir, maxDepth, results) {
198312
198561
  }
198313
198562
  for (const entry of entries) {
198314
198563
  if (results.length >= MAX_FILE_COMPLETIONS) break;
198315
- if (entry.isDirectory() && !SKIP_DIRS3.has(entry.name)) {
198564
+ if (entry.isDirectory() && !SKIP_DIRS2.has(entry.name)) {
198316
198565
  await findDatabaseDirs(join22(dir, entry.name), _baseDir, maxDepth - 1, results);
198317
198566
  }
198318
198567
  }
@@ -198335,11 +198584,11 @@ async function completePackRoot(value) {
198335
198584
  (e) => e.isFile() && e.name === "codeql-pack.yml"
198336
198585
  );
198337
198586
  if (hasPackYml) {
198338
- results.push(relative(workspace, dir) || ".");
198587
+ results.push(relative2(workspace, dir) || ".");
198339
198588
  }
198340
198589
  for (const entry of entries) {
198341
198590
  if (results.length >= MAX_FILE_COMPLETIONS) break;
198342
- if (entry.isDirectory() && !SKIP_DIRS3.has(entry.name)) {
198591
+ if (entry.isDirectory() && !SKIP_DIRS2.has(entry.name)) {
198343
198592
  await scan(join22(dir, entry.name), depth - 1);
198344
198593
  }
198345
198594
  }
@@ -198580,8 +198829,8 @@ async function resolvePromptFilePath(filePath, workspaceRoot) {
198580
198829
  const inputWasAbsolute = isAbsolute7(normalizedPath);
198581
198830
  const absolutePath = inputWasAbsolute ? normalizedPath : resolve13(effectiveRoot, normalizedPath);
198582
198831
  if (!inputWasAbsolute) {
198583
- const rel = relative2(effectiveRoot, absolutePath);
198584
- if (rel === ".." || rel.startsWith(`..${sep3}`) || isAbsolute7(rel)) {
198832
+ const rel = relative3(effectiveRoot, absolutePath);
198833
+ if (rel === ".." || rel.startsWith(`..${sep4}`) || isAbsolute7(rel)) {
198585
198834
  return {
198586
198835
  blocked: true,
198587
198836
  resolvedPath: "",
@@ -198851,7 +199100,7 @@ ${content}`
198851
199100
  const langResult = await getEffectiveLanguage("workshop_creation_workflow", language, resolvedQueryPath);
198852
199101
  const effectiveLanguage = langResult.language;
198853
199102
  if (langResult.warning) warnings.push(langResult.warning);
198854
- const derivedName = workshopName || basename9(resolvedQueryPath).replace(/\.(ql|qlref)$/, "").toLowerCase().replace(/[^a-z0-9]+/g, "-") || "codeql-workshop";
199103
+ const derivedName = workshopName || basename10(resolvedQueryPath).replace(/\.(ql|qlref)$/, "").toLowerCase().replace(/[^a-z0-9]+/g, "-") || "codeql-workshop";
198855
199104
  const contextSection = buildWorkshopContext(
198856
199105
  resolvedQueryPath,
198857
199106
  effectiveLanguage ?? "unknown",
@@ -200225,13 +200474,6 @@ function generateListRecommendations(sessions) {
200225
200474
  // src/tools/annotation-tools.ts
200226
200475
  init_logger();
200227
200476
  function registerAnnotationTools(server) {
200228
- const config2 = sessionDataManager.getConfig();
200229
- if (!config2.enableAnnotationTools) {
200230
- logger.info(
200231
- "Annotation tools are disabled (opt-in). Set ENABLE_ANNOTATION_TOOLS=true to enable annotation_* tools."
200232
- );
200233
- return;
200234
- }
200235
200477
  registerAnnotationCreateTool(server);
200236
200478
  registerAnnotationGetTool(server);
200237
200479
  registerAnnotationListTool(server);
@@ -200366,13 +200608,6 @@ function registerAnnotationSearchTool(server) {
200366
200608
  init_logger();
200367
200609
  var AUDIT_CATEGORY = "audit-finding";
200368
200610
  function registerAuditTools(server) {
200369
- const config2 = sessionDataManager.getConfig();
200370
- if (!config2.enableAnnotationTools) {
200371
- logger.info(
200372
- "Audit tools are disabled (opt-in). Set ENABLE_ANNOTATION_TOOLS=true to enable audit_* and annotation_* tools."
200373
- );
200374
- return;
200375
- }
200376
200611
  registerAuditStoreFindingsTool(server);
200377
200612
  registerAuditListFindingsTool(server);
200378
200613
  registerAuditAddNotesTool(server);
@@ -200540,13 +200775,6 @@ function registerAuditClearRepoTool(server) {
200540
200775
  // src/tools/cache-tools.ts
200541
200776
  init_logger();
200542
200777
  function registerCacheTools(server) {
200543
- const config2 = sessionDataManager.getConfig();
200544
- if (!config2.enableAnnotationTools) {
200545
- logger.info(
200546
- "Cache tools are disabled (opt-in). Set ENABLE_ANNOTATION_TOOLS=true to enable query_results_cache_* tools."
200547
- );
200548
- return;
200549
- }
200550
200778
  registerQueryResultsCacheLookupTool(server);
200551
200779
  registerQueryResultsCacheRetrieveTool(server);
200552
200780
  registerQueryResultsCacheClearTool(server);
@@ -200736,26 +200964,25 @@ function registerQueryResultsCacheCompareTool(server) {
200736
200964
  import { readFileSync as readFileSync13 } from "fs";
200737
200965
  init_logger();
200738
200966
  function registerSarifTools(server) {
200739
- const config2 = sessionDataManager.getConfig();
200740
- if (!config2.enableAnnotationTools) {
200741
- logger.info(
200742
- "SARIF tools are disabled (opt-in). Set ENABLE_ANNOTATION_TOOLS=true to enable sarif_* tools."
200743
- );
200744
- return;
200745
- }
200967
+ registerSarifCompareAlertsTool(server);
200968
+ registerSarifDeduplicateRulesTool(server);
200969
+ registerSarifDiffByCommitsTool(server);
200970
+ registerSarifDiffRunsTool(server);
200746
200971
  registerSarifExtractRuleTool(server);
200747
200972
  registerSarifListRulesTool(server);
200748
200973
  registerSarifRuleToMarkdownTool(server);
200749
- registerSarifCompareAlertsTool(server);
200750
- registerSarifDiffRunsTool(server);
200974
+ registerSarifStoreTool(server);
200751
200975
  logger.info("Registered SARIF analysis tools");
200752
200976
  }
200753
- function loadSarif(sarifPath, cacheKey2) {
200754
- if (!sarifPath && !cacheKey2) {
200755
- return { error: "Either sarifPath or cacheKey is required." };
200977
+ function loadSarif(opts) {
200978
+ const { cacheKey: cacheKey2, inlineContent, sarifPath } = opts;
200979
+ if (!sarifPath && !cacheKey2 && !inlineContent) {
200980
+ return { error: "No SARIF source provided." };
200756
200981
  }
200757
200982
  let content;
200758
- if (cacheKey2) {
200983
+ if (inlineContent) {
200984
+ content = inlineContent;
200985
+ } else if (cacheKey2) {
200759
200986
  const store = sessionDataManager.getStore();
200760
200987
  const cached2 = store.getCacheContent(cacheKey2);
200761
200988
  if (!cached2) {
@@ -200799,7 +201026,7 @@ function registerSarifExtractRuleTool(server) {
200799
201026
  sarifPath: external_exports.string().optional().describe("Path to the SARIF file.")
200800
201027
  },
200801
201028
  async ({ sarifPath, cacheKey: cacheKey2, ruleId }) => {
200802
- const loaded = loadSarif(sarifPath, cacheKey2);
201029
+ const loaded = loadSarif({ sarifPath, cacheKey: cacheKey2 });
200803
201030
  if (loaded.error) {
200804
201031
  return { content: [{ type: "text", text: loaded.error }] };
200805
201032
  }
@@ -200836,7 +201063,7 @@ function registerSarifListRulesTool(server) {
200836
201063
  sarifPath: external_exports.string().optional().describe("Path to the SARIF file.")
200837
201064
  },
200838
201065
  async ({ sarifPath, cacheKey: cacheKey2 }) => {
200839
- const loaded = loadSarif(sarifPath, cacheKey2);
201066
+ const loaded = loadSarif({ sarifPath, cacheKey: cacheKey2 });
200840
201067
  if (loaded.error) {
200841
201068
  return { content: [{ type: "text", text: loaded.error }] };
200842
201069
  }
@@ -200864,7 +201091,7 @@ function registerSarifRuleToMarkdownTool(server) {
200864
201091
  sarifPath: external_exports.string().optional().describe("Path to the SARIF file.")
200865
201092
  },
200866
201093
  async ({ sarifPath, cacheKey: cacheKey2, ruleId }) => {
200867
- const loaded = loadSarif(sarifPath, cacheKey2);
201094
+ const loaded = loadSarif({ sarifPath, cacheKey: cacheKey2 });
200868
201095
  if (loaded.error) {
200869
201096
  return { content: [{ type: "text", text: loaded.error }] };
200870
201097
  }
@@ -200895,18 +201122,18 @@ function registerSarifCompareAlertsTool(server) {
200895
201122
  });
200896
201123
  server.tool(
200897
201124
  "sarif_compare_alerts",
200898
- "Compare code locations of two SARIF alerts to detect overlap. Supports sink, source, any-location, and full-path comparison modes.",
201125
+ "Compare code locations of two SARIF alerts to detect overlap. Supports sink, source, any-location, full-path, and fingerprint comparison modes.",
200899
201126
  {
200900
201127
  alertA: alertSpecSchema.describe("First alert to compare."),
200901
201128
  alertB: alertSpecSchema.describe("Second alert to compare."),
200902
- overlapMode: external_exports.enum(["sink", "source", "any-location", "full-path"]).optional().default("sink").describe('Comparison mode: "sink" (primary locations), "source" (first dataflow step), "any-location" (all locations), "full-path" (structural path similarity).')
201129
+ overlapMode: external_exports.enum(["sink", "source", "any-location", "full-path", "fingerprint"]).optional().default("sink").describe('Comparison mode: "sink" (primary locations), "source" (first dataflow step), "any-location" (all locations), "full-path" (structural path similarity), "fingerprint" (partialFingerprints match, falls back to full-path).')
200903
201130
  },
200904
201131
  async ({ alertA, alertB, overlapMode }) => {
200905
- const loadedA = loadSarif(alertA.sarifPath, alertA.cacheKey);
201132
+ const loadedA = loadSarif({ sarifPath: alertA.sarifPath, cacheKey: alertA.cacheKey });
200906
201133
  if (loadedA.error) {
200907
201134
  return { content: [{ type: "text", text: `Alert A: ${loadedA.error}` }] };
200908
201135
  }
200909
- const loadedB = loadSarif(alertB.sarifPath, alertB.cacheKey);
201136
+ const loadedB = loadSarif({ sarifPath: alertB.sarifPath, cacheKey: alertB.cacheKey });
200910
201137
  if (loadedB.error) {
200911
201138
  return { content: [{ type: "text", text: `Alert B: ${loadedB.error}` }] };
200912
201139
  }
@@ -200945,6 +201172,12 @@ function registerSarifCompareAlertsTool(server) {
200945
201172
  if (overlap.pathSimilarity !== void 0) {
200946
201173
  response.pathSimilarity = overlap.pathSimilarity;
200947
201174
  }
201175
+ if (overlap.fingerprintMatch !== void 0) {
201176
+ response.fingerprintMatch = overlap.fingerprintMatch;
201177
+ }
201178
+ if (overlap.matchedFingerprints !== void 0) {
201179
+ response.matchedFingerprints = overlap.matchedFingerprints;
201180
+ }
200948
201181
  return {
200949
201182
  content: [{
200950
201183
  type: "text",
@@ -200954,6 +201187,81 @@ function registerSarifCompareAlertsTool(server) {
200954
201187
  }
200955
201188
  );
200956
201189
  }
201190
+ function parseGitDiffOutput(diffOutput) {
201191
+ const files = [];
201192
+ let currentFile = null;
201193
+ for (const line of diffOutput.split(/\r?\n/)) {
201194
+ if (line.startsWith("+++ b/")) {
201195
+ if (currentFile) files.push(currentFile);
201196
+ currentFile = { hunks: [], path: line.substring(6) };
201197
+ continue;
201198
+ }
201199
+ if (currentFile && line.startsWith("@@")) {
201200
+ const match = line.match(/@@ [^ ]+ \+(\d+)(?:,(\d+))? @@/);
201201
+ if (match) {
201202
+ currentFile.hunksParsed = true;
201203
+ const startLine = parseInt(match[1], 10);
201204
+ const lineCount = match[2] !== void 0 ? parseInt(match[2], 10) : 1;
201205
+ if (lineCount > 0) {
201206
+ currentFile.hunks.push({ startLine, lineCount });
201207
+ }
201208
+ }
201209
+ }
201210
+ }
201211
+ if (currentFile) files.push(currentFile);
201212
+ return files;
201213
+ }
201214
+ function registerSarifDiffByCommitsTool(server) {
201215
+ server.tool(
201216
+ "sarif_diff_by_commits",
201217
+ 'Correlate SARIF results with a git diff to classify findings as "new" (introduced in the diff) or "pre-existing". Accepts a SARIF file and a git ref range (e.g. "main..HEAD"). Supports file-level or line-level granularity.',
201218
+ {
201219
+ cacheKey: external_exports.string().optional().describe("Cache key to read SARIF from (alternative to sarifPath)."),
201220
+ granularity: external_exports.enum(["file", "line"]).optional().default("file").describe('Matching granularity: "file" classifies any result in a changed file as new; "line" additionally checks that the result line falls within a changed hunk. Default: "file".'),
201221
+ refRange: external_exports.string().describe('Git ref range for the diff (e.g. "main..HEAD", "abc123..def456"). Passed directly to `git diff`.'),
201222
+ repoPath: external_exports.string().optional().describe("Path to the git repository. Defaults to the current working directory."),
201223
+ sarifPath: external_exports.string().optional().describe("Path to the SARIF file.")
201224
+ },
201225
+ async ({ sarifPath, cacheKey: cacheKey2, refRange, repoPath, granularity }) => {
201226
+ if (/^\s*-/.test(refRange) || /\s/.test(refRange)) {
201227
+ return {
201228
+ content: [{
201229
+ type: "text",
201230
+ text: 'Invalid refRange: must not start with "-" or contain whitespace.'
201231
+ }]
201232
+ };
201233
+ }
201234
+ const loaded = loadSarif({ sarifPath, cacheKey: cacheKey2 });
201235
+ if (loaded.error) {
201236
+ return { content: [{ type: "text", text: loaded.error }] };
201237
+ }
201238
+ const { executeCLICommand: executeCLICommand2 } = await Promise.resolve().then(() => (init_cli_executor(), cli_executor_exports));
201239
+ const gitArgs = ["diff", "--unified=0", "--diff-filter=ACMR", "--no-color", refRange];
201240
+ const gitResult = await executeCLICommand2({
201241
+ args: gitArgs,
201242
+ command: "git",
201243
+ cwd: repoPath
201244
+ });
201245
+ if (!gitResult.success) {
201246
+ return {
201247
+ content: [{
201248
+ type: "text",
201249
+ text: `git diff failed: ${gitResult.error ?? gitResult.stderr}`
201250
+ }]
201251
+ };
201252
+ }
201253
+ const diffFiles = parseGitDiffOutput(gitResult.stdout);
201254
+ const g = granularity;
201255
+ const result = diffSarifByCommits(loaded.sarif, diffFiles, refRange, g);
201256
+ return {
201257
+ content: [{
201258
+ type: "text",
201259
+ text: JSON.stringify(result, null, 2)
201260
+ }]
201261
+ };
201262
+ }
201263
+ );
201264
+ }
200957
201265
  function registerSarifDiffRunsTool(server) {
200958
201266
  server.tool(
200959
201267
  "sarif_diff_runs",
@@ -200967,11 +201275,11 @@ function registerSarifDiffRunsTool(server) {
200967
201275
  sarifPathB: external_exports.string().optional().describe("Path to the second (comparison) SARIF file.")
200968
201276
  },
200969
201277
  async ({ sarifPathA, sarifPathB, cacheKeyA, cacheKeyB, labelA, labelB }) => {
200970
- const loadedA = loadSarif(sarifPathA, cacheKeyA);
201278
+ const loadedA = loadSarif({ sarifPath: sarifPathA, cacheKey: cacheKeyA });
200971
201279
  if (loadedA.error) {
200972
201280
  return { content: [{ type: "text", text: `Run A: ${loadedA.error}` }] };
200973
201281
  }
200974
- const loadedB = loadSarif(sarifPathB, cacheKeyB);
201282
+ const loadedB = loadSarif({ sarifPath: sarifPathB, cacheKey: cacheKeyB });
200975
201283
  if (loadedB.error) {
200976
201284
  return { content: [{ type: "text", text: `Run B: ${loadedB.error}` }] };
200977
201285
  }
@@ -200989,6 +201297,165 @@ function registerSarifDiffRunsTool(server) {
200989
201297
  }
200990
201298
  );
200991
201299
  }
201300
+ function registerSarifStoreTool(server) {
201301
+ server.tool(
201302
+ "sarif_store",
201303
+ "Store SARIF content in the session cache for use by other sarif_* tools. Returns a cache key that can be passed to sarifPath/cacheKey parameters of other tools.",
201304
+ {
201305
+ label: external_exports.string().optional().describe('Human-readable label for this SARIF (e.g. "dubbo-java-2025-03").'),
201306
+ sarifContent: external_exports.string().optional().describe("SARIF JSON content as a string (alternative to sarifPath)."),
201307
+ sarifPath: external_exports.string().optional().describe("Path to a SARIF file on disk.")
201308
+ },
201309
+ async ({ sarifContent, sarifPath, label }) => {
201310
+ if (!sarifContent && !sarifPath) {
201311
+ return { content: [{ type: "text", text: "Either sarifContent or sarifPath is required." }] };
201312
+ }
201313
+ let content;
201314
+ if (sarifPath) {
201315
+ try {
201316
+ content = readFileSync13(sarifPath, "utf8");
201317
+ } catch {
201318
+ return { content: [{ type: "text", text: `Failed to read SARIF file: ${sarifPath}` }] };
201319
+ }
201320
+ } else {
201321
+ content = sarifContent;
201322
+ }
201323
+ const loaded = loadSarif({ inlineContent: content });
201324
+ if (loaded.error) {
201325
+ return { content: [{ type: "text", text: loaded.error }] };
201326
+ }
201327
+ const { createHash: createHash3 } = await import("crypto");
201328
+ const hash = createHash3("sha256").update(content).digest("hex").slice(0, 16);
201329
+ const cacheKey2 = `sarif-store-${hash}`;
201330
+ const sarif = loaded.sarif;
201331
+ const resultCount = sarif.runs[0]?.results?.length ?? 0;
201332
+ const ruleCount = sarif.runs[0]?.tool.driver.rules?.length ?? 0;
201333
+ const toolName = sarif.runs[0]?.tool.driver.name ?? "unknown";
201334
+ const store = sessionDataManager.getStore();
201335
+ store.putCacheEntry({
201336
+ cacheKey: cacheKey2,
201337
+ codeqlVersion: sarif.runs[0]?.tool.driver.version ?? "unknown",
201338
+ databasePath: sarifPath ?? "inline",
201339
+ language: "sarif",
201340
+ outputFormat: "sarif",
201341
+ queryName: "sarif_store",
201342
+ queryPath: sarifPath ?? "inline",
201343
+ resultContent: content,
201344
+ resultCount
201345
+ });
201346
+ return {
201347
+ content: [{
201348
+ type: "text",
201349
+ text: JSON.stringify({
201350
+ cacheKey: cacheKey2,
201351
+ label: label ?? null,
201352
+ resultCount,
201353
+ ruleCount,
201354
+ source: sarifPath ? "file" : "inline",
201355
+ toolName
201356
+ }, null, 2)
201357
+ }]
201358
+ };
201359
+ }
201360
+ );
201361
+ }
201362
+ function registerSarifDeduplicateRulesTool(server) {
201363
+ server.tool(
201364
+ "sarif_deduplicate_rules",
201365
+ "Identify duplicate alerts across two SARIF files by comparing rules pairwise. Uses fingerprint matching first, then full-path location overlap as fallback. Useful for cleanup after query changes or pack upgrades.",
201366
+ {
201367
+ cacheKeyA: external_exports.string().optional().describe("Cache key for the first SARIF."),
201368
+ cacheKeyB: external_exports.string().optional().describe("Cache key for the second SARIF."),
201369
+ overlapThreshold: external_exports.number().min(0).max(1).optional().default(0.8).describe("Minimum overlap score (0-1) to consider a rule pair as duplicates. Default: 0.8."),
201370
+ sarifPathA: external_exports.string().optional().describe("Path to the first SARIF file."),
201371
+ sarifPathB: external_exports.string().optional().describe("Path to the second SARIF file.")
201372
+ },
201373
+ async ({ sarifPathA, sarifPathB, cacheKeyA, cacheKeyB, overlapThreshold }) => {
201374
+ const loadedA = loadSarif({ sarifPath: sarifPathA, cacheKey: cacheKeyA });
201375
+ if (loadedA.error) {
201376
+ return { content: [{ type: "text", text: `SARIF A: ${loadedA.error}` }] };
201377
+ }
201378
+ const loadedB = loadSarif({ sarifPath: sarifPathB, cacheKey: cacheKeyB });
201379
+ if (loadedB.error) {
201380
+ return { content: [{ type: "text", text: `SARIF B: ${loadedB.error}` }] };
201381
+ }
201382
+ const rulesA = listSarifRules(loadedA.sarif);
201383
+ const rulesB = listSarifRules(loadedB.sarif);
201384
+ const duplicateGroups = [];
201385
+ const ruleDataA = /* @__PURE__ */ new Map();
201386
+ for (const rA of rulesA) {
201387
+ if (rA.resultCount === 0) continue;
201388
+ const extracted = extractRuleFromSarif(loadedA.sarif, rA.ruleId);
201389
+ ruleDataA.set(rA.ruleId, {
201390
+ results: extracted.runs[0]?.results ?? [],
201391
+ ruleObj: extracted.runs[0]?.tool.driver.rules?.[0] ?? { id: rA.ruleId }
201392
+ });
201393
+ }
201394
+ const ruleDataB = /* @__PURE__ */ new Map();
201395
+ for (const rB of rulesB) {
201396
+ if (rB.resultCount === 0) continue;
201397
+ const extracted = extractRuleFromSarif(loadedB.sarif, rB.ruleId);
201398
+ ruleDataB.set(rB.ruleId, {
201399
+ results: extracted.runs[0]?.results ?? [],
201400
+ ruleObj: extracted.runs[0]?.tool.driver.rules?.[0] ?? { id: rB.ruleId }
201401
+ });
201402
+ }
201403
+ for (const rA of rulesA) {
201404
+ const dataA = ruleDataA.get(rA.ruleId);
201405
+ if (!dataA) continue;
201406
+ for (const rB of rulesB) {
201407
+ const dataB = ruleDataB.get(rB.ruleId);
201408
+ if (!dataB) continue;
201409
+ const { results: resultsA, ruleObj: ruleObjA } = dataA;
201410
+ const { results: resultsB, ruleObj: ruleObjB } = dataB;
201411
+ const overlaps = findOverlappingAlerts(resultsA, ruleObjA, resultsB, ruleObjB, "full-path");
201412
+ const matchedAIndices = /* @__PURE__ */ new Set();
201413
+ for (let ai = 0; ai < resultsA.length; ai++) {
201414
+ for (const rResultB of resultsB) {
201415
+ const fpResult = computeFingerprintOverlap(resultsA[ai], rResultB);
201416
+ if (fpResult.fingerprintMatch) {
201417
+ matchedAIndices.add(ai);
201418
+ break;
201419
+ }
201420
+ }
201421
+ }
201422
+ const matchedAlerts = Math.max(overlaps.length, matchedAIndices.size);
201423
+ const minResults = Math.min(resultsA.length, resultsB.length);
201424
+ const cappedMatched = Math.min(matchedAlerts, minResults);
201425
+ const totalUnique = resultsA.length + resultsB.length - cappedMatched;
201426
+ const overlapScore = totalUnique > 0 ? cappedMatched / totalUnique : 0;
201427
+ if (overlapScore >= (overlapThreshold ?? 0.8)) {
201428
+ duplicateGroups.push({
201429
+ matchedAlerts: cappedMatched,
201430
+ overlapScore: Math.round(overlapScore * 1e3) / 1e3,
201431
+ ruleIdA: rA.ruleId,
201432
+ ruleIdB: rB.ruleId,
201433
+ totalA: resultsA.length,
201434
+ totalB: resultsB.length,
201435
+ unmatchedA: Math.max(0, resultsA.length - cappedMatched),
201436
+ unmatchedB: Math.max(0, resultsB.length - cappedMatched)
201437
+ });
201438
+ }
201439
+ }
201440
+ }
201441
+ duplicateGroups.sort((a, b) => b.overlapScore - a.overlapScore);
201442
+ return {
201443
+ content: [{
201444
+ type: "text",
201445
+ text: JSON.stringify({
201446
+ duplicateGroups,
201447
+ summary: {
201448
+ duplicatePairsFound: duplicateGroups.length,
201449
+ overlapThreshold: overlapThreshold ?? 0.8,
201450
+ totalRulesA: rulesA.length,
201451
+ totalRulesB: rulesB.length
201452
+ }
201453
+ }, null, 2)
201454
+ }]
201455
+ };
201456
+ }
201457
+ );
201458
+ }
200992
201459
 
200993
201460
  // src/lib/tool-validation.ts
200994
201461
  function formatAllValidationErrors(error2) {
@@ -201057,7 +201524,7 @@ init_package_paths();
201057
201524
  init_logger();
201058
201525
  import_dotenv.default.config({ path: resolve14(packageRootDir, ".env"), quiet: true });
201059
201526
  var PACKAGE_NAME = "codeql-development-mcp-server";
201060
- var VERSION = "2.25.1-next.3";
201527
+ var VERSION = "2.25.2-next.1";
201061
201528
  async function startServer(mode = "stdio") {
201062
201529
  logger.info(`Starting CodeQL Development MCP McpServer v${VERSION} in ${mode} mode`);
201063
201530
  const codeqlBinary = resolveCodeQLBinary();