trace-mcp 1.21.2 → 1.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -137
- package/README.md +9 -1
- package/dist/cli.js +1186 -649
- package/dist/cli.js.map +1 -1
- package/dist/index.js +724 -311
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -10,10 +10,10 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
10
10
|
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
11
11
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
12
12
|
});
|
|
13
|
-
var __glob = (map) => (
|
|
14
|
-
var fn2 = map[
|
|
13
|
+
var __glob = (map) => (path66) => {
|
|
14
|
+
var fn2 = map[path66];
|
|
15
15
|
if (fn2) return fn2();
|
|
16
|
-
throw new Error("Module not found in bundle: " +
|
|
16
|
+
throw new Error("Module not found in bundle: " + path66);
|
|
17
17
|
};
|
|
18
18
|
var __esm = (fn2, res) => function __init() {
|
|
19
19
|
return fn2 && (res = (0, fn2[__getOwnPropNames(fn2)[0]])(fn2 = 0)), res;
|
|
@@ -149,9 +149,9 @@ var require_backend_impl = __commonJS({
|
|
|
149
149
|
if (!backend) {
|
|
150
150
|
throw new Error(`no available backend found. ERR: ${errors.map((e) => `[${e.name}] ${e.err}`).join(", ")}`);
|
|
151
151
|
}
|
|
152
|
-
for (const { name, err:
|
|
152
|
+
for (const { name, err: err14 } of errors) {
|
|
153
153
|
if (backendHints.includes(name)) {
|
|
154
|
-
console.warn(`removing requested execution provider "${name}" from session options because it is not available: ${
|
|
154
|
+
console.warn(`removing requested execution provider "${name}" from session options because it is not available: ${err14}`);
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
157
|
const filteredEps = eps.filter((i) => availableBackendNames.has(typeof i === "string" ? i : i.name));
|
|
@@ -2641,18 +2641,18 @@ var require_filesystem = __commonJS({
|
|
|
2641
2641
|
var LDD_PATH = "/usr/bin/ldd";
|
|
2642
2642
|
var SELF_PATH = "/proc/self/exe";
|
|
2643
2643
|
var MAX_LENGTH = 2048;
|
|
2644
|
-
var
|
|
2645
|
-
const fd = fs56.openSync(
|
|
2644
|
+
var readFileSync10 = (path66) => {
|
|
2645
|
+
const fd = fs56.openSync(path66, "r");
|
|
2646
2646
|
const buffer = Buffer.alloc(MAX_LENGTH);
|
|
2647
2647
|
const bytesRead = fs56.readSync(fd, buffer, 0, MAX_LENGTH, 0);
|
|
2648
2648
|
fs56.close(fd, () => {
|
|
2649
2649
|
});
|
|
2650
2650
|
return buffer.subarray(0, bytesRead);
|
|
2651
2651
|
};
|
|
2652
|
-
var readFile = (
|
|
2653
|
-
fs56.open(
|
|
2654
|
-
if (
|
|
2655
|
-
reject(
|
|
2652
|
+
var readFile = (path66) => new Promise((resolve3, reject) => {
|
|
2653
|
+
fs56.open(path66, "r", (err14, fd) => {
|
|
2654
|
+
if (err14) {
|
|
2655
|
+
reject(err14);
|
|
2656
2656
|
} else {
|
|
2657
2657
|
const buffer = Buffer.alloc(MAX_LENGTH);
|
|
2658
2658
|
fs56.read(fd, buffer, 0, MAX_LENGTH, 0, (_, bytesRead) => {
|
|
@@ -2666,7 +2666,7 @@ var require_filesystem = __commonJS({
|
|
|
2666
2666
|
module.exports = {
|
|
2667
2667
|
LDD_PATH,
|
|
2668
2668
|
SELF_PATH,
|
|
2669
|
-
readFileSync:
|
|
2669
|
+
readFileSync: readFileSync10,
|
|
2670
2670
|
readFile
|
|
2671
2671
|
};
|
|
2672
2672
|
}
|
|
@@ -2715,7 +2715,7 @@ var require_detect_libc = __commonJS({
|
|
|
2715
2715
|
"use strict";
|
|
2716
2716
|
var childProcess = __require("child_process");
|
|
2717
2717
|
var { isLinux, getReport } = require_process();
|
|
2718
|
-
var { LDD_PATH, SELF_PATH, readFile, readFileSync:
|
|
2718
|
+
var { LDD_PATH, SELF_PATH, readFile, readFileSync: readFileSync10 } = require_filesystem();
|
|
2719
2719
|
var { interpreterPath } = require_elf();
|
|
2720
2720
|
var cachedFamilyInterpreter;
|
|
2721
2721
|
var cachedFamilyFilesystem;
|
|
@@ -2725,8 +2725,8 @@ var require_detect_libc = __commonJS({
|
|
|
2725
2725
|
var safeCommand = () => {
|
|
2726
2726
|
if (!commandOut) {
|
|
2727
2727
|
return new Promise((resolve3) => {
|
|
2728
|
-
childProcess.exec(command, (
|
|
2729
|
-
commandOut =
|
|
2728
|
+
childProcess.exec(command, (err14, out) => {
|
|
2729
|
+
commandOut = err14 ? " " : out;
|
|
2730
2730
|
resolve3(commandOut);
|
|
2731
2731
|
});
|
|
2732
2732
|
});
|
|
@@ -2769,11 +2769,11 @@ var require_detect_libc = __commonJS({
|
|
|
2769
2769
|
}
|
|
2770
2770
|
return null;
|
|
2771
2771
|
};
|
|
2772
|
-
var familyFromInterpreterPath = (
|
|
2773
|
-
if (
|
|
2774
|
-
if (
|
|
2772
|
+
var familyFromInterpreterPath = (path66) => {
|
|
2773
|
+
if (path66) {
|
|
2774
|
+
if (path66.includes("/ld-musl-")) {
|
|
2775
2775
|
return MUSL;
|
|
2776
|
-
} else if (
|
|
2776
|
+
} else if (path66.includes("/ld-linux-")) {
|
|
2777
2777
|
return GLIBC;
|
|
2778
2778
|
}
|
|
2779
2779
|
}
|
|
@@ -2807,7 +2807,7 @@ var require_detect_libc = __commonJS({
|
|
|
2807
2807
|
}
|
|
2808
2808
|
cachedFamilyFilesystem = null;
|
|
2809
2809
|
try {
|
|
2810
|
-
const lddContent =
|
|
2810
|
+
const lddContent = readFileSync10(LDD_PATH);
|
|
2811
2811
|
cachedFamilyFilesystem = getFamilyFromLddContent(lddContent);
|
|
2812
2812
|
} catch (e) {
|
|
2813
2813
|
}
|
|
@@ -2820,8 +2820,8 @@ var require_detect_libc = __commonJS({
|
|
|
2820
2820
|
cachedFamilyInterpreter = null;
|
|
2821
2821
|
try {
|
|
2822
2822
|
const selfContent = await readFile(SELF_PATH);
|
|
2823
|
-
const
|
|
2824
|
-
cachedFamilyInterpreter = familyFromInterpreterPath(
|
|
2823
|
+
const path66 = interpreterPath(selfContent);
|
|
2824
|
+
cachedFamilyInterpreter = familyFromInterpreterPath(path66);
|
|
2825
2825
|
} catch (e) {
|
|
2826
2826
|
}
|
|
2827
2827
|
return cachedFamilyInterpreter;
|
|
@@ -2832,9 +2832,9 @@ var require_detect_libc = __commonJS({
|
|
|
2832
2832
|
}
|
|
2833
2833
|
cachedFamilyInterpreter = null;
|
|
2834
2834
|
try {
|
|
2835
|
-
const selfContent =
|
|
2836
|
-
const
|
|
2837
|
-
cachedFamilyInterpreter = familyFromInterpreterPath(
|
|
2835
|
+
const selfContent = readFileSync10(SELF_PATH);
|
|
2836
|
+
const path66 = interpreterPath(selfContent);
|
|
2837
|
+
cachedFamilyInterpreter = familyFromInterpreterPath(path66);
|
|
2838
2838
|
} catch (e) {
|
|
2839
2839
|
}
|
|
2840
2840
|
return cachedFamilyInterpreter;
|
|
@@ -2896,7 +2896,7 @@ var require_detect_libc = __commonJS({
|
|
|
2896
2896
|
}
|
|
2897
2897
|
cachedVersionFilesystem = null;
|
|
2898
2898
|
try {
|
|
2899
|
-
const lddContent =
|
|
2899
|
+
const lddContent = readFileSync10(LDD_PATH);
|
|
2900
2900
|
const versionMatch = lddContent.match(RE_GLIBC_VERSION);
|
|
2901
2901
|
if (versionMatch) {
|
|
2902
2902
|
cachedVersionFilesystem = versionMatch[1];
|
|
@@ -4553,21 +4553,21 @@ var require_sharp = __commonJS({
|
|
|
4553
4553
|
`@img/sharp-${runtimePlatform}/sharp.node`,
|
|
4554
4554
|
"@img/sharp-wasm32/sharp.node"
|
|
4555
4555
|
];
|
|
4556
|
-
var
|
|
4556
|
+
var path66;
|
|
4557
4557
|
var sharp2;
|
|
4558
4558
|
var errors = [];
|
|
4559
|
-
for (
|
|
4559
|
+
for (path66 of paths) {
|
|
4560
4560
|
try {
|
|
4561
|
-
sharp2 = __require(
|
|
4561
|
+
sharp2 = __require(path66);
|
|
4562
4562
|
break;
|
|
4563
|
-
} catch (
|
|
4564
|
-
errors.push(
|
|
4563
|
+
} catch (err14) {
|
|
4564
|
+
errors.push(err14);
|
|
4565
4565
|
}
|
|
4566
4566
|
}
|
|
4567
|
-
if (sharp2 &&
|
|
4568
|
-
const
|
|
4569
|
-
|
|
4570
|
-
errors.push(
|
|
4567
|
+
if (sharp2 && path66.startsWith("@img/sharp-linux-x64") && !sharp2._isUsingX64V2()) {
|
|
4568
|
+
const err14 = new Error("Prebuilt binaries for linux-x64 require v2 microarchitecture");
|
|
4569
|
+
err14.code = "Unsupported CPU";
|
|
4570
|
+
errors.push(err14);
|
|
4571
4571
|
sharp2 = null;
|
|
4572
4572
|
}
|
|
4573
4573
|
if (sharp2) {
|
|
@@ -4575,12 +4575,12 @@ var require_sharp = __commonJS({
|
|
|
4575
4575
|
} else {
|
|
4576
4576
|
const [isLinux, isMacOs, isWindows] = ["linux", "darwin", "win32"].map((os8) => runtimePlatform.startsWith(os8));
|
|
4577
4577
|
const help = [`Could not load the "sharp" module using the ${runtimePlatform} runtime`];
|
|
4578
|
-
errors.forEach((
|
|
4579
|
-
if (
|
|
4580
|
-
help.push(`${
|
|
4578
|
+
errors.forEach((err14) => {
|
|
4579
|
+
if (err14.code !== "MODULE_NOT_FOUND") {
|
|
4580
|
+
help.push(`${err14.code}: ${err14.message}`);
|
|
4581
4581
|
}
|
|
4582
4582
|
});
|
|
4583
|
-
const messages = errors.map((
|
|
4583
|
+
const messages = errors.map((err14) => err14.message).join(" ");
|
|
4584
4584
|
help.push("Possible solutions:");
|
|
4585
4585
|
if (isUnsupportedNodeRuntime()) {
|
|
4586
4586
|
const { found, expected } = isUnsupportedNodeRuntime();
|
|
@@ -4633,7 +4633,7 @@ var require_sharp = __commonJS({
|
|
|
4633
4633
|
" brew update && brew upgrade vips"
|
|
4634
4634
|
);
|
|
4635
4635
|
}
|
|
4636
|
-
if (errors.some((
|
|
4636
|
+
if (errors.some((err14) => err14.code === "ERR_DLOPEN_DISABLED")) {
|
|
4637
4637
|
help.push("- Run Node.js without using the --no-addons flag");
|
|
4638
4638
|
}
|
|
4639
4639
|
if (isWindows && /The specified procedure could not be found/.test(messages)) {
|
|
@@ -5387,18 +5387,18 @@ var require_input = __commonJS({
|
|
|
5387
5387
|
if (this._isStreamInput()) {
|
|
5388
5388
|
this.on("finish", () => {
|
|
5389
5389
|
this._flattenBufferIn();
|
|
5390
|
-
sharp2.metadata(this.options, (
|
|
5391
|
-
if (
|
|
5392
|
-
callback(is2.nativeError(
|
|
5390
|
+
sharp2.metadata(this.options, (err14, metadata2) => {
|
|
5391
|
+
if (err14) {
|
|
5392
|
+
callback(is2.nativeError(err14, stack2));
|
|
5393
5393
|
} else {
|
|
5394
5394
|
callback(null, metadata2);
|
|
5395
5395
|
}
|
|
5396
5396
|
});
|
|
5397
5397
|
});
|
|
5398
5398
|
} else {
|
|
5399
|
-
sharp2.metadata(this.options, (
|
|
5400
|
-
if (
|
|
5401
|
-
callback(is2.nativeError(
|
|
5399
|
+
sharp2.metadata(this.options, (err14, metadata2) => {
|
|
5400
|
+
if (err14) {
|
|
5401
|
+
callback(is2.nativeError(err14, stack2));
|
|
5402
5402
|
} else {
|
|
5403
5403
|
callback(null, metadata2);
|
|
5404
5404
|
}
|
|
@@ -5410,9 +5410,9 @@ var require_input = __commonJS({
|
|
|
5410
5410
|
return new Promise((resolve3, reject) => {
|
|
5411
5411
|
const finished = () => {
|
|
5412
5412
|
this._flattenBufferIn();
|
|
5413
|
-
sharp2.metadata(this.options, (
|
|
5414
|
-
if (
|
|
5415
|
-
reject(is2.nativeError(
|
|
5413
|
+
sharp2.metadata(this.options, (err14, metadata2) => {
|
|
5414
|
+
if (err14) {
|
|
5415
|
+
reject(is2.nativeError(err14, stack2));
|
|
5416
5416
|
} else {
|
|
5417
5417
|
resolve3(metadata2);
|
|
5418
5418
|
}
|
|
@@ -5426,9 +5426,9 @@ var require_input = __commonJS({
|
|
|
5426
5426
|
});
|
|
5427
5427
|
} else {
|
|
5428
5428
|
return new Promise((resolve3, reject) => {
|
|
5429
|
-
sharp2.metadata(this.options, (
|
|
5430
|
-
if (
|
|
5431
|
-
reject(is2.nativeError(
|
|
5429
|
+
sharp2.metadata(this.options, (err14, metadata2) => {
|
|
5430
|
+
if (err14) {
|
|
5431
|
+
reject(is2.nativeError(err14, stack2));
|
|
5432
5432
|
} else {
|
|
5433
5433
|
resolve3(metadata2);
|
|
5434
5434
|
}
|
|
@@ -5443,18 +5443,18 @@ var require_input = __commonJS({
|
|
|
5443
5443
|
if (this._isStreamInput()) {
|
|
5444
5444
|
this.on("finish", () => {
|
|
5445
5445
|
this._flattenBufferIn();
|
|
5446
|
-
sharp2.stats(this.options, (
|
|
5447
|
-
if (
|
|
5448
|
-
callback(is2.nativeError(
|
|
5446
|
+
sharp2.stats(this.options, (err14, stats2) => {
|
|
5447
|
+
if (err14) {
|
|
5448
|
+
callback(is2.nativeError(err14, stack2));
|
|
5449
5449
|
} else {
|
|
5450
5450
|
callback(null, stats2);
|
|
5451
5451
|
}
|
|
5452
5452
|
});
|
|
5453
5453
|
});
|
|
5454
5454
|
} else {
|
|
5455
|
-
sharp2.stats(this.options, (
|
|
5456
|
-
if (
|
|
5457
|
-
callback(is2.nativeError(
|
|
5455
|
+
sharp2.stats(this.options, (err14, stats2) => {
|
|
5456
|
+
if (err14) {
|
|
5457
|
+
callback(is2.nativeError(err14, stack2));
|
|
5458
5458
|
} else {
|
|
5459
5459
|
callback(null, stats2);
|
|
5460
5460
|
}
|
|
@@ -5466,9 +5466,9 @@ var require_input = __commonJS({
|
|
|
5466
5466
|
return new Promise((resolve3, reject) => {
|
|
5467
5467
|
this.on("finish", function() {
|
|
5468
5468
|
this._flattenBufferIn();
|
|
5469
|
-
sharp2.stats(this.options, (
|
|
5470
|
-
if (
|
|
5471
|
-
reject(is2.nativeError(
|
|
5469
|
+
sharp2.stats(this.options, (err14, stats2) => {
|
|
5470
|
+
if (err14) {
|
|
5471
|
+
reject(is2.nativeError(err14, stack2));
|
|
5472
5472
|
} else {
|
|
5473
5473
|
resolve3(stats2);
|
|
5474
5474
|
}
|
|
@@ -5477,9 +5477,9 @@ var require_input = __commonJS({
|
|
|
5477
5477
|
});
|
|
5478
5478
|
} else {
|
|
5479
5479
|
return new Promise((resolve3, reject) => {
|
|
5480
|
-
sharp2.stats(this.options, (
|
|
5481
|
-
if (
|
|
5482
|
-
reject(is2.nativeError(
|
|
5480
|
+
sharp2.stats(this.options, (err14, stats2) => {
|
|
5481
|
+
if (err14) {
|
|
5482
|
+
reject(is2.nativeError(err14, stack2));
|
|
5483
5483
|
} else {
|
|
5484
5484
|
resolve3(stats2);
|
|
5485
5485
|
}
|
|
@@ -7475,15 +7475,15 @@ var require_color = __commonJS({
|
|
|
7475
7475
|
};
|
|
7476
7476
|
}
|
|
7477
7477
|
function wrapConversion(toModel, graph) {
|
|
7478
|
-
const
|
|
7478
|
+
const path66 = [graph[toModel].parent, toModel];
|
|
7479
7479
|
let fn2 = conversions_default[graph[toModel].parent][toModel];
|
|
7480
7480
|
let cur = graph[toModel].parent;
|
|
7481
7481
|
while (graph[cur].parent) {
|
|
7482
|
-
|
|
7482
|
+
path66.unshift(graph[cur].parent);
|
|
7483
7483
|
fn2 = link(conversions_default[graph[cur].parent][cur], fn2);
|
|
7484
7484
|
cur = graph[cur].parent;
|
|
7485
7485
|
}
|
|
7486
|
-
fn2.conversion =
|
|
7486
|
+
fn2.conversion = path66;
|
|
7487
7487
|
return fn2;
|
|
7488
7488
|
}
|
|
7489
7489
|
function route(fromModel) {
|
|
@@ -8100,7 +8100,7 @@ var require_channel = __commonJS({
|
|
|
8100
8100
|
var require_output = __commonJS({
|
|
8101
8101
|
"node_modules/sharp/lib/output.js"(exports, module) {
|
|
8102
8102
|
"use strict";
|
|
8103
|
-
var
|
|
8103
|
+
var path66 = __require("path");
|
|
8104
8104
|
var is2 = require_is();
|
|
8105
8105
|
var sharp2 = require_sharp();
|
|
8106
8106
|
var formats = /* @__PURE__ */ new Map([
|
|
@@ -8128,19 +8128,19 @@ var require_output = __commonJS({
|
|
|
8128
8128
|
var errJp2Save = () => new Error("JP2 output requires libvips with support for OpenJPEG");
|
|
8129
8129
|
var bitdepthFromColourCount = (colours) => 1 << 31 - Math.clz32(Math.ceil(Math.log2(colours)));
|
|
8130
8130
|
function toFile(fileOut, callback) {
|
|
8131
|
-
let
|
|
8131
|
+
let err14;
|
|
8132
8132
|
if (!is2.string(fileOut)) {
|
|
8133
|
-
|
|
8134
|
-
} else if (is2.string(this.options.input.file) &&
|
|
8135
|
-
|
|
8136
|
-
} else if (jp2Regex.test(
|
|
8137
|
-
|
|
8133
|
+
err14 = new Error("Missing output file path");
|
|
8134
|
+
} else if (is2.string(this.options.input.file) && path66.resolve(this.options.input.file) === path66.resolve(fileOut)) {
|
|
8135
|
+
err14 = new Error("Cannot use same file for input and output");
|
|
8136
|
+
} else if (jp2Regex.test(path66.extname(fileOut)) && !this.constructor.format.jp2k.output.file) {
|
|
8137
|
+
err14 = errJp2Save();
|
|
8138
8138
|
}
|
|
8139
|
-
if (
|
|
8139
|
+
if (err14) {
|
|
8140
8140
|
if (is2.fn(callback)) {
|
|
8141
|
-
callback(
|
|
8141
|
+
callback(err14);
|
|
8142
8142
|
} else {
|
|
8143
|
-
return Promise.reject(
|
|
8143
|
+
return Promise.reject(err14);
|
|
8144
8144
|
}
|
|
8145
8145
|
} else {
|
|
8146
8146
|
this.options.fileOut = fileOut;
|
|
@@ -8854,18 +8854,18 @@ var require_output = __commonJS({
|
|
|
8854
8854
|
if (this._isStreamInput()) {
|
|
8855
8855
|
this.on("finish", () => {
|
|
8856
8856
|
this._flattenBufferIn();
|
|
8857
|
-
sharp2.pipeline(this.options, (
|
|
8858
|
-
if (
|
|
8859
|
-
callback(is2.nativeError(
|
|
8857
|
+
sharp2.pipeline(this.options, (err14, data, info) => {
|
|
8858
|
+
if (err14) {
|
|
8859
|
+
callback(is2.nativeError(err14, stack2));
|
|
8860
8860
|
} else {
|
|
8861
8861
|
callback(null, data, info);
|
|
8862
8862
|
}
|
|
8863
8863
|
});
|
|
8864
8864
|
});
|
|
8865
8865
|
} else {
|
|
8866
|
-
sharp2.pipeline(this.options, (
|
|
8867
|
-
if (
|
|
8868
|
-
callback(is2.nativeError(
|
|
8866
|
+
sharp2.pipeline(this.options, (err14, data, info) => {
|
|
8867
|
+
if (err14) {
|
|
8868
|
+
callback(is2.nativeError(err14, stack2));
|
|
8869
8869
|
} else {
|
|
8870
8870
|
callback(null, data, info);
|
|
8871
8871
|
}
|
|
@@ -8876,9 +8876,9 @@ var require_output = __commonJS({
|
|
|
8876
8876
|
if (this._isStreamInput()) {
|
|
8877
8877
|
this.once("finish", () => {
|
|
8878
8878
|
this._flattenBufferIn();
|
|
8879
|
-
sharp2.pipeline(this.options, (
|
|
8880
|
-
if (
|
|
8881
|
-
this.emit("error", is2.nativeError(
|
|
8879
|
+
sharp2.pipeline(this.options, (err14, data, info) => {
|
|
8880
|
+
if (err14) {
|
|
8881
|
+
this.emit("error", is2.nativeError(err14, stack2));
|
|
8882
8882
|
} else {
|
|
8883
8883
|
this.emit("info", info);
|
|
8884
8884
|
this.push(data);
|
|
@@ -8891,9 +8891,9 @@ var require_output = __commonJS({
|
|
|
8891
8891
|
this.emit("finish");
|
|
8892
8892
|
}
|
|
8893
8893
|
} else {
|
|
8894
|
-
sharp2.pipeline(this.options, (
|
|
8895
|
-
if (
|
|
8896
|
-
this.emit("error", is2.nativeError(
|
|
8894
|
+
sharp2.pipeline(this.options, (err14, data, info) => {
|
|
8895
|
+
if (err14) {
|
|
8896
|
+
this.emit("error", is2.nativeError(err14, stack2));
|
|
8897
8897
|
} else {
|
|
8898
8898
|
this.emit("info", info);
|
|
8899
8899
|
this.push(data);
|
|
@@ -8908,9 +8908,9 @@ var require_output = __commonJS({
|
|
|
8908
8908
|
return new Promise((resolve3, reject) => {
|
|
8909
8909
|
this.once("finish", () => {
|
|
8910
8910
|
this._flattenBufferIn();
|
|
8911
|
-
sharp2.pipeline(this.options, (
|
|
8912
|
-
if (
|
|
8913
|
-
reject(is2.nativeError(
|
|
8911
|
+
sharp2.pipeline(this.options, (err14, data, info) => {
|
|
8912
|
+
if (err14) {
|
|
8913
|
+
reject(is2.nativeError(err14, stack2));
|
|
8914
8914
|
} else {
|
|
8915
8915
|
if (this.options.resolveWithObject) {
|
|
8916
8916
|
resolve3({ data, info });
|
|
@@ -8923,9 +8923,9 @@ var require_output = __commonJS({
|
|
|
8923
8923
|
});
|
|
8924
8924
|
} else {
|
|
8925
8925
|
return new Promise((resolve3, reject) => {
|
|
8926
|
-
sharp2.pipeline(this.options, (
|
|
8927
|
-
if (
|
|
8928
|
-
reject(is2.nativeError(
|
|
8926
|
+
sharp2.pipeline(this.options, (err14, data, info) => {
|
|
8927
|
+
if (err14) {
|
|
8928
|
+
reject(is2.nativeError(err14, stack2));
|
|
8929
8929
|
} else {
|
|
8930
8930
|
if (this.options.resolveWithObject) {
|
|
8931
8931
|
resolve3({ data, info });
|
|
@@ -11561,9 +11561,9 @@ function memoizePromise(key, factory) {
|
|
|
11561
11561
|
}
|
|
11562
11562
|
const promise = factory().then(
|
|
11563
11563
|
(value) => value,
|
|
11564
|
-
(
|
|
11564
|
+
(err14) => {
|
|
11565
11565
|
cache.delete(key);
|
|
11566
|
-
return Promise.reject(
|
|
11566
|
+
return Promise.reject(err14);
|
|
11567
11567
|
}
|
|
11568
11568
|
);
|
|
11569
11569
|
cache.put(key, promise);
|
|
@@ -11750,8 +11750,8 @@ async function storeCachedResource(path_or_repo_id, filename, cache2, cacheKey,
|
|
|
11750
11750
|
headers
|
|
11751
11751
|
}
|
|
11752
11752
|
)
|
|
11753
|
-
).catch((
|
|
11754
|
-
logger2.warn(`Unable to add response to browser cache: ${
|
|
11753
|
+
).catch((err14) => {
|
|
11754
|
+
logger2.warn(`Unable to add response to browser cache: ${err14}.`);
|
|
11755
11755
|
});
|
|
11756
11756
|
}
|
|
11757
11757
|
}
|
|
@@ -11934,9 +11934,9 @@ async function getModelFile(path_or_repo_id, filename, fatal = true, options = {
|
|
|
11934
11934
|
INFLIGHT_LOADS.delete(key);
|
|
11935
11935
|
return result;
|
|
11936
11936
|
},
|
|
11937
|
-
(
|
|
11937
|
+
(err14) => {
|
|
11938
11938
|
INFLIGHT_LOADS.delete(key);
|
|
11939
|
-
throw
|
|
11939
|
+
throw err14;
|
|
11940
11940
|
}
|
|
11941
11941
|
);
|
|
11942
11942
|
INFLIGHT_LOADS.set(key, pending);
|
|
@@ -14011,8 +14011,8 @@ async function ensureWasmLoaded() {
|
|
|
14011
14011
|
ONNX_ENV.wasm.wasmBinary = wasmBinary;
|
|
14012
14012
|
wasmBinaryLoaded = true;
|
|
14013
14013
|
}
|
|
14014
|
-
} catch (
|
|
14015
|
-
logger2.warn("Failed to pre-load WASM binary:",
|
|
14014
|
+
} catch (err14) {
|
|
14015
|
+
logger2.warn("Failed to pre-load WASM binary:", err14);
|
|
14016
14016
|
}
|
|
14017
14017
|
})() : Promise.resolve(),
|
|
14018
14018
|
// Load and cache the WASM factory as a blob URL
|
|
@@ -14022,8 +14022,8 @@ async function ensureWasmLoaded() {
|
|
|
14022
14022
|
if (wasmFactoryBlob) {
|
|
14023
14023
|
ONNX_ENV.wasm.wasmPaths.mjs = wasmFactoryBlob;
|
|
14024
14024
|
}
|
|
14025
|
-
} catch (
|
|
14026
|
-
logger2.warn("Failed to pre-load WASM factory:",
|
|
14025
|
+
} catch (err14) {
|
|
14026
|
+
logger2.warn("Failed to pre-load WASM factory:", err14);
|
|
14027
14027
|
}
|
|
14028
14028
|
})() : Promise.resolve()
|
|
14029
14029
|
]);
|
|
@@ -21166,14 +21166,14 @@ var init_transformers_node = __esm({
|
|
|
21166
21166
|
try {
|
|
21167
21167
|
const evaluated = this.evaluateBlock(node.body, scope);
|
|
21168
21168
|
result += evaluated.value;
|
|
21169
|
-
} catch (
|
|
21170
|
-
if (
|
|
21169
|
+
} catch (err14) {
|
|
21170
|
+
if (err14 instanceof ContinueControl) {
|
|
21171
21171
|
continue;
|
|
21172
21172
|
}
|
|
21173
|
-
if (
|
|
21173
|
+
if (err14 instanceof BreakControl) {
|
|
21174
21174
|
break;
|
|
21175
21175
|
}
|
|
21176
|
-
throw
|
|
21176
|
+
throw err14;
|
|
21177
21177
|
}
|
|
21178
21178
|
noIteration = false;
|
|
21179
21179
|
}
|
|
@@ -21378,7 +21378,7 @@ var init_transformers_node = __esm({
|
|
|
21378
21378
|
start(controller) {
|
|
21379
21379
|
stream.on("data", (chunk2) => controller.enqueue(chunk2));
|
|
21380
21380
|
stream.on("end", () => controller.close());
|
|
21381
|
-
stream.on("error", (
|
|
21381
|
+
stream.on("error", (err14) => controller.error(err14));
|
|
21382
21382
|
},
|
|
21383
21383
|
cancel() {
|
|
21384
21384
|
stream.destroy();
|
|
@@ -21655,9 +21655,9 @@ var init_transformers_node = __esm({
|
|
|
21655
21655
|
break;
|
|
21656
21656
|
}
|
|
21657
21657
|
await new Promise((resolve3, reject) => {
|
|
21658
|
-
fileStream.write(value, (
|
|
21659
|
-
if (
|
|
21660
|
-
reject(
|
|
21658
|
+
fileStream.write(value, (err14) => {
|
|
21659
|
+
if (err14) {
|
|
21660
|
+
reject(err14);
|
|
21661
21661
|
return;
|
|
21662
21662
|
}
|
|
21663
21663
|
resolve3();
|
|
@@ -21668,7 +21668,7 @@ var init_transformers_node = __esm({
|
|
|
21668
21668
|
progress_callback?.({ progress, loaded, total });
|
|
21669
21669
|
}
|
|
21670
21670
|
await new Promise((resolve3, reject) => {
|
|
21671
|
-
fileStream.close((
|
|
21671
|
+
fileStream.close((err14) => err14 ? reject(err14) : resolve3());
|
|
21672
21672
|
});
|
|
21673
21673
|
await fs3.promises.rename(tmpPath, filePath);
|
|
21674
21674
|
} catch (error) {
|
|
@@ -42998,9 +42998,9 @@ var init_client = __esm({
|
|
|
42998
42998
|
this.proc.stderr.on("data", (chunk2) => {
|
|
42999
42999
|
logger.debug({ lsp: this.command, stderr: chunk2.toString().trim() }, "LSP stderr");
|
|
43000
43000
|
});
|
|
43001
|
-
this.proc.on("error", (
|
|
43002
|
-
logger.warn({ lsp: this.command, error:
|
|
43003
|
-
this.rejectAll(new Error(`LSP process error: ${
|
|
43001
|
+
this.proc.on("error", (err14) => {
|
|
43002
|
+
logger.warn({ lsp: this.command, error: err14.message }, "LSP process error");
|
|
43003
|
+
this.rejectAll(new Error(`LSP process error: ${err14.message}`));
|
|
43004
43004
|
});
|
|
43005
43005
|
this.proc.on("exit", (code, signal) => {
|
|
43006
43006
|
logger.debug({ lsp: this.command, code, signal }, "LSP process exited");
|
|
@@ -46337,8 +46337,8 @@ var SessionJournal = class _SessionJournal {
|
|
|
46337
46337
|
};
|
|
46338
46338
|
this.entries.push(entry);
|
|
46339
46339
|
if (tool === "get_symbol" || tool === "get_outline") {
|
|
46340
|
-
const
|
|
46341
|
-
if (
|
|
46340
|
+
const path66 = params.path ?? params.file_path ?? "";
|
|
46341
|
+
if (path66) this.filesRead.add(path66);
|
|
46342
46342
|
}
|
|
46343
46343
|
if (resultCount === 0 && this.isSearchTool(tool)) {
|
|
46344
46344
|
this.zeroResultQueries.set(hash, summary);
|
|
@@ -47490,6 +47490,7 @@ var COMPACT_CORE_PARAMS = {
|
|
|
47490
47490
|
scan_security: ["file_pattern", "rules"],
|
|
47491
47491
|
check_quality_gates: ["scope"],
|
|
47492
47492
|
taint_analysis: ["source_symbol_id", "file_pattern"],
|
|
47493
|
+
export_security_context: ["scope", "depth"],
|
|
47493
47494
|
audit_config: [],
|
|
47494
47495
|
// Framework
|
|
47495
47496
|
get_request_flow: ["route", "method"],
|
|
@@ -47515,6 +47516,86 @@ var COMPACT_CORE_PARAMS = {
|
|
|
47515
47516
|
batch: ["calls"]
|
|
47516
47517
|
};
|
|
47517
47518
|
|
|
47519
|
+
// src/server/tool-annotations.ts
|
|
47520
|
+
var READ_ONLY = {
|
|
47521
|
+
readOnlyHint: true,
|
|
47522
|
+
destructiveHint: false,
|
|
47523
|
+
idempotentHint: true,
|
|
47524
|
+
openWorldHint: false
|
|
47525
|
+
};
|
|
47526
|
+
var INDEX_MUTATING = {
|
|
47527
|
+
readOnlyHint: false,
|
|
47528
|
+
destructiveHint: false,
|
|
47529
|
+
idempotentHint: true,
|
|
47530
|
+
openWorldHint: false
|
|
47531
|
+
};
|
|
47532
|
+
var FILE_WRITING = {
|
|
47533
|
+
readOnlyHint: false,
|
|
47534
|
+
destructiveHint: false,
|
|
47535
|
+
idempotentHint: false,
|
|
47536
|
+
openWorldHint: false
|
|
47537
|
+
};
|
|
47538
|
+
var FILE_DESTRUCTIVE = {
|
|
47539
|
+
readOnlyHint: false,
|
|
47540
|
+
destructiveHint: true,
|
|
47541
|
+
idempotentHint: false,
|
|
47542
|
+
openWorldHint: false
|
|
47543
|
+
};
|
|
47544
|
+
var OUTPUT_WRITING = {
|
|
47545
|
+
readOnlyHint: false,
|
|
47546
|
+
destructiveHint: false,
|
|
47547
|
+
idempotentHint: true,
|
|
47548
|
+
openWorldHint: false
|
|
47549
|
+
};
|
|
47550
|
+
var RUNTIME_READ = {
|
|
47551
|
+
readOnlyHint: true,
|
|
47552
|
+
destructiveHint: false,
|
|
47553
|
+
idempotentHint: true,
|
|
47554
|
+
openWorldHint: true
|
|
47555
|
+
};
|
|
47556
|
+
var OVERRIDES = {
|
|
47557
|
+
// ── Refactoring: file-destructive ──
|
|
47558
|
+
apply_codemod: FILE_DESTRUCTIVE,
|
|
47559
|
+
remove_dead_code: FILE_DESTRUCTIVE,
|
|
47560
|
+
// ── Refactoring: file-writing (non-destructive) ──
|
|
47561
|
+
apply_rename: FILE_WRITING,
|
|
47562
|
+
apply_move: FILE_WRITING,
|
|
47563
|
+
change_signature: FILE_WRITING,
|
|
47564
|
+
extract_function: FILE_WRITING,
|
|
47565
|
+
// ── Output generation (writes files but doesn't modify source) ──
|
|
47566
|
+
generate_docs: OUTPUT_WRITING,
|
|
47567
|
+
generate_sbom: OUTPUT_WRITING,
|
|
47568
|
+
visualize_graph: OUTPUT_WRITING,
|
|
47569
|
+
visualize_subproject_topology: OUTPUT_WRITING,
|
|
47570
|
+
// ── Index / store mutation (idempotent) ──
|
|
47571
|
+
reindex: INDEX_MUTATING,
|
|
47572
|
+
register_edit: INDEX_MUTATING,
|
|
47573
|
+
embed_repo: INDEX_MUTATING,
|
|
47574
|
+
subproject_add_repo: INDEX_MUTATING,
|
|
47575
|
+
subproject_sync: INDEX_MUTATING,
|
|
47576
|
+
invalidate_decision: INDEX_MUTATING,
|
|
47577
|
+
index_sessions: INDEX_MUTATING,
|
|
47578
|
+
mine_sessions: INDEX_MUTATING,
|
|
47579
|
+
refresh_co_changes: INDEX_MUTATING,
|
|
47580
|
+
detect_communities: INDEX_MUTATING,
|
|
47581
|
+
// ── Store mutation (not idempotent — creates new records) ──
|
|
47582
|
+
add_decision: {
|
|
47583
|
+
readOnlyHint: false,
|
|
47584
|
+
destructiveHint: false,
|
|
47585
|
+
idempotentHint: false,
|
|
47586
|
+
openWorldHint: false
|
|
47587
|
+
},
|
|
47588
|
+
// ── Runtime intelligence (reads external OTLP data) ──
|
|
47589
|
+
get_runtime_profile: RUNTIME_READ,
|
|
47590
|
+
get_runtime_call_graph: RUNTIME_READ,
|
|
47591
|
+
get_endpoint_analytics: RUNTIME_READ,
|
|
47592
|
+
get_runtime_deps: RUNTIME_READ
|
|
47593
|
+
};
|
|
47594
|
+
var DEFAULT_ANNOTATIONS = READ_ONLY;
|
|
47595
|
+
function getToolAnnotations(toolName) {
|
|
47596
|
+
return OVERRIDES[toolName] ?? DEFAULT_ANNOTATIONS;
|
|
47597
|
+
}
|
|
47598
|
+
|
|
47518
47599
|
// src/server/tool-gate.ts
|
|
47519
47600
|
function applyParamOverrides(schema, toolOverrides, sharedOverrides) {
|
|
47520
47601
|
for (const paramName of Object.keys(schema)) {
|
|
@@ -47676,9 +47757,23 @@ function installToolGate(server, config, activePreset, savings, journal, j3, ext
|
|
|
47676
47757
|
return result;
|
|
47677
47758
|
};
|
|
47678
47759
|
}
|
|
47760
|
+
const annotations = getToolAnnotations(name);
|
|
47761
|
+
const lastIdx = args.length - 1;
|
|
47762
|
+
if (typeof args[lastIdx] === "function") {
|
|
47763
|
+
args.splice(lastIdx, 0, annotations);
|
|
47764
|
+
}
|
|
47679
47765
|
return _originalTool(...args);
|
|
47680
47766
|
});
|
|
47681
|
-
|
|
47767
|
+
const annotatedOriginalTool = ((...oArgs) => {
|
|
47768
|
+
const oName = oArgs[0];
|
|
47769
|
+
const ann = getToolAnnotations(oName);
|
|
47770
|
+
const oLastIdx = oArgs.length - 1;
|
|
47771
|
+
if (typeof oArgs[oLastIdx] === "function") {
|
|
47772
|
+
oArgs.splice(oLastIdx, 0, ann);
|
|
47773
|
+
}
|
|
47774
|
+
return _originalTool(...oArgs);
|
|
47775
|
+
});
|
|
47776
|
+
return { _originalTool: annotatedOriginalTool, registeredToolNames, toolHandlers };
|
|
47682
47777
|
}
|
|
47683
47778
|
|
|
47684
47779
|
// src/tools/register/core.ts
|
|
@@ -52474,7 +52569,7 @@ function registerCoreTools(server, ctx) {
|
|
|
52474
52569
|
const { store, registry, config, projectRoot, guardPath, j: j3, jh, journal, vectorStore, embeddingService, progress } = ctx;
|
|
52475
52570
|
server.tool(
|
|
52476
52571
|
"get_index_health",
|
|
52477
|
-
"Get index status, statistics, health information, and pipeline progress (indexing, summarization, embedding)",
|
|
52572
|
+
"Get index status, statistics, health information, and pipeline progress (indexing, summarization, embedding). Read-only, no side effects. Use to verify the index is ready before running queries. Returns JSON: { totalFiles, totalSymbols, languages, frameworks, pipelineProgress }.",
|
|
52478
52573
|
{},
|
|
52479
52574
|
async () => {
|
|
52480
52575
|
const result = getIndexHealth(store, config);
|
|
@@ -52486,7 +52581,7 @@ function registerCoreTools(server, ctx) {
|
|
|
52486
52581
|
);
|
|
52487
52582
|
server.tool(
|
|
52488
52583
|
"reindex",
|
|
52489
|
-
"Trigger (re)indexing of the project or a subdirectory",
|
|
52584
|
+
"Trigger (re)indexing of the project or a subdirectory. Mutates the local index (SQLite). Use after major file changes; for single-file updates prefer register_edit instead. Idempotent \u2014 safe to re-run. Returns JSON: { status, totalFiles, indexed, skipped, errors, durationMs }.",
|
|
52490
52585
|
{
|
|
52491
52586
|
path: z2.string().max(512).optional().describe("Subdirectory to index (default: project root)"),
|
|
52492
52587
|
force: z2.boolean().optional().describe("Skip hash check and reindex all files")
|
|
@@ -52504,7 +52599,7 @@ function registerCoreTools(server, ctx) {
|
|
|
52504
52599
|
);
|
|
52505
52600
|
server.tool(
|
|
52506
52601
|
"embed_repo",
|
|
52507
|
-
"Precompute and cache symbol embeddings for semantic / hybrid search. Embeddings are also computed lazily on first semantic query, but calling this once after a fresh index avoids the first-query latency spike. Requires AI provider to be enabled in config (ollama/openai). Set force=true to drop and recompute all existing embeddings.",
|
|
52602
|
+
"Precompute and cache symbol embeddings for semantic / hybrid search. Embeddings are also computed lazily on first semantic query, but calling this once after a fresh index avoids the first-query latency spike. Requires AI provider to be enabled in config (ollama/openai). Set force=true to drop and recompute all existing embeddings. Mutates the vector store; idempotent. Use after reindex when you plan to use semantic search. Returns JSON: { status, indexed_this_run, total_embedded, coverage_pct, duration_ms }.",
|
|
52508
52603
|
{
|
|
52509
52604
|
batch_size: z2.number().int().min(1).max(500).optional().describe("Symbols per embedding API batch (default 50)"),
|
|
52510
52605
|
force: z2.boolean().optional().describe("Drop existing embeddings and re-embed everything (default false \u2014 incremental)")
|
|
@@ -52559,7 +52654,7 @@ function registerCoreTools(server, ctx) {
|
|
|
52559
52654
|
);
|
|
52560
52655
|
server.tool(
|
|
52561
52656
|
"register_edit",
|
|
52562
|
-
"Notify trace-mcp that a file was edited. Reindexes the single file and invalidates search caches. Call after Edit/Write to keep index fresh. Also checks for duplicate symbols \u2014 if `_duplication_warnings` appears in the response, you may be recreating existing logic; review the referenced symbols before continuing.",
|
|
52657
|
+
"Notify trace-mcp that a file was edited. Reindexes the single file and invalidates search caches. Call after Edit/Write to keep index fresh \u2014 much lighter than full reindex. Also checks for duplicate symbols \u2014 if `_duplication_warnings` appears in the response, you may be recreating existing logic; review the referenced symbols before continuing. Mutates the index; idempotent. Returns JSON: { status, file, totalFiles, indexed, _duplication_warnings? }.",
|
|
52563
52658
|
{
|
|
52564
52659
|
file_path: z2.string().min(1).max(512).describe("Relative path to the edited file")
|
|
52565
52660
|
},
|
|
@@ -52595,7 +52690,7 @@ function registerCoreTools(server, ctx) {
|
|
|
52595
52690
|
);
|
|
52596
52691
|
server.tool(
|
|
52597
52692
|
"get_project_map",
|
|
52598
|
-
"Get project overview: detected frameworks, languages, file counts, structure. Call with summary_only=true at session start to orient yourself before diving into code.",
|
|
52693
|
+
"Get project overview: detected frameworks, languages, file counts, structure. Read-only, no side effects. Call with summary_only=true at session start to orient yourself before diving into code. Use instead of manual ls/find. Returns JSON: { frameworks, languages, fileCount, symbolCount, structure }.",
|
|
52599
52694
|
{
|
|
52600
52695
|
summary_only: z2.boolean().optional().describe("Return only framework list + counts (default false)")
|
|
52601
52696
|
},
|
|
@@ -52607,7 +52702,7 @@ function registerCoreTools(server, ctx) {
|
|
|
52607
52702
|
);
|
|
52608
52703
|
server.tool(
|
|
52609
52704
|
"get_env_vars",
|
|
52610
|
-
"List environment variable keys from .env files with inferred value types/formats. Never exposes actual values \u2014 only keys, types (string/number/boolean/empty), and formats (url/email/ip/path/uuid/json/base64/csv/dsn/etc). Use to understand project configuration without accessing
|
|
52705
|
+
"List environment variable keys from .env files with inferred value types/formats. Never exposes actual values \u2014 only keys, types (string/number/boolean/empty), and formats (url/email/ip/path/uuid/json/base64/csv/dsn/etc). Read-only, no side effects, safe for secrets. Use to understand project configuration without accessing actual values. Returns JSON grouped by file: { [file]: [{ key, type, format, comment }] }.",
|
|
52611
52706
|
{
|
|
52612
52707
|
pattern: z2.string().max(256).optional().describe('Filter keys by pattern (e.g. "DB_" or "REDIS")'),
|
|
52613
52708
|
file: z2.string().max(512).optional().describe("Filter by specific .env file path")
|
|
@@ -53702,9 +53797,9 @@ function deduplicateByFile(rawDeps) {
|
|
|
53702
53797
|
}
|
|
53703
53798
|
}
|
|
53704
53799
|
const result = [];
|
|
53705
|
-
for (const [
|
|
53800
|
+
for (const [path66, entry] of fileMap) {
|
|
53706
53801
|
const dep = {
|
|
53707
|
-
path:
|
|
53802
|
+
path: path66,
|
|
53708
53803
|
edgeTypes: [...entry.edgeTypes],
|
|
53709
53804
|
depth: entry.depth
|
|
53710
53805
|
};
|
|
@@ -56957,7 +57052,7 @@ function registerNavigationTools(server, ctx) {
|
|
|
56957
57052
|
const { store, projectRoot, guardPath, j: j3, jh, savings, vectorStore, embeddingService, reranker, markExplored, decisionStore } = ctx;
|
|
56958
57053
|
server.tool(
|
|
56959
57054
|
"get_symbol",
|
|
56960
|
-
"Look up a symbol by symbol_id or FQN and return its source code. Use instead of Read when you need one specific function/class/method \u2014 returns only the symbol, not the whole file.",
|
|
57055
|
+
"Look up a symbol by symbol_id or FQN and return its source code. Use instead of Read when you need one specific function/class/method \u2014 returns only the symbol, not the whole file. For multiple symbols at once, prefer get_context_bundle. Read-only. Returns JSON: { symbol_id, name, kind, fqn, signature, file, line_start, line_end, source }.",
|
|
56961
57056
|
{
|
|
56962
57057
|
symbol_id: z3.string().max(512).optional().describe("The symbol_id to look up"),
|
|
56963
57058
|
fqn: z3.string().max(512).optional().describe("The fully qualified name to look up"),
|
|
@@ -56992,7 +57087,7 @@ function registerNavigationTools(server, ctx) {
|
|
|
56992
57087
|
);
|
|
56993
57088
|
server.tool(
|
|
56994
57089
|
"search",
|
|
56995
|
-
'Search symbols by name, kind, or text. Use instead of Grep when looking for functions, classes, methods, or variables in source code. Supports kind/language/file_pattern filters. Set fuzzy=true for typo-tolerant search (trigram + Levenshtein). For natural-language / conceptual queries set semantic="on" (requires an AI provider configured + embed_repo run once). Set fusion=true for Signal Fusion \u2014 multi-channel ranking (BM25 + PageRank + embeddings + identity match) via Weighted Reciprocal Rank fusion.',
|
|
57090
|
+
'Search symbols by name, kind, or text. Use instead of Grep when looking for functions, classes, methods, or variables in source code. For raw text/string/comment search use search_text instead. For finding who references a known symbol use find_usages instead. Supports kind/language/file_pattern filters. Set fuzzy=true for typo-tolerant search (trigram + Levenshtein). For natural-language / conceptual queries set semantic="on" (requires an AI provider configured + embed_repo run once). Set fusion=true for Signal Fusion \u2014 multi-channel ranking (BM25 + PageRank + embeddings + identity match) via Weighted Reciprocal Rank fusion. Read-only. Returns JSON: { items: [{ symbol_id, name, kind, fqn, signature, file, line, score }], total, search_mode }.',
|
|
56996
57091
|
{
|
|
56997
57092
|
query: z3.string().min(1).max(500).describe("Search query"),
|
|
56998
57093
|
kind: z3.string().max(64).optional().describe("Filter by symbol kind (class, method, function, etc.)"),
|
|
@@ -57107,7 +57202,7 @@ function registerNavigationTools(server, ctx) {
|
|
|
57107
57202
|
);
|
|
57108
57203
|
server.tool(
|
|
57109
57204
|
"get_outline",
|
|
57110
|
-
"Get all symbols for a file (signatures only, no bodies). Use instead of Read to understand a file before editing \u2014 much cheaper in tokens.",
|
|
57205
|
+
"Get all symbols for a file (signatures only, no bodies). Use instead of Read to understand a file before editing \u2014 much cheaper in tokens. For reading one symbol's source, follow up with get_symbol. Read-only. Returns JSON: { path, language, symbols: [{ symbolId, name, kind, signature, lineStart, lineEnd }] }.",
|
|
57111
57206
|
{
|
|
57112
57207
|
path: z3.string().max(512).describe("Relative file path")
|
|
57113
57208
|
},
|
|
@@ -57133,7 +57228,7 @@ function registerNavigationTools(server, ctx) {
|
|
|
57133
57228
|
);
|
|
57134
57229
|
server.tool(
|
|
57135
57230
|
"get_change_impact",
|
|
57136
|
-
"Full change impact report: risk score + mitigations, breaking change detection, enriched dependents (complexity, coverage, exports), module groups, affected tests, co-change hidden couplings. Supports diff-aware mode via symbol_ids to scope analysis to only changed symbols.",
|
|
57231
|
+
"Full change impact report: risk score + mitigations, breaking change detection, enriched dependents (complexity, coverage, exports), module groups, affected tests, co-change hidden couplings. Supports diff-aware mode via symbol_ids to scope analysis to only changed symbols. Use before modifying code to understand blast radius. For quick risk assessment without full report, use assess_change_risk instead. Read-only. Returns JSON: { risk, dependents, affectedTests, breakingChanges, totalAffected }.",
|
|
57137
57232
|
{
|
|
57138
57233
|
file_path: z3.string().max(512).optional().describe("Relative file path to analyze"),
|
|
57139
57234
|
symbol_id: z3.string().max(512).optional().describe("Symbol ID to analyze"),
|
|
@@ -57176,7 +57271,7 @@ function registerNavigationTools(server, ctx) {
|
|
|
57176
57271
|
);
|
|
57177
57272
|
server.tool(
|
|
57178
57273
|
"get_feature_context",
|
|
57179
|
-
"Search code by keyword/topic \u2192 returns ranked source code snippets within a token budget. Use when you need to READ actual code for a concept or feature.",
|
|
57274
|
+
"Search code by keyword/topic \u2192 returns ranked source code snippets within a token budget. Use when you need to READ actual code for a concept or feature. For structured task context with tests and entry points, use get_task_context instead. For symbol metadata without source, use search. Read-only. Returns JSON: { items: [{ symbol_id, name, file, source, score }], token_usage }.",
|
|
57180
57275
|
{
|
|
57181
57276
|
description: z3.string().min(1).max(2e3).describe("Natural language description of the feature to find context for"),
|
|
57182
57277
|
token_budget: z3.number().int().min(100).max(1e5).optional().describe("Max tokens for assembled context (default 4000)")
|
|
@@ -57195,7 +57290,7 @@ function registerNavigationTools(server, ctx) {
|
|
|
57195
57290
|
);
|
|
57196
57291
|
server.tool(
|
|
57197
57292
|
"suggest_queries",
|
|
57198
|
-
"Onboarding helper: shows top imported files, most connected symbols (PageRank), language stats, and example tool calls. Call this first when exploring an unfamiliar project.",
|
|
57293
|
+
"Onboarding helper: shows top imported files, most connected symbols (PageRank), language stats, and example tool calls. Call this first when exploring an unfamiliar project. For a structured project map use get_project_map instead. Read-only. Returns JSON: { topFiles, topSymbols, languageStats, exampleQueries }.",
|
|
57199
57294
|
{},
|
|
57200
57295
|
async () => {
|
|
57201
57296
|
const result = suggestQueries(store);
|
|
@@ -57204,7 +57299,7 @@ function registerNavigationTools(server, ctx) {
|
|
|
57204
57299
|
);
|
|
57205
57300
|
server.tool(
|
|
57206
57301
|
"get_related_symbols",
|
|
57207
|
-
"Find symbols related via co-location (same file), shared importers, and name similarity.
|
|
57302
|
+
"Find symbols related via co-location (same file), shared importers, and name similarity. Use when exploring a symbol to discover sibling code. For call-graph relationships use get_call_graph instead; for all usages use find_usages. Read-only. Returns JSON: { related: [{ symbol_id, name, kind, file, relation_type, score }] }.",
|
|
57208
57303
|
{
|
|
57209
57304
|
symbol_id: z3.string().max(512).describe("Symbol ID to find related symbols for"),
|
|
57210
57305
|
max_results: z3.number().int().min(1).max(100).optional().describe("Max results (default 20)")
|
|
@@ -57219,7 +57314,7 @@ function registerNavigationTools(server, ctx) {
|
|
|
57219
57314
|
);
|
|
57220
57315
|
server.tool(
|
|
57221
57316
|
"get_context_bundle",
|
|
57222
|
-
"Get a symbol's source code + its import dependencies + optional callers, packed within a token budget. Supports batch queries with shared-import deduplication.",
|
|
57317
|
+
"Get a symbol's source code + its import dependencies + optional callers, packed within a token budget. Supports batch queries with shared-import deduplication. Use instead of chaining get_symbol calls \u2014 deduplicates shared imports across symbols. For a single symbol without imports, get_symbol is lighter. Read-only. Returns JSON: { primary: [{ symbol_id, file, source }], imports: [{ file, source }], token_usage }.",
|
|
57223
57318
|
{
|
|
57224
57319
|
symbol_id: z3.string().max(512).optional().describe("Single symbol ID"),
|
|
57225
57320
|
symbol_ids: z3.array(z3.string().max(512)).max(20).optional().describe("Batch: multiple symbol IDs"),
|
|
@@ -57250,7 +57345,7 @@ function registerNavigationTools(server, ctx) {
|
|
|
57250
57345
|
);
|
|
57251
57346
|
server.tool(
|
|
57252
57347
|
"get_task_context",
|
|
57253
|
-
"All-in-one context for starting a dev task: execution paths, tests, entry points, adapted by task type. Use as your FIRST call when beginning any new task.",
|
|
57348
|
+
"All-in-one context for starting a dev task: execution paths, tests, entry points, adapted by task type. Use as your FIRST call when beginning any new task \u2014 replaces manual chaining of search \u2192 get_symbol \u2192 Read. For narrower feature-code lookup use get_feature_context instead. Read-only. Returns JSON: { symbols: [{ symbol_id, name, file, source }], tests, entryPoints, taskType, token_usage }.",
|
|
57254
57349
|
{
|
|
57255
57350
|
task: z3.string().min(1).max(2e3).describe("Natural language description of the task"),
|
|
57256
57351
|
token_budget: z3.number().int().min(100).max(1e5).optional().describe("Max tokens (default 8000)"),
|
|
@@ -58913,7 +59008,7 @@ function registerFrameworkTools(server, ctx) {
|
|
|
58913
59008
|
if (has("vue", "nuxt", "inertia")) {
|
|
58914
59009
|
server.tool(
|
|
58915
59010
|
"get_component_tree",
|
|
58916
|
-
"Build a component render tree starting from a given .vue file",
|
|
59011
|
+
"Build a component render tree starting from a given .vue file. Use to visualize parent-child component hierarchy. Read-only. Returns JSON: { root, children: [{ component, props, slots, depth }], totalComponents }.",
|
|
58917
59012
|
{
|
|
58918
59013
|
component_path: z4.string().max(512).describe("Relative path to the root .vue file"),
|
|
58919
59014
|
depth: z4.number().int().min(1).max(20).optional().describe("Max tree depth (default 3)"),
|
|
@@ -58933,7 +59028,7 @@ function registerFrameworkTools(server, ctx) {
|
|
|
58933
59028
|
if (has("express", "nestjs", "laravel", "fastapi", "flask", "drf", "spring", "rails", "fastify", "hono", "trpc")) {
|
|
58934
59029
|
server.tool(
|
|
58935
59030
|
"get_request_flow",
|
|
58936
|
-
"Trace request flow for a URL+method: route \u2192 middleware \u2192 controller \u2192 service (Laravel/Express/NestJS/Fastify/Hono/tRPC/FastAPI/Flask/DRF)",
|
|
59031
|
+
"Trace request flow for a URL+method: route \u2192 middleware \u2192 controller \u2192 service (Laravel/Express/NestJS/Fastify/Hono/tRPC/FastAPI/Flask/DRF). Use to understand how a request is handled end-to-end. For middleware-only analysis use get_middleware_chain instead. Read-only. Returns JSON: { route, steps: [{ type, symbol_id, name, file }] }.",
|
|
58937
59032
|
{
|
|
58938
59033
|
url: z4.string().max(512).describe("Route URL (e.g. /api/users)"),
|
|
58939
59034
|
method: z4.string().max(64).optional().describe("HTTP method (default GET)")
|
|
@@ -58950,7 +59045,7 @@ function registerFrameworkTools(server, ctx) {
|
|
|
58950
59045
|
if (has("express", "nestjs", "fastapi", "flask", "spring")) {
|
|
58951
59046
|
server.tool(
|
|
58952
59047
|
"get_middleware_chain",
|
|
58953
|
-
"Trace middleware chain for a route URL (Express/NestJS/FastAPI/Flask)",
|
|
59048
|
+
"Trace middleware chain for a route URL (Express/NestJS/FastAPI/Flask). Use when you only need the middleware stack, not the full request flow. For full route\u2192controller\u2192service flow use get_request_flow instead. Read-only. Returns JSON: { url, middlewares: [{ name, file, order }] }.",
|
|
58954
59049
|
{
|
|
58955
59050
|
url: z4.string().max(512).describe("Route URL to trace middleware for")
|
|
58956
59051
|
},
|
|
@@ -58966,7 +59061,7 @@ function registerFrameworkTools(server, ctx) {
|
|
|
58966
59061
|
if (has("nestjs")) {
|
|
58967
59062
|
server.tool(
|
|
58968
59063
|
"get_module_graph",
|
|
58969
|
-
"Build NestJS module dependency graph (module -> imports -> controllers -> providers -> exports)",
|
|
59064
|
+
"Build NestJS module dependency graph (module -> imports -> controllers -> providers -> exports). Use to understand NestJS module structure and DI wiring. For provider-level DI tree use get_di_tree instead. Read-only. Returns JSON: { module, imports, controllers, providers, exports, edges }.",
|
|
58970
59065
|
{
|
|
58971
59066
|
module_name: z4.string().max(256).describe("NestJS module class name (e.g. AppModule)")
|
|
58972
59067
|
},
|
|
@@ -58980,7 +59075,7 @@ function registerFrameworkTools(server, ctx) {
|
|
|
58980
59075
|
);
|
|
58981
59076
|
server.tool(
|
|
58982
59077
|
"get_di_tree",
|
|
58983
|
-
"Trace NestJS dependency injection tree (what a service injects + who injects it)",
|
|
59078
|
+
"Trace NestJS dependency injection tree (what a service injects + who injects it). Use to understand DI wiring for a specific provider. For module-level graph use get_module_graph instead. Read-only. Returns JSON: { service, injects: [{ name, kind }], injected_by: [{ name, kind }] }.",
|
|
58984
59079
|
{
|
|
58985
59080
|
service_name: z4.string().max(256).describe("NestJS service/provider class name")
|
|
58986
59081
|
},
|
|
@@ -58996,7 +59091,7 @@ function registerFrameworkTools(server, ctx) {
|
|
|
58996
59091
|
if (has("react-native")) {
|
|
58997
59092
|
server.tool(
|
|
58998
59093
|
"get_navigation_graph",
|
|
58999
|
-
"Build React Native navigation tree from screens, navigators, and deep links",
|
|
59094
|
+
"Build React Native navigation tree from screens, navigators, and deep links. Use to understand app navigation structure. For details on a specific screen use get_screen_context instead. Read-only. Returns JSON: { navigators, screens, deepLinks, edges }.",
|
|
59000
59095
|
{},
|
|
59001
59096
|
async () => {
|
|
59002
59097
|
const result = getNavigationGraph(store);
|
|
@@ -59008,7 +59103,7 @@ function registerFrameworkTools(server, ctx) {
|
|
|
59008
59103
|
);
|
|
59009
59104
|
server.tool(
|
|
59010
59105
|
"get_screen_context",
|
|
59011
|
-
"Get full context for a React Native screen: navigator, navigation edges, deep link, platform variants, native modules",
|
|
59106
|
+
"Get full context for a React Native screen: navigator, navigation edges, deep link, platform variants, native modules. Use to understand a specific screen before modifying it. For the full navigation tree use get_navigation_graph instead. Read-only. Returns JSON: { screen, navigator, deepLink, platformVariants, nativeModules, navigationEdges }.",
|
|
59012
59107
|
{
|
|
59013
59108
|
screen_name: z4.string().max(256).describe("Screen name (e.g. ProfileScreen or Profile)")
|
|
59014
59109
|
},
|
|
@@ -59024,7 +59119,7 @@ function registerFrameworkTools(server, ctx) {
|
|
|
59024
59119
|
if (has("laravel", "mongoose", "sequelize", "prisma", "typeorm", "drizzle", "sqlalchemy")) {
|
|
59025
59120
|
server.tool(
|
|
59026
59121
|
"get_model_context",
|
|
59027
|
-
"Get full model context: relationships, schema, and metadata (Eloquent/Mongoose/Sequelize/SQLAlchemy/Prisma/TypeORM/Drizzle)",
|
|
59122
|
+
"Get full model context: relationships, schema, and metadata (Eloquent/Mongoose/Sequelize/SQLAlchemy/Prisma/TypeORM/Drizzle). Use to understand a specific ORM model. For raw table schema without ORM context use get_schema instead. Read-only. Returns JSON: { model, table, relationships: [{ type, related, foreignKey }], fields, metadata }.",
|
|
59028
59123
|
{
|
|
59029
59124
|
model_name: z4.string().max(256).describe("Model class name (e.g. User, Post)")
|
|
59030
59125
|
},
|
|
@@ -59038,7 +59133,7 @@ function registerFrameworkTools(server, ctx) {
|
|
|
59038
59133
|
);
|
|
59039
59134
|
server.tool(
|
|
59040
59135
|
"get_schema",
|
|
59041
|
-
"Get database schema reconstructed from migrations or ORM model definitions",
|
|
59136
|
+
"Get database schema reconstructed from migrations or ORM model definitions. Use to understand table structure. For ORM-level context with relationships use get_model_context instead. Read-only. Returns JSON: { tables: [{ name, columns: [{ name, type, nullable, default }], indexes }] }.",
|
|
59042
59137
|
{
|
|
59043
59138
|
table_name: z4.string().max(256).optional().describe("Table/collection/model name (omit for all)")
|
|
59044
59139
|
},
|
|
@@ -59054,7 +59149,7 @@ function registerFrameworkTools(server, ctx) {
|
|
|
59054
59149
|
if (has("laravel", "nestjs", "celery", "django", "socketio")) {
|
|
59055
59150
|
server.tool(
|
|
59056
59151
|
"get_event_graph",
|
|
59057
|
-
"Get event/signal/task dispatch graph (Laravel events, Django signals, NestJS events, Celery tasks, Socket.io events)",
|
|
59152
|
+
"Get event/signal/task dispatch graph (Laravel events, Django signals, NestJS events, Celery tasks, Socket.io events). Use to understand event-driven architecture and trace event producers/consumers. Read-only. Returns JSON: { events: [{ name, dispatchers, listeners, file }] }.",
|
|
59058
59153
|
{
|
|
59059
59154
|
event_name: z4.string().max(256).optional().describe("Filter to a specific event class name")
|
|
59060
59155
|
},
|
|
@@ -59069,7 +59164,7 @@ function registerFrameworkTools(server, ctx) {
|
|
|
59069
59164
|
}
|
|
59070
59165
|
server.tool(
|
|
59071
59166
|
"find_usages",
|
|
59072
|
-
"Find all places that reference a symbol or file (imports, calls, renders, dispatches). Use instead of Grep for symbol usages \u2014 understands semantic relationships, not just text matches.",
|
|
59167
|
+
"Find all places that reference a symbol or file (imports, calls, renders, dispatches). Use instead of Grep for symbol usages \u2014 understands semantic relationships, not just text matches. For bidirectional call graph use get_call_graph instead. Read-only. Returns JSON: { references: [{ file, line, kind, context }], total }.",
|
|
59073
59168
|
{
|
|
59074
59169
|
symbol_id: z4.string().max(512).optional().describe("Symbol ID to find references for"),
|
|
59075
59170
|
fqn: z4.string().max(512).optional().describe("Fully qualified name to find references for"),
|
|
@@ -59103,7 +59198,7 @@ function registerFrameworkTools(server, ctx) {
|
|
|
59103
59198
|
);
|
|
59104
59199
|
server.tool(
|
|
59105
59200
|
"get_call_graph",
|
|
59106
|
-
"Build a bidirectional call graph centered on a symbol (who calls it + what it calls). Use to understand control flow through a function.",
|
|
59201
|
+
"Build a bidirectional call graph centered on a symbol (who calls it + what it calls). Use to understand control flow through a function. For flat list of all references use find_usages instead. Read-only. Returns JSON: { root: { symbol_id, name, calls: [...], called_by: [...] } }.",
|
|
59107
59202
|
{
|
|
59108
59203
|
symbol_id: z4.string().max(512).optional().describe("Symbol ID to center the graph on"),
|
|
59109
59204
|
fqn: z4.string().max(512).optional().describe("Fully qualified name to center the graph on"),
|
|
@@ -59136,7 +59231,7 @@ function registerFrameworkTools(server, ctx) {
|
|
|
59136
59231
|
);
|
|
59137
59232
|
server.tool(
|
|
59138
59233
|
"get_tests_for",
|
|
59139
|
-
"Find test files and test functions that cover a given symbol or file. Use instead of Glob/Grep \u2014 understands test-to-source mapping, not just filename conventions.",
|
|
59234
|
+
"Find test files and test functions that cover a given symbol or file. Use instead of Glob/Grep \u2014 understands test-to-source mapping, not just filename conventions. For project-wide test coverage gaps use get_untested_symbols instead. Read-only. Returns JSON: { tests: [{ file, testName, symbol_id }], total }.",
|
|
59140
59235
|
{
|
|
59141
59236
|
symbol_id: z4.string().max(512).optional().describe("Symbol ID to find tests for"),
|
|
59142
59237
|
fqn: z4.string().max(512).optional().describe("Fully qualified name to find tests for"),
|
|
@@ -59171,7 +59266,7 @@ function registerFrameworkTools(server, ctx) {
|
|
|
59171
59266
|
if (has("laravel")) {
|
|
59172
59267
|
server.tool(
|
|
59173
59268
|
"get_livewire_context",
|
|
59174
|
-
"Get full context for a Livewire component: properties, actions, events, view, child components",
|
|
59269
|
+
"Get full context for a Livewire component: properties, actions, events, view, child components. Use to understand a specific Livewire component before modifying it. Read-only. Returns JSON: { component, properties, actions, events, view, children }.",
|
|
59175
59270
|
{
|
|
59176
59271
|
component_name: z4.string().max(256).describe("Livewire component class name or FQN (e.g. UserProfile or App\\Livewire\\UserProfile)")
|
|
59177
59272
|
},
|
|
@@ -59185,7 +59280,7 @@ function registerFrameworkTools(server, ctx) {
|
|
|
59185
59280
|
);
|
|
59186
59281
|
server.tool(
|
|
59187
59282
|
"get_nova_resource",
|
|
59188
|
-
"Get full context for a Laravel Nova resource: model, fields, actions, filters, lenses, metrics",
|
|
59283
|
+
"Get full context for a Laravel Nova resource: model, fields, actions, filters, lenses, metrics. Use to understand a Nova admin resource before modifying it. Read-only. Returns JSON: { resource, model, fields, actions, filters, lenses, metrics }.",
|
|
59189
59284
|
{
|
|
59190
59285
|
resource_name: z4.string().max(256).describe("Nova resource class name or FQN (e.g. User or App\\Nova\\User)")
|
|
59191
59286
|
},
|
|
@@ -59201,7 +59296,7 @@ function registerFrameworkTools(server, ctx) {
|
|
|
59201
59296
|
if (has("zustand-redux")) {
|
|
59202
59297
|
server.tool(
|
|
59203
59298
|
"get_state_stores",
|
|
59204
|
-
"List all Zustand stores and Redux Toolkit slices with their state fields, actions/reducers, and dispatch sites",
|
|
59299
|
+
"List all Zustand stores and Redux Toolkit slices with their state fields, actions/reducers, and dispatch sites. Use to understand state management architecture. Read-only. Returns JSON: { stores: [{ type, name, handler, metadata }], dispatches, totalStores, totalDispatches }.",
|
|
59205
59300
|
{},
|
|
59206
59301
|
async () => {
|
|
59207
59302
|
const routes = store.getAllRoutes();
|
|
@@ -60049,7 +60144,7 @@ function registerAnalysisTools(server, ctx) {
|
|
|
60049
60144
|
);
|
|
60050
60145
|
server.tool(
|
|
60051
60146
|
"get_implementations",
|
|
60052
|
-
"Find all classes that implement or extend a given interface or base class",
|
|
60147
|
+
"Find all classes that implement or extend a given interface or base class. Use when you know the interface name. For full hierarchy tree (ancestors + descendants) use get_type_hierarchy instead. Read-only. Returns JSON: { implementations: [{ symbol_id, name, kind, file, line }], total }.",
|
|
60053
60148
|
{
|
|
60054
60149
|
name: z5.string().max(256).describe("Interface or base class name (e.g. UserRepositoryInterface)")
|
|
60055
60150
|
},
|
|
@@ -60075,7 +60170,7 @@ function registerAnalysisTools(server, ctx) {
|
|
|
60075
60170
|
);
|
|
60076
60171
|
server.tool(
|
|
60077
60172
|
"get_api_surface",
|
|
60078
|
-
"List all exported symbols (public API) of a file or matching files",
|
|
60173
|
+
"List all exported symbols (public API) of a file or matching files. Use to understand what a module exposes. For finding unused exports use get_dead_exports instead. Read-only. Returns JSON: { files: [{ path, exports: [{ name, kind, signature }] }] }.",
|
|
60079
60174
|
{
|
|
60080
60175
|
file_pattern: z5.string().max(512).optional().describe("Glob-style pattern to filter files (e.g. src/services/*.ts)")
|
|
60081
60176
|
},
|
|
@@ -60086,7 +60181,7 @@ function registerAnalysisTools(server, ctx) {
|
|
|
60086
60181
|
);
|
|
60087
60182
|
server.tool(
|
|
60088
60183
|
"get_plugin_registry",
|
|
60089
|
-
"List all registered indexer plugins and the edge types they emit",
|
|
60184
|
+
"List all registered indexer plugins and the edge types they emit. Use for debugging indexer behavior or understanding which frameworks are supported. Read-only. Returns JSON: { languagePlugins, frameworkPlugins, edgeTypes }.",
|
|
60090
60185
|
{},
|
|
60091
60186
|
async () => {
|
|
60092
60187
|
const result = getPluginRegistry(store, registry, frameworkNames);
|
|
@@ -60095,7 +60190,7 @@ function registerAnalysisTools(server, ctx) {
|
|
|
60095
60190
|
);
|
|
60096
60191
|
server.tool(
|
|
60097
60192
|
"get_type_hierarchy",
|
|
60098
|
-
"Walk TypeScript class/interface hierarchy: ancestors (what it extends/implements) and descendants (what extends/implements it)",
|
|
60193
|
+
"Walk TypeScript class/interface hierarchy: ancestors (what it extends/implements) and descendants (what extends/implements it). Use to understand inheritance trees. For a flat list of implementations only use get_implementations instead. Read-only. Returns JSON: { name, ancestors: [...], descendants: [...] }.",
|
|
60099
60194
|
{
|
|
60100
60195
|
name: z5.string().max(256).describe('Class or interface name (e.g. "LanguagePlugin", "Store")'),
|
|
60101
60196
|
max_depth: z5.number().int().min(1).max(20).optional().describe("Max traversal depth (default 10)")
|
|
@@ -60122,7 +60217,7 @@ function registerAnalysisTools(server, ctx) {
|
|
|
60122
60217
|
);
|
|
60123
60218
|
server.tool(
|
|
60124
60219
|
"get_dead_exports",
|
|
60125
|
-
"Find exported symbols never imported by any other file \u2014 dead code candidates",
|
|
60220
|
+
"Find exported symbols never imported by any other file \u2014 dead code candidates. Use for quick export-level dead code scan. For deeper multi-signal dead code detection (including call graph) use get_dead_code instead. Read-only. Returns JSON: { deadExports: [{ symbol_id, name, kind, file }], total }.",
|
|
60126
60221
|
{
|
|
60127
60222
|
file_pattern: z5.string().max(512).optional().describe('Filter files by glob pattern (e.g. "src/tools/*.ts")')
|
|
60128
60223
|
},
|
|
@@ -60133,7 +60228,7 @@ function registerAnalysisTools(server, ctx) {
|
|
|
60133
60228
|
);
|
|
60134
60229
|
server.tool(
|
|
60135
60230
|
"get_import_graph",
|
|
60136
|
-
"Show file-level dependency graph: what a file imports and what imports it (requires reindex for ESM edge resolution)",
|
|
60231
|
+
"Show file-level dependency graph: what a file imports and what imports it (requires reindex for ESM edge resolution). Use to understand module dependencies for a specific file. For project-wide coupling analysis use get_coupling; for visual diagram use get_dependency_diagram. Read-only. Returns JSON: { file, imports: [{ path }], importedBy: [{ path }] }.",
|
|
60137
60232
|
{
|
|
60138
60233
|
file_path: z5.string().max(512).describe('Relative file path to analyze (e.g. "src/server.ts")')
|
|
60139
60234
|
},
|
|
@@ -60146,7 +60241,7 @@ function registerAnalysisTools(server, ctx) {
|
|
|
60146
60241
|
);
|
|
60147
60242
|
server.tool(
|
|
60148
60243
|
"get_untested_exports",
|
|
60149
|
-
"Find exported public symbols with no matching test file \u2014 test coverage gaps",
|
|
60244
|
+
"Find exported public symbols with no matching test file \u2014 test coverage gaps. For deeper analysis including non-exported symbols use get_untested_symbols instead. Read-only. Returns JSON: { untested: [{ symbol_id, name, kind, file }], total }.",
|
|
60150
60245
|
{
|
|
60151
60246
|
file_pattern: z5.string().max(512).optional().describe('Filter by file glob pattern (e.g. "src/tools/%")')
|
|
60152
60247
|
},
|
|
@@ -60157,7 +60252,7 @@ function registerAnalysisTools(server, ctx) {
|
|
|
60157
60252
|
);
|
|
60158
60253
|
server.tool(
|
|
60159
60254
|
"get_untested_symbols",
|
|
60160
|
-
'Find ALL symbols (not just exports) lacking test coverage. Classifies as "unreached" (no test file imports the source) or "imported_not_called" (test imports file but never references this symbol). Use for thorough coverage gap analysis.',
|
|
60255
|
+
'Find ALL symbols (not just exports) lacking test coverage. Classifies as "unreached" (no test file imports the source) or "imported_not_called" (test imports file but never references this symbol). Use for thorough coverage gap analysis. For exports-only quick scan use get_untested_exports instead. Read-only. Returns JSON: { untested: [{ symbol_id, name, kind, file, classification }], total }.',
|
|
60161
60256
|
{
|
|
60162
60257
|
file_pattern: z5.string().max(512).optional().describe('Filter by file glob pattern (e.g. "src/tools/%")'),
|
|
60163
60258
|
max_results: z5.number().int().min(1).max(500).optional().describe("Cap on returned items (default: all)")
|
|
@@ -60167,12 +60262,12 @@ function registerAnalysisTools(server, ctx) {
|
|
|
60167
60262
|
return { content: [{ type: "text", text: jh("get_untested_symbols", result) }] };
|
|
60168
60263
|
}
|
|
60169
60264
|
);
|
|
60170
|
-
server.tool("self_audit", "Dead code & coverage audit: dead exports, untested public symbols, heritage debt. Use
|
|
60265
|
+
server.tool("self_audit", "Dead code & coverage audit: dead exports, untested public symbols, heritage debt. Use as a one-shot health check combining dead exports + untested symbols + heritage debt. For individual checks use get_dead_exports, get_untested_symbols, or get_dead_code separately. Read-only. Returns JSON: { deadExports, untestedSymbols, heritageDebt, summary }.", {}, async () => {
|
|
60171
60266
|
return { content: [{ type: "text", text: j3(selfAudit(store)) }] };
|
|
60172
60267
|
});
|
|
60173
60268
|
server.tool(
|
|
60174
60269
|
"get_coupling",
|
|
60175
|
-
"Coupling analysis: afferent (Ca), efferent (Ce), instability index per file. Shows which modules are stable vs unstable",
|
|
60270
|
+
"Coupling analysis: afferent (Ca), efferent (Ce), instability index per file. Shows which modules are stable vs unstable. Use to identify fragile or overly-depended-on modules. For coupling changes over time use get_coupling_trend instead. Read-only. Returns JSON: [{ file, ca, ce, instability, assessment }].",
|
|
60176
60271
|
{
|
|
60177
60272
|
limit: z5.number().int().min(1).max(500).optional().describe("Max results (default: all)"),
|
|
60178
60273
|
assessment: z5.enum(["stable", "neutral", "unstable", "isolated"]).optional().describe("Filter by stability assessment")
|
|
@@ -60186,7 +60281,7 @@ function registerAnalysisTools(server, ctx) {
|
|
|
60186
60281
|
);
|
|
60187
60282
|
server.tool(
|
|
60188
60283
|
"get_circular_imports",
|
|
60189
|
-
"Find circular dependency chains in the import graph (Kosaraju SCC algorithm)",
|
|
60284
|
+
"Find circular dependency chains in the import graph (Kosaraju SCC algorithm). Use to detect and break dependency cycles. Read-only. Returns JSON: { total_cycles, cycles: [[file1, file2, ...]] }.",
|
|
60190
60285
|
{},
|
|
60191
60286
|
async () => {
|
|
60192
60287
|
const cycles = getDependencyCycles(store);
|
|
@@ -60205,7 +60300,7 @@ function registerAnalysisTools(server, ctx) {
|
|
|
60205
60300
|
);
|
|
60206
60301
|
server.tool(
|
|
60207
60302
|
"get_pagerank",
|
|
60208
|
-
"File importance ranking via PageRank on the import graph. Shows most central/important files",
|
|
60303
|
+
"File importance ranking via PageRank on the import graph. Shows most central/important files. Use to identify architecturally critical files. For combined health metrics use get_project_health instead. Read-only. Returns JSON: [{ file, score }].",
|
|
60209
60304
|
{
|
|
60210
60305
|
limit: z5.number().int().min(1).max(200).optional().describe("Max results (default: 50)")
|
|
60211
60306
|
},
|
|
@@ -60216,7 +60311,7 @@ function registerAnalysisTools(server, ctx) {
|
|
|
60216
60311
|
);
|
|
60217
60312
|
server.tool(
|
|
60218
60313
|
"get_refactor_candidates",
|
|
60219
|
-
"Find functions with high complexity called from many files \u2014 candidates for extraction to shared modules",
|
|
60314
|
+
"Find functions with high complexity called from many files \u2014 candidates for extraction to shared modules. Use during architecture review to identify hotspots worth refactoring. Read-only. Returns JSON: [{ symbol_id, name, file, cyclomatic, callerCount }].",
|
|
60220
60315
|
{
|
|
60221
60316
|
min_cyclomatic: z5.number().int().min(1).optional().describe("Min cyclomatic complexity (default: 5)"),
|
|
60222
60317
|
min_callers: z5.number().int().min(1).optional().describe("Min distinct caller files (default: 2)"),
|
|
@@ -60233,7 +60328,7 @@ function registerAnalysisTools(server, ctx) {
|
|
|
60233
60328
|
);
|
|
60234
60329
|
server.tool(
|
|
60235
60330
|
"get_project_health",
|
|
60236
|
-
"Structural health: coupling instability, dependency cycles, PageRank rankings, refactor candidates. Use for architecture review.",
|
|
60331
|
+
"Structural health: coupling instability, dependency cycles, PageRank rankings, refactor candidates. Use for architecture review as a single aggregated report. For individual metrics use get_coupling, get_circular_imports, or get_pagerank separately. Read-only. Returns JSON: { coupling, cycles, pagerank, refactorCandidates, hotspots }.",
|
|
60237
60332
|
{},
|
|
60238
60333
|
async () => {
|
|
60239
60334
|
const result = getRepoHealth(store);
|
|
@@ -60243,7 +60338,7 @@ function registerAnalysisTools(server, ctx) {
|
|
|
60243
60338
|
);
|
|
60244
60339
|
server.tool(
|
|
60245
60340
|
"check_architecture",
|
|
60246
|
-
"Check architectural layer rules: detect forbidden imports between layers (e.g. domain importing infrastructure). Supports auto-detected presets (clean-architecture, hexagonal) or custom layers.",
|
|
60341
|
+
"Check architectural layer rules: detect forbidden imports between layers (e.g. domain importing infrastructure). Supports auto-detected presets (clean-architecture, hexagonal) or custom layers. Use to enforce architectural boundaries. Read-only. Returns JSON: { violations: [{ from, to, rule, file, line }], total, preset }.",
|
|
60247
60342
|
{
|
|
60248
60343
|
preset: z5.enum(["clean-architecture", "hexagonal"]).optional().describe("Use a built-in layer preset (auto-detected if omitted)"),
|
|
60249
60344
|
layers: z5.array(z5.object({
|
|
@@ -60272,7 +60367,7 @@ function registerAnalysisTools(server, ctx) {
|
|
|
60272
60367
|
);
|
|
60273
60368
|
server.tool(
|
|
60274
60369
|
"get_code_owners",
|
|
60275
|
-
"Git-based code ownership: who contributed most to specific files (git shortlog). Requires git.",
|
|
60370
|
+
"Git-based code ownership: who contributed most to specific files (git shortlog). Requires git. Use to identify who to ask about specific files. For symbol-level ownership use get_symbol_owners instead. Read-only. Returns JSON: [{ file, owners: [{ author, commits, percentage }] }].",
|
|
60276
60371
|
{
|
|
60277
60372
|
file_paths: z5.array(z5.string().max(512)).min(1).max(20).describe("File paths to check ownership for")
|
|
60278
60373
|
},
|
|
@@ -60290,7 +60385,7 @@ function registerAnalysisTools(server, ctx) {
|
|
|
60290
60385
|
);
|
|
60291
60386
|
server.tool(
|
|
60292
60387
|
"get_symbol_owners",
|
|
60293
|
-
"Git blame-based symbol ownership: who wrote which lines of a specific symbol. Requires git.",
|
|
60388
|
+
"Git blame-based symbol ownership: who wrote which lines of a specific symbol. Requires git. Use for fine-grained ownership of a specific function/class. For file-level ownership use get_code_owners instead. Read-only. Returns JSON: { symbol_id, owners: [{ author, lines, percentage }] }.",
|
|
60294
60389
|
{
|
|
60295
60390
|
symbol_id: z5.string().max(512).describe("Symbol ID to check ownership for")
|
|
60296
60391
|
},
|
|
@@ -60304,7 +60399,7 @@ function registerAnalysisTools(server, ctx) {
|
|
|
60304
60399
|
);
|
|
60305
60400
|
server.tool(
|
|
60306
60401
|
"get_complexity_trend",
|
|
60307
|
-
"File complexity over git history: cyclomatic complexity at past commits. Shows if a file is getting more or less complex.",
|
|
60402
|
+
"File complexity over git history: cyclomatic complexity at past commits. Shows if a file is getting more or less complex. Requires git. Use to track whether a file is improving or degrading. For current snapshot use get_complexity_report; for symbol-level trends use get_symbol_complexity_trend. Read-only. Returns JSON: { file, snapshots: [{ commit, date, complexity }] }.",
|
|
60308
60403
|
{
|
|
60309
60404
|
file_path: z5.string().max(512).describe("File path to analyze"),
|
|
60310
60405
|
snapshots: z5.number().int().min(2).max(20).optional().describe("Number of historical snapshots (default: 5)")
|
|
@@ -60321,7 +60416,7 @@ function registerAnalysisTools(server, ctx) {
|
|
|
60321
60416
|
);
|
|
60322
60417
|
server.tool(
|
|
60323
60418
|
"get_coupling_trend",
|
|
60324
|
-
"File coupling over git history: Ca/Ce/instability at past commits. Shows if a module is stabilizing or destabilizing.",
|
|
60419
|
+
"File coupling over git history: Ca/Ce/instability at past commits. Shows if a module is stabilizing or destabilizing. Requires git. Use to track module stability over time. For current coupling snapshot use get_coupling instead. Read-only. Returns JSON: { file, snapshots: [{ commit, date, ca, ce, instability }] }.",
|
|
60325
60420
|
{
|
|
60326
60421
|
file_path: z5.string().max(512).describe("File path to analyze"),
|
|
60327
60422
|
since_days: z5.number().int().min(1).optional().describe("Analyze last N days (default: 90)"),
|
|
@@ -60342,7 +60437,7 @@ function registerAnalysisTools(server, ctx) {
|
|
|
60342
60437
|
);
|
|
60343
60438
|
server.tool(
|
|
60344
60439
|
"get_symbol_complexity_trend",
|
|
60345
|
-
"Single symbol complexity over git history: cyclomatic, nesting, params, lines at past commits.",
|
|
60440
|
+
"Single symbol complexity over git history: cyclomatic, nesting, params, lines at past commits. Requires git. Use to track a specific function's complexity evolution. For file-level trends use get_complexity_trend instead. Read-only. Returns JSON: { symbol_id, snapshots: [{ commit, date, cyclomatic, nesting, params, lines }] }.",
|
|
60346
60441
|
{
|
|
60347
60442
|
symbol_id: z5.string().min(1).max(512).describe("Symbol ID to analyze (from search or outline)"),
|
|
60348
60443
|
since_days: z5.number().int().min(1).optional().describe("Analyze last N days (default: all history)"),
|
|
@@ -60361,7 +60456,7 @@ function registerAnalysisTools(server, ctx) {
|
|
|
60361
60456
|
);
|
|
60362
60457
|
server.tool(
|
|
60363
60458
|
"check_duplication",
|
|
60364
|
-
"Check if a function/class name already exists elsewhere in the codebase before creating it. Prevents duplicating existing logic. Call with just a name when planning new code, or symbol_id to check an existing symbol. Returns scored matches \u2014 score \u22650.7 means high likelihood of duplication, review the existing symbol before proceeding.",
|
|
60459
|
+
"Check if a function/class name already exists elsewhere in the codebase before creating it. Prevents duplicating existing logic. Call with just a name when planning new code, or symbol_id to check an existing symbol. Returns scored matches \u2014 score \u22650.7 means high likelihood of duplication, review the existing symbol before proceeding. Read-only. Returns JSON: { duplicates: [{ symbol_id, name, file, score }], hasDuplication }.",
|
|
60365
60460
|
{
|
|
60366
60461
|
symbol_id: z5.string().max(512).optional().describe("Existing symbol ID to check for duplicates"),
|
|
60367
60462
|
name: z5.string().max(256).optional().describe("Function/class name to check (when symbol_id not available)"),
|
|
@@ -63516,7 +63611,7 @@ function registerGitTools(server, ctx) {
|
|
|
63516
63611
|
const detectedFrameworks = registry.getAllFrameworkPlugins().map((p) => p.manifest.name);
|
|
63517
63612
|
server.tool(
|
|
63518
63613
|
"get_git_churn",
|
|
63519
|
-
"Per-file git churn: commits, unique authors, frequency, volatility assessment. Requires git.",
|
|
63614
|
+
"Per-file git churn: commits, unique authors, frequency, volatility assessment. Requires git. Use to identify frequently-changed files. For combined churn+complexity hotspots use get_risk_hotspots instead. Read-only. Returns JSON: { results: [{ file, commits, authors, frequency, volatility }], total }.",
|
|
63520
63615
|
{
|
|
63521
63616
|
since_days: z6.number().int().min(1).optional().describe("Analyze commits from last N days (default: all history)"),
|
|
63522
63617
|
limit: z6.number().int().min(1).max(500).optional().describe("Max results (default: 50)"),
|
|
@@ -63536,7 +63631,7 @@ function registerGitTools(server, ctx) {
|
|
|
63536
63631
|
);
|
|
63537
63632
|
server.tool(
|
|
63538
63633
|
"get_risk_hotspots",
|
|
63539
|
-
"Code hotspots: files with both high complexity AND high git churn (Adam Tornhill methodology). Score = complexity \xD7 log(1 + commits). Each entry includes a confidence_level (low/medium/multi_signal) counting how many of the two independent signals fired strongly. Result envelope includes _methodology disclosure and _warnings when git is unavailable.",
|
|
63634
|
+
"Code hotspots: files with both high complexity AND high git churn (Adam Tornhill methodology). Score = complexity \xD7 log(1 + commits). Each entry includes a confidence_level (low/medium/multi_signal) counting how many of the two independent signals fired strongly. Result envelope includes _methodology disclosure and _warnings when git is unavailable. Requires git. Use to prioritize refactoring. For per-file bug prediction use predict_bugs instead. Read-only. Returns JSON: { hotspots: [{ file, score, complexity, commits, confidence_level }], total }.",
|
|
63540
63635
|
{
|
|
63541
63636
|
since_days: z6.number().int().min(1).optional().describe("Git churn window in days (default: 90)"),
|
|
63542
63637
|
limit: z6.number().int().min(1).max(100).optional().describe("Max results (default: 20)"),
|
|
@@ -63567,7 +63662,7 @@ function registerGitTools(server, ctx) {
|
|
|
63567
63662
|
);
|
|
63568
63663
|
server.tool(
|
|
63569
63664
|
"get_dead_code",
|
|
63570
|
-
'Dead code detection. Two modes: (1) "multi-signal" (default) combines import graph, call graph, and barrel export analysis with confidence scores. (2) "reachability" runs forward BFS from auto-detected entry points (tests, package.json main/bin, src/{cli,main,index}, routes, framework-tagged controllers) \u2014 stricter but more accurate when entry points are enumerable. Pass entry_points to add custom roots. Both modes emit _methodology and _warnings.',
|
|
63665
|
+
'Dead code detection. Two modes: (1) "multi-signal" (default) combines import graph, call graph, and barrel export analysis with confidence scores. (2) "reachability" runs forward BFS from auto-detected entry points (tests, package.json main/bin, src/{cli,main,index}, routes, framework-tagged controllers) \u2014 stricter but more accurate when entry points are enumerable. Pass entry_points to add custom roots. Both modes emit _methodology and _warnings. Use for comprehensive dead code analysis. For quick export-only scan use get_dead_exports; to safely remove detected dead code use remove_dead_code. Read-only. Returns JSON: { dead_symbols: [{ symbol_id, name, file, confidence, signals }], total }.',
|
|
63571
63666
|
{
|
|
63572
63667
|
file_pattern: z6.string().max(512).optional().describe('Filter by file glob pattern (e.g. "src/tools/%")'),
|
|
63573
63668
|
threshold: z6.number().min(0).max(1).optional().describe("[multi-signal mode] Min confidence to report (default: 0.5 = at least 2 of 3 signals)"),
|
|
@@ -63597,7 +63692,7 @@ function registerGitTools(server, ctx) {
|
|
|
63597
63692
|
);
|
|
63598
63693
|
server.tool(
|
|
63599
63694
|
"scan_security",
|
|
63600
|
-
"Scan project files for OWASP Top-10 security vulnerabilities using pattern matching. Detects SQL injection (CWE-89), XSS (CWE-79), command injection (CWE-78), path traversal (CWE-22), hardcoded secrets (CWE-798), insecure crypto (CWE-327), open redirects (CWE-601), and SSRF (CWE-918). Skips test files.",
|
|
63695
|
+
"Scan project files for OWASP Top-10 security vulnerabilities using pattern matching. Detects SQL injection (CWE-89), XSS (CWE-79), command injection (CWE-78), path traversal (CWE-22), hardcoded secrets (CWE-798), insecure crypto (CWE-327), open redirects (CWE-601), and SSRF (CWE-918). Skips test files. Use for pattern-based security audit. For data-flow-aware analysis use taint_analysis instead. Read-only. Returns JSON: { findings: [{ rule, severity, cwe, file, line, message }], total, summary }.",
|
|
63601
63696
|
{
|
|
63602
63697
|
scope: z6.string().max(512).optional().describe("Directory to scan (default: whole project)"),
|
|
63603
63698
|
rules: z6.array(z6.enum([
|
|
@@ -63631,7 +63726,7 @@ function registerGitTools(server, ctx) {
|
|
|
63631
63726
|
);
|
|
63632
63727
|
server.tool(
|
|
63633
63728
|
"detect_antipatterns",
|
|
63634
|
-
"Detect performance antipatterns: N+1 query risks, missing eager loading, unbounded queries, event listener leaks, circular model dependencies, missing indexes, memory leaks (unbounded caches, closure leaks). Static analysis across all indexed ORMs (Eloquent, Sequelize, Mongoose, Django, Prisma, TypeORM, Drizzle).",
|
|
63729
|
+
"Detect performance antipatterns: N+1 query risks, missing eager loading, unbounded queries, event listener leaks, circular model dependencies, missing indexes, memory leaks (unbounded caches, closure leaks). Static analysis across all indexed ORMs (Eloquent, Sequelize, Mongoose, Django, Prisma, TypeORM, Drizzle). Use to find performance issues. For code quality issues (TODOs, empty functions) use scan_code_smells instead. Read-only. Returns JSON: { findings: [{ category, severity, file, line, message, suggestion }], total }.",
|
|
63635
63730
|
{
|
|
63636
63731
|
category: z6.array(z6.enum([
|
|
63637
63732
|
"n_plus_one_risk",
|
|
@@ -63661,7 +63756,7 @@ function registerGitTools(server, ctx) {
|
|
|
63661
63756
|
);
|
|
63662
63757
|
server.tool(
|
|
63663
63758
|
"scan_code_smells",
|
|
63664
|
-
"Find deferred work and shortcuts: TODO/FIXME/HACK/XXX comments, empty functions & stubs, hardcoded values (IPs, URLs, credentials, magic numbers, feature flags). Surfaces technical debt that grep alone misses by combining comment scanning, symbol body analysis, and context-aware false-positive filtering.",
|
|
63759
|
+
"Find deferred work and shortcuts: TODO/FIXME/HACK/XXX comments, empty functions & stubs, hardcoded values (IPs, URLs, credentials, magic numbers, feature flags). Surfaces technical debt that grep alone misses by combining comment scanning, symbol body analysis, and context-aware false-positive filtering. Use for code quality audit. For performance-specific antipatterns use detect_antipatterns; for security issues use scan_security. Read-only. Returns JSON: { findings: [{ category, priority, file, line, message }], total, summary }.",
|
|
63665
63760
|
{
|
|
63666
63761
|
category: z6.array(z6.enum([
|
|
63667
63762
|
"todo_comment",
|
|
@@ -63695,7 +63790,7 @@ function registerGitTools(server, ctx) {
|
|
|
63695
63790
|
);
|
|
63696
63791
|
server.tool(
|
|
63697
63792
|
"taint_analysis",
|
|
63698
|
-
"Track flow of untrusted data from sources (HTTP params, env vars, file reads) to dangerous sinks (SQL queries, exec, innerHTML, redirects). Framework-aware: knows Express req.params, Laravel $request->input, Django request.GET, FastAPI Query(), etc. Reports unsanitized flows with CWE IDs and fix suggestions. More accurate than pattern-based scanning \u2014 traces actual data flow paths.",
|
|
63793
|
+
"Track flow of untrusted data from sources (HTTP params, env vars, file reads) to dangerous sinks (SQL queries, exec, innerHTML, redirects). Framework-aware: knows Express req.params, Laravel $request->input, Django request.GET, FastAPI Query(), etc. Reports unsanitized flows with CWE IDs and fix suggestions. More accurate than pattern-based scanning \u2014 traces actual data flow paths. Use for data-flow security analysis. For pattern-based OWASP scanning use scan_security instead. Read-only. Returns JSON: { flows: [{ source, sink, path, sanitized, cwe, suggestion }], total }.",
|
|
63699
63794
|
{
|
|
63700
63795
|
scope: z6.string().max(512).optional().describe("Directory to scan (default: whole project)"),
|
|
63701
63796
|
sources: z6.array(z6.enum([
|
|
@@ -63741,7 +63836,7 @@ function registerGitTools(server, ctx) {
|
|
|
63741
63836
|
);
|
|
63742
63837
|
server.tool(
|
|
63743
63838
|
"generate_sbom",
|
|
63744
|
-
"Generate a Software Bill of Materials (SBOM) from package manifests and lockfiles. Supports npm, Composer, pip, Go, Cargo, Bundler, Maven. Outputs CycloneDX, SPDX, or plain JSON. Includes license compliance warnings for copyleft licenses.",
|
|
63839
|
+
"Generate a Software Bill of Materials (SBOM) from package manifests and lockfiles. Supports npm, Composer, pip, Go, Cargo, Bundler, Maven. Outputs CycloneDX, SPDX, or plain JSON. Includes license compliance warnings for copyleft licenses. Use for supply chain audits or compliance reports. Returns JSON/CycloneDX/SPDX: { components: [{ name, version, license, type }], warnings }.",
|
|
63745
63840
|
{
|
|
63746
63841
|
format: z6.enum(["cyclonedx", "spdx", "json"]).optional().describe("Output format (default: json)"),
|
|
63747
63842
|
include_dev: z6.boolean().optional().describe("Include devDependencies (default: false)"),
|
|
@@ -63761,7 +63856,7 @@ function registerGitTools(server, ctx) {
|
|
|
63761
63856
|
);
|
|
63762
63857
|
server.tool(
|
|
63763
63858
|
"get_artifacts",
|
|
63764
|
-
"Surface non-code knowledge from the index: DB schemas (migrations, ORM models), API specs (routes, OpenAPI endpoints), infrastructure (docker-compose services, K8s resources), CI pipelines (jobs, stages), and config (env vars). All data from the existing index \u2014 no extra I/O.",
|
|
63859
|
+
"Surface non-code knowledge from the index: DB schemas (migrations, ORM models), API specs (routes, OpenAPI endpoints), infrastructure (docker-compose services, K8s resources), CI pipelines (jobs, stages), and config (env vars). All data from the existing index \u2014 no extra I/O. Use to discover infrastructure and config artifacts without reading files. Read-only. Returns JSON: { artifacts: [{ category, kind, name, file }], total }.",
|
|
63765
63860
|
{
|
|
63766
63861
|
category: z6.enum(["database", "api", "infra", "ci", "config", "all"]).optional().describe("Filter by artifact category (default: all)"),
|
|
63767
63862
|
query: z6.string().max(256).optional().describe("Text filter on name/kind/file"),
|
|
@@ -63778,7 +63873,7 @@ function registerGitTools(server, ctx) {
|
|
|
63778
63873
|
);
|
|
63779
63874
|
server.tool(
|
|
63780
63875
|
"plan_batch_change",
|
|
63781
|
-
"Analyze the impact of updating a package/dependency. Shows all affected files, import references, and generates a PR template with checklist. Use before upgrading a dependency to understand blast radius.",
|
|
63876
|
+
"Analyze the impact of updating a package/dependency. Shows all affected files, import references, and generates a PR template with checklist. Use before upgrading a dependency to understand blast radius. Read-only (analysis only, does not modify files). Returns JSON: { package, affectedFiles, importReferences, prTemplate, checklist }.",
|
|
63782
63877
|
{
|
|
63783
63878
|
package: z6.string().min(1).max(256).describe('Package name (e.g. "express", "laravel/framework", "react")'),
|
|
63784
63879
|
from_version: z6.string().max(64).optional().describe("Current version"),
|
|
@@ -63800,7 +63895,7 @@ function registerGitTools(server, ctx) {
|
|
|
63800
63895
|
);
|
|
63801
63896
|
server.tool(
|
|
63802
63897
|
"get_complexity_report",
|
|
63803
|
-
"Get complexity metrics (cyclomatic, max nesting, param count) for symbols in a file or across the project.
|
|
63898
|
+
"Get complexity metrics (cyclomatic, max nesting, param count) for symbols in a file or across the project. Use to identify complex code before refactoring. For historical trends use get_complexity_trend instead. Read-only. Returns JSON: { symbols: [{ symbol_id, name, kind, file, line, cyclomatic, max_nesting, param_count }], total }.",
|
|
63804
63899
|
{
|
|
63805
63900
|
file_path: z6.string().max(512).optional().describe("File path to report on (omit for project-wide top complex symbols)"),
|
|
63806
63901
|
min_cyclomatic: z6.number().int().min(1).optional().describe("Min cyclomatic complexity to include (default: 1 for file, 5 for project)"),
|
|
@@ -63835,7 +63930,7 @@ function registerGitTools(server, ctx) {
|
|
|
63835
63930
|
);
|
|
63836
63931
|
server.tool(
|
|
63837
63932
|
"check_rename",
|
|
63838
|
-
"Pre-rename collision detection: checks the symbol's own file and all importing files for existing symbols with the target name",
|
|
63933
|
+
"Pre-rename collision detection: checks the symbol's own file and all importing files for existing symbols with the target name. Use before apply_rename to verify safety. Read-only (does not modify files). Returns JSON: { safe, conflicts: [{ symbol_id, name, file }] }.",
|
|
63839
63934
|
{
|
|
63840
63935
|
symbol_id: z6.string().max(512).describe("Symbol ID to rename"),
|
|
63841
63936
|
target_name: z6.string().min(1).max(256).describe("Proposed new name")
|
|
@@ -65701,7 +65796,7 @@ function registerRefactoringTools(server, ctx) {
|
|
|
65701
65796
|
const { store, projectRoot, guardPath, j: j3 } = ctx;
|
|
65702
65797
|
server.tool(
|
|
65703
65798
|
"apply_rename",
|
|
65704
|
-
|
|
65799
|
+
'Rename a symbol across all usages (definition + all importing files). Runs collision detection first and aborts on conflicts. Returns the list of edits applied. Modifies source files. Use check_rename first to verify safety; use plan_refactoring with type="rename" to preview edits. Returns JSON: { success, edits: [{ file, old_text, new_text }], filesModified }.',
|
|
65705
65800
|
{
|
|
65706
65801
|
symbol_id: z7.string().max(512).describe("Symbol ID to rename (from search or outline)"),
|
|
65707
65802
|
new_name: z7.string().min(1).max(256).describe("New name for the symbol"),
|
|
@@ -65717,7 +65812,7 @@ function registerRefactoringTools(server, ctx) {
|
|
|
65717
65812
|
);
|
|
65718
65813
|
server.tool(
|
|
65719
65814
|
"remove_dead_code",
|
|
65720
|
-
"Safely remove a dead symbol from its file. Verifies the symbol is actually dead (multi-signal detection or zero incoming edges) before removal. Warns about orphaned imports in other files.",
|
|
65815
|
+
"Safely remove a dead symbol from its file. Verifies the symbol is actually dead (multi-signal detection or zero incoming edges) before removal. Warns about orphaned imports in other files. Destructive \u2014 deletes code from source files. Use get_dead_code first to identify candidates. Returns JSON: { success, removed: { symbol_id, file }, orphanedImports }.",
|
|
65721
65816
|
{
|
|
65722
65817
|
symbol_id: z7.string().max(512).describe("Symbol ID to remove (from get_dead_code results)"),
|
|
65723
65818
|
dry_run: z7.boolean().default(false).describe("Preview changes without applying (default: false)")
|
|
@@ -65732,7 +65827,7 @@ function registerRefactoringTools(server, ctx) {
|
|
|
65732
65827
|
);
|
|
65733
65828
|
server.tool(
|
|
65734
65829
|
"extract_function",
|
|
65735
|
-
|
|
65830
|
+
'Extract a range of lines into a new named function. Detects parameters (variables from outer scope) and return values (variables used after the range). Supports TypeScript/JavaScript, Python, and Go. Modifies source files. Use plan_refactoring with type="extract" to preview first. Returns JSON: { success, edits: [{ file, old_text, new_text }], extractedFunction }.',
|
|
65736
65831
|
{
|
|
65737
65832
|
file_path: z7.string().max(512).describe("File path (relative to project root)"),
|
|
65738
65833
|
start_line: z7.number().int().min(1).describe("First line to extract (1-indexed, inclusive)"),
|
|
@@ -65752,7 +65847,7 @@ function registerRefactoringTools(server, ctx) {
|
|
|
65752
65847
|
);
|
|
65753
65848
|
server.tool(
|
|
65754
65849
|
"apply_codemod",
|
|
65755
|
-
"Bulk regex find-and-replace across files. Dry-run by default \u2014 first call shows preview, second call with dry_run=false applies. Use for mechanical changes like adding async/await, renaming patterns, updating imports across many files.",
|
|
65850
|
+
"Bulk regex find-and-replace across files. Dry-run by default \u2014 first call shows preview, second call with dry_run=false applies. Use for mechanical changes like adding async/await, renaming patterns, updating imports across many files. Potentially destructive \u2014 can modify or delete code. Always preview with dry_run=true first. Returns JSON: { success, matchedFiles, changes: [{ file, matches }], applied }.",
|
|
65756
65851
|
{
|
|
65757
65852
|
pattern: z7.string().min(1).max(1e3).describe("Regex pattern to match (JavaScript regex syntax)"),
|
|
65758
65853
|
replacement: z7.string().max(1e3).describe("Replacement string ($1, $2 for capture groups)"),
|
|
@@ -65777,7 +65872,7 @@ function registerRefactoringTools(server, ctx) {
|
|
|
65777
65872
|
);
|
|
65778
65873
|
server.tool(
|
|
65779
65874
|
"apply_move",
|
|
65780
|
-
|
|
65875
|
+
'Move a symbol to a different file or rename/move a file, updating all import paths across the codebase. Dry-run by default (safe preview). Modifies source files. Use plan_refactoring with type="move" to preview first. Returns JSON: { success, edits: [{ file, old_text, new_text }], filesModified }.',
|
|
65781
65876
|
{
|
|
65782
65877
|
symbol_id: z7.string().max(512).optional().describe("Symbol ID to move (mode: symbol)"),
|
|
65783
65878
|
target_file: z7.string().max(512).optional().describe("Target file path for the symbol (mode: symbol)"),
|
|
@@ -65841,7 +65936,7 @@ function registerRefactoringTools(server, ctx) {
|
|
|
65841
65936
|
});
|
|
65842
65937
|
server.tool(
|
|
65843
65938
|
"change_signature",
|
|
65844
|
-
|
|
65939
|
+
'Change a function/method signature (add/remove/rename/reorder parameters) and update all call sites. Dry-run by default (safe preview). Modifies source files. Use plan_refactoring with type="signature" to preview first. Returns JSON: { success, edits: [{ file, old_text, new_text }], callSitesUpdated }.',
|
|
65845
65940
|
{
|
|
65846
65941
|
symbol_id: z7.string().max(512).describe("Symbol ID of the function/method to modify"),
|
|
65847
65942
|
changes: z7.array(signatureChangeSchema).min(1).max(20).describe("Array of changes to apply"),
|
|
@@ -65871,7 +65966,7 @@ function registerRefactoringTools(server, ctx) {
|
|
|
65871
65966
|
});
|
|
65872
65967
|
server.tool(
|
|
65873
65968
|
"plan_refactoring",
|
|
65874
|
-
"Preview any refactoring (rename, move, extract, signature) without applying. Returns all edits as {old_text, new_text} pairs. Use to review
|
|
65969
|
+
"Preview any refactoring (rename, move, extract, signature) without applying. Returns all edits as {old_text, new_text} pairs. Read-only (does not modify files). Use to review the blast radius before calling apply_rename, apply_move, change_signature, or extract_function. Returns JSON: { success, type, edits: [{ file, old_text, new_text }], filesAffected }.",
|
|
65875
65970
|
{
|
|
65876
65971
|
type: z7.enum(["rename", "move", "extract", "signature"]).describe("Type of refactoring to preview"),
|
|
65877
65972
|
symbol_id: z7.string().max(512).optional().describe("Symbol ID (for rename, move symbol, signature)"),
|
|
@@ -66391,9 +66486,9 @@ var OtlpReceiver = class {
|
|
|
66391
66486
|
if (this.options.port === 0) return;
|
|
66392
66487
|
return new Promise((resolve3, reject) => {
|
|
66393
66488
|
this.server = createServer((req, res) => this.handleRequest(req, res));
|
|
66394
|
-
this.server.on("error", (
|
|
66395
|
-
logger.error({ error:
|
|
66396
|
-
reject(
|
|
66489
|
+
this.server.on("error", (err14) => {
|
|
66490
|
+
logger.error({ error: err14 }, "OTLP receiver error");
|
|
66491
|
+
reject(err14);
|
|
66397
66492
|
});
|
|
66398
66493
|
this.server.listen(this.options.port, this.options.host, () => {
|
|
66399
66494
|
logger.info(
|
|
@@ -68006,16 +68101,16 @@ function findShortestPath(store, startNodeId, endNodeId, maxDepth) {
|
|
|
68006
68101
|
parent.set(nodeId, { from, edgeType: edge.edge_type_name });
|
|
68007
68102
|
nextFrontier.push(nodeId);
|
|
68008
68103
|
if (nodeId === endNodeId) {
|
|
68009
|
-
const
|
|
68104
|
+
const path66 = [endNodeId];
|
|
68010
68105
|
const edgeTypes = [];
|
|
68011
68106
|
let cur = endNodeId;
|
|
68012
68107
|
while (cur !== startNodeId) {
|
|
68013
68108
|
const p = parent.get(cur);
|
|
68014
|
-
|
|
68109
|
+
path66.unshift(p.from);
|
|
68015
68110
|
edgeTypes.unshift(p.edgeType);
|
|
68016
68111
|
cur = p.from;
|
|
68017
68112
|
}
|
|
68018
|
-
return { path:
|
|
68113
|
+
return { path: path66, edgeTypes };
|
|
68019
68114
|
}
|
|
68020
68115
|
}
|
|
68021
68116
|
}
|
|
@@ -68404,14 +68499,14 @@ var FileRepository = class {
|
|
|
68404
68499
|
}
|
|
68405
68500
|
db;
|
|
68406
68501
|
_stmts;
|
|
68407
|
-
insertFile(
|
|
68408
|
-
const result = this._stmts.insertFile.run(
|
|
68502
|
+
insertFile(path66, language, contentHash, byteLength, workspace, mtimeMs, createNode) {
|
|
68503
|
+
const result = this._stmts.insertFile.run(path66, language, contentHash, byteLength, workspace, mtimeMs);
|
|
68409
68504
|
const fileId = Number(result.lastInsertRowid);
|
|
68410
68505
|
createNode("file", fileId);
|
|
68411
68506
|
return fileId;
|
|
68412
68507
|
}
|
|
68413
|
-
getFile(
|
|
68414
|
-
return this._stmts.getFile.get(
|
|
68508
|
+
getFile(path66) {
|
|
68509
|
+
return this._stmts.getFile.get(path66);
|
|
68415
68510
|
}
|
|
68416
68511
|
getFileById(id) {
|
|
68417
68512
|
return this._stmts.getFileById.get(id);
|
|
@@ -69269,9 +69364,9 @@ var Store = class {
|
|
|
69269
69364
|
domain;
|
|
69270
69365
|
analytics;
|
|
69271
69366
|
// --- Files (delegates to FileRepository) ---
|
|
69272
|
-
insertFile(
|
|
69367
|
+
insertFile(path66, language, contentHash, byteLength, workspace, mtimeMs) {
|
|
69273
69368
|
return this.files.insertFile(
|
|
69274
|
-
|
|
69369
|
+
path66,
|
|
69275
69370
|
language,
|
|
69276
69371
|
contentHash,
|
|
69277
69372
|
byteLength,
|
|
@@ -69280,8 +69375,8 @@ var Store = class {
|
|
|
69280
69375
|
(nodeType, refId) => this.graph.createNode(nodeType, refId)
|
|
69281
69376
|
);
|
|
69282
69377
|
}
|
|
69283
|
-
getFile(
|
|
69284
|
-
return this.files.getFile(
|
|
69378
|
+
getFile(path66) {
|
|
69379
|
+
return this.files.getFile(path66);
|
|
69285
69380
|
}
|
|
69286
69381
|
getFileById(id) {
|
|
69287
69382
|
return this.files.getFileById(id);
|
|
@@ -70292,6 +70387,7 @@ const preTicks = Math.min(300, Math.max(50, Math.ceil(Math.log(N + 1) * 40)));
|
|
|
70292
70387
|
let ticksDone = 0;
|
|
70293
70388
|
const TICK_BATCH = N > 5000 ? 5 : 15;
|
|
70294
70389
|
let layoutDone = false;
|
|
70390
|
+
let frameRequested = false;
|
|
70295
70391
|
(function tickBatch() {
|
|
70296
70392
|
const t0 = performance.now();
|
|
70297
70393
|
while (ticksDone < preTicks && performance.now() - t0 < 12) { sim.tick(); ticksDone++; }
|
|
@@ -70433,7 +70529,6 @@ let highlightSet = null;
|
|
|
70433
70529
|
let hoveredNode = null;
|
|
70434
70530
|
let searchQ = '';
|
|
70435
70531
|
let animating = false;
|
|
70436
|
-
let frameRequested = false;
|
|
70437
70532
|
|
|
70438
70533
|
function scheduleFrame() {
|
|
70439
70534
|
if (!frameRequested) { frameRequested = true; requestAnimationFrame(frame); }
|
|
@@ -72116,7 +72211,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72116
72211
|
const additionalRepos = config.topology.repos ?? [];
|
|
72117
72212
|
server.tool(
|
|
72118
72213
|
"get_service_map",
|
|
72119
|
-
"Get map of all services, their APIs, and inter-service dependencies. Auto-detects services from Docker Compose or treats each repo as a service.",
|
|
72214
|
+
"Get map of all services, their APIs, and inter-service dependencies. Auto-detects services from Docker Compose or treats each repo as a service. Use to understand microservice topology. For subproject-level graph use get_subproject_graph instead. Read-only. Returns JSON: { services: [{ name, endpoints, dependencies }], total }.",
|
|
72120
72215
|
{
|
|
72121
72216
|
include_endpoints: z8.boolean().optional().describe("Include full endpoint list per service (default false)")
|
|
72122
72217
|
},
|
|
@@ -72128,7 +72223,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72128
72223
|
);
|
|
72129
72224
|
server.tool(
|
|
72130
72225
|
"get_cross_service_impact",
|
|
72131
|
-
"Analyze cross-service impact of changing an endpoint or event. Shows which services would be affected.",
|
|
72226
|
+
"Analyze cross-service impact of changing an endpoint or event. Shows which services would be affected. Use before modifying a shared endpoint. For within-codebase impact use get_change_impact instead. Read-only. Returns JSON: { service, affectedServices: [{ name, reason }], total }.",
|
|
72132
72227
|
{
|
|
72133
72228
|
service: z8.string().min(1).max(256).describe("Service name"),
|
|
72134
72229
|
endpoint: z8.string().max(512).optional().describe("Endpoint path (e.g. /api/users/{id})"),
|
|
@@ -72142,7 +72237,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72142
72237
|
);
|
|
72143
72238
|
server.tool(
|
|
72144
72239
|
"get_api_contract",
|
|
72145
|
-
"Get API contract (OpenAPI/gRPC/GraphQL) for a service. Parses spec files found in the service repo.",
|
|
72240
|
+
"Get API contract (OpenAPI/gRPC/GraphQL) for a service. Parses spec files found in the service repo. Use to inspect a service's public API. For detecting spec-vs-code mismatches use get_contract_drift instead. Read-only. Returns JSON: { service, contract_type, endpoints, schemas }.",
|
|
72146
72241
|
{
|
|
72147
72242
|
service: z8.string().min(1).max(256).describe("Service name"),
|
|
72148
72243
|
contract_type: z8.enum(["openapi", "grpc", "graphql"]).optional().describe("Filter by contract type")
|
|
@@ -72155,7 +72250,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72155
72250
|
);
|
|
72156
72251
|
server.tool(
|
|
72157
72252
|
"get_service_deps",
|
|
72158
|
-
"Get external service dependencies: which services this one calls (outgoing) and which call it (incoming).",
|
|
72253
|
+
"Get external service dependencies: which services this one calls (outgoing) and which call it (incoming). Use to understand a single service's dependency profile. For full topology use get_service_map instead. Read-only. Returns JSON: { service, outgoing, incoming }.",
|
|
72159
72254
|
{
|
|
72160
72255
|
service: z8.string().min(1).max(256).describe("Service name"),
|
|
72161
72256
|
direction: z8.enum(["outgoing", "incoming", "both"]).optional().describe("Dependency direction (default both)")
|
|
@@ -72168,7 +72263,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72168
72263
|
);
|
|
72169
72264
|
server.tool(
|
|
72170
72265
|
"get_contract_drift",
|
|
72171
|
-
"Detect mismatches between API spec and implementation: endpoints in spec but not in code, or in code but not in spec.",
|
|
72266
|
+
"Detect mismatches between API spec and implementation: endpoints in spec but not in code, or in code but not in spec. Use to verify API contract accuracy. For reading the contract itself use get_api_contract instead. Read-only. Returns JSON: { service, missingInCode, missingInSpec, total }.",
|
|
72172
72267
|
{
|
|
72173
72268
|
service: z8.string().min(1).max(256).describe("Service name")
|
|
72174
72269
|
},
|
|
@@ -72180,7 +72275,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72180
72275
|
);
|
|
72181
72276
|
server.tool(
|
|
72182
72277
|
"get_subproject_graph",
|
|
72183
|
-
"Show all subprojects and their cross-repo connections. A subproject is any working repository in your project ecosystem (microservices, frontends, backends, shared libraries, CLI tools, etc.). Displays repos, endpoints, client calls, and inter-repo dependency edges.",
|
|
72278
|
+
"Show all subprojects and their cross-repo connections. A subproject is any working repository in your project ecosystem (microservices, frontends, backends, shared libraries, CLI tools, etc.). Displays repos, endpoints, client calls, and inter-repo dependency edges. Use to understand multi-repo topology. Register repos first with subproject_add_repo. Read-only. Returns JSON: { repos, endpoints, clientCalls, edges }.",
|
|
72184
72279
|
{},
|
|
72185
72280
|
async () => {
|
|
72186
72281
|
const result = getSubprojectGraph(topoStore);
|
|
@@ -72190,7 +72285,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72190
72285
|
);
|
|
72191
72286
|
server.tool(
|
|
72192
72287
|
"get_subproject_impact",
|
|
72193
|
-
"Cross-repo impact analysis: find all client code across subprojects that would break if an endpoint changes. Resolves down to symbol level when per-repo indexes exist.",
|
|
72288
|
+
"Cross-repo impact analysis: find all client code across subprojects that would break if an endpoint changes. Resolves down to symbol level when per-repo indexes exist. Use before modifying a shared API endpoint. Read-only. Returns JSON: { endpoint, affectedClients: [{ repo, file, line, callType }], total }.",
|
|
72194
72289
|
{
|
|
72195
72290
|
endpoint: z8.string().max(512).optional().describe("Endpoint path pattern (e.g. /api/users)"),
|
|
72196
72291
|
method: z8.string().max(10).optional().describe("HTTP method filter (e.g. GET, POST)"),
|
|
@@ -72204,7 +72299,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72204
72299
|
);
|
|
72205
72300
|
server.tool(
|
|
72206
72301
|
"subproject_add_repo",
|
|
72207
|
-
"Add a repository as a subproject of the current project. A subproject is any working repository in your ecosystem: microservices, frontends, backends, shared libraries, CLI tools. Discovers services, parses API contracts (OpenAPI/gRPC/GraphQL), scans for HTTP client calls, and links them to known endpoints.",
|
|
72302
|
+
"Add a repository as a subproject of the current project. A subproject is any working repository in your ecosystem: microservices, frontends, backends, shared libraries, CLI tools. Discovers services, parses API contracts (OpenAPI/gRPC/GraphQL), scans for HTTP client calls, and links them to known endpoints. Mutates the topology store; idempotent. Use to build multi-repo intelligence. Returns JSON: { added, services, contracts, clientCalls }.",
|
|
72208
72303
|
{
|
|
72209
72304
|
repo_path: z8.string().min(1).max(1024).describe("Absolute or relative path to the repository/service"),
|
|
72210
72305
|
name: z8.string().max(256).optional().describe("Display name for the repo (default: directory basename)"),
|
|
@@ -72220,7 +72315,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72220
72315
|
);
|
|
72221
72316
|
server.tool(
|
|
72222
72317
|
"subproject_sync",
|
|
72223
|
-
"Re-scan all subprojects: re-discover services, re-parse contracts, re-scan client calls, and re-link everything.",
|
|
72318
|
+
"Re-scan all subprojects: re-discover services, re-parse contracts, re-scan client calls, and re-link everything. Mutates the topology store; idempotent. Use after code changes in subproject repos. Returns JSON: { synced, services, contracts, clientCalls }.",
|
|
72224
72319
|
{},
|
|
72225
72320
|
async () => {
|
|
72226
72321
|
const result = subprojectSync(topoStore);
|
|
@@ -72230,7 +72325,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72230
72325
|
);
|
|
72231
72326
|
server.tool(
|
|
72232
72327
|
"get_subproject_clients",
|
|
72233
|
-
"Find all client calls across subprojects that call a specific endpoint. Shows file, line, call type, and confidence.",
|
|
72328
|
+
"Find all client calls across subprojects that call a specific endpoint. Shows file, line, call type, and confidence. Use to find all consumers of an endpoint before modifying it. Read-only. Returns JSON: { endpoint, clients: [{ repo, file, line, callType, confidence }], total }.",
|
|
72234
72329
|
{
|
|
72235
72330
|
endpoint: z8.string().min(1).max(512).describe("Endpoint path to search for (e.g. /api/users)"),
|
|
72236
72331
|
method: z8.string().max(10).optional().describe("HTTP method filter")
|
|
@@ -72243,7 +72338,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72243
72338
|
);
|
|
72244
72339
|
server.tool(
|
|
72245
72340
|
"get_contract_versions",
|
|
72246
|
-
"Show version history for a service API contract with breaking change detection between versions. Compares request/response schemas across snapshots to flag removed fields, type changes, and renames.",
|
|
72341
|
+
"Show version history for a service API contract with breaking change detection between versions. Compares request/response schemas across snapshots to flag removed fields, type changes, and renames. Use to review API evolution. For current spec-vs-code drift use get_contract_drift instead. Read-only. Returns JSON: { service, versions: [{ version, date, breakingChanges }] }.",
|
|
72247
72342
|
{
|
|
72248
72343
|
service: z8.string().min(1).max(256).describe("Service name"),
|
|
72249
72344
|
limit: z8.number().int().min(1).max(50).optional().describe("Max versions to show (default 10)")
|
|
@@ -72256,7 +72351,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72256
72351
|
);
|
|
72257
72352
|
server.tool(
|
|
72258
72353
|
"discover_claude_sessions",
|
|
72259
|
-
"Scan ~/.claude/projects for projects Claude Code has touched on this machine, decode each directory name back to its absolute path, and report which ones still exist plus session-file count and last activity. With add_as_subprojects=true, every existing project is registered as a subproject in one call \u2014 useful for spinning up multi-repo intelligence after a fresh clone.",
|
|
72354
|
+
"Scan ~/.claude/projects for projects Claude Code has touched on this machine, decode each directory name back to its absolute path, and report which ones still exist plus session-file count and last activity. With add_as_subprojects=true, every existing project is registered as a subproject in one call \u2014 useful for spinning up multi-repo intelligence after a fresh clone. Reads local filesystem; with add_as_subprojects=true also mutates topology store. Returns JSON: { projects: [{ path, sessions, lastActivity }], total }.",
|
|
72260
72355
|
{
|
|
72261
72356
|
scan_root: z8.string().max(1024).optional().describe("Override the scan root (default: ~/.claude/projects)"),
|
|
72262
72357
|
exclude_current: z8.boolean().optional().describe("Exclude the current project from results (default: true)"),
|
|
@@ -72278,7 +72373,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72278
72373
|
);
|
|
72279
72374
|
server.tool(
|
|
72280
72375
|
"visualize_subproject_topology",
|
|
72281
|
-
"Open interactive HTML visualization of the subproject topology: services as nodes, API calls as edges, health/risk indicators per service. Node size = endpoint count, color = health (green/yellow/red).",
|
|
72376
|
+
"Open interactive HTML visualization of the subproject topology: services as nodes, API calls as edges, health/risk indicators per service. Node size = endpoint count, color = health (green/yellow/red). Writes an HTML file to disk. Use for visual architecture review. Returns JSON: { outputPath, services, edges }.",
|
|
72282
72377
|
{
|
|
72283
72378
|
output: z8.string().max(512).optional().describe("Output file path (default: /tmp/trace-mcp-subproject-topology.html)"),
|
|
72284
72379
|
layout: z8.enum(["force", "hierarchical", "radial"]).optional().describe("Graph layout (default force)")
|
|
@@ -72300,7 +72395,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72300
72395
|
runtimeIntelligence.start().catch((e) => logger.error({ error: e }, "Failed to start Runtime Intelligence"));
|
|
72301
72396
|
server.tool(
|
|
72302
72397
|
"get_runtime_profile",
|
|
72303
|
-
"Runtime profile for a symbol or route: call count, latency percentiles (p50/p95/p99), error rate, calls per hour. Requires OTLP trace ingestion.",
|
|
72398
|
+
"Runtime profile for a symbol or route: call count, latency percentiles (p50/p95/p99), error rate, calls per hour. Requires OTLP trace ingestion. Read-only, queries external runtime data. Use for performance analysis of specific endpoints. Returns JSON: { symbol_id, callCount, latency: { p50, p95, p99 }, errorRate, callsPerHour }.",
|
|
72304
72399
|
{
|
|
72305
72400
|
symbol_id: z8.string().max(512).optional().describe("Symbol ID to profile"),
|
|
72306
72401
|
fqn: z8.string().max(512).optional().describe("Fully qualified name"),
|
|
@@ -72315,7 +72410,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72315
72410
|
);
|
|
72316
72411
|
server.tool(
|
|
72317
72412
|
"get_runtime_call_graph",
|
|
72318
|
-
"Actual call graph from runtime traces (vs static analysis). Shows observed call paths with call counts and latency.",
|
|
72413
|
+
"Actual call graph from runtime traces (vs static analysis). Shows observed call paths with call counts and latency. Requires OTLP trace ingestion. Read-only, queries external runtime data. For static call graph use get_call_graph instead. Returns JSON: { root, calls: [{ symbol, count, latency }] }.",
|
|
72319
72414
|
{
|
|
72320
72415
|
symbol_id: z8.string().max(512).optional().describe("Symbol ID as root"),
|
|
72321
72416
|
fqn: z8.string().max(512).optional().describe("Fully qualified name as root"),
|
|
@@ -72330,7 +72425,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72330
72425
|
);
|
|
72331
72426
|
server.tool(
|
|
72332
72427
|
"get_endpoint_analytics",
|
|
72333
|
-
"Per-route analytics: request count, error rate, latency, caller services. Requires OTLP trace ingestion.",
|
|
72428
|
+
"Per-route analytics: request count, error rate, latency, caller services. Requires OTLP trace ingestion. Read-only, queries external runtime data. Use to understand endpoint performance and traffic. Returns JSON: { uri, method, requestCount, errorRate, latency, callerServices }.",
|
|
72334
72429
|
{
|
|
72335
72430
|
uri: z8.string().max(512).describe('Route URI (e.g. "/api/users/{id}")'),
|
|
72336
72431
|
method: z8.string().max(10).optional().describe("HTTP method filter"),
|
|
@@ -72344,7 +72439,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72344
72439
|
);
|
|
72345
72440
|
server.tool(
|
|
72346
72441
|
"get_runtime_deps",
|
|
72347
|
-
"Which external services (databases, caches, APIs, queues) does this code actually call at runtime. Based on OTLP traces.",
|
|
72442
|
+
"Which external services (databases, caches, APIs, queues) does this code actually call at runtime. Based on OTLP traces. Read-only, queries external runtime data. Use to discover actual runtime dependencies vs static analysis. Returns JSON: { dependencies: [{ type, name, callCount }] }.",
|
|
72348
72443
|
{
|
|
72349
72444
|
symbol_id: z8.string().max(512).optional().describe("Symbol ID"),
|
|
72350
72445
|
fqn: z8.string().max(512).optional().describe("Fully qualified name"),
|
|
@@ -72363,7 +72458,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72363
72458
|
}
|
|
72364
72459
|
server.tool(
|
|
72365
72460
|
"query_by_intent",
|
|
72366
|
-
"Map a business question to domain taxonomy \u2192 returns domain ownership and relevance scores (no source code). Use when you need to know WHICH DOMAIN owns specific functionality.",
|
|
72461
|
+
"Map a business question to domain taxonomy \u2192 returns domain ownership and relevance scores (no source code). Use when you need to know WHICH DOMAIN owns specific functionality. For actual source code use get_feature_context instead. Read-only. Returns JSON: { symbols: [{ symbol_id, domain, relevance }] }.",
|
|
72367
72462
|
{
|
|
72368
72463
|
query: z8.string().min(1).max(500).describe("Business-level question about the codebase"),
|
|
72369
72464
|
limit: z8.number().int().min(1).max(50).optional().describe("Max symbols to return (default 15)")
|
|
@@ -72381,7 +72476,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72381
72476
|
);
|
|
72382
72477
|
server.tool(
|
|
72383
72478
|
"get_domain_map",
|
|
72384
|
-
"Get hierarchical map of business domains with key symbols per domain. Auto-builds domain taxonomy on first call using heuristic classification.",
|
|
72479
|
+
"Get hierarchical map of business domains with key symbols per domain. Auto-builds domain taxonomy on first call using heuristic classification. Use to understand business domain boundaries. For specific domain code use get_domain_context instead. Read-only. Returns JSON: { domains: [{ name, children, symbols }] }.",
|
|
72385
72480
|
{
|
|
72386
72481
|
depth: z8.number().int().min(1).max(5).optional().describe("Max taxonomy depth (default 3)"),
|
|
72387
72482
|
include_symbols: z8.boolean().optional().describe("Include top symbols per domain (default true)"),
|
|
@@ -72395,7 +72490,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72395
72490
|
);
|
|
72396
72491
|
server.tool(
|
|
72397
72492
|
"get_domain_context",
|
|
72398
|
-
'Get all code related to a specific business domain. Supports "parent/child" notation (e.g. "payments/refunds").',
|
|
72493
|
+
'Get all code related to a specific business domain. Supports "parent/child" notation (e.g. "payments/refunds"). Use to explore code within a domain boundary. For the full domain taxonomy use get_domain_map instead. Read-only. Returns JSON: { domain, symbols: [{ symbol_id, name, file, source }], relatedDomains }.',
|
|
72399
72494
|
{
|
|
72400
72495
|
domain: z8.string().min(1).max(256).describe('Domain name (e.g. "payments" or "payments/refunds")'),
|
|
72401
72496
|
include_related: z8.boolean().optional().describe("Include symbols from related domains (default false)"),
|
|
@@ -72409,7 +72504,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72409
72504
|
);
|
|
72410
72505
|
server.tool(
|
|
72411
72506
|
"get_cross_domain_deps",
|
|
72412
|
-
"Show which business domains depend on which. Based on edges between symbols in different domains.",
|
|
72507
|
+
"Show which business domains depend on which. Based on edges between symbols in different domains. Use to understand domain coupling. Read-only. Returns JSON: { dependencies: [{ from, to, edgeCount }] }.",
|
|
72413
72508
|
{
|
|
72414
72509
|
domain: z8.string().max(256).optional().describe("Focus on a specific domain (default: all)")
|
|
72415
72510
|
},
|
|
@@ -72421,7 +72516,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72421
72516
|
);
|
|
72422
72517
|
server.tool(
|
|
72423
72518
|
"graph_query",
|
|
72424
|
-
'Trace how named symbols relate in the dependency graph \u2192 returns subgraph + Mermaid diagram. Input must contain symbol/class names (e.g. "How does AuthService reach Database?", "What depends on UserModel?").',
|
|
72519
|
+
'Trace how named symbols relate in the dependency graph \u2192 returns subgraph + Mermaid diagram. Input must contain symbol/class names (e.g. "How does AuthService reach Database?", "What depends on UserModel?"). Use for ad-hoc graph exploration. For structured call graph use get_call_graph instead. Read-only. Returns JSON: { nodes, edges, mermaid }.',
|
|
72425
72520
|
{
|
|
72426
72521
|
query: z8.string().min(1).max(500).describe("Natural language question about code relationships"),
|
|
72427
72522
|
depth: z8.number().int().min(1).max(6).optional().describe("Max traversal depth (default 3)"),
|
|
@@ -72435,7 +72530,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72435
72530
|
);
|
|
72436
72531
|
server.tool(
|
|
72437
72532
|
"get_dataflow",
|
|
72438
|
-
"Intra-function dataflow analysis: track how each parameter flows through the function body \u2014 into which calls, where it gets mutated, and what is returned. Phase 1: single function scope.",
|
|
72533
|
+
"Intra-function dataflow analysis: track how each parameter flows through the function body \u2014 into which calls, where it gets mutated, and what is returned. Phase 1: single function scope. Use to understand data transformations within a function. For security-focused data flow use taint_analysis instead. Read-only. Returns JSON: { symbol_id, params: [{ name, flows: [{ target, mutated }] }], returnPaths }.",
|
|
72439
72534
|
{
|
|
72440
72535
|
symbol_id: z8.string().max(512).optional().describe("Symbol ID of the function/method to analyze"),
|
|
72441
72536
|
fqn: z8.string().max(512).optional().describe("Fully qualified name of the function/method"),
|
|
@@ -72450,7 +72545,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72450
72545
|
);
|
|
72451
72546
|
server.tool(
|
|
72452
72547
|
"visualize_graph",
|
|
72453
|
-
"Open interactive HTML graph in browser showing file/symbol dependencies. Supports force/hierarchical/radial layouts, community coloring. Use granularity=symbol to see individual functions/classes/methods as nodes instead of files.",
|
|
72548
|
+
"Open interactive HTML graph in browser showing file/symbol dependencies. Supports force/hierarchical/radial layouts, community coloring. Use granularity=symbol to see individual functions/classes/methods as nodes instead of files. Writes an HTML file to disk. For static Mermaid/DOT output use get_dependency_diagram instead. Returns JSON: { outputPath, nodes, edges }.",
|
|
72454
72549
|
{
|
|
72455
72550
|
scope: z8.string().min(1).max(512).describe('Scope: file path, directory (e.g. "src/"), or "project"'),
|
|
72456
72551
|
depth: z8.number().int().min(1).max(5).optional().describe("Max hops from scope (default 2)"),
|
|
@@ -72486,7 +72581,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72486
72581
|
);
|
|
72487
72582
|
server.tool(
|
|
72488
72583
|
"get_dependency_diagram",
|
|
72489
|
-
'Render dependency diagram for a file/directory path as Mermaid or DOT. Input: a path like "src/tools/" \u2014 not a question. Trims to max_nodes most important nodes.',
|
|
72584
|
+
'Render dependency diagram for a file/directory path as Mermaid or DOT. Input: a path like "src/tools/" \u2014 not a question. Trims to max_nodes most important nodes. Read-only. For interactive HTML visualization use visualize_graph instead. Returns JSON: { format, diagram, nodes, edges }.',
|
|
72490
72585
|
{
|
|
72491
72586
|
scope: z8.string().min(1).max(512).describe('Scope: file path, directory, or "project"'),
|
|
72492
72587
|
depth: z8.number().int().min(1).max(5).optional().describe("Max hops from scope (default 2)"),
|
|
@@ -72501,7 +72596,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72501
72596
|
);
|
|
72502
72597
|
server.tool(
|
|
72503
72598
|
"search_text",
|
|
72504
|
-
"Full-text search across all indexed files. Supports regex, glob file patterns, language filter. Use for finding strings, comments, TODOs, config values, error messages \u2014 anything not captured as a symbol.",
|
|
72599
|
+
"Full-text search across all indexed files. Supports regex, glob file patterns, language filter. Use for finding strings, comments, TODOs, config values, error messages \u2014 anything not captured as a symbol. For symbol search (functions, classes) use search instead. Read-only. Returns JSON: { matches: [{ file, line, text, context }], total_matches }.",
|
|
72505
72600
|
{
|
|
72506
72601
|
query: z8.string().min(1).max(1e3).describe("Search string or regex pattern"),
|
|
72507
72602
|
is_regex: z8.boolean().optional().describe("Treat query as regex (default false)"),
|
|
@@ -72532,7 +72627,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72532
72627
|
);
|
|
72533
72628
|
server.tool(
|
|
72534
72629
|
"predict_bugs",
|
|
72535
|
-
"Predict which files are most likely to contain bugs. Multi-signal scoring: git churn, fix-commit ratio, complexity, coupling, PageRank importance, author count. Each prediction includes a numeric score, risk bucket (low/medium/high/critical) AND a confidence_level (low/medium/high/multi_signal) counting how many independent signals actually fired. Result envelope includes _methodology disclosure. Cached for 1 hour; use refresh=true to recompute.",
|
|
72630
|
+
"Predict which files are most likely to contain bugs. Multi-signal scoring: git churn, fix-commit ratio, complexity, coupling, PageRank importance, author count. Each prediction includes a numeric score, risk bucket (low/medium/high/critical) AND a confidence_level (low/medium/high/multi_signal) counting how many independent signals actually fired. Result envelope includes _methodology disclosure. Cached for 1 hour; use refresh=true to recompute. Requires git. Use for proactive bug hunting. For complexity+churn hotspots only use get_risk_hotspots instead. Read-only. Returns JSON: { predictions: [{ file, score, risk, confidence_level, signals }], total }.",
|
|
72536
72631
|
{
|
|
72537
72632
|
limit: z8.number().int().min(1).max(200).optional().describe("Max results (default: 50)"),
|
|
72538
72633
|
min_score: z8.number().min(0).max(1).optional().describe("Min bug probability score to include (default: 0)"),
|
|
@@ -72555,7 +72650,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72555
72650
|
);
|
|
72556
72651
|
server.tool(
|
|
72557
72652
|
"detect_drift",
|
|
72558
|
-
"Detect architectural drift: cross-module co-change anomalies (files in different modules that always change together) and shotgun surgery patterns (commits touching 3+ modules). Requires git.",
|
|
72653
|
+
"Detect architectural drift: cross-module co-change anomalies (files in different modules that always change together) and shotgun surgery patterns (commits touching 3+ modules). Requires git. Use to identify hidden coupling across modules. For file-pair co-changes use get_co_changes instead. Read-only. Returns JSON: { anomalies, shotgunSurgery, total }.",
|
|
72559
72654
|
{
|
|
72560
72655
|
since_days: z8.number().int().min(1).optional().describe("Analyze commits from last N days (default: 180)"),
|
|
72561
72656
|
min_confidence: z8.number().min(0).max(1).optional().describe("Min Jaccard confidence for co-change anomalies (default: 0.3)")
|
|
@@ -72572,7 +72667,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72572
72667
|
);
|
|
72573
72668
|
server.tool(
|
|
72574
72669
|
"get_tech_debt",
|
|
72575
|
-
"Per-module tech debt score (A\u2013F grade) combining: complexity, coupling instability, test coverage gaps, and git churn. Includes actionable recommendations.",
|
|
72670
|
+
"Per-module tech debt score (A\u2013F grade) combining: complexity, coupling instability, test coverage gaps, and git churn. Includes actionable recommendations. Use for architecture review and prioritizing cleanup. Read-only. Returns JSON: { modules: [{ module, grade, score, factors, recommendations }] }.",
|
|
72576
72671
|
{
|
|
72577
72672
|
module: z8.string().max(256).optional().describe('Focus on a specific module path (e.g. "src/tools")'),
|
|
72578
72673
|
refresh: z8.boolean().optional().describe("Force recomputation (default: false)")
|
|
@@ -72591,7 +72686,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72591
72686
|
);
|
|
72592
72687
|
server.tool(
|
|
72593
72688
|
"assess_change_risk",
|
|
72594
|
-
"Before modifying a file or symbol, predict risk level (low/medium/high/critical) with contributing factors and recommended mitigations. Combines blast radius, complexity, git churn, test coverage, and coupling.",
|
|
72689
|
+
"Before modifying a file or symbol, predict risk level (low/medium/high/critical) with contributing factors and recommended mitigations. Combines blast radius, complexity, git churn, test coverage, and coupling. Use as a quick risk check. For full impact report with affected tests and dependents use get_change_impact instead. Read-only. Returns JSON: { risk, level, factors: [{ name, value }], mitigations }.",
|
|
72595
72690
|
{
|
|
72596
72691
|
file_path: z8.string().max(512).optional().describe("File path to assess"),
|
|
72597
72692
|
symbol_id: z8.string().max(512).optional().describe("Symbol ID to assess")
|
|
@@ -72613,7 +72708,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72613
72708
|
);
|
|
72614
72709
|
server.tool(
|
|
72615
72710
|
"get_health_trends",
|
|
72616
|
-
"Time-series health metrics for a file or module: bug score, complexity, coupling, churn over time. Populated by predict_bugs runs.",
|
|
72711
|
+
"Time-series health metrics for a file or module: bug score, complexity, coupling, churn over time. Populated by predict_bugs runs. Use to track if a module is improving or degrading. Read-only. Returns JSON: { dataPoints: [{ date, bugScore, complexity, coupling, churn }] }.",
|
|
72617
72712
|
{
|
|
72618
72713
|
file_path: z8.string().max(512).optional().describe("File path to check"),
|
|
72619
72714
|
module: z8.string().max(256).optional().describe("Module path prefix to check"),
|
|
@@ -72631,7 +72726,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72631
72726
|
);
|
|
72632
72727
|
server.tool(
|
|
72633
72728
|
"get_workspace_map",
|
|
72634
|
-
"List all detected monorepo workspaces with file counts, symbol counts, and languages. Returns dependency graph between workspaces showing cross-workspace imports.",
|
|
72729
|
+
"List all detected monorepo workspaces with file counts, symbol counts, and languages. Returns dependency graph between workspaces showing cross-workspace imports. Use for monorepo structure overview. For impact of changes on other workspaces use get_cross_workspace_impact instead. Read-only. Returns JSON: { workspaces: [{ name, files, symbols, languages }], dependencies }.",
|
|
72635
72730
|
{
|
|
72636
72731
|
include_dependencies: z8.boolean().optional().describe("Include cross-workspace dependency graph (default: true)")
|
|
72637
72732
|
},
|
|
@@ -72662,7 +72757,7 @@ function registerAdvancedTools(server, ctx) {
|
|
|
72662
72757
|
);
|
|
72663
72758
|
server.tool(
|
|
72664
72759
|
"get_cross_workspace_impact",
|
|
72665
|
-
"Show which workspaces are affected by changes in a given workspace. Lists all cross-workspace edges, affected symbols, and the public API surface consumed by other workspaces.",
|
|
72760
|
+
"Show which workspaces are affected by changes in a given workspace. Lists all cross-workspace edges, affected symbols, and the public API surface consumed by other workspaces. Use before modifying shared code in a monorepo. Read-only. Returns JSON: { workspace, public_api, consumed_by, depends_on, cross_workspace_edges }.",
|
|
72666
72761
|
{
|
|
72667
72762
|
workspace: z8.string().max(256).describe("Workspace name to analyze")
|
|
72668
72763
|
},
|
|
@@ -74493,28 +74588,331 @@ function evaluateQualityGates(store, projectRoot, gatesConfig, options = {}) {
|
|
|
74493
74588
|
};
|
|
74494
74589
|
}
|
|
74495
74590
|
|
|
74591
|
+
// src/tools/quality/security-context-export.ts
|
|
74592
|
+
import { readFileSync as readFileSync7 } from "fs";
|
|
74593
|
+
import path57 from "path";
|
|
74594
|
+
import { ok as ok10 } from "neverthrow";
|
|
74595
|
+
var CATEGORY_PATTERNS = [
|
|
74596
|
+
// file_read
|
|
74597
|
+
{ pattern: /^(?:readFile|readFileSync|readdir|readdirSync|createReadStream|promises\.readFile)$/, category: "file_read" },
|
|
74598
|
+
{ pattern: /^(?:fs\.read|fs\.promises\.read|fsPromises\.read)/, category: "file_read" },
|
|
74599
|
+
// file_write
|
|
74600
|
+
{ pattern: /^(?:writeFile|writeFileSync|appendFile|appendFileSync|createWriteStream|promises\.writeFile)$/, category: "file_write" },
|
|
74601
|
+
{ pattern: /^(?:unlink|unlinkSync|rm|rmSync|rmdir|rmdirSync|rename|renameSync|copyFile|copyFileSync)$/, category: "file_write" },
|
|
74602
|
+
{ pattern: /^(?:fs\.write|fs\.promises\.write|fs\.unlink|fs\.rm|fsPromises\.write)/, category: "file_write" },
|
|
74603
|
+
{ pattern: /^(?:mkdir|mkdirSync|promises\.mkdir)$/, category: "file_write" },
|
|
74604
|
+
// network_outbound
|
|
74605
|
+
{ pattern: /^(?:fetch|request|got|axios)$/, category: "network_outbound" },
|
|
74606
|
+
{ pattern: /^(?:http\.request|https\.request|http\.get|https\.get)$/, category: "network_outbound" },
|
|
74607
|
+
{ pattern: /^(?:net\.connect|net\.createConnection|tls\.connect)$/, category: "network_outbound" },
|
|
74608
|
+
{ pattern: /^(?:XMLHttpRequest|WebSocket)$/, category: "network_outbound" },
|
|
74609
|
+
// env_read
|
|
74610
|
+
{ pattern: /^(?:process\.env|env\.)/, category: "env_read" },
|
|
74611
|
+
{ pattern: /^(?:getenv|os\.environ|dotenv)/, category: "env_read" },
|
|
74612
|
+
// shell_exec
|
|
74613
|
+
{ pattern: /^(?:exec|execSync|execFile|execFileSync|spawn|spawnSync|fork)$/, category: "shell_exec" },
|
|
74614
|
+
{ pattern: /^(?:child_process\.|cp\.)/, category: "shell_exec" },
|
|
74615
|
+
// crypto
|
|
74616
|
+
{ pattern: /^(?:createHash|createCipher|createCipheriv|createDecipher|createDecipheriv|createSign|createVerify|createHmac)$/, category: "crypto" },
|
|
74617
|
+
{ pattern: /^(?:crypto\.)/, category: "crypto" },
|
|
74618
|
+
// serialization
|
|
74619
|
+
{ pattern: /^(?:eval|Function)$/, category: "serialization" },
|
|
74620
|
+
{ pattern: /^(?:deserialize|unserialize|pickle\.loads|yaml\.load)$/, category: "serialization" }
|
|
74621
|
+
];
|
|
74622
|
+
function classifyFunction(name) {
|
|
74623
|
+
for (const { pattern, category } of CATEGORY_PATTERNS) {
|
|
74624
|
+
if (pattern.test(name)) return category;
|
|
74625
|
+
}
|
|
74626
|
+
return null;
|
|
74627
|
+
}
|
|
74628
|
+
var ANNOTATION_RE = /\{\s*(?:readOnlyHint|destructiveHint|idempotentHint|openWorldHint)\s*:/;
|
|
74629
|
+
function parseAnnotations(source, toolCallIndex) {
|
|
74630
|
+
const searchRegion = source.slice(toolCallIndex, toolCallIndex + 2e3);
|
|
74631
|
+
const annotationMatch = searchRegion.match(
|
|
74632
|
+
/\{\s*(readOnlyHint\s*:\s*(true|false)\s*,?\s*)?(destructiveHint\s*:\s*(true|false)\s*,?\s*)?(idempotentHint\s*:\s*(true|false)\s*,?\s*)?(openWorldHint\s*:\s*(true|false)\s*,?\s*)\}/
|
|
74633
|
+
);
|
|
74634
|
+
if (!annotationMatch) return null;
|
|
74635
|
+
const annotations = {};
|
|
74636
|
+
if (annotationMatch[2]) annotations.readOnlyHint = annotationMatch[2] === "true";
|
|
74637
|
+
if (annotationMatch[4]) annotations.destructiveHint = annotationMatch[4] === "true";
|
|
74638
|
+
if (annotationMatch[6]) annotations.idempotentHint = annotationMatch[6] === "true";
|
|
74639
|
+
if (annotationMatch[8]) annotations.openWorldHint = annotationMatch[8] === "true";
|
|
74640
|
+
return Object.keys(annotations).length > 0 ? annotations : null;
|
|
74641
|
+
}
|
|
74642
|
+
function parseAnnotationsFlexible(source, toolCallIndex) {
|
|
74643
|
+
const searchRegion = source.slice(toolCallIndex, toolCallIndex + 3e3);
|
|
74644
|
+
if (!ANNOTATION_RE.test(searchRegion)) return null;
|
|
74645
|
+
const annotations = {};
|
|
74646
|
+
const hints = ["readOnlyHint", "destructiveHint", "idempotentHint", "openWorldHint"];
|
|
74647
|
+
for (const hint of hints) {
|
|
74648
|
+
const re = new RegExp(`${hint}\\s*:\\s*(true|false)`);
|
|
74649
|
+
const m = searchRegion.match(re);
|
|
74650
|
+
if (m) annotations[hint] = m[1] === "true";
|
|
74651
|
+
}
|
|
74652
|
+
return Object.keys(annotations).length > 0 ? annotations : null;
|
|
74653
|
+
}
|
|
74654
|
+
function collectCallsFromGraph(node, visited, results) {
|
|
74655
|
+
if (visited.has(node.symbol_id)) return;
|
|
74656
|
+
visited.add(node.symbol_id);
|
|
74657
|
+
const category = classifyFunction(node.name);
|
|
74658
|
+
if (category && node.file && node.line) {
|
|
74659
|
+
results.push({
|
|
74660
|
+
function: node.name,
|
|
74661
|
+
file: node.file,
|
|
74662
|
+
line: node.line,
|
|
74663
|
+
category
|
|
74664
|
+
});
|
|
74665
|
+
}
|
|
74666
|
+
if (node.calls) {
|
|
74667
|
+
for (const callee of node.calls) {
|
|
74668
|
+
collectCallsFromGraph(callee, visited, results);
|
|
74669
|
+
}
|
|
74670
|
+
}
|
|
74671
|
+
}
|
|
74672
|
+
var SECURITY_CALL_RE = /\b((?:fs|http|https|net|crypto|child_process|cp)\.\w+|fetch|exec|execSync|spawn|spawnSync|eval|require|writeFile\w*|readFile\w*|unlink\w*|request|axios|got)\s*\(/g;
|
|
74673
|
+
var ENV_ACCESS_RE = /process\.env\b/g;
|
|
74674
|
+
var GENERIC_CALL_RE = /\b([a-zA-Z_$]\w*)\s*\(/g;
|
|
74675
|
+
var SKIP_KEYWORDS = /* @__PURE__ */ new Set([
|
|
74676
|
+
"if",
|
|
74677
|
+
"for",
|
|
74678
|
+
"while",
|
|
74679
|
+
"switch",
|
|
74680
|
+
"catch",
|
|
74681
|
+
"return",
|
|
74682
|
+
"typeof",
|
|
74683
|
+
"new",
|
|
74684
|
+
"async",
|
|
74685
|
+
"await",
|
|
74686
|
+
"function",
|
|
74687
|
+
"const",
|
|
74688
|
+
"let",
|
|
74689
|
+
"var",
|
|
74690
|
+
"class",
|
|
74691
|
+
"import",
|
|
74692
|
+
"export",
|
|
74693
|
+
"throw",
|
|
74694
|
+
"delete",
|
|
74695
|
+
"void",
|
|
74696
|
+
"yield",
|
|
74697
|
+
"as",
|
|
74698
|
+
"from"
|
|
74699
|
+
]);
|
|
74700
|
+
function findHandlerBounds(source, toolCallIndex) {
|
|
74701
|
+
const region = source.slice(toolCallIndex, toolCallIndex + 1e4);
|
|
74702
|
+
const arrowMatch = region.match(/async\s+(?:\([^)]*\)|[^=]*?)\s*=>\s*\{/);
|
|
74703
|
+
const funcMatch = region.match(/async\s+function\s*\([^)]*\)\s*\{/);
|
|
74704
|
+
const match = arrowMatch ?? funcMatch;
|
|
74705
|
+
if (!match || match.index === void 0) return null;
|
|
74706
|
+
const bodyBraceOffset = match.index + match[0].length - 1;
|
|
74707
|
+
const afterBrace = region.slice(bodyBraceOffset);
|
|
74708
|
+
let depth = 1;
|
|
74709
|
+
let end = -1;
|
|
74710
|
+
for (let i = 1; i < afterBrace.length; i++) {
|
|
74711
|
+
if (afterBrace[i] === "{") depth++;
|
|
74712
|
+
else if (afterBrace[i] === "}") {
|
|
74713
|
+
depth--;
|
|
74714
|
+
if (depth === 0) {
|
|
74715
|
+
end = i + 1;
|
|
74716
|
+
break;
|
|
74717
|
+
}
|
|
74718
|
+
}
|
|
74719
|
+
}
|
|
74720
|
+
if (end === -1) end = Math.min(afterBrace.length, 5e3);
|
|
74721
|
+
const absStart = toolCallIndex + bodyBraceOffset;
|
|
74722
|
+
const absEnd = toolCallIndex + bodyBraceOffset + end;
|
|
74723
|
+
return { start: absStart, end: absEnd };
|
|
74724
|
+
}
|
|
74725
|
+
function scanInlineHandler(source, toolCallIndex, filePath, store, projectRoot, depth) {
|
|
74726
|
+
const bounds = findHandlerBounds(source, toolCallIndex);
|
|
74727
|
+
if (!bounds) return { calls: [], calledSymbolIds: [] };
|
|
74728
|
+
const handlerBody = source.slice(bounds.start, bounds.end);
|
|
74729
|
+
const results = [];
|
|
74730
|
+
const calledSymbolIds = [];
|
|
74731
|
+
let m;
|
|
74732
|
+
const secRe = new RegExp(SECURITY_CALL_RE.source, "g");
|
|
74733
|
+
while ((m = secRe.exec(handlerBody)) !== null) {
|
|
74734
|
+
const funcName = m[1];
|
|
74735
|
+
const category = classifyFunction(funcName);
|
|
74736
|
+
if (category) {
|
|
74737
|
+
const lineOffset = source.slice(0, bounds.start + m.index).split("\n").length;
|
|
74738
|
+
results.push({ function: funcName, file: filePath, line: lineOffset, category });
|
|
74739
|
+
}
|
|
74740
|
+
}
|
|
74741
|
+
const envRe = new RegExp(ENV_ACCESS_RE.source, "g");
|
|
74742
|
+
while ((m = envRe.exec(handlerBody)) !== null) {
|
|
74743
|
+
const lineOffset = source.slice(0, bounds.start + m.index).split("\n").length;
|
|
74744
|
+
results.push({ function: "process.env", file: filePath, line: lineOffset, category: "env_read" });
|
|
74745
|
+
}
|
|
74746
|
+
const genericRe = new RegExp(GENERIC_CALL_RE.source, "g");
|
|
74747
|
+
const seenFuncs = /* @__PURE__ */ new Set();
|
|
74748
|
+
while ((m = genericRe.exec(handlerBody)) !== null) {
|
|
74749
|
+
const funcName = m[1];
|
|
74750
|
+
if (SKIP_KEYWORDS.has(funcName) || seenFuncs.has(funcName)) continue;
|
|
74751
|
+
seenFuncs.add(funcName);
|
|
74752
|
+
const sym = store.getSymbolByName(funcName, "function") ?? store.getSymbolByName(funcName, "method");
|
|
74753
|
+
if (!sym) continue;
|
|
74754
|
+
calledSymbolIds.push(sym.symbol_id);
|
|
74755
|
+
const cgResult = getCallGraph(store, { symbolId: sym.symbol_id }, depth);
|
|
74756
|
+
if (cgResult.isOk() && cgResult.value.root) {
|
|
74757
|
+
const visited = /* @__PURE__ */ new Set();
|
|
74758
|
+
collectCallsFromGraph(cgResult.value.root, visited, results);
|
|
74759
|
+
}
|
|
74760
|
+
const file = sym.file_id ? store.getFileById(sym.file_id) : null;
|
|
74761
|
+
if (file && sym.line_start && sym.line_end) {
|
|
74762
|
+
const symAbsPath = path57.resolve(projectRoot, file.path);
|
|
74763
|
+
try {
|
|
74764
|
+
const symSource = readFileSync7(symAbsPath, "utf-8");
|
|
74765
|
+
const lines = symSource.split("\n");
|
|
74766
|
+
const symBody = lines.slice(sym.line_start - 1, sym.line_end).join("\n");
|
|
74767
|
+
scanSourceForSecurityCalls(symBody, file.path, sym.line_start, results);
|
|
74768
|
+
} catch {
|
|
74769
|
+
}
|
|
74770
|
+
}
|
|
74771
|
+
}
|
|
74772
|
+
return { calls: results, calledSymbolIds };
|
|
74773
|
+
}
|
|
74774
|
+
function scanSourceForSecurityCalls(body, filePath, startLine, results) {
|
|
74775
|
+
let m;
|
|
74776
|
+
const secRe = new RegExp(SECURITY_CALL_RE.source, "g");
|
|
74777
|
+
while ((m = secRe.exec(body)) !== null) {
|
|
74778
|
+
const funcName = m[1];
|
|
74779
|
+
const category = classifyFunction(funcName);
|
|
74780
|
+
if (category) {
|
|
74781
|
+
const lineOffset = startLine + body.slice(0, m.index).split("\n").length - 1;
|
|
74782
|
+
results.push({ function: funcName, file: filePath, line: lineOffset, category });
|
|
74783
|
+
}
|
|
74784
|
+
}
|
|
74785
|
+
const envRe = new RegExp(ENV_ACCESS_RE.source, "g");
|
|
74786
|
+
while ((m = envRe.exec(body)) !== null) {
|
|
74787
|
+
const lineOffset = startLine + body.slice(0, m.index).split("\n").length - 1;
|
|
74788
|
+
results.push({ function: "process.env", file: filePath, line: lineOffset, category: "env_read" });
|
|
74789
|
+
}
|
|
74790
|
+
}
|
|
74791
|
+
var PKG_VERSION = true ? "1.22.0" : "0.0.0-dev";
|
|
74792
|
+
function exportSecurityContext(store, projectRoot, opts = {}) {
|
|
74793
|
+
const depth = Math.min(opts.depth ?? 3, 5);
|
|
74794
|
+
const warnings = [];
|
|
74795
|
+
const allRoutes = store.getAllRoutes();
|
|
74796
|
+
const toolRoutes = allRoutes.filter((r) => r.method === "TOOL");
|
|
74797
|
+
if (toolRoutes.length === 0) {
|
|
74798
|
+
warnings.push("No MCP tool registrations found in the index. Ensure the project uses @modelcontextprotocol/sdk and has been indexed.");
|
|
74799
|
+
}
|
|
74800
|
+
const toolRegistrations = [];
|
|
74801
|
+
const capabilityMap = {};
|
|
74802
|
+
for (const route of toolRoutes) {
|
|
74803
|
+
const fileRow = route.file_id ? store.getFileById(route.file_id) : null;
|
|
74804
|
+
if (!fileRow) continue;
|
|
74805
|
+
if (opts.scope && !fileRow.path.startsWith(opts.scope)) continue;
|
|
74806
|
+
const absPath = path57.resolve(projectRoot, fileRow.path);
|
|
74807
|
+
let source;
|
|
74808
|
+
try {
|
|
74809
|
+
source = readFileSync7(absPath, "utf-8");
|
|
74810
|
+
} catch {
|
|
74811
|
+
continue;
|
|
74812
|
+
}
|
|
74813
|
+
const toolNameEscaped = route.uri.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
74814
|
+
const toolCallRe = new RegExp(`\\.tool\\(\\s*['"]${toolNameEscaped}['"]`);
|
|
74815
|
+
const toolCallMatch = toolCallRe.exec(source);
|
|
74816
|
+
const toolCallIndex = toolCallMatch?.index ?? 0;
|
|
74817
|
+
const toolLine = toolCallIndex > 0 ? source.slice(0, toolCallIndex).split("\n").length : route.line ?? 0;
|
|
74818
|
+
const annotations = parseAnnotationsFlexible(source, toolCallIndex) ?? parseAnnotations(source, toolCallIndex);
|
|
74819
|
+
let handlerCalls = [];
|
|
74820
|
+
let handlerResolved = false;
|
|
74821
|
+
if (toolCallIndex > 0) {
|
|
74822
|
+
const scanResult = scanInlineHandler(source, toolCallIndex, fileRow.path, store, projectRoot, depth);
|
|
74823
|
+
handlerCalls = scanResult.calls;
|
|
74824
|
+
handlerResolved = handlerCalls.length > 0 || scanResult.calledSymbolIds.length > 0;
|
|
74825
|
+
}
|
|
74826
|
+
const seen = /* @__PURE__ */ new Set();
|
|
74827
|
+
handlerCalls = handlerCalls.filter((c) => {
|
|
74828
|
+
const key = `${c.function}:${c.file}:${c.line}`;
|
|
74829
|
+
if (seen.has(key)) return false;
|
|
74830
|
+
seen.add(key);
|
|
74831
|
+
return true;
|
|
74832
|
+
});
|
|
74833
|
+
for (const call of handlerCalls) {
|
|
74834
|
+
if (!capabilityMap[call.file]) capabilityMap[call.file] = /* @__PURE__ */ new Set();
|
|
74835
|
+
capabilityMap[call.file].add(call.category);
|
|
74836
|
+
}
|
|
74837
|
+
toolRegistrations.push({
|
|
74838
|
+
name: route.uri,
|
|
74839
|
+
description: route.name ?? null,
|
|
74840
|
+
file: fileRow.path,
|
|
74841
|
+
line: toolLine,
|
|
74842
|
+
annotations,
|
|
74843
|
+
handler_resolved: handlerResolved,
|
|
74844
|
+
handler_calls: handlerCalls
|
|
74845
|
+
});
|
|
74846
|
+
}
|
|
74847
|
+
const sensitiveFlows = [];
|
|
74848
|
+
const mcpServerFiles = new Set(toolRegistrations.map((t) => t.file));
|
|
74849
|
+
if (mcpServerFiles.size > 0) {
|
|
74850
|
+
const mcpDirs = [...new Set([...mcpServerFiles].map((f) => path57.dirname(f)))];
|
|
74851
|
+
for (const dir of mcpDirs) {
|
|
74852
|
+
const taintResult = taintAnalysis(store, projectRoot, {
|
|
74853
|
+
scope: dir,
|
|
74854
|
+
sources: ["env", "file_read"],
|
|
74855
|
+
includeSanitized: false,
|
|
74856
|
+
limit: 50
|
|
74857
|
+
});
|
|
74858
|
+
if (taintResult.isOk()) {
|
|
74859
|
+
for (const flow of taintResult.value.flows) {
|
|
74860
|
+
sensitiveFlows.push({
|
|
74861
|
+
source: {
|
|
74862
|
+
kind: flow.source.kind,
|
|
74863
|
+
name: flow.source.variable,
|
|
74864
|
+
file: flow.file,
|
|
74865
|
+
line: flow.source.line
|
|
74866
|
+
},
|
|
74867
|
+
sink: {
|
|
74868
|
+
kind: flow.sink.kind,
|
|
74869
|
+
file: flow.file,
|
|
74870
|
+
line: flow.sink.line
|
|
74871
|
+
},
|
|
74872
|
+
hops: flow.path.map((step) => `${flow.file}:${step.line}`)
|
|
74873
|
+
});
|
|
74874
|
+
}
|
|
74875
|
+
}
|
|
74876
|
+
}
|
|
74877
|
+
}
|
|
74878
|
+
const capabilityMapOutput = {};
|
|
74879
|
+
for (const [file, categories] of Object.entries(capabilityMap)) {
|
|
74880
|
+
capabilityMapOutput[file] = [...categories].sort();
|
|
74881
|
+
}
|
|
74882
|
+
return ok10({
|
|
74883
|
+
$schema: "https://skill-scan.dev/schemas/enrichment/v1.json",
|
|
74884
|
+
version: "1",
|
|
74885
|
+
generator: `trace-mcp/${PKG_VERSION}`,
|
|
74886
|
+
generated_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
74887
|
+
tool_registrations: toolRegistrations,
|
|
74888
|
+
sensitive_flows: sensitiveFlows,
|
|
74889
|
+
capability_map: capabilityMapOutput,
|
|
74890
|
+
warnings
|
|
74891
|
+
});
|
|
74892
|
+
}
|
|
74893
|
+
|
|
74496
74894
|
// src/tools/register/quality.ts
|
|
74497
74895
|
function registerQualityTools(server, ctx) {
|
|
74498
74896
|
const { store, registry, config, projectRoot, j: j3 } = ctx;
|
|
74499
|
-
server.tool("get_co_changes", "Find files that frequently change together in git history (temporal coupling).", { file: z10.string().min(1).max(512).describe("File path to analyze"), min_confidence: z10.number().min(0).max(1).optional().describe("Minimum confidence threshold (default 0.3)"), min_count: z10.number().int().min(1).optional().describe("Minimum co-change count (default 3)"), window_days: z10.number().int().min(1).max(730).optional().describe("Git history window in days (default 180)"), limit: z10.number().int().min(1).max(100).optional().describe("Max results (default 20)") }, async ({ file, min_confidence, min_count, window_days, limit: lim }) => {
|
|
74897
|
+
server.tool("get_co_changes", "Find files that frequently change together in git history (temporal coupling). Requires git. Use to discover hidden dependencies between files. For cross-module co-change anomalies use detect_drift instead. Read-only. Returns JSON: { file, coChanges: [{ file, confidence, count }] }.", { file: z10.string().min(1).max(512).describe("File path to analyze"), min_confidence: z10.number().min(0).max(1).optional().describe("Minimum confidence threshold (default 0.3)"), min_count: z10.number().int().min(1).optional().describe("Minimum co-change count (default 3)"), window_days: z10.number().int().min(1).max(730).optional().describe("Git history window in days (default 180)"), limit: z10.number().int().min(1).max(100).optional().describe("Max results (default 20)") }, async ({ file, min_confidence, min_count, window_days, limit: lim }) => {
|
|
74500
74898
|
const result = getCoChanges(store, { file, minConfidence: min_confidence, minCount: min_count, windowDays: window_days, limit: lim });
|
|
74501
74899
|
if (result.isErr()) return { content: [{ type: "text", text: j3(formatToolError(result.error)) }], isError: true };
|
|
74502
74900
|
return { content: [{ type: "text", text: j3(result.value) }] };
|
|
74503
74901
|
});
|
|
74504
|
-
server.tool("refresh_co_changes", "Rebuild co-change index from git history.", { window_days: z10.number().int().min(1).max(730).optional().describe("Git history window in days (default 180)") }, async ({ window_days }) => {
|
|
74902
|
+
server.tool("refresh_co_changes", "Rebuild co-change index from git history. Mutates the co-change index; idempotent. Use after significant git history changes. Returns JSON: { status, pairs_stored, window_days }.", { window_days: z10.number().int().min(1).max(730).optional().describe("Git history window in days (default 180)") }, async ({ window_days }) => {
|
|
74505
74903
|
const days = window_days ?? 180;
|
|
74506
74904
|
const pairs = collectCoChanges(projectRoot, days);
|
|
74507
74905
|
const count2 = persistCoChanges(store, pairs, projectRoot, days);
|
|
74508
74906
|
return { content: [{ type: "text", text: j3({ status: "completed", pairs_stored: count2, window_days: days }) }] };
|
|
74509
74907
|
});
|
|
74510
|
-
server.tool("get_changed_symbols", 'Map a git diff to affected symbols (functions, classes, methods). For PR review. If "since" is omitted, auto-detects main/master as the base.', { since: z10.string().min(1).max(256).optional().describe("Git ref to compare from (SHA, branch, tag). If omitted, auto-detects main/master merge-base"), until: z10.string().max(256).optional().describe("Git ref to compare to (default: HEAD)"), include_blast_radius: z10.boolean().optional().describe("Include blast radius for each changed symbol (default false)"), max_blast_depth: z10.number().int().min(1).max(10).optional().describe("Max blast radius traversal depth (default 3)") }, async ({ since, until, include_blast_radius, max_blast_depth }) => {
|
|
74908
|
+
server.tool("get_changed_symbols", 'Map a git diff to affected symbols (functions, classes, methods). For PR review. If "since" is omitted, auto-detects main/master as the base. Requires git. Use for PR review to see which symbols changed. For full branch comparison with risk assessment use compare_branches instead. Read-only. Returns JSON: { changes: [{ symbol_id, name, kind, file, changeType }], total }.', { since: z10.string().min(1).max(256).optional().describe("Git ref to compare from (SHA, branch, tag). If omitted, auto-detects main/master merge-base"), until: z10.string().max(256).optional().describe("Git ref to compare to (default: HEAD)"), include_blast_radius: z10.boolean().optional().describe("Include blast radius for each changed symbol (default false)"), max_blast_depth: z10.number().int().min(1).max(10).optional().describe("Max blast radius traversal depth (default 3)") }, async ({ since, until, include_blast_radius, max_blast_depth }) => {
|
|
74511
74909
|
const result = getChangedSymbols(store, projectRoot, { since, until, includeBlastRadius: include_blast_radius, maxBlastDepth: max_blast_depth, defaultBaseBranch: config.git?.defaultBaseBranch });
|
|
74512
74910
|
if (result.isErr()) return { content: [{ type: "text", text: j3(formatToolError(result.error)) }], isError: true };
|
|
74513
74911
|
return { content: [{ type: "text", text: j3(result.value) }] };
|
|
74514
74912
|
});
|
|
74515
74913
|
server.tool(
|
|
74516
74914
|
"compare_branches",
|
|
74517
|
-
"Compare two branches at symbol level: what was added, modified, removed. Resolves merge-base automatically, groups by category/file/risk, includes blast radius and risk assessment.",
|
|
74915
|
+
"Compare two branches at symbol level: what was added, modified, removed. Resolves merge-base automatically, groups by category/file/risk, includes blast radius and risk assessment. Requires git. Use for comprehensive PR comparison. For a quick list of changed symbols without risk analysis use get_changed_symbols instead. Read-only. Returns JSON: { branch, base, mergeBase, changes: [{ symbol_id, category, risk }], summary }.",
|
|
74518
74916
|
{
|
|
74519
74917
|
branch: z10.string().min(1).max(256).describe('Branch to compare (e.g. "feature/payments")'),
|
|
74520
74918
|
base: z10.string().max(256).optional().describe('Base branch (default: "main")'),
|
|
@@ -74535,28 +74933,28 @@ function registerQualityTools(server, ctx) {
|
|
|
74535
74933
|
return { content: [{ type: "text", text: j3(result.value) }] };
|
|
74536
74934
|
}
|
|
74537
74935
|
);
|
|
74538
|
-
server.tool("detect_communities", "Run Leiden community detection on the file dependency graph. Identifies tightly-coupled file clusters (modules).", { resolution: z10.number().min(0.1).max(5).optional().describe("Resolution parameter \u2014 higher values produce more communities (default 1.0)") }, async ({ resolution }) => {
|
|
74936
|
+
server.tool("detect_communities", "Run Leiden community detection on the file dependency graph. Identifies tightly-coupled file clusters (modules). Mutates the community index (stores results); idempotent. Use before get_communities or get_community. Returns JSON: { communities: [{ id, files, size }], modularity }.", { resolution: z10.number().min(0.1).max(5).optional().describe("Resolution parameter \u2014 higher values produce more communities (default 1.0)") }, async ({ resolution }) => {
|
|
74539
74937
|
const result = detectCommunities2(store, resolution ?? 1);
|
|
74540
74938
|
if (result.isErr()) return { content: [{ type: "text", text: j3(formatToolError(result.error)) }], isError: true };
|
|
74541
74939
|
return { content: [{ type: "text", text: j3(result.value) }] };
|
|
74542
74940
|
});
|
|
74543
|
-
server.tool("get_communities", "Get previously detected communities (file clusters). Run detect_communities first.", {}, async () => {
|
|
74941
|
+
server.tool("get_communities", "Get previously detected communities (file clusters). Run detect_communities first. Read-only. Returns JSON: { communities: [{ id, files, size }], total }.", {}, async () => {
|
|
74544
74942
|
const result = getCommunities(store);
|
|
74545
74943
|
if (result.isErr()) return { content: [{ type: "text", text: j3(formatToolError(result.error)) }], isError: true };
|
|
74546
74944
|
return { content: [{ type: "text", text: j3(result.value) }] };
|
|
74547
74945
|
});
|
|
74548
|
-
server.tool("get_community", "Get details for a specific community: files, inter-community dependencies.", { id: z10.number().int().min(0).describe("Community ID") }, async ({ id }) => {
|
|
74946
|
+
server.tool("get_community", "Get details for a specific community: files, inter-community dependencies. Read-only. Use after detect_communities to drill into a specific cluster. Returns JSON: { id, files, interCommunityDeps }.", { id: z10.number().int().min(0).describe("Community ID") }, async ({ id }) => {
|
|
74549
74947
|
const result = getCommunityDetail(store, id);
|
|
74550
74948
|
if (result.isErr()) return { content: [{ type: "text", text: j3(formatToolError(result.error)) }], isError: true };
|
|
74551
74949
|
return { content: [{ type: "text", text: j3(result.value) }] };
|
|
74552
74950
|
});
|
|
74553
|
-
server.tool("audit_config", "Scan AI agent config files for stale references, dead paths, and token bloat.", { config_files: z10.array(z10.string().max(512)).optional().describe("Specific config files to audit (default: auto-detect)"), fix_suggestions: z10.boolean().optional().describe("Include fix suggestions (default true)") }, async ({ config_files, fix_suggestions }) => {
|
|
74951
|
+
server.tool("audit_config", "Scan AI agent config files for stale references, dead paths, and token bloat. Read-only. Use periodically to clean up CLAUDE.md and settings. Returns JSON: { issues: [{ file, type, message, suggestion }], total }.", { config_files: z10.array(z10.string().max(512)).optional().describe("Specific config files to audit (default: auto-detect)"), fix_suggestions: z10.boolean().optional().describe("Include fix suggestions (default true)") }, async ({ config_files, fix_suggestions }) => {
|
|
74554
74952
|
const result = auditConfig(store, projectRoot, { configFiles: config_files, fixSuggestions: fix_suggestions ?? true });
|
|
74555
74953
|
return { content: [{ type: "text", text: j3(result) }] };
|
|
74556
74954
|
});
|
|
74557
74955
|
server.tool(
|
|
74558
74956
|
"get_control_flow",
|
|
74559
|
-
"Build a Control Flow Graph (CFG) for a function/method: if/else branches, loops, try/catch, returns, throws. Shows logical paths through the code. Outputs Mermaid diagram, ASCII, or JSON.",
|
|
74957
|
+
"Build a Control Flow Graph (CFG) for a function/method: if/else branches, loops, try/catch, returns, throws. Shows logical paths through the code. Outputs Mermaid diagram, ASCII, or JSON. Use to understand branching logic before modifying complex functions. For call-level graph (who calls whom) use get_call_graph instead. Read-only. Returns Mermaid/ASCII/JSON: { nodes, edges, entryPoint, exitPoints }.",
|
|
74560
74958
|
{
|
|
74561
74959
|
symbol_id: z10.string().max(512).optional().describe("Symbol ID of the function/method"),
|
|
74562
74960
|
fqn: z10.string().max(512).optional().describe("Fully qualified name of the function/method"),
|
|
@@ -74578,7 +74976,7 @@ function registerQualityTools(server, ctx) {
|
|
|
74578
74976
|
);
|
|
74579
74977
|
server.tool(
|
|
74580
74978
|
"get_package_deps",
|
|
74581
|
-
"Cross-repo package dependency analysis: find which registered projects depend on a package, or what packages a project publishes. Scans package.json/composer.json/pyproject.toml across all repos in the registry.",
|
|
74979
|
+
"Cross-repo package dependency analysis: find which registered projects depend on a package, or what packages a project publishes. Scans package.json/composer.json/pyproject.toml across all repos in the registry. Use for cross-project dependency mapping. For impact of upgrading a specific package use plan_batch_change instead. Read-only. Returns JSON: { dependents, dependencies, package }.",
|
|
74582
74980
|
{
|
|
74583
74981
|
package: z10.string().max(256).optional().describe('Package name to analyze (e.g. "@myorg/shared-utils")'),
|
|
74584
74982
|
project: z10.string().max(256).optional().describe("Project name \u2014 analyze all packages it publishes"),
|
|
@@ -74595,7 +74993,7 @@ function registerQualityTools(server, ctx) {
|
|
|
74595
74993
|
);
|
|
74596
74994
|
server.tool(
|
|
74597
74995
|
"generate_docs",
|
|
74598
|
-
"Auto-generate project documentation from the code graph. Produces structured docs with architecture, API surface, data models, components, and dependency analysis.",
|
|
74996
|
+
"Auto-generate project documentation from the code graph. Produces structured docs with architecture, API surface, data models, components, and dependency analysis. Writes output file (markdown or HTML). Use when you need a comprehensive documentation snapshot. Returns JSON: { format, sections, outputPath }.",
|
|
74599
74997
|
{
|
|
74600
74998
|
scope: z10.enum(["project", "module", "directory"]).optional().describe("Scope (default: project)"),
|
|
74601
74999
|
path: z10.string().max(512).optional().describe("Path for module/directory scope"),
|
|
@@ -74615,7 +75013,7 @@ function registerQualityTools(server, ctx) {
|
|
|
74615
75013
|
);
|
|
74616
75014
|
server.tool(
|
|
74617
75015
|
"pack_context",
|
|
74618
|
-
"Pack project context into a single document for external LLMs. Intelligent selection by graph importance, fits within token budget. Better than Repomix for focused context. Strategies: most_relevant (default \u2014 feature/PageRank ranked), core_first (PageRank always wins, surfaces architecturally central code), compact (signatures only \u2014 drops source bodies, lets outlines cover much more of the repo per token).",
|
|
75016
|
+
"Pack project context into a single document for external LLMs. Intelligent selection by graph importance, fits within token budget. Better than Repomix for focused context. Strategies: most_relevant (default \u2014 feature/PageRank ranked), core_first (PageRank always wins, surfaces architecturally central code), compact (signatures only \u2014 drops source bodies, lets outlines cover much more of the repo per token). Read-only. Use when sharing project context with external tools. Returns XML/Markdown/JSON with selected code within budget.",
|
|
74619
75017
|
{
|
|
74620
75018
|
scope: z10.enum(["project", "module", "feature"]).describe("Scope: project (whole repo), module (subdirectory), feature (NL query)"),
|
|
74621
75019
|
path: z10.string().max(512).optional().describe("Subdirectory path (for module scope)"),
|
|
@@ -74645,7 +75043,7 @@ function registerQualityTools(server, ctx) {
|
|
|
74645
75043
|
);
|
|
74646
75044
|
server.tool(
|
|
74647
75045
|
"check_quality_gates",
|
|
74648
|
-
"Run configurable quality gate checks against the project. Returns pass/fail for each gate (complexity, coupling, circular imports, dead exports, tech debt, security, antipatterns, code smells). Designed for CI integration \u2014 AI can verify gates pass before committing.",
|
|
75046
|
+
"Run configurable quality gate checks against the project. Returns pass/fail for each gate (complexity, coupling, circular imports, dead exports, tech debt, security, antipatterns, code smells). Designed for CI integration \u2014 AI can verify gates pass before committing. Use before PR/commit to ensure quality standards. Read-only. Returns JSON: { passed, gates: [{ name, status, value, threshold }], summary }.",
|
|
74649
75047
|
{
|
|
74650
75048
|
scope: z10.enum(["project", "changed"]).optional().describe('Scope: "project" (all) or "changed" (git diff). Default: project'),
|
|
74651
75049
|
since: z10.string().max(128).optional().describe('Git ref for "changed" scope (e.g. "main")'),
|
|
@@ -74690,6 +75088,21 @@ function registerQualityTools(server, ctx) {
|
|
|
74690
75088
|
return { content: [{ type: "text", text: j3(report) }] };
|
|
74691
75089
|
}
|
|
74692
75090
|
);
|
|
75091
|
+
server.tool(
|
|
75092
|
+
"export_security_context",
|
|
75093
|
+
"Export security context for MCP server analysis. Generates enrichment JSON for skill-scan: tool registrations with annotations, transitive call graphs classified by security category (file_read, file_write, network_outbound, env_read, shell_exec, crypto, serialization), sensitive data flows, and per-file capability maps. Use to analyze MCP server security before installation. Read-only. Returns JSON: { tool_registrations, sensitive_flows, capability_map, warnings }.",
|
|
75094
|
+
{
|
|
75095
|
+
scope: z10.string().max(512).optional().describe("Limit analysis to directory (relative to project root)"),
|
|
75096
|
+
depth: z10.number().int().min(1).max(5).optional().describe("Call graph traversal depth (default: 3)")
|
|
75097
|
+
},
|
|
75098
|
+
async ({ scope, depth }) => {
|
|
75099
|
+
const result = exportSecurityContext(store, projectRoot, { scope, depth });
|
|
75100
|
+
if (result.isErr()) {
|
|
75101
|
+
return { content: [{ type: "text", text: j3(formatToolError(result.error)) }], isError: true };
|
|
75102
|
+
}
|
|
75103
|
+
return { content: [{ type: "text", text: j3(result.value) }] };
|
|
75104
|
+
}
|
|
75105
|
+
);
|
|
74693
75106
|
}
|
|
74694
75107
|
|
|
74695
75108
|
// src/tools/register/session.ts
|
|
@@ -74697,7 +75110,7 @@ import { z as z13 } from "zod";
|
|
|
74697
75110
|
|
|
74698
75111
|
// src/tools/ai/ai-tools.ts
|
|
74699
75112
|
import { z as z11 } from "zod";
|
|
74700
|
-
import
|
|
75113
|
+
import path58 from "path";
|
|
74701
75114
|
function j(value) {
|
|
74702
75115
|
return JSON.stringify(value);
|
|
74703
75116
|
}
|
|
@@ -74713,7 +75126,7 @@ function symbolToContextItem(sym, file, projectRoot, score = 1) {
|
|
|
74713
75126
|
}
|
|
74714
75127
|
function readSourceSafe(filePath, byteStart, byteEnd, projectRoot, gitignored) {
|
|
74715
75128
|
try {
|
|
74716
|
-
const absPath =
|
|
75129
|
+
const absPath = path58.resolve(projectRoot, filePath);
|
|
74717
75130
|
return readByteRange(absPath, byteStart, byteEnd, gitignored);
|
|
74718
75131
|
} catch {
|
|
74719
75132
|
return null;
|
|
@@ -75029,16 +75442,16 @@ function registerAITools(server, ctx) {
|
|
|
75029
75442
|
// src/bundles.ts
|
|
75030
75443
|
init_logger();
|
|
75031
75444
|
import Database5 from "better-sqlite3";
|
|
75032
|
-
import
|
|
75445
|
+
import path59 from "path";
|
|
75033
75446
|
import fs49 from "fs";
|
|
75034
75447
|
import crypto6 from "crypto";
|
|
75035
|
-
var BUNDLES_DIR =
|
|
75448
|
+
var BUNDLES_DIR = path59.join(TRACE_MCP_HOME, "bundles");
|
|
75036
75449
|
function getBundlePath(packageName, version2) {
|
|
75037
75450
|
const safeName = packageName.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
75038
|
-
return
|
|
75451
|
+
return path59.join(BUNDLES_DIR, `${safeName}-${version2}.bundle.db`);
|
|
75039
75452
|
}
|
|
75040
75453
|
function getManifestPath() {
|
|
75041
|
-
return
|
|
75454
|
+
return path59.join(BUNDLES_DIR, "manifest.json");
|
|
75042
75455
|
}
|
|
75043
75456
|
function loadManifest() {
|
|
75044
75457
|
const p = getManifestPath();
|
|
@@ -75108,8 +75521,8 @@ function searchBundles(bundles, query, opts = {}) {
|
|
|
75108
75521
|
|
|
75109
75522
|
// src/analytics/analytics-store.ts
|
|
75110
75523
|
import Database6 from "better-sqlite3";
|
|
75111
|
-
import
|
|
75112
|
-
var ANALYTICS_DB_PATH =
|
|
75524
|
+
import path60 from "path";
|
|
75525
|
+
var ANALYTICS_DB_PATH = path60.join(TRACE_MCP_HOME, "analytics.db");
|
|
75113
75526
|
var SCHEMA_SQL = `
|
|
75114
75527
|
CREATE TABLE IF NOT EXISTS sessions (
|
|
75115
75528
|
id TEXT PRIMARY KEY,
|
|
@@ -75342,9 +75755,9 @@ var AnalyticsStore = class {
|
|
|
75342
75755
|
// src/analytics/log-parser.ts
|
|
75343
75756
|
init_logger();
|
|
75344
75757
|
import fs50 from "fs";
|
|
75345
|
-
import
|
|
75758
|
+
import path61 from "path";
|
|
75346
75759
|
import os7 from "os";
|
|
75347
|
-
var CLAUDE_PROJECTS_DIR =
|
|
75760
|
+
var CLAUDE_PROJECTS_DIR = path61.join(os7.homedir(), ".claude", "projects");
|
|
75348
75761
|
var CLAW_SESSIONS_DIR_NAME = ".claw/sessions";
|
|
75349
75762
|
function parseToolName(fullName) {
|
|
75350
75763
|
const match = fullName.match(/^mcp__([^_]+)__(.+)$/);
|
|
@@ -75421,7 +75834,7 @@ function parseSessionFile(filePath, projectPath) {
|
|
|
75421
75834
|
try {
|
|
75422
75835
|
const content = fs50.readFileSync(filePath, "utf-8");
|
|
75423
75836
|
const lines = content.split("\n").filter((l) => l.trim());
|
|
75424
|
-
const sessionId =
|
|
75837
|
+
const sessionId = path61.basename(filePath, ".jsonl");
|
|
75425
75838
|
const toolCalls = [];
|
|
75426
75839
|
const toolResults = /* @__PURE__ */ new Map();
|
|
75427
75840
|
let model = "";
|
|
@@ -75542,11 +75955,11 @@ function listProjectDirs() {
|
|
|
75542
75955
|
}));
|
|
75543
75956
|
}
|
|
75544
75957
|
function listSessionFiles(projectDirName) {
|
|
75545
|
-
const dir =
|
|
75958
|
+
const dir = path61.join(CLAUDE_PROJECTS_DIR, projectDirName);
|
|
75546
75959
|
if (!fs50.existsSync(dir)) return [];
|
|
75547
75960
|
const entries = fs50.readdirSync(dir, { withFileTypes: true });
|
|
75548
75961
|
return entries.filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => {
|
|
75549
|
-
const filePath =
|
|
75962
|
+
const filePath = path61.join(dir, e.name);
|
|
75550
75963
|
const stat = fs50.statSync(filePath);
|
|
75551
75964
|
return { filePath, mtime: stat.mtimeMs };
|
|
75552
75965
|
});
|
|
@@ -75560,13 +75973,13 @@ function listAllSessions() {
|
|
|
75560
75973
|
}
|
|
75561
75974
|
const clawProjectPaths = discoverClawProjects();
|
|
75562
75975
|
for (const projectPath of clawProjectPaths) {
|
|
75563
|
-
const sessionsDir =
|
|
75976
|
+
const sessionsDir = path61.join(projectPath, CLAW_SESSIONS_DIR_NAME);
|
|
75564
75977
|
if (!fs50.existsSync(sessionsDir)) continue;
|
|
75565
75978
|
try {
|
|
75566
75979
|
const entries = fs50.readdirSync(sessionsDir, { withFileTypes: true });
|
|
75567
75980
|
for (const e of entries) {
|
|
75568
75981
|
if (!e.isFile() || !e.name.endsWith(".jsonl")) continue;
|
|
75569
|
-
const filePath =
|
|
75982
|
+
const filePath = path61.join(sessionsDir, e.name);
|
|
75570
75983
|
try {
|
|
75571
75984
|
const stat = fs50.statSync(filePath);
|
|
75572
75985
|
results.push({ filePath, projectPath, client: "claw-code", mtime: stat.mtimeMs });
|
|
@@ -75581,25 +75994,25 @@ function listAllSessions() {
|
|
|
75581
75994
|
function discoverClawProjects() {
|
|
75582
75995
|
const paths = /* @__PURE__ */ new Set();
|
|
75583
75996
|
for (const { projectPath } of listProjectDirs()) {
|
|
75584
|
-
if (fs50.existsSync(
|
|
75997
|
+
if (fs50.existsSync(path61.join(projectPath, CLAW_SESSIONS_DIR_NAME))) {
|
|
75585
75998
|
paths.add(projectPath);
|
|
75586
75999
|
}
|
|
75587
76000
|
}
|
|
75588
76001
|
const cwd = process.cwd();
|
|
75589
|
-
if (fs50.existsSync(
|
|
76002
|
+
if (fs50.existsSync(path61.join(cwd, CLAW_SESSIONS_DIR_NAME))) {
|
|
75590
76003
|
paths.add(cwd);
|
|
75591
76004
|
}
|
|
75592
76005
|
const home = os7.homedir();
|
|
75593
76006
|
const commonRoots = ["Projects", "projects", "dev", "workspace", "code", "PhpstormProjects", "WebstormProjects", "src"];
|
|
75594
76007
|
for (const root of commonRoots) {
|
|
75595
|
-
const rootDir =
|
|
76008
|
+
const rootDir = path61.join(home, root);
|
|
75596
76009
|
if (!fs50.existsSync(rootDir)) continue;
|
|
75597
76010
|
try {
|
|
75598
76011
|
const entries = fs50.readdirSync(rootDir, { withFileTypes: true });
|
|
75599
76012
|
for (const e of entries) {
|
|
75600
76013
|
if (!e.isDirectory()) continue;
|
|
75601
|
-
const projectDir =
|
|
75602
|
-
if (fs50.existsSync(
|
|
76014
|
+
const projectDir = path61.join(rootDir, e.name);
|
|
76015
|
+
if (fs50.existsSync(path61.join(projectDir, CLAW_SESSIONS_DIR_NAME))) {
|
|
75603
76016
|
paths.add(projectDir);
|
|
75604
76017
|
}
|
|
75605
76018
|
}
|
|
@@ -76305,7 +76718,7 @@ function formatBenchmarkMarkdown(result) {
|
|
|
76305
76718
|
|
|
76306
76719
|
// src/analytics/tech-detector.ts
|
|
76307
76720
|
import fs51 from "fs";
|
|
76308
|
-
import
|
|
76721
|
+
import path62 from "path";
|
|
76309
76722
|
|
|
76310
76723
|
// src/analytics/known-packages.ts
|
|
76311
76724
|
var KNOWN_PACKAGES = {
|
|
@@ -77969,7 +78382,7 @@ function detectCoverage(projectRoot, opts = {}) {
|
|
|
77969
78382
|
const manifestsFound = [];
|
|
77970
78383
|
const allDeps = [];
|
|
77971
78384
|
for (const { file, ecosystem, parser } of MANIFEST_PARSERS) {
|
|
77972
|
-
const filePath =
|
|
78385
|
+
const filePath = path62.join(projectRoot, file);
|
|
77973
78386
|
if (!fs51.existsSync(filePath)) continue;
|
|
77974
78387
|
manifestsFound.push(file);
|
|
77975
78388
|
const rawDeps = parser(filePath);
|
|
@@ -79146,7 +79559,7 @@ function registerSessionTools(server, ctx) {
|
|
|
79146
79559
|
}
|
|
79147
79560
|
server.tool(
|
|
79148
79561
|
"search_bundles",
|
|
79149
|
-
"Search pre-indexed bundles for symbols from popular libraries (React, Express, etc.). Returns symbol definitions from dependency bundles \u2014 useful for go-to-definition into node_modules/vendor. Install bundles via CLI: `trace-mcp bundles export`.",
|
|
79562
|
+
"Search pre-indexed bundles for symbols from popular libraries (React, Express, etc.). Returns symbol definitions from dependency bundles \u2014 useful for go-to-definition into node_modules/vendor. Install bundles via CLI: `trace-mcp bundles export`. For project source code search use search instead. Read-only. Returns JSON: { results: [{ name, kind, signature, bundle }], bundles_searched }.",
|
|
79150
79563
|
{
|
|
79151
79564
|
query: z13.string().min(1).max(256).describe("Symbol name or FQN to search"),
|
|
79152
79565
|
kind: z13.string().max(64).optional().describe("Filter by symbol kind (function, class, interface, etc.)"),
|
|
@@ -79164,7 +79577,7 @@ function registerSessionTools(server, ctx) {
|
|
|
79164
79577
|
);
|
|
79165
79578
|
server.tool(
|
|
79166
79579
|
"list_bundles",
|
|
79167
|
-
"List installed pre-indexed bundles for dependency libraries. Shows package name, version, symbol/edge counts, and size.",
|
|
79580
|
+
"List installed pre-indexed bundles for dependency libraries. Shows package name, version, symbol/edge counts, and size. Read-only. Returns JSON: { bundles: [{ name, version, symbols, edges, size }], total }.",
|
|
79168
79581
|
{},
|
|
79169
79582
|
async () => {
|
|
79170
79583
|
const bundles = listBundles();
|
|
@@ -79173,7 +79586,7 @@ function registerSessionTools(server, ctx) {
|
|
|
79173
79586
|
);
|
|
79174
79587
|
_originalTool(
|
|
79175
79588
|
"get_preset_info",
|
|
79176
|
-
"Show active tool preset, available presets, and which tools are registered in this session",
|
|
79589
|
+
"Show active tool preset, available presets, and which tools are registered in this session. Read-only. Returns JSON: { active_preset, registered_tools, tool_names, available_presets }.",
|
|
79177
79590
|
{},
|
|
79178
79591
|
async () => {
|
|
79179
79592
|
const presets = listPresets();
|
|
@@ -79192,7 +79605,7 @@ function registerSessionTools(server, ctx) {
|
|
|
79192
79605
|
);
|
|
79193
79606
|
_originalTool(
|
|
79194
79607
|
"get_session_analytics",
|
|
79195
|
-
"Analyze AI agent session logs: token usage, cost breakdown by tool/server, top files, models used. Parses Claude Code JSONL logs automatically.",
|
|
79608
|
+
"Analyze AI agent session logs: token usage, cost breakdown by tool/server, top files, models used. Parses Claude Code JSONL logs automatically. Read-only. For waste detection use get_optimization_report; for cost trends use get_usage_trends. Returns JSON: { sessions, tokens, cost_usd, tools, models, topFiles }.",
|
|
79196
79609
|
{
|
|
79197
79610
|
period: z13.enum(["today", "week", "month", "all"]).optional().describe("Time period (default: week)"),
|
|
79198
79611
|
session_id: z13.string().max(128).optional().describe("Specific session ID to analyze")
|
|
@@ -79213,7 +79626,7 @@ function registerSessionTools(server, ctx) {
|
|
|
79213
79626
|
);
|
|
79214
79627
|
_originalTool(
|
|
79215
79628
|
"get_optimization_report",
|
|
79216
|
-
"Detect token waste patterns in AI agent sessions: repeated file reads, Bash grep instead of search, large file reads, unused trace-mcp tools. Provides savings estimates.",
|
|
79629
|
+
"Detect token waste patterns in AI agent sessions: repeated file reads, Bash grep instead of search, large file reads, unused trace-mcp tools. Provides savings estimates. Read-only. For usage/cost overview use get_session_analytics; for A/B savings comparison use get_real_savings. Returns JSON: { patterns: [{ type, description, savings_estimate }], total_waste }.",
|
|
79217
79630
|
{
|
|
79218
79631
|
period: z13.enum(["today", "week", "month", "all"]).optional().describe("Time period (default: week)")
|
|
79219
79632
|
},
|
|
@@ -79233,7 +79646,7 @@ function registerSessionTools(server, ctx) {
|
|
|
79233
79646
|
);
|
|
79234
79647
|
server.tool(
|
|
79235
79648
|
"benchmark_project",
|
|
79236
|
-
"Synthetic token efficiency benchmark: compare raw file reads vs trace-mcp compact responses across symbol lookup, file exploration, search, and impact analysis scenarios.",
|
|
79649
|
+
"Synthetic token efficiency benchmark: compare raw file reads vs trace-mcp compact responses across symbol lookup, file exploration, search, and impact analysis scenarios. Read-only, no side effects. Use to quantify token savings. Returns JSON: { scenarios: [{ name, raw_tokens, compact_tokens, savings_pct }], summary }.",
|
|
79237
79650
|
{
|
|
79238
79651
|
queries: z13.number().int().min(1).max(50).optional().describe("Queries per scenario (default 10)"),
|
|
79239
79652
|
seed: z13.number().int().optional().describe("Random seed for reproducibility (default 42)"),
|
|
@@ -79249,7 +79662,7 @@ function registerSessionTools(server, ctx) {
|
|
|
79249
79662
|
);
|
|
79250
79663
|
_originalTool(
|
|
79251
79664
|
"get_coverage_report",
|
|
79252
|
-
"Technology profile of the project: detected frameworks/ORMs/UI libs from manifests (package.json, composer.json, etc.), which are covered by trace-mcp plugins, and coverage gaps.",
|
|
79665
|
+
"Technology profile of the project: detected frameworks/ORMs/UI libs from manifests (package.json, composer.json, etc.), which are covered by trace-mcp plugins, and coverage gaps. Read-only. Returns JSON: { detected, covered, gaps }.",
|
|
79253
79666
|
{},
|
|
79254
79667
|
async () => {
|
|
79255
79668
|
try {
|
|
@@ -79262,7 +79675,7 @@ function registerSessionTools(server, ctx) {
|
|
|
79262
79675
|
);
|
|
79263
79676
|
_originalTool(
|
|
79264
79677
|
"get_real_savings",
|
|
79265
|
-
"A/B comparison: how many tokens could be saved by using trace-mcp instead of raw Read/Bash file reads. Per-file breakdown.",
|
|
79678
|
+
"A/B comparison: how many tokens could be saved by using trace-mcp instead of raw Read/Bash file reads. Per-file breakdown. Read-only. For pattern-based waste detection use get_optimization_report instead. Returns JSON: { files: [{ file, raw_tokens, compact_tokens, savings }], total_savings }.",
|
|
79266
79679
|
{
|
|
79267
79680
|
period: z13.enum(["today", "week", "month", "all"]).optional().describe("Time period (default: week)")
|
|
79268
79681
|
},
|
|
@@ -79284,7 +79697,7 @@ function registerSessionTools(server, ctx) {
|
|
|
79284
79697
|
);
|
|
79285
79698
|
_originalTool(
|
|
79286
79699
|
"get_usage_trends",
|
|
79287
|
-
"Daily token usage time-series: sessions, tokens, estimated cost, tool calls per day. For spotting cost spikes.",
|
|
79700
|
+
"Daily token usage time-series: sessions, tokens, estimated cost, tool calls per day. For spotting cost spikes. Read-only. For detailed session breakdown use get_session_analytics instead. Returns JSON: { days, daily: [{ date, sessions, tokens, cost_usd, tool_calls }], totals }.",
|
|
79288
79701
|
{
|
|
79289
79702
|
days: z13.number().int().min(1).max(365).optional().describe("Number of days to show (default: 30)")
|
|
79290
79703
|
},
|
|
@@ -79311,7 +79724,7 @@ function registerSessionTools(server, ctx) {
|
|
|
79311
79724
|
);
|
|
79312
79725
|
_originalTool(
|
|
79313
79726
|
"get_session_stats",
|
|
79314
|
-
"Token savings stats for this session: per-tool call counts, estimated token savings, reduction percentage, dedup savings.",
|
|
79727
|
+
"Token savings stats for this session: per-tool call counts, estimated token savings, reduction percentage, dedup savings. Read-only. Returns JSON: { total_calls, total_raw_tokens, total_compact_tokens, savings_pct, dedup_saved_tokens, per_tool }.",
|
|
79315
79728
|
{},
|
|
79316
79729
|
async () => {
|
|
79317
79730
|
const stats = savings.getFullStats();
|
|
@@ -79329,7 +79742,7 @@ function registerSessionTools(server, ctx) {
|
|
|
79329
79742
|
);
|
|
79330
79743
|
server.tool(
|
|
79331
79744
|
"get_session_journal",
|
|
79332
|
-
"Session history: all tool calls made, files read, zero-result searches, and duplicate queries. Use to avoid repeating work.",
|
|
79745
|
+
"Session history: all tool calls made, files read, zero-result searches, and duplicate queries. Use to avoid repeating work. For a compact snapshot use get_session_snapshot instead. Read-only. Returns JSON: { calls, filesRead, zeroResults, duplicates }.",
|
|
79333
79746
|
{},
|
|
79334
79747
|
async () => {
|
|
79335
79748
|
const summary = journal.getSummary();
|
|
@@ -79338,7 +79751,7 @@ function registerSessionTools(server, ctx) {
|
|
|
79338
79751
|
);
|
|
79339
79752
|
server.tool(
|
|
79340
79753
|
"get_session_snapshot",
|
|
79341
|
-
"Compact session snapshot (~200 tokens) for context recovery after compaction. Returns focus files (by read count), edited files, key searches, and dead ends. Also used by the PreCompact hook to preserve session orientation automatically.",
|
|
79754
|
+
"Compact session snapshot (~200 tokens) for context recovery after compaction. Returns focus files (by read count), edited files, key searches, and dead ends. Also used by the PreCompact hook to preserve session orientation automatically. Read-only. For full journal use get_session_journal; for cross-session context use get_session_resume. Returns JSON: { focusFiles, editedFiles, keySearches, deadEnds }.",
|
|
79342
79755
|
{
|
|
79343
79756
|
max_files: z13.number().int().min(1).max(50).optional().describe("Max focus files to include (default: 10)"),
|
|
79344
79757
|
max_searches: z13.number().int().min(1).max(20).optional().describe("Max key searches to include (default: 5)"),
|
|
@@ -79357,7 +79770,7 @@ function registerSessionTools(server, ctx) {
|
|
|
79357
79770
|
);
|
|
79358
79771
|
server.tool(
|
|
79359
79772
|
"get_session_resume",
|
|
79360
|
-
"Cross-session context carryover: shows what was explored in recent past sessions (files touched, tools used, dead-end searches). Call at session start to orient yourself without re-reading files. Much cheaper than re-exploring the codebase.",
|
|
79773
|
+
"Cross-session context carryover: shows what was explored in recent past sessions (files touched, tools used, dead-end searches). Call at session start to orient yourself without re-reading files. Much cheaper than re-exploring the codebase. Read-only. For decision-aware wake-up use get_wake_up instead. Returns JSON: { sessions: [{ files, tools, deadEnds }], active_decisions }.",
|
|
79361
79774
|
{
|
|
79362
79775
|
max_sessions: z13.number().int().min(1).max(20).optional().describe("Number of past sessions to include (default: 5)")
|
|
79363
79776
|
},
|
|
@@ -79376,7 +79789,7 @@ function registerSessionTools(server, ctx) {
|
|
|
79376
79789
|
);
|
|
79377
79790
|
_originalTool(
|
|
79378
79791
|
"plan_turn",
|
|
79379
|
-
"Opening-move router for new tasks. Combines BM25/PageRank search + session journal (negative evidence + focus signals) + framework-aware insertion-point suggestions + change-risk + turn-budget advisor into ONE call. Returns verdict (exists/partial/missing/ambiguous), confidence, ranked targets with provenance, scaffold hints when missing, and recommended next tool calls. Call this FIRST on a new task to break the empty-result hallucination chain.",
|
|
79792
|
+
"Opening-move router for new tasks. Combines BM25/PageRank search + session journal (negative evidence + focus signals) + framework-aware insertion-point suggestions + change-risk + turn-budget advisor into ONE call. Returns verdict (exists/partial/missing/ambiguous), confidence, ranked targets with provenance, scaffold hints when missing, and recommended next tool calls. Call this FIRST on a new task to break the empty-result hallucination chain. Read-only. For broader task context with source code use get_task_context instead. Returns JSON: { verdict, confidence, targets, scaffoldHints, nextSteps }.",
|
|
79380
79793
|
{
|
|
79381
79794
|
task: z13.string().min(1).max(512).describe('Natural-language task description (e.g. "add a webhook endpoint for stripe payments")'),
|
|
79382
79795
|
intent: z13.enum(["bugfix", "new_feature", "refactor", "understand"]).optional().describe("Optional intent hint; auto-classified from task if omitted"),
|
|
@@ -79410,7 +79823,7 @@ function registerSessionTools(server, ctx) {
|
|
|
79410
79823
|
);
|
|
79411
79824
|
_originalTool(
|
|
79412
79825
|
"batch",
|
|
79413
|
-
"Execute multiple trace-mcp tools in a single MCP request. Returns results for all calls. Use to reduce round-trips when you need several independent queries (e.g., get_outline for 3 files, or search + get_symbol together).",
|
|
79826
|
+
"Execute multiple trace-mcp tools in a single MCP request. Returns results for all calls. Use to reduce round-trips when you need several independent queries (e.g., get_outline for 3 files, or search + get_symbol together). Read-only (delegates to other tools). Returns JSON: { batch_results: [{ tool, result }], total }.",
|
|
79414
79827
|
{
|
|
79415
79828
|
calls: z13.array(z13.object({
|
|
79416
79829
|
tool: z13.string().describe('Tool name (e.g., "get_outline", "get_symbol", "search")'),
|
|
@@ -79460,7 +79873,7 @@ import { z as z14 } from "zod";
|
|
|
79460
79873
|
|
|
79461
79874
|
// src/memory/conversation-miner.ts
|
|
79462
79875
|
import * as fs52 from "fs";
|
|
79463
|
-
import * as
|
|
79876
|
+
import * as path63 from "path";
|
|
79464
79877
|
init_logger();
|
|
79465
79878
|
var DECISION_PATTERNS = [
|
|
79466
79879
|
// Architecture decisions: "decided to", "we'll use", "going with", "chose X over Y"
|
|
@@ -79688,7 +80101,7 @@ function mineSessions(decisionStore, opts = {}) {
|
|
|
79688
80101
|
file_path: d.file_path,
|
|
79689
80102
|
tags: d.tags,
|
|
79690
80103
|
valid_from: d.timestamp,
|
|
79691
|
-
session_id:
|
|
80104
|
+
session_id: path63.basename(session.filePath, ".jsonl"),
|
|
79692
80105
|
source: "mined",
|
|
79693
80106
|
confidence: d.confidence
|
|
79694
80107
|
}));
|
|
@@ -79714,7 +80127,7 @@ function mineSessions(decisionStore, opts = {}) {
|
|
|
79714
80127
|
|
|
79715
80128
|
// src/memory/session-indexer.ts
|
|
79716
80129
|
import * as fs53 from "fs";
|
|
79717
|
-
import * as
|
|
80130
|
+
import * as path64 from "path";
|
|
79718
80131
|
init_logger();
|
|
79719
80132
|
var MAX_CHUNK_CHARS = 2e3;
|
|
79720
80133
|
var MIN_MESSAGE_CHARS = 50;
|
|
@@ -79755,7 +80168,7 @@ function truncateChunk(text) {
|
|
|
79755
80168
|
function indexSessionFile(filePath, projectPath, decisionStore) {
|
|
79756
80169
|
const content = fs53.readFileSync(filePath, "utf-8");
|
|
79757
80170
|
const lines = content.split("\n").filter((l) => l.trim());
|
|
79758
|
-
const sessionId =
|
|
80171
|
+
const sessionId = path64.basename(filePath, ".jsonl");
|
|
79759
80172
|
const chunks = [];
|
|
79760
80173
|
let chunkIndex = 0;
|
|
79761
80174
|
for (const line of lines) {
|
|
@@ -79806,7 +80219,7 @@ function indexSessions(decisionStore, opts = {}) {
|
|
|
79806
80219
|
skipped++;
|
|
79807
80220
|
continue;
|
|
79808
80221
|
}
|
|
79809
|
-
const sessionId =
|
|
80222
|
+
const sessionId = path64.basename(session.filePath, ".jsonl");
|
|
79810
80223
|
if (!opts.force && decisionStore.isSessionIndexed(sessionId)) {
|
|
79811
80224
|
skipped++;
|
|
79812
80225
|
continue;
|
|
@@ -79831,7 +80244,7 @@ function indexSessions(decisionStore, opts = {}) {
|
|
|
79831
80244
|
}
|
|
79832
80245
|
|
|
79833
80246
|
// src/memory/wake-up.ts
|
|
79834
|
-
import * as
|
|
80247
|
+
import * as path65 from "path";
|
|
79835
80248
|
function compactDecision(d) {
|
|
79836
80249
|
const entry = {
|
|
79837
80250
|
id: d.id,
|
|
@@ -79855,7 +80268,7 @@ function assembleWakeUp(decisionStore, projectRoot, opts = {}) {
|
|
|
79855
80268
|
const indexedSessions = decisionStore.getIndexedSessionIds(projectRoot);
|
|
79856
80269
|
const result = {
|
|
79857
80270
|
project: {
|
|
79858
|
-
name:
|
|
80271
|
+
name: path65.basename(projectRoot),
|
|
79859
80272
|
root: projectRoot
|
|
79860
80273
|
},
|
|
79861
80274
|
decisions: {
|
|
@@ -79899,7 +80312,7 @@ function registerMemoryTools(server, ctx) {
|
|
|
79899
80312
|
}
|
|
79900
80313
|
server.tool(
|
|
79901
80314
|
"mine_sessions",
|
|
79902
|
-
"Mine Claude Code / Claw Code session logs for architectural decisions, tech choices, bug root causes, and preferences. Extracts decision-like content using pattern matching (no LLM calls). Skips already-mined sessions unless force=true.",
|
|
80315
|
+
"Mine Claude Code / Claw Code session logs for architectural decisions, tech choices, bug root causes, and preferences. Extracts decision-like content using pattern matching (no LLM calls). Skips already-mined sessions unless force=true. Mutates the decision store; idempotent. Use to populate the decision knowledge graph. Returns JSON: { mined, decisions_extracted, sessions_processed }.",
|
|
79903
80316
|
{
|
|
79904
80317
|
project_root: z14.string().max(1024).optional().describe("Only mine sessions for this project path (default: all projects)"),
|
|
79905
80318
|
force: z14.boolean().optional().describe("Re-mine already processed sessions (default: false)"),
|
|
@@ -79916,7 +80329,7 @@ function registerMemoryTools(server, ctx) {
|
|
|
79916
80329
|
);
|
|
79917
80330
|
server.tool(
|
|
79918
80331
|
"add_decision",
|
|
79919
|
-
"Manually record an architectural decision, tech choice, preference, or convention. Links to code symbols/files and optionally to a specific subproject for code-aware memory. Decisions have temporal validity \u2014 they can be invalidated later when they become outdated.",
|
|
80332
|
+
"Manually record an architectural decision, tech choice, preference, or convention. Links to code symbols/files and optionally to a specific subproject for code-aware memory. Decisions have temporal validity \u2014 they can be invalidated later when they become outdated. Mutates the decision store (creates a new record). For automated extraction from session logs use mine_sessions instead. Returns JSON: { added: { id, title, type } }.",
|
|
79920
80333
|
{
|
|
79921
80334
|
title: z14.string().min(1).max(200).describe("Short summary of the decision"),
|
|
79922
80335
|
content: z14.string().min(1).max(5e3).describe("Full decision text \u2014 reasoning, context, tradeoffs"),
|
|
@@ -79944,7 +80357,7 @@ function registerMemoryTools(server, ctx) {
|
|
|
79944
80357
|
);
|
|
79945
80358
|
server.tool(
|
|
79946
80359
|
"query_decisions",
|
|
79947
|
-
'Query the decision knowledge graph. Filter by type, subproject, code symbol, file path, tag, or time. Returns decisions linked to code \u2014 "why was this architecture chosen?" answered with the actual decision record. Use service_name to filter by a specific subproject within the project.',
|
|
80360
|
+
'Query the decision knowledge graph. Filter by type, subproject, code symbol, file path, tag, or time. Returns decisions linked to code \u2014 "why was this architecture chosen?" answered with the actual decision record. Use service_name to filter by a specific subproject within the project. Read-only. Returns JSON: { decisions: [{ id, title, type, content, tags }], total_results }.',
|
|
79948
80361
|
{
|
|
79949
80362
|
type: z14.enum(DECISION_TYPES).optional().describe("Filter by decision type"),
|
|
79950
80363
|
service_name: z14.string().max(256).optional().describe('Filter by subproject name (e.g., "auth-api")'),
|
|
@@ -79980,14 +80393,14 @@ function registerMemoryTools(server, ctx) {
|
|
|
79980
80393
|
);
|
|
79981
80394
|
server.tool(
|
|
79982
80395
|
"invalidate_decision",
|
|
79983
|
-
"Mark a decision as no longer valid. The decision remains in the knowledge graph for historical queries but is excluded from active queries. Use when a decision is superseded or reversed.",
|
|
80396
|
+
"Mark a decision as no longer valid. The decision remains in the knowledge graph for historical queries but is excluded from active queries. Use when a decision is superseded or reversed. Mutates the decision store; idempotent. Returns JSON: { invalidated: { id, title, valid_until } }.",
|
|
79984
80397
|
{
|
|
79985
80398
|
id: z14.number().int().min(1).describe("Decision ID to invalidate"),
|
|
79986
80399
|
valid_until: z14.string().max(30).optional().describe("ISO timestamp when decision became invalid (default: now)")
|
|
79987
80400
|
},
|
|
79988
80401
|
async ({ id, valid_until }) => {
|
|
79989
|
-
const
|
|
79990
|
-
if (!
|
|
80402
|
+
const ok11 = decisionStore.invalidateDecision(id, valid_until);
|
|
80403
|
+
if (!ok11) {
|
|
79991
80404
|
return { content: [{ type: "text", text: j3({ error: `Decision ${id} not found or already invalidated` }) }], isError: true };
|
|
79992
80405
|
}
|
|
79993
80406
|
const updated = decisionStore.getDecision(id);
|
|
@@ -79996,7 +80409,7 @@ function registerMemoryTools(server, ctx) {
|
|
|
79996
80409
|
);
|
|
79997
80410
|
server.tool(
|
|
79998
80411
|
"get_decision_timeline",
|
|
79999
|
-
"Chronological timeline of decisions for a project, symbol, or file. Shows when decisions were made and invalidated \u2014 like git log but for architectural decisions.",
|
|
80412
|
+
"Chronological timeline of decisions for a project, symbol, or file. Shows when decisions were made and invalidated \u2014 like git log but for architectural decisions. Read-only. Use to review decision history. Returns JSON: { timeline: [{ id, title, type, created_at, valid_until }], count }.",
|
|
80000
80413
|
{
|
|
80001
80414
|
symbol_id: z14.string().max(512).optional().describe("Filter timeline to decisions about this symbol"),
|
|
80002
80415
|
file_path: z14.string().max(1024).optional().describe("Filter timeline to decisions about this file"),
|
|
@@ -80014,7 +80427,7 @@ function registerMemoryTools(server, ctx) {
|
|
|
80014
80427
|
);
|
|
80015
80428
|
server.tool(
|
|
80016
80429
|
"get_decision_stats",
|
|
80017
|
-
"Overview of the decision knowledge graph: total decisions, active/invalidated counts, breakdown by type and source. Shows how much institutional knowledge is captured.",
|
|
80430
|
+
"Overview of the decision knowledge graph: total decisions, active/invalidated counts, breakdown by type and source. Shows how much institutional knowledge is captured. Read-only. Returns JSON: { total, active, invalidated, by_type, by_source, sessions_mined }.",
|
|
80018
80431
|
{},
|
|
80019
80432
|
async () => {
|
|
80020
80433
|
const stats = decisionStore.getStats(projectRoot);
|
|
@@ -80026,7 +80439,7 @@ function registerMemoryTools(server, ctx) {
|
|
|
80026
80439
|
);
|
|
80027
80440
|
server.tool(
|
|
80028
80441
|
"index_sessions",
|
|
80029
|
-
'Index conversation content from Claude Code / Claw Code sessions for cross-session search. Stores chunked messages in FTS5 \u2014 enables "what did we discuss about X?" queries across all past sessions. Skips already-indexed sessions unless force=true.',
|
|
80442
|
+
'Index conversation content from Claude Code / Claw Code sessions for cross-session search. Stores chunked messages in FTS5 \u2014 enables "what did we discuss about X?" queries across all past sessions. Skips already-indexed sessions unless force=true. Mutates the session index; idempotent. Use before search_sessions. Returns JSON: { indexed, sessions_processed, chunks_stored }.',
|
|
80030
80443
|
{
|
|
80031
80444
|
project_root: z14.string().max(1024).optional().describe("Only index sessions for this project path (default: current project)"),
|
|
80032
80445
|
force: z14.boolean().optional().describe("Re-index already processed sessions (default: false)")
|
|
@@ -80041,7 +80454,7 @@ function registerMemoryTools(server, ctx) {
|
|
|
80041
80454
|
);
|
|
80042
80455
|
server.tool(
|
|
80043
80456
|
"search_sessions",
|
|
80044
|
-
'Search across all past session conversations. Finds what was discussed, decided, or debugged in previous sessions. Full-text search with porter stemming \u2014 e.g., "why did we switch to GraphQL", "auth middleware bug", "database migration approach".',
|
|
80457
|
+
'Search across all past session conversations. Finds what was discussed, decided, or debugged in previous sessions. Full-text search with porter stemming \u2014 e.g., "why did we switch to GraphQL", "auth middleware bug", "database migration approach". Requires index_sessions to be run first. Read-only. Returns JSON: { results: [{ session_id, text, score }], total_results }.',
|
|
80045
80458
|
{
|
|
80046
80459
|
query: z14.string().min(1).max(500).describe("Search query (FTS5 with porter stemming)"),
|
|
80047
80460
|
limit: z14.number().int().min(1).max(50).optional().describe("Max results (default: 20)")
|
|
@@ -80060,7 +80473,7 @@ function registerMemoryTools(server, ctx) {
|
|
|
80060
80473
|
);
|
|
80061
80474
|
server.tool(
|
|
80062
80475
|
"get_wake_up",
|
|
80063
|
-
"Compact orientation context (~300 tokens) for session start. Returns: project identity, active architectural decisions (linked to code symbols/files), and memory stats. Auto-mines sessions on first call if no decisions exist yet. Like MemPalace wake-up but code-aware \u2014 decisions are tied to the dependency graph.",
|
|
80476
|
+
"Compact orientation context (~300 tokens) for session start. Returns: project identity, active architectural decisions (linked to code symbols/files), and memory stats. Auto-mines sessions on first call if no decisions exist yet. Like MemPalace wake-up but code-aware \u2014 decisions are tied to the dependency graph. Use at session start for context recovery. For cross-session file/tool history use get_session_resume instead. Returns JSON: { project, decisions, stats }.",
|
|
80064
80477
|
{
|
|
80065
80478
|
max_decisions: z14.number().int().min(1).max(30).optional().describe("Max recent decisions to include (default: 10)"),
|
|
80066
80479
|
auto_mine: z14.boolean().optional().describe("Auto-mine sessions if decision store is empty (default: true)")
|
|
@@ -81053,7 +81466,7 @@ var DecisionStore = class {
|
|
|
81053
81466
|
};
|
|
81054
81467
|
|
|
81055
81468
|
// src/server/server.ts
|
|
81056
|
-
var
|
|
81469
|
+
var PKG_VERSION2 = true ? "1.22.0" : "0.0.0-dev";
|
|
81057
81470
|
function j2(value) {
|
|
81058
81471
|
return JSON.stringify(value, (_key, val) => val === null || val === void 0 ? void 0 : val);
|
|
81059
81472
|
}
|
|
@@ -81169,7 +81582,7 @@ function createServer2(store, registry, config, rootPath, progress) {
|
|
|
81169
81582
|
const detectedFrameworks = [...frameworkNames].join(", ") || "none";
|
|
81170
81583
|
const instructionsVerbosity = config.tools?.instructions_verbosity ?? "full";
|
|
81171
81584
|
const server = new McpServer(
|
|
81172
|
-
{ name: "trace-mcp", version:
|
|
81585
|
+
{ name: "trace-mcp", version: PKG_VERSION2 },
|
|
81173
81586
|
{ instructions: buildInstructions(detectedFrameworks, instructionsVerbosity) }
|
|
81174
81587
|
);
|
|
81175
81588
|
const savings = new SavingsTracker(projectRoot);
|