@softerist/heuristic-mcp 3.0.17 → 3.1.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/config.jsonc +23 -6
- package/features/ann-config.js +7 -14
- package/features/clear-cache.js +3 -3
- package/features/find-similar-code.js +17 -22
- package/features/hybrid-search.js +59 -67
- package/features/index-codebase.js +305 -268
- package/features/lifecycle.js +370 -176
- package/features/package-version.js +15 -26
- package/features/register.js +75 -57
- package/features/resources.js +21 -47
- package/features/set-workspace.js +31 -43
- package/index.js +818 -172
- package/lib/cache-utils.js +95 -99
- package/lib/cache.js +121 -166
- package/lib/cli.js +246 -238
- package/lib/config.js +232 -62
- package/lib/constants.js +22 -2
- package/lib/embed-query-process.js +13 -29
- package/lib/embedding-process.js +29 -19
- package/lib/embedding-worker.js +166 -149
- package/lib/ignore-patterns.js +39 -39
- package/lib/json-writer.js +7 -34
- package/lib/logging.js +11 -42
- package/lib/onnx-backend.js +4 -4
- package/lib/path-utils.js +4 -21
- package/lib/project-detector.js +3 -3
- package/lib/server-lifecycle.js +109 -15
- package/lib/settings-editor.js +25 -18
- package/lib/slice-normalize.js +6 -16
- package/lib/tokenizer.js +56 -109
- package/lib/utils.js +62 -81
- package/lib/vector-store-binary.js +7 -7
- package/lib/vector-store-sqlite.js +35 -67
- package/lib/workspace-cache-key.js +36 -0
- package/lib/workspace-env.js +55 -14
- package/package.json +86 -86
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* SQLite Vector Store
|
|
3
|
-
*
|
|
4
|
-
* An alternative to binary/JSON vector stores using SQLite for persistence.
|
|
5
|
-
* Provides ACID transactions, simpler concurrent access, and query flexibility.
|
|
6
|
-
*/
|
|
1
|
+
|
|
7
2
|
|
|
8
3
|
import Database from 'better-sqlite3';
|
|
9
4
|
import path from 'path';
|
|
@@ -42,7 +37,7 @@ async function bestEffortUnlink(targetPath) {
|
|
|
42
37
|
try {
|
|
43
38
|
await retryUnlink(targetPath);
|
|
44
39
|
} catch {
|
|
45
|
-
|
|
40
|
+
|
|
46
41
|
}
|
|
47
42
|
}
|
|
48
43
|
|
|
@@ -63,17 +58,14 @@ async function retryRename(fromPath, toPath, retries = SQLITE_FILE_RETRY_COUNT)
|
|
|
63
58
|
}
|
|
64
59
|
}
|
|
65
60
|
|
|
66
|
-
|
|
67
|
-
* SQLite-backed vector store for embeddings cache.
|
|
68
|
-
* Follows the same API pattern as BinaryVectorStore for compatibility.
|
|
69
|
-
*/
|
|
61
|
+
|
|
70
62
|
export class SqliteVectorStore {
|
|
71
63
|
constructor({ db, dim, count }) {
|
|
72
64
|
this.db = db;
|
|
73
65
|
this.dim = dim;
|
|
74
66
|
this.count = count;
|
|
75
67
|
|
|
76
|
-
|
|
68
|
+
|
|
77
69
|
this._stmtGetChunk = db.prepare(`
|
|
78
70
|
SELECT file, startLine, endLine, content, vector FROM chunks WHERE id = ?
|
|
79
71
|
`);
|
|
@@ -83,9 +75,7 @@ export class SqliteVectorStore {
|
|
|
83
75
|
this._stmtGetChunksForFile = db.prepare(`SELECT id FROM chunks WHERE file = ?`);
|
|
84
76
|
}
|
|
85
77
|
|
|
86
|
-
|
|
87
|
-
* Close the database connection
|
|
88
|
-
*/
|
|
78
|
+
|
|
89
79
|
close() {
|
|
90
80
|
if (this._closed) return;
|
|
91
81
|
this._closed = true;
|
|
@@ -94,44 +84,40 @@ export class SqliteVectorStore {
|
|
|
94
84
|
this.db.close();
|
|
95
85
|
}
|
|
96
86
|
} catch {
|
|
97
|
-
|
|
87
|
+
|
|
98
88
|
}
|
|
99
89
|
}
|
|
100
90
|
|
|
101
|
-
|
|
102
|
-
* Get the path to the SQLite file
|
|
103
|
-
*/
|
|
91
|
+
|
|
104
92
|
static getPath(cacheDir) {
|
|
105
93
|
return path.join(cacheDir, SQLITE_FILE);
|
|
106
94
|
}
|
|
107
95
|
|
|
108
|
-
|
|
109
|
-
* Load an existing SQLite vector store from disk
|
|
110
|
-
*/
|
|
96
|
+
|
|
111
97
|
static async load(cacheDir, _options = {}) {
|
|
112
98
|
const dbPath = SqliteVectorStore.getPath(cacheDir);
|
|
113
99
|
|
|
114
100
|
try {
|
|
115
101
|
await fs.access(dbPath);
|
|
116
102
|
} catch {
|
|
117
|
-
return null;
|
|
103
|
+
return null;
|
|
118
104
|
}
|
|
119
105
|
|
|
120
106
|
let db;
|
|
121
107
|
try {
|
|
122
108
|
db = new Database(dbPath, { readonly: true });
|
|
123
109
|
} catch (err) {
|
|
124
|
-
|
|
110
|
+
|
|
125
111
|
console.warn(`[SQLite] Failed to open database: ${err.message}`);
|
|
126
112
|
return null;
|
|
127
113
|
}
|
|
128
114
|
|
|
129
|
-
|
|
115
|
+
|
|
130
116
|
let meta;
|
|
131
117
|
try {
|
|
132
118
|
meta = db.prepare(`SELECT key, value FROM metadata`).all();
|
|
133
119
|
} catch (err) {
|
|
134
|
-
|
|
120
|
+
|
|
135
121
|
console.warn(`[SQLite] Failed to read metadata: ${err.message}`);
|
|
136
122
|
db.close();
|
|
137
123
|
return null;
|
|
@@ -141,7 +127,7 @@ export class SqliteVectorStore {
|
|
|
141
127
|
const version = parseInt(metaMap.get('version') || '0', 10);
|
|
142
128
|
if (version !== STORE_VERSION) {
|
|
143
129
|
db.close();
|
|
144
|
-
return null;
|
|
130
|
+
return null;
|
|
145
131
|
}
|
|
146
132
|
|
|
147
133
|
const dim = parseInt(metaMap.get('dim') || '0', 10);
|
|
@@ -150,16 +136,12 @@ export class SqliteVectorStore {
|
|
|
150
136
|
return new SqliteVectorStore({ db, dim, count });
|
|
151
137
|
}
|
|
152
138
|
|
|
153
|
-
|
|
154
|
-
* Get the number of chunks in the store
|
|
155
|
-
*/
|
|
139
|
+
|
|
156
140
|
length() {
|
|
157
141
|
return this.count;
|
|
158
142
|
}
|
|
159
143
|
|
|
160
|
-
|
|
161
|
-
* Get a chunk record by index (0-based)
|
|
162
|
-
*/
|
|
144
|
+
|
|
163
145
|
getRecord(index) {
|
|
164
146
|
if (index < 0 || index >= this.count) return null;
|
|
165
147
|
|
|
@@ -173,27 +155,22 @@ export class SqliteVectorStore {
|
|
|
173
155
|
};
|
|
174
156
|
}
|
|
175
157
|
|
|
176
|
-
|
|
177
|
-
* Get a vector by index (0-based)
|
|
178
|
-
* Returns Float32Array
|
|
179
|
-
*/
|
|
158
|
+
|
|
180
159
|
getVector(index) {
|
|
181
160
|
if (index < 0 || index >= this.count) return null;
|
|
182
161
|
|
|
183
162
|
const row = this._stmtGetVector.get(index);
|
|
184
163
|
if (!row || !row.vector) return null;
|
|
185
164
|
|
|
186
|
-
|
|
165
|
+
|
|
187
166
|
const expectedBytes = this.dim * Float32Array.BYTES_PER_ELEMENT;
|
|
188
167
|
if (row.vector.byteLength < expectedBytes) return null;
|
|
189
|
-
|
|
168
|
+
|
|
190
169
|
const view = new Float32Array(row.vector.buffer, row.vector.byteOffset, this.dim);
|
|
191
170
|
return new Float32Array(view);
|
|
192
171
|
}
|
|
193
172
|
|
|
194
|
-
|
|
195
|
-
* Get content by index (0-based)
|
|
196
|
-
*/
|
|
173
|
+
|
|
197
174
|
getContent(index) {
|
|
198
175
|
if (index < 0 || index >= this.count) return null;
|
|
199
176
|
|
|
@@ -201,9 +178,7 @@ export class SqliteVectorStore {
|
|
|
201
178
|
return row ? row.content : null;
|
|
202
179
|
}
|
|
203
180
|
|
|
204
|
-
|
|
205
|
-
* Get all chunks as lightweight views (for search iteration)
|
|
206
|
-
*/
|
|
181
|
+
|
|
207
182
|
toChunkViews({ includeContent = false, includeVector = true } = {}) {
|
|
208
183
|
const views = [];
|
|
209
184
|
const stmt = this.db.prepare(`
|
|
@@ -227,7 +202,7 @@ export class SqliteVectorStore {
|
|
|
227
202
|
if (includeVector && row.vector) {
|
|
228
203
|
const expectedBytes = this.dim * Float32Array.BYTES_PER_ELEMENT;
|
|
229
204
|
if (row.vector.byteLength >= expectedBytes) {
|
|
230
|
-
|
|
205
|
+
|
|
231
206
|
const bufferView = new Float32Array(
|
|
232
207
|
row.vector.buffer,
|
|
233
208
|
row.vector.byteOffset,
|
|
@@ -243,9 +218,7 @@ export class SqliteVectorStore {
|
|
|
243
218
|
return views;
|
|
244
219
|
}
|
|
245
220
|
|
|
246
|
-
|
|
247
|
-
* Get all unique file paths and their chunk indices
|
|
248
|
-
*/
|
|
221
|
+
|
|
249
222
|
getAllFileIndices() {
|
|
250
223
|
const fileIndices = new Map();
|
|
251
224
|
|
|
@@ -258,12 +231,7 @@ export class SqliteVectorStore {
|
|
|
258
231
|
return fileIndices;
|
|
259
232
|
}
|
|
260
233
|
|
|
261
|
-
|
|
262
|
-
* Write chunks to a new SQLite database
|
|
263
|
-
* @param {string} cacheDir - Directory to write the database
|
|
264
|
-
* @param {Array} chunks - Array of chunk objects with vector, file, startLine, endLine, content
|
|
265
|
-
* @param {Object} options - { getContent, preRename }
|
|
266
|
-
*/
|
|
234
|
+
|
|
267
235
|
static async write(cacheDir, chunks, { getContent, getVector, preRename } = {}) {
|
|
268
236
|
if (!chunks || chunks.length === 0) {
|
|
269
237
|
return null;
|
|
@@ -331,14 +299,14 @@ export class SqliteVectorStore {
|
|
|
331
299
|
? (await resolveVector(denseChunks[0], denseSourceIndices[0])).length
|
|
332
300
|
: 0;
|
|
333
301
|
|
|
334
|
-
|
|
302
|
+
|
|
335
303
|
const db = new Database(writePath);
|
|
336
304
|
|
|
337
|
-
|
|
305
|
+
|
|
338
306
|
db.pragma(`journal_mode = ${useTemp ? 'WAL' : 'DELETE'}`);
|
|
339
307
|
db.pragma('synchronous = NORMAL');
|
|
340
308
|
|
|
341
|
-
|
|
309
|
+
|
|
342
310
|
if (!useTemp) {
|
|
343
311
|
db.exec(`
|
|
344
312
|
DROP TABLE IF EXISTS metadata;
|
|
@@ -364,14 +332,14 @@ export class SqliteVectorStore {
|
|
|
364
332
|
CREATE INDEX idx_chunks_file ON chunks(file);
|
|
365
333
|
`);
|
|
366
334
|
|
|
367
|
-
|
|
335
|
+
|
|
368
336
|
const insertMeta = db.prepare(`INSERT INTO metadata (key, value) VALUES (?, ?)`);
|
|
369
337
|
insertMeta.run('version', String(STORE_VERSION));
|
|
370
338
|
insertMeta.run('dim', String(dim));
|
|
371
339
|
insertMeta.run('count', String(denseChunks.length));
|
|
372
340
|
insertMeta.run('createdAt', new Date().toISOString());
|
|
373
341
|
|
|
374
|
-
|
|
342
|
+
|
|
375
343
|
const insertChunk = db.prepare(`
|
|
376
344
|
INSERT INTO chunks (id, file, startLine, endLine, content, vector)
|
|
377
345
|
VALUES (?, ?, ?, ?, ?, ?)
|
|
@@ -405,31 +373,31 @@ export class SqliteVectorStore {
|
|
|
405
373
|
try {
|
|
406
374
|
db.exec('ROLLBACK');
|
|
407
375
|
} catch {
|
|
408
|
-
|
|
376
|
+
|
|
409
377
|
}
|
|
410
378
|
throw error;
|
|
411
379
|
}
|
|
412
380
|
|
|
413
|
-
|
|
381
|
+
|
|
414
382
|
db.exec('ANALYZE');
|
|
415
383
|
db.close();
|
|
416
384
|
if (process.platform === 'win32') {
|
|
417
|
-
|
|
385
|
+
|
|
418
386
|
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
419
387
|
}
|
|
420
388
|
|
|
421
|
-
|
|
389
|
+
|
|
422
390
|
if (typeof preRename === 'function') {
|
|
423
391
|
await preRename();
|
|
424
392
|
}
|
|
425
393
|
|
|
426
|
-
|
|
394
|
+
|
|
427
395
|
if (useTemp) {
|
|
428
396
|
await retryUnlink(dbPath);
|
|
429
397
|
await retryRename(tempPath, dbPath);
|
|
430
398
|
}
|
|
431
399
|
|
|
432
|
-
|
|
400
|
+
|
|
433
401
|
if (useTemp) {
|
|
434
402
|
await bestEffortUnlink(tempPath + '-wal');
|
|
435
403
|
await bestEffortUnlink(tempPath + '-shm');
|
|
@@ -438,7 +406,7 @@ export class SqliteVectorStore {
|
|
|
438
406
|
await bestEffortUnlink(dbPath + '-shm');
|
|
439
407
|
}
|
|
440
408
|
|
|
441
|
-
|
|
409
|
+
|
|
442
410
|
return SqliteVectorStore.load(cacheDir);
|
|
443
411
|
}
|
|
444
412
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import crypto from 'crypto';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
export function normalizeWorkspacePathForCacheKey(workspacePath) {
|
|
5
|
+
const resolved = path.resolve(workspacePath);
|
|
6
|
+
if (process.platform !== 'win32') {
|
|
7
|
+
return resolved;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Windows paths are case-insensitive for drive letters; normalize only the
|
|
11
|
+
// drive prefix so F:\repo and f:\repo map to the same cache key while
|
|
12
|
+
// preserving existing segment casing for backward compatibility.
|
|
13
|
+
if (/^[A-Za-z]:/.test(resolved)) {
|
|
14
|
+
return `${resolved[0].toLowerCase()}${resolved.slice(1)}`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return resolved;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function getWorkspaceCacheKey(workspacePath) {
|
|
21
|
+
const normalized = normalizeWorkspacePathForCacheKey(workspacePath);
|
|
22
|
+
return crypto.createHash('md5').update(normalized).digest('hex').slice(0, 12);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function getLegacyWorkspaceCacheKey(workspacePath) {
|
|
26
|
+
const resolved = path.resolve(workspacePath);
|
|
27
|
+
return crypto.createHash('md5').update(resolved).digest('hex').slice(0, 12);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function getWorkspaceCachePath(workspacePath, globalCacheRoot) {
|
|
31
|
+
return path.join(globalCacheRoot, 'heuristic-mcp', getWorkspaceCacheKey(workspacePath));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function getLegacyWorkspaceCachePath(workspacePath, globalCacheRoot) {
|
|
35
|
+
return path.join(globalCacheRoot, 'heuristic-mcp', getLegacyWorkspaceCacheKey(workspacePath));
|
|
36
|
+
}
|
package/lib/workspace-env.js
CHANGED
|
@@ -1,10 +1,26 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import {
|
|
2
|
+
DYNAMIC_WORKSPACE_ENV_PREFIXES,
|
|
3
|
+
WORKSPACE_ENV_GENERIC_DISCOVERY_PATTERN,
|
|
4
|
+
WORKSPACE_ENV_KEY_PATTERN,
|
|
5
|
+
WORKSPACE_ENV_VARS,
|
|
6
|
+
} from './constants.js';
|
|
7
|
+
|
|
8
|
+
const EXCLUDED_DYNAMIC_WORKSPACE_ENV_KEYS = new Set([
|
|
9
|
+
'ANTIGRAVITY_EDITOR_APP_ROOT',
|
|
10
|
+
]);
|
|
11
|
+
|
|
12
|
+
function isTruthy(value) {
|
|
13
|
+
return /^(1|true|yes|on)$/i.test(String(value || '').trim());
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function isDynamicWorkspaceEnvEnabled(env = process.env, options = {}) {
|
|
17
|
+
if (typeof options.enableDynamic === 'boolean') {
|
|
18
|
+
return options.enableDynamic;
|
|
19
|
+
}
|
|
20
|
+
return isTruthy(env.HEURISTIC_MCP_ENABLE_DYNAMIC_WORKSPACE_ENV);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function scoreWorkspaceEnvKey(key) {
|
|
8
24
|
const upper = String(key || '').toUpperCase();
|
|
9
25
|
let score = 0;
|
|
10
26
|
if (upper.includes('WORKSPACE')) score += 8;
|
|
@@ -15,14 +31,39 @@ export function scoreWorkspaceEnvKey(key) {
|
|
|
15
31
|
return score;
|
|
16
32
|
}
|
|
17
33
|
|
|
18
|
-
|
|
19
|
-
return
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
34
|
+
function hasDynamicWorkspacePrefix(key) {
|
|
35
|
+
return DYNAMIC_WORKSPACE_ENV_PREFIXES.some((prefix) => key.startsWith(prefix));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function getDynamicWorkspaceEnvKeys(env = process.env, options = {}) {
|
|
39
|
+
if (!isDynamicWorkspaceEnvEnabled(env, options)) {
|
|
40
|
+
return [];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return Object.keys(env)
|
|
44
|
+
.filter((key) => !EXCLUDED_DYNAMIC_WORKSPACE_ENV_KEYS.has(String(key || '').toUpperCase()))
|
|
45
|
+
.filter((key) => !WORKSPACE_ENV_VARS.includes(key))
|
|
46
|
+
.filter((key) => {
|
|
47
|
+
const providerSpecific = hasDynamicWorkspacePrefix(key) && WORKSPACE_ENV_KEY_PATTERN.test(key);
|
|
48
|
+
const genericWorkspace = WORKSPACE_ENV_GENERIC_DISCOVERY_PATTERN.test(key);
|
|
49
|
+
return providerSpecific || genericWorkspace;
|
|
50
|
+
})
|
|
23
51
|
.sort((a, b) => scoreWorkspaceEnvKey(b) - scoreWorkspaceEnvKey(a));
|
|
24
52
|
}
|
|
25
53
|
|
|
26
|
-
export function getWorkspaceEnvKeys(env = process.env) {
|
|
27
|
-
return [...WORKSPACE_ENV_VARS, ...getDynamicWorkspaceEnvKeys(env)];
|
|
54
|
+
export function getWorkspaceEnvKeys(env = process.env, options = {}) {
|
|
55
|
+
return [...WORKSPACE_ENV_VARS, ...getDynamicWorkspaceEnvKeys(env, options)];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
export function getWorkspaceEnvDiagnosticKeys(env = process.env, options = {}) {
|
|
60
|
+
const prioritized = getWorkspaceEnvKeys(env, options);
|
|
61
|
+
const prioritizedSet = new Set(prioritized);
|
|
62
|
+
|
|
63
|
+
const extraKeys = Object.keys(env)
|
|
64
|
+
.filter((key) => !prioritizedSet.has(key))
|
|
65
|
+
.filter((key) => WORKSPACE_ENV_KEY_PATTERN.test(key))
|
|
66
|
+
.sort((a, b) => scoreWorkspaceEnvKey(b) - scoreWorkspaceEnvKey(a));
|
|
67
|
+
|
|
68
|
+
return [...prioritized, ...extraKeys];
|
|
28
69
|
}
|
package/package.json
CHANGED
|
@@ -1,86 +1,86 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@softerist/heuristic-mcp",
|
|
3
|
-
"version": "3.0
|
|
4
|
-
"description": "An enhanced MCP server providing intelligent semantic code search with find-similar-code, recency ranking, and improved chunking. Fork of smart-coding-mcp.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "index.js",
|
|
7
|
-
"bin": {
|
|
8
|
-
"heuristic-mcp": "index.js"
|
|
9
|
-
},
|
|
10
|
-
"files": [
|
|
11
|
-
"index.js",
|
|
12
|
-
"config.jsonc",
|
|
13
|
-
"mcp_config.json",
|
|
14
|
-
"search-configs.js",
|
|
15
|
-
"lib/",
|
|
16
|
-
"features/",
|
|
17
|
-
"scripts/",
|
|
18
|
-
"README.md",
|
|
19
|
-
"LICENSE"
|
|
20
|
-
],
|
|
21
|
-
"scripts": {
|
|
22
|
-
"start": "node --expose-gc index.js",
|
|
23
|
-
"dev": "node --expose-gc --watch index.js",
|
|
24
|
-
"test": "vitest run",
|
|
25
|
-
"test:watch": "vitest",
|
|
26
|
-
"clean": "node scripts/clear-cache.js",
|
|
27
|
-
"lint": "eslint .",
|
|
28
|
-
"format": "prettier --write .",
|
|
29
|
-
"postinstall": "node scripts/postinstall.js && node scripts/download-model.js"
|
|
30
|
-
},
|
|
31
|
-
"keywords": [
|
|
32
|
-
"mcp",
|
|
33
|
-
"semantic-search",
|
|
34
|
-
"code-search",
|
|
35
|
-
"embeddings",
|
|
36
|
-
"ai",
|
|
37
|
-
"model-context-protocol",
|
|
38
|
-
"hybrid-search",
|
|
39
|
-
"code-intelligence",
|
|
40
|
-
"cursor",
|
|
41
|
-
"vscode",
|
|
42
|
-
"claude",
|
|
43
|
-
"codex",
|
|
44
|
-
"openai",
|
|
45
|
-
"gemini",
|
|
46
|
-
"anthropic",
|
|
47
|
-
"antigravity",
|
|
48
|
-
"heuristic"
|
|
49
|
-
],
|
|
50
|
-
"author": {
|
|
51
|
-
"name": "Softerist",
|
|
52
|
-
"url": "https://github.com/softerist"
|
|
53
|
-
},
|
|
54
|
-
"repository": {
|
|
55
|
-
"type": "git",
|
|
56
|
-
"url": "git+https://github.com/softerist/heuristic-mcp.git"
|
|
57
|
-
},
|
|
58
|
-
"homepage": "https://github.com/softerist/heuristic-mcp#readme",
|
|
59
|
-
"license": "MIT",
|
|
60
|
-
"dependencies": {
|
|
61
|
-
"@huggingface/transformers": "^3.8.1",
|
|
62
|
-
"@modelcontextprotocol/sdk": "^1.0.4",
|
|
63
|
-
"better-sqlite3": "^12.6.2",
|
|
64
|
-
"chokidar": "^3.5.3",
|
|
65
|
-
"fdir": "^6.5.0",
|
|
66
|
-
"ignore": "^7.0.5",
|
|
67
|
-
"punycode": "^2.3.1"
|
|
68
|
-
},
|
|
69
|
-
"optionalDependencies": {
|
|
70
|
-
"hnswlib-node": "^3.0.0"
|
|
71
|
-
},
|
|
72
|
-
"engines": {
|
|
73
|
-
"node": ">=18.0.0"
|
|
74
|
-
},
|
|
75
|
-
"overrides": {
|
|
76
|
-
"punycode": "^2.3.1"
|
|
77
|
-
},
|
|
78
|
-
"devDependencies": {
|
|
79
|
-
"@eslint/js": "^9.39.2",
|
|
80
|
-
"@vitest/coverage-v8": "^4.0.18",
|
|
81
|
-
"eslint": "^9.39.2",
|
|
82
|
-
"globals": "^17.1.0",
|
|
83
|
-
"prettier": "^3.8.1",
|
|
84
|
-
"vitest": "^4.0.16"
|
|
85
|
-
}
|
|
86
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@softerist/heuristic-mcp",
|
|
3
|
+
"version": "3.1.0",
|
|
4
|
+
"description": "An enhanced MCP server providing intelligent semantic code search with find-similar-code, recency ranking, and improved chunking. Fork of smart-coding-mcp.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"heuristic-mcp": "index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"index.js",
|
|
12
|
+
"config.jsonc",
|
|
13
|
+
"mcp_config.json",
|
|
14
|
+
"search-configs.js",
|
|
15
|
+
"lib/",
|
|
16
|
+
"features/",
|
|
17
|
+
"scripts/",
|
|
18
|
+
"README.md",
|
|
19
|
+
"LICENSE"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"start": "node --expose-gc index.js",
|
|
23
|
+
"dev": "node --expose-gc --watch index.js",
|
|
24
|
+
"test": "vitest run",
|
|
25
|
+
"test:watch": "vitest",
|
|
26
|
+
"clean": "node scripts/clear-cache.js",
|
|
27
|
+
"lint": "eslint .",
|
|
28
|
+
"format": "prettier --write .",
|
|
29
|
+
"postinstall": "node scripts/postinstall.js && node scripts/download-model.js"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"mcp",
|
|
33
|
+
"semantic-search",
|
|
34
|
+
"code-search",
|
|
35
|
+
"embeddings",
|
|
36
|
+
"ai",
|
|
37
|
+
"model-context-protocol",
|
|
38
|
+
"hybrid-search",
|
|
39
|
+
"code-intelligence",
|
|
40
|
+
"cursor",
|
|
41
|
+
"vscode",
|
|
42
|
+
"claude",
|
|
43
|
+
"codex",
|
|
44
|
+
"openai",
|
|
45
|
+
"gemini",
|
|
46
|
+
"anthropic",
|
|
47
|
+
"antigravity",
|
|
48
|
+
"heuristic"
|
|
49
|
+
],
|
|
50
|
+
"author": {
|
|
51
|
+
"name": "Softerist",
|
|
52
|
+
"url": "https://github.com/softerist"
|
|
53
|
+
},
|
|
54
|
+
"repository": {
|
|
55
|
+
"type": "git",
|
|
56
|
+
"url": "git+https://github.com/softerist/heuristic-mcp.git"
|
|
57
|
+
},
|
|
58
|
+
"homepage": "https://github.com/softerist/heuristic-mcp#readme",
|
|
59
|
+
"license": "MIT",
|
|
60
|
+
"dependencies": {
|
|
61
|
+
"@huggingface/transformers": "^3.8.1",
|
|
62
|
+
"@modelcontextprotocol/sdk": "^1.0.4",
|
|
63
|
+
"better-sqlite3": "^12.6.2",
|
|
64
|
+
"chokidar": "^3.5.3",
|
|
65
|
+
"fdir": "^6.5.0",
|
|
66
|
+
"ignore": "^7.0.5",
|
|
67
|
+
"punycode": "^2.3.1"
|
|
68
|
+
},
|
|
69
|
+
"optionalDependencies": {
|
|
70
|
+
"hnswlib-node": "^3.0.0"
|
|
71
|
+
},
|
|
72
|
+
"engines": {
|
|
73
|
+
"node": ">=18.0.0"
|
|
74
|
+
},
|
|
75
|
+
"overrides": {
|
|
76
|
+
"punycode": "^2.3.1"
|
|
77
|
+
},
|
|
78
|
+
"devDependencies": {
|
|
79
|
+
"@eslint/js": "^9.39.2",
|
|
80
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
81
|
+
"eslint": "^9.39.2",
|
|
82
|
+
"globals": "^17.1.0",
|
|
83
|
+
"prettier": "^3.8.1",
|
|
84
|
+
"vitest": "^4.0.16"
|
|
85
|
+
}
|
|
86
|
+
}
|