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.
- package/README.md +1 -1
- package/dist/codeql-development-mcp-server.js +608 -141
- package/dist/codeql-development-mcp-server.js.map +3 -3
- package/package.json +9 -9
- package/ql/actions/tools/src/codeql-pack.yml +1 -1
- package/ql/cpp/tools/src/codeql-pack.yml +1 -1
- package/ql/csharp/tools/src/codeql-pack.yml +1 -1
- package/ql/go/tools/src/codeql-pack.yml +1 -1
- package/ql/java/tools/src/codeql-pack.yml +1 -1
- package/ql/javascript/tools/src/codeql-pack.yml +1 -1
- package/ql/python/tools/src/codeql-pack.yml +1 -1
- package/ql/ruby/tools/src/codeql-pack.yml +1 -1
- package/ql/rust/tools/src/codeql-pack.yml +1 -1
- package/ql/swift/tools/src/codeql-pack.yml +1 -1
|
@@ -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,
|
|
3603
|
+
function resolveComponent(base, relative4, options, skipNormalization) {
|
|
3604
3604
|
const target = {};
|
|
3605
3605
|
if (!skipNormalization) {
|
|
3606
3606
|
base = parse4(serialize(base, options), options);
|
|
3607
|
-
|
|
3607
|
+
relative4 = parse4(serialize(relative4, options), options);
|
|
3608
3608
|
}
|
|
3609
3609
|
options = options || {};
|
|
3610
|
-
if (!options.tolerant &&
|
|
3611
|
-
target.scheme =
|
|
3612
|
-
target.userinfo =
|
|
3613
|
-
target.host =
|
|
3614
|
-
target.port =
|
|
3615
|
-
target.path = removeDotSegments(
|
|
3616
|
-
target.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 (
|
|
3619
|
-
target.userinfo =
|
|
3620
|
-
target.host =
|
|
3621
|
-
target.port =
|
|
3622
|
-
target.path = removeDotSegments(
|
|
3623
|
-
target.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 (!
|
|
3625
|
+
if (!relative4.path) {
|
|
3626
3626
|
target.path = base.path;
|
|
3627
|
-
if (
|
|
3628
|
-
target.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 (
|
|
3634
|
-
target.path = removeDotSegments(
|
|
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 = "/" +
|
|
3637
|
+
target.path = "/" + relative4.path;
|
|
3638
3638
|
} else if (!base.path) {
|
|
3639
|
-
target.path =
|
|
3639
|
+
target.path = relative4.path;
|
|
3640
3640
|
} else {
|
|
3641
|
-
target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) +
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
|
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 &&
|
|
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
|
|
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 =
|
|
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,
|
|
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
|
|
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 =
|
|
38406
|
+
var name = basename11(filename);
|
|
38410
38407
|
var isQuotedString = TEXT_REGEXP.test(name);
|
|
38411
|
-
var fallbackName = typeof fallback !== "string" ? fallback && getlatin1(name) :
|
|
38408
|
+
var fallbackName = typeof fallback !== "string" ? fallback && getlatin1(name) : basename11(fallback);
|
|
38412
38409
|
var hasFallback = typeof fallbackName === "string" && fallbackName !== name;
|
|
38413
|
-
if (hasFallback || !isQuotedString ||
|
|
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
|
-
|
|
38437
|
+
const match = EXT_VALUE_REGEXP.exec(str2);
|
|
38441
38438
|
if (!match) {
|
|
38442
38439
|
throw new TypeError("invalid extended field value");
|
|
38443
38440
|
}
|
|
38444
|
-
|
|
38445
|
-
|
|
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
|
-
|
|
38451
|
-
|
|
38444
|
+
case "iso-8859-1": {
|
|
38445
|
+
const binary2 = decodeHexEscapes(encoded);
|
|
38446
|
+
return getlatin1(binary2);
|
|
38447
|
+
}
|
|
38452
38448
|
case "utf-8":
|
|
38453
|
-
case "utf8":
|
|
38454
|
-
|
|
38455
|
-
|
|
38456
|
-
|
|
38457
|
-
|
|
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
|
-
|
|
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
|
|
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("." +
|
|
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(
|
|
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(
|
|
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] ===
|
|
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
|
|
40387
|
-
shortPaths.push(
|
|
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(`
|
|
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:
|
|
172218
|
-
return join23(pth.isAbsolute(zipPath) ? "/" : ".", normalize2(
|
|
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
|
-
|
|
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(
|
|
190296
|
-
//
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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
|
|
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["${
|
|
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: ${
|
|
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
|
|
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
|
-
|
|
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 (
|
|
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
|
|
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
|
|
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
|
|
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 (
|
|
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(
|
|
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(
|
|
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() && !
|
|
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(
|
|
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() && !
|
|
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 =
|
|
198584
|
-
if (rel === ".." || rel.startsWith(`..${
|
|
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 ||
|
|
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
|
-
|
|
200740
|
-
|
|
200741
|
-
|
|
200742
|
-
|
|
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
|
-
|
|
200750
|
-
registerSarifDiffRunsTool(server);
|
|
200974
|
+
registerSarifStoreTool(server);
|
|
200751
200975
|
logger.info("Registered SARIF analysis tools");
|
|
200752
200976
|
}
|
|
200753
|
-
function loadSarif(
|
|
200754
|
-
|
|
200755
|
-
|
|
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 (
|
|
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,
|
|
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.
|
|
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();
|