kontexta-mcp 2.0.10 → 3.0.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/dist/index.js +114 -35
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1048,6 +1048,47 @@ function listProjectFolders(projectPath) {
|
|
|
1048
1048
|
}
|
|
1049
1049
|
return folders;
|
|
1050
1050
|
}
|
|
1051
|
+
function listProjectFoldersWithFiles(projectPath) {
|
|
1052
|
+
const folderFileCount = /* @__PURE__ */ new Map();
|
|
1053
|
+
function scan(dir, currentRel) {
|
|
1054
|
+
const entries = readdirSync3(dir);
|
|
1055
|
+
for (const entry of entries) {
|
|
1056
|
+
if (entry.startsWith(".") || entry === "node_modules")
|
|
1057
|
+
continue;
|
|
1058
|
+
const fullPath = join4(dir, entry);
|
|
1059
|
+
const relPath = currentRel ? join4(currentRel, entry) : entry;
|
|
1060
|
+
try {
|
|
1061
|
+
const lst = lstatSync2(fullPath);
|
|
1062
|
+
if (lst.isSymbolicLink())
|
|
1063
|
+
continue;
|
|
1064
|
+
if (lst.isDirectory()) {
|
|
1065
|
+
scan(fullPath, relPath);
|
|
1066
|
+
} else if (lst.isFile()) {
|
|
1067
|
+
const ext = entry.endsWith(".mmd") ? ".mmd" : entry.endsWith(".md") ? ".md" : "";
|
|
1068
|
+
if (ext) {
|
|
1069
|
+
const parts = relPath.split("/");
|
|
1070
|
+
for (let i4 = 0; i4 < parts.length - 1; i4++) {
|
|
1071
|
+
const ancestor = parts.slice(0, i4 + 1).join("/");
|
|
1072
|
+
folderFileCount.set(ancestor, (folderFileCount.get(ancestor) ?? 0) + 1);
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
} catch (e3) {
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
try {
|
|
1081
|
+
scan(projectPath, "");
|
|
1082
|
+
} catch (e3) {
|
|
1083
|
+
console.error("Failed to scan project folders with files:", e3);
|
|
1084
|
+
}
|
|
1085
|
+
const result = [];
|
|
1086
|
+
for (const [folder, count] of folderFileCount.entries()) {
|
|
1087
|
+
if (count > 0)
|
|
1088
|
+
result.push(folder);
|
|
1089
|
+
}
|
|
1090
|
+
return result.sort();
|
|
1091
|
+
}
|
|
1051
1092
|
function computeHash(content) {
|
|
1052
1093
|
return createHash2("sha256").update(content, "utf8").digest("hex");
|
|
1053
1094
|
}
|
|
@@ -1333,9 +1374,15 @@ function listFiles(opts) {
|
|
|
1333
1374
|
}
|
|
1334
1375
|
if (filters.folder !== void 0) {
|
|
1335
1376
|
const segment = escapeLike(filters.folder);
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1377
|
+
if (filters.project_path) {
|
|
1378
|
+
sql += " AND (path LIKE ? ESCAPE '\\' OR path LIKE ? ESCAPE '\\')";
|
|
1379
|
+
params.push(`${filters.project_path}/${segment}/%`);
|
|
1380
|
+
params.push(`${filters.project_path}\\${segment}\\%`);
|
|
1381
|
+
} else {
|
|
1382
|
+
sql += " AND (path LIKE ? ESCAPE '\\' OR path LIKE ? ESCAPE '\\')";
|
|
1383
|
+
params.push(`%/${segment}/%`);
|
|
1384
|
+
params.push(`%\\${segment}\\%`);
|
|
1385
|
+
}
|
|
1339
1386
|
}
|
|
1340
1387
|
}
|
|
1341
1388
|
sql += " ORDER BY updated_at DESC";
|
|
@@ -1582,27 +1629,33 @@ function registerProject(name50, path3, description, remoteUrl) {
|
|
|
1582
1629
|
`);
|
|
1583
1630
|
const absolutePath = resolve5(path3);
|
|
1584
1631
|
const result = insertStmt.run(name50, slug, absolutePath, description || null, remoteUrl || null);
|
|
1632
|
+
let projectId;
|
|
1585
1633
|
if (result.changes > 0) {
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1634
|
+
projectId = Number(result.lastInsertRowid);
|
|
1635
|
+
} else {
|
|
1636
|
+
const byName = db2.prepare("SELECT * FROM projects WHERE name = ?").get(name50);
|
|
1637
|
+
const bySlug = db2.prepare("SELECT * FROM projects WHERE slug = ?").get(slug);
|
|
1638
|
+
const existing = byName ?? bySlug;
|
|
1639
|
+
if (!existing) {
|
|
1640
|
+
throw new Error(`registerProject: insert ignored but no matching project found for name='${name50}'`);
|
|
1641
|
+
}
|
|
1642
|
+
if (existing.path !== absolutePath) {
|
|
1643
|
+
const conflicts = [];
|
|
1644
|
+
if (byName)
|
|
1645
|
+
conflicts.push(`name conflicts with '${byName.name}' at '${byName.path}'`);
|
|
1646
|
+
if (bySlug && bySlug.id !== byName?.id)
|
|
1647
|
+
conflicts.push(`slug '${slug}' conflicts with '${bySlug.name}' at '${bySlug.path}'`);
|
|
1648
|
+
const err = new Error(`Cannot register '${name50}' at '${path3}': ${conflicts.join("; ")}. Pick a different name or unregister the existing project first.`);
|
|
1649
|
+
err.code = "PROJECT_CONFLICT";
|
|
1650
|
+
throw err;
|
|
1651
|
+
}
|
|
1652
|
+
projectId = existing.id;
|
|
1653
|
+
}
|
|
1654
|
+
const newlyIndexed = reconcileIndex({ projectId, dataDir: getDataDir() }).newRecords.length;
|
|
1655
|
+
return {
|
|
1656
|
+
...db2.prepare("SELECT * FROM projects WHERE id = ?").get(projectId),
|
|
1657
|
+
newlyIndexed
|
|
1658
|
+
};
|
|
1606
1659
|
}
|
|
1607
1660
|
function unregisterProject(projectId, dataDir2) {
|
|
1608
1661
|
const db2 = getDatabase();
|
|
@@ -1678,9 +1731,14 @@ function reconcileIndex(opts) {
|
|
|
1678
1731
|
} catch (e3) {
|
|
1679
1732
|
if (isTopLevel) {
|
|
1680
1733
|
if (typeof projectId === "number") {
|
|
1681
|
-
|
|
1734
|
+
if (e3?.code === "ENOENT") {
|
|
1735
|
+
console.warn(`reconcileIndex: project root does not exist yet: ${dir}`);
|
|
1736
|
+
} else {
|
|
1737
|
+
throw new Error(`Failed to read project root ${dir}: ${e3?.message ?? e3}`);
|
|
1738
|
+
}
|
|
1739
|
+
} else {
|
|
1740
|
+
console.warn(`reconcileIndex: failed to read KB root ${dir}: ${e3?.message ?? e3}`);
|
|
1682
1741
|
}
|
|
1683
|
-
console.warn(`reconcileIndex: failed to read KB root ${dir}: ${e3?.message ?? e3}`);
|
|
1684
1742
|
}
|
|
1685
1743
|
return;
|
|
1686
1744
|
}
|
|
@@ -1775,7 +1833,9 @@ function reconcileIndex(opts) {
|
|
|
1775
1833
|
return { scope, newly_indexed, refreshed, pruned, newRecords };
|
|
1776
1834
|
}
|
|
1777
1835
|
function discoverFiles(projectId, dataDir2) {
|
|
1778
|
-
|
|
1836
|
+
reconcileIndex({ projectId, dataDir: dataDir2 });
|
|
1837
|
+
const db2 = getDatabase();
|
|
1838
|
+
return db2.prepare("SELECT * FROM files WHERE project_id = ? ORDER BY path").all(projectId);
|
|
1779
1839
|
}
|
|
1780
1840
|
function getTagsForFiles(fileIds) {
|
|
1781
1841
|
const out = /* @__PURE__ */ new Map();
|
|
@@ -1822,6 +1882,7 @@ var init_metadata = __esm({
|
|
|
1822
1882
|
init_safety();
|
|
1823
1883
|
init_files();
|
|
1824
1884
|
init_extensions();
|
|
1885
|
+
init_paths();
|
|
1825
1886
|
FtsQueryError = class extends Error {
|
|
1826
1887
|
code = "FTS_PARSE";
|
|
1827
1888
|
constructor(message) {
|
|
@@ -130573,7 +130634,7 @@ var init_dist3 = __esm({
|
|
|
130573
130634
|
}
|
|
130574
130635
|
});
|
|
130575
130636
|
|
|
130576
|
-
// ../../node_modules/.pnpm/@csstools+css-calc@3.2.1_@csstools+css-parser-algorithms@4.0.0_@csstools+css-tokenizer@
|
|
130637
|
+
// ../../node_modules/.pnpm/@csstools+css-calc@3.2.1_@csstools+css-parser-algorithms@4.0.0_@csstools+css-tokenizer@_3b33f237655dfa7a35d4b0433ee15cf1/node_modules/@csstools/css-calc/dist/index.mjs
|
|
130577
130638
|
function toLowerCaseAZ(e3) {
|
|
130578
130639
|
return e3.replace(M, (e4) => String.fromCharCode(e4.charCodeAt(0) + 32));
|
|
130579
130640
|
}
|
|
@@ -131332,7 +131393,7 @@ function replaceComponentValues2(n3, r5) {
|
|
|
131332
131393
|
}
|
|
131333
131394
|
var ParseError2, ParseErrorWithComponentValues, y, M, T, x, P, k, W, O, U, L, $2, V, Z, z, q, G, R, j, Y, _, H, J, K, Q;
|
|
131334
131395
|
var init_dist4 = __esm({
|
|
131335
|
-
"../../node_modules/.pnpm/@csstools+css-calc@3.2.1_@csstools+css-parser-algorithms@4.0.0_@csstools+css-tokenizer@
|
|
131396
|
+
"../../node_modules/.pnpm/@csstools+css-calc@3.2.1_@csstools+css-parser-algorithms@4.0.0_@csstools+css-tokenizer@_3b33f237655dfa7a35d4b0433ee15cf1/node_modules/@csstools/css-calc/dist/index.mjs"() {
|
|
131336
131397
|
"use strict";
|
|
131337
131398
|
init_dist3();
|
|
131338
131399
|
init_dist2();
|
|
@@ -132456,7 +132517,7 @@ var init_dist5 = __esm({
|
|
|
132456
132517
|
}
|
|
132457
132518
|
});
|
|
132458
132519
|
|
|
132459
|
-
// ../../node_modules/.pnpm/@csstools+css-color-parser@4.1.1_@csstools+css-parser-algorithms@4.0.0_@csstools+css-
|
|
132520
|
+
// ../../node_modules/.pnpm/@csstools+css-color-parser@4.1.1_@csstools+css-parser-algorithms@4.0.0_@csstools+css-to_402b4b31fb8b001854d943f6a3e18a48/node_modules/@csstools/css-color-parser/dist/index.mjs
|
|
132460
132521
|
function convertNaNToZero(e3) {
|
|
132461
132522
|
return [Number.isNaN(e3[0]) ? 0 : e3[0], Number.isNaN(e3[1]) ? 0 : e3[1], Number.isNaN(e3[2]) ? 0 : e3[2]];
|
|
132462
132523
|
}
|
|
@@ -133521,7 +133582,7 @@ function color(e3) {
|
|
|
133521
133582
|
}
|
|
133522
133583
|
var he, me, pe, Ne, be, ge, ve, fe, ye;
|
|
133523
133584
|
var init_dist6 = __esm({
|
|
133524
|
-
"../../node_modules/.pnpm/@csstools+css-color-parser@4.1.1_@csstools+css-parser-algorithms@4.0.0_@csstools+css-
|
|
133585
|
+
"../../node_modules/.pnpm/@csstools+css-color-parser@4.1.1_@csstools+css-parser-algorithms@4.0.0_@csstools+css-to_402b4b31fb8b001854d943f6a3e18a48/node_modules/@csstools/css-color-parser/dist/index.mjs"() {
|
|
133525
133586
|
"use strict";
|
|
133526
133587
|
init_dist2();
|
|
133527
133588
|
init_dist5();
|
|
@@ -331165,6 +331226,7 @@ __export(dist_exports2, {
|
|
|
331165
331226
|
journalRefsByValue: () => journalRefsByValue,
|
|
331166
331227
|
listFiles: () => listFiles,
|
|
331167
331228
|
listProjectFolders: () => listProjectFolders,
|
|
331229
|
+
listProjectFoldersWithFiles: () => listProjectFoldersWithFiles,
|
|
331168
331230
|
listProjects: () => listProjects,
|
|
331169
331231
|
listTags: () => listTags,
|
|
331170
331232
|
loadExtraPatterns: () => loadExtraPatterns,
|
|
@@ -331230,8 +331292,24 @@ var init_dist7 = __esm({
|
|
|
331230
331292
|
}
|
|
331231
331293
|
});
|
|
331232
331294
|
|
|
331295
|
+
// src/re2-compat.ts
|
|
331296
|
+
import { createRequire as createRequire4 } from "module";
|
|
331297
|
+
var require5, RE2Class, re2_compat_default;
|
|
331298
|
+
var init_re2_compat = __esm({
|
|
331299
|
+
"src/re2-compat.ts"() {
|
|
331300
|
+
"use strict";
|
|
331301
|
+
require5 = createRequire4(import.meta.url);
|
|
331302
|
+
try {
|
|
331303
|
+
RE2Class = require5("re2");
|
|
331304
|
+
} catch (e3) {
|
|
331305
|
+
console.warn("kontexta-mcp: Failed to load native 're2' module, falling back to standard RegExp.");
|
|
331306
|
+
RE2Class = RegExp;
|
|
331307
|
+
}
|
|
331308
|
+
re2_compat_default = RE2Class;
|
|
331309
|
+
}
|
|
331310
|
+
});
|
|
331311
|
+
|
|
331233
331312
|
// src/hands/sanitizer.ts
|
|
331234
|
-
import RE2 from "re2";
|
|
331235
331313
|
function rejectNul(s3) {
|
|
331236
331314
|
if (s3.includes("\0")) {
|
|
331237
331315
|
throw new Error("NUL byte not permitted in param value");
|
|
@@ -331267,7 +331345,7 @@ function isLiteralArgv0(s3) {
|
|
|
331267
331345
|
function compilePattern(src) {
|
|
331268
331346
|
let r5;
|
|
331269
331347
|
try {
|
|
331270
|
-
r5 = new
|
|
331348
|
+
r5 = new re2_compat_default(src);
|
|
331271
331349
|
} catch (e3) {
|
|
331272
331350
|
throw new Error(`invalid pattern: ${e3?.message ?? e3}`);
|
|
331273
331351
|
}
|
|
@@ -331304,6 +331382,7 @@ var SAFE_INT_MIN, SAFE_INT_MAX, DEFAULT_STRING_PATTERN, MAX_STRING_LENGTH, CONTR
|
|
|
331304
331382
|
var init_sanitizer = __esm({
|
|
331305
331383
|
"src/hands/sanitizer.ts"() {
|
|
331306
331384
|
"use strict";
|
|
331385
|
+
init_re2_compat();
|
|
331307
331386
|
SAFE_INT_MIN = Number.MIN_SAFE_INTEGER;
|
|
331308
331387
|
SAFE_INT_MAX = Number.MAX_SAFE_INTEGER;
|
|
331309
331388
|
DEFAULT_STRING_PATTERN = "^[^-\\s][^\\n\\r]*$";
|
|
@@ -331542,10 +331621,10 @@ ${tailStr}`;
|
|
|
331542
331621
|
|
|
331543
331622
|
// src/index.ts
|
|
331544
331623
|
init_dist7();
|
|
331624
|
+
init_re2_compat();
|
|
331545
331625
|
import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
331546
331626
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
331547
331627
|
import { z as z6 } from "zod";
|
|
331548
|
-
import RE22 from "re2";
|
|
331549
331628
|
import { isAbsolute as isAbsolute7, join as join16, resolve as resolve7, sep as sep9, dirname as dirname6 } from "path";
|
|
331550
331629
|
import { statSync as statSync5, lstatSync as lstatSync5, openSync as openSync2, readSync, closeSync as closeSync2, readFileSync as readFileSync12, existsSync as existsSync13, realpathSync as realpathSync2 } from "fs";
|
|
331551
331630
|
import { createHash as createHash3 } from "crypto";
|
|
@@ -332929,7 +333008,7 @@ server.tool(
|
|
|
332929
333008
|
try {
|
|
332930
333009
|
let re;
|
|
332931
333010
|
try {
|
|
332932
|
-
re = new
|
|
333011
|
+
re = new re2_compat_default(pattern, case_insensitive ? "i" : "");
|
|
332933
333012
|
} catch (e3) {
|
|
332934
333013
|
throw new Error(`invalid regex: ${e3?.message ?? e3}`);
|
|
332935
333014
|
}
|
|
@@ -332984,7 +333063,7 @@ server.tool(
|
|
|
332984
333063
|
try {
|
|
332985
333064
|
let re;
|
|
332986
333065
|
try {
|
|
332987
|
-
re = new
|
|
333066
|
+
re = new re2_compat_default(pattern, case_insensitive ? "i" : "");
|
|
332988
333067
|
} catch (e3) {
|
|
332989
333068
|
throw new Error(`invalid regex: ${e3?.message ?? e3}`);
|
|
332990
333069
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kontexta-mcp",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "The local Brain and Hands for AI coding agents (MCP Server)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"./hands/types": "./dist/hands/types.js"
|
|
39
39
|
},
|
|
40
40
|
"engines": {
|
|
41
|
-
"node": ">=
|
|
41
|
+
"node": ">=22"
|
|
42
42
|
},
|
|
43
43
|
"files": [
|
|
44
44
|
"dist",
|