openkrak-mcp 1.0.18 → 1.0.19
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/dist/index.js +145 -26
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -242516,7 +242516,7 @@ function detectSecurityPatterns(filePath, content) {
|
|
|
242516
242516
|
}
|
|
242517
242517
|
async function classifyTopology(repoRoot, allFiles) {
|
|
242518
242518
|
const type = await detectProjectType(repoRoot);
|
|
242519
|
-
const framework = await detectFramework(repoRoot);
|
|
242519
|
+
const framework = await detectFramework(repoRoot, allFiles);
|
|
242520
242520
|
const entryPoints = detectEntryPoints(allFiles);
|
|
242521
242521
|
const layers = detectLayers(allFiles);
|
|
242522
242522
|
const modules = detectModules(allFiles);
|
|
@@ -242539,9 +242539,8 @@ async function detectProjectType(repoRoot) {
|
|
|
242539
242539
|
}
|
|
242540
242540
|
return "monolith";
|
|
242541
242541
|
}
|
|
242542
|
-
async function
|
|
242542
|
+
async function readFrameworkFromPkg(pkgPath) {
|
|
242543
242543
|
try {
|
|
242544
|
-
const pkgPath = import_path4.default.join(repoRoot, "package.json");
|
|
242545
242544
|
const pkg = JSON.parse(await import_promises3.default.readFile(pkgPath, "utf-8"));
|
|
242546
242545
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
242547
242546
|
if (deps["next"]) return `next@${deps["next"].replace(/[\^~]/g, "")}`;
|
|
@@ -242558,30 +242557,68 @@ async function detectFramework(repoRoot) {
|
|
|
242558
242557
|
if (deps["@angular/core"]) return "angular";
|
|
242559
242558
|
} catch {
|
|
242560
242559
|
}
|
|
242561
|
-
|
|
242562
|
-
|
|
242563
|
-
|
|
242564
|
-
|
|
242565
|
-
|
|
242566
|
-
|
|
242567
|
-
|
|
242568
|
-
|
|
242569
|
-
} catch {
|
|
242560
|
+
return null;
|
|
242561
|
+
}
|
|
242562
|
+
async function findSubPackageRoots(repoRoot, allFiles) {
|
|
242563
|
+
const candidates = /* @__PURE__ */ new Set();
|
|
242564
|
+
for (const f of allFiles) {
|
|
242565
|
+
const parts = f.split("/");
|
|
242566
|
+
if (parts.length >= 1) candidates.add(parts[0]);
|
|
242567
|
+
if (parts.length >= 2) candidates.add(`${parts[0]}/${parts[1]}`);
|
|
242570
242568
|
}
|
|
242571
|
-
|
|
242572
|
-
|
|
242573
|
-
|
|
242574
|
-
|
|
242569
|
+
const roots = [];
|
|
242570
|
+
for (const candidate of candidates) {
|
|
242571
|
+
const pkgPath = import_path4.default.join(repoRoot, candidate, "package.json");
|
|
242572
|
+
try {
|
|
242573
|
+
await import_promises3.default.access(pkgPath);
|
|
242574
|
+
roots.push(candidate);
|
|
242575
|
+
} catch {
|
|
242576
|
+
}
|
|
242575
242577
|
}
|
|
242576
|
-
|
|
242577
|
-
|
|
242578
|
-
|
|
242579
|
-
|
|
242578
|
+
return roots;
|
|
242579
|
+
}
|
|
242580
|
+
async function detectFramework(repoRoot, allFiles) {
|
|
242581
|
+
const rootFramework = await readFrameworkFromPkg(import_path4.default.join(repoRoot, "package.json"));
|
|
242582
|
+
if (rootFramework) return rootFramework;
|
|
242583
|
+
const configChecks = [
|
|
242584
|
+
["next.config.js", "next"],
|
|
242585
|
+
["next.config.mjs", "next"],
|
|
242586
|
+
["next.config.ts", "next"],
|
|
242587
|
+
["vite.config.ts", "vite"],
|
|
242588
|
+
["astro.config.mjs", "astro"]
|
|
242589
|
+
];
|
|
242590
|
+
for (const [cfg, name] of configChecks) {
|
|
242591
|
+
try {
|
|
242592
|
+
await import_promises3.default.access(import_path4.default.join(repoRoot, cfg));
|
|
242593
|
+
return name;
|
|
242594
|
+
} catch {
|
|
242595
|
+
}
|
|
242580
242596
|
}
|
|
242581
|
-
|
|
242582
|
-
await
|
|
242583
|
-
|
|
242584
|
-
|
|
242597
|
+
if (allFiles && allFiles.length > 0) {
|
|
242598
|
+
const subRoots = await findSubPackageRoots(repoRoot, allFiles);
|
|
242599
|
+
const detected = [];
|
|
242600
|
+
for (const subRoot of subRoots) {
|
|
242601
|
+
const fw = await readFrameworkFromPkg(import_path4.default.join(repoRoot, subRoot, "package.json"));
|
|
242602
|
+
if (fw && !detected.includes(fw)) detected.push(fw);
|
|
242603
|
+
}
|
|
242604
|
+
for (const subRoot of subRoots) {
|
|
242605
|
+
for (const [cfg, name] of configChecks) {
|
|
242606
|
+
try {
|
|
242607
|
+
await import_promises3.default.access(import_path4.default.join(repoRoot, subRoot, cfg));
|
|
242608
|
+
if (!detected.includes(name)) detected.push(name);
|
|
242609
|
+
} catch {
|
|
242610
|
+
}
|
|
242611
|
+
}
|
|
242612
|
+
}
|
|
242613
|
+
if (detected.length === 1) return detected[0];
|
|
242614
|
+
if (detected.length > 1) {
|
|
242615
|
+
const prefixCount = /* @__PURE__ */ new Map();
|
|
242616
|
+
for (const d of detected) {
|
|
242617
|
+
const prefix = d.split("@")[0];
|
|
242618
|
+
prefixCount.set(prefix, (prefixCount.get(prefix) ?? 0) + 1);
|
|
242619
|
+
}
|
|
242620
|
+
return [...prefixCount.entries()].map(([fw, count]) => count > 1 ? `${fw} (\xD7${count})` : fw).join(", ");
|
|
242621
|
+
}
|
|
242585
242622
|
}
|
|
242586
242623
|
return null;
|
|
242587
242624
|
}
|
|
@@ -242593,11 +242630,15 @@ function detectEntryPoints(files) {
|
|
|
242593
242630
|
entries.push({ path: f, type });
|
|
242594
242631
|
continue;
|
|
242595
242632
|
}
|
|
242596
|
-
if (
|
|
242633
|
+
if (/(?:^|\/)app\/.*page\.(ts|js)x?$/.test(f) || /(?:^|\/)app\/layout\.(ts|js)x?$/.test(f)) {
|
|
242634
|
+
entries.push({ path: f, type: "api" });
|
|
242635
|
+
continue;
|
|
242636
|
+
}
|
|
242637
|
+
if (/(?:^|\/)app\/.*(?:loading|error|not-found)\.(ts|js)x?$/.test(f)) {
|
|
242597
242638
|
entries.push({ path: f, type: "api" });
|
|
242598
242639
|
continue;
|
|
242599
242640
|
}
|
|
242600
|
-
if (
|
|
242641
|
+
if (/(?:^|\/)app\/.*route\.(ts|js)x?$/.test(f) || /(?:^|\/)pages\/api\//.test(f)) {
|
|
242601
242642
|
entries.push({ path: f, type: "api" });
|
|
242602
242643
|
continue;
|
|
242603
242644
|
}
|
|
@@ -243034,6 +243075,73 @@ function buildImpactChains(candidates) {
|
|
|
243034
243075
|
function describeMechanism(root, related, depth) {
|
|
243035
243076
|
return `${root.type} in ${root.file} propagates via ${depth} dependency hop(s) to ${related.type} in ${related.file}`;
|
|
243036
243077
|
}
|
|
243078
|
+
var CROSS_BUNDLE_SAFE_EXPORTS = /* @__PURE__ */ new Set([
|
|
243079
|
+
// action_contracts
|
|
243080
|
+
"ActionType",
|
|
243081
|
+
"PlannedAction",
|
|
243082
|
+
"ShellCommandSpec",
|
|
243083
|
+
"TEST_COMMAND_WHITELIST",
|
|
243084
|
+
"SENSITIVE_KEY_RE",
|
|
243085
|
+
"DESTRUCTIVE_RE",
|
|
243086
|
+
// orchestrator / plan
|
|
243087
|
+
"OrchestratorPlan",
|
|
243088
|
+
"OrchestratorStep",
|
|
243089
|
+
// contracts / store
|
|
243090
|
+
"MahadataStore",
|
|
243091
|
+
"InMemoryMahadataStore",
|
|
243092
|
+
"Mahadata",
|
|
243093
|
+
"TokenCounter",
|
|
243094
|
+
"LLMClientConfig",
|
|
243095
|
+
// handlers exposed via MCP tool layer
|
|
243096
|
+
"handleAnalyzeRepo",
|
|
243097
|
+
"handleBlastRadius",
|
|
243098
|
+
"handleGetHotspots",
|
|
243099
|
+
"handleGetMahadata",
|
|
243100
|
+
// shared utilities
|
|
243101
|
+
"calculateRiskScore",
|
|
243102
|
+
"assembleGraph",
|
|
243103
|
+
"classifyTopology",
|
|
243104
|
+
"resolveTaskDependencies",
|
|
243105
|
+
// constants / prompts
|
|
243106
|
+
"SYSTEM_PROMPT",
|
|
243107
|
+
"JSON_TAG_RE",
|
|
243108
|
+
// Next.js / framework reserved exports — always safe
|
|
243109
|
+
"metadata",
|
|
243110
|
+
"nextConfig",
|
|
243111
|
+
"geistSans",
|
|
243112
|
+
"geistMono",
|
|
243113
|
+
"default"
|
|
243114
|
+
// default exports are always externally consumable
|
|
243115
|
+
]);
|
|
243116
|
+
var SAFE_EXPORT_PREFIXES = [
|
|
243117
|
+
"handle",
|
|
243118
|
+
// MCP handlers
|
|
243119
|
+
"create",
|
|
243120
|
+
// factory functions
|
|
243121
|
+
"build",
|
|
243122
|
+
// builder functions
|
|
243123
|
+
"run"
|
|
243124
|
+
// runner functions exposed to orchestrator
|
|
243125
|
+
];
|
|
243126
|
+
var CROSS_BUNDLE_BARREL_PATTERNS = [
|
|
243127
|
+
/\/contracts\/index\.ts$/,
|
|
243128
|
+
/\/action_contracts\/index\.ts$/,
|
|
243129
|
+
/\/action_layer\/index\.ts$/,
|
|
243130
|
+
/\/shared\/index\.ts$/,
|
|
243131
|
+
/\/shared\/logger\/index\.ts$/,
|
|
243132
|
+
/\/orchestrator\/index\.ts$/
|
|
243133
|
+
];
|
|
243134
|
+
function isCrossBundleSafeSymbol(symbolName, filePath) {
|
|
243135
|
+
if (CROSS_BUNDLE_SAFE_EXPORTS.has(symbolName)) return true;
|
|
243136
|
+
for (const prefix of SAFE_EXPORT_PREFIXES) {
|
|
243137
|
+
if (symbolName.startsWith(prefix)) return true;
|
|
243138
|
+
}
|
|
243139
|
+
if (symbolName === "logger" || symbolName.startsWith("logger")) return true;
|
|
243140
|
+
for (const pattern of CROSS_BUNDLE_BARREL_PATTERNS) {
|
|
243141
|
+
if (pattern.test(filePath)) return true;
|
|
243142
|
+
}
|
|
243143
|
+
return false;
|
|
243144
|
+
}
|
|
243037
243145
|
function tagNoise(findings, chains) {
|
|
243038
243146
|
const suppressionReasons = /* @__PURE__ */ new Map();
|
|
243039
243147
|
const severityOrder = {
|
|
@@ -243043,6 +243151,17 @@ function tagNoise(findings, chains) {
|
|
|
243043
243151
|
low: 1,
|
|
243044
243152
|
info: 0
|
|
243045
243153
|
};
|
|
243154
|
+
for (const f of findings) {
|
|
243155
|
+
if (f.type !== "dead_code") continue;
|
|
243156
|
+
if (suppressionReasons.has(f.id)) continue;
|
|
243157
|
+
const symbolName = f.symbol ? f.symbol.split("::")[1] ?? f.symbol : "";
|
|
243158
|
+
if (isCrossBundleSafeSymbol(symbolName, f.file)) {
|
|
243159
|
+
suppressionReasons.set(
|
|
243160
|
+
f.id,
|
|
243161
|
+
`Cross-bundle false positive: '${symbolName}' is a known exported interface consumed outside this scan boundary.`
|
|
243162
|
+
);
|
|
243163
|
+
}
|
|
243164
|
+
}
|
|
243046
243165
|
const groupedByFileType = /* @__PURE__ */ new Map();
|
|
243047
243166
|
for (const f of findings) {
|
|
243048
243167
|
const key = `${f.file}::${f.type}`;
|