@softerist/heuristic-mcp 3.2.3 → 3.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +387 -376
- package/config.jsonc +800 -800
- package/features/ann-config.js +102 -110
- package/features/clear-cache.js +81 -84
- package/features/find-similar-code.js +265 -286
- package/features/hybrid-search.js +487 -536
- package/features/index-codebase.js +3146 -3271
- package/features/lifecycle.js +1011 -1063
- package/features/package-version.js +277 -291
- package/features/register.js +351 -370
- package/features/resources.js +115 -130
- package/features/set-workspace.js +214 -240
- package/index.js +788 -781
- package/lib/cache-ops.js +22 -22
- package/lib/cache-utils.js +465 -519
- package/lib/cache.js +1749 -1849
- package/lib/call-graph.js +396 -396
- package/lib/cli.js +232 -226
- package/lib/config.js +1483 -1495
- package/lib/constants.js +511 -493
- package/lib/embed-query-process.js +206 -212
- package/lib/embedding-process.js +434 -451
- package/lib/embedding-worker.js +862 -934
- package/lib/ignore-patterns.js +276 -316
- package/lib/json-worker.js +14 -14
- package/lib/json-writer.js +302 -310
- package/lib/logging.js +133 -127
- package/lib/memory-logger.js +13 -13
- package/lib/onnx-backend.js +188 -193
- package/lib/path-utils.js +18 -23
- package/lib/project-detector.js +82 -84
- package/lib/server-lifecycle.js +164 -147
- package/lib/settings-editor.js +738 -739
- package/lib/slice-normalize.js +25 -31
- package/lib/tokenizer.js +168 -203
- package/lib/utils.js +364 -409
- package/lib/vector-store-binary.js +973 -991
- package/lib/vector-store-sqlite.js +377 -414
- package/lib/workspace-env.js +32 -34
- package/mcp_config.json +9 -9
- package/package.json +86 -86
- package/scripts/clear-cache.js +20 -20
- package/scripts/download-model.js +43 -43
- package/scripts/mcp-launcher.js +49 -49
- package/scripts/postinstall.js +12 -12
- package/search-configs.js +36 -36
package/features/register.js
CHANGED
|
@@ -1,265 +1,252 @@
|
|
|
1
|
-
import fs from 'fs/promises';
|
|
2
|
-
import { writeFileSync } from 'fs';
|
|
3
|
-
|
|
4
|
-
import path from 'path';
|
|
5
|
-
import os from 'os';
|
|
6
|
-
import {
|
|
7
|
-
parseJsonc,
|
|
8
|
-
upsertMcpServerEntryInText,
|
|
9
|
-
upsertMcpServerEntryInToml,
|
|
10
|
-
} from '../lib/settings-editor.js';
|
|
11
|
-
|
|
12
|
-
function getUserHomeDir() {
|
|
13
|
-
if (process.platform === 'win32' && process.env.USERPROFILE) {
|
|
14
|
-
return process.env.USERPROFILE;
|
|
15
|
-
}
|
|
16
|
-
return os.homedir();
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
process.env.
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
process.env.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
),
|
|
87
|
-
format: 'json',
|
|
88
|
-
canCreate: false,
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
allPaths.push({
|
|
134
|
-
name: '
|
|
135
|
-
path: path.join(home, '.
|
|
136
|
-
format: 'json',
|
|
137
|
-
canCreate:
|
|
138
|
-
preferredContainerKey: 'mcpServers',
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
}
|
|
230
|
-
} catch (_e) {
|
|
231
|
-
console.error(message);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
function normalizeIdeName(name) {
|
|
236
|
-
return String(name || '')
|
|
237
|
-
.toLowerCase()
|
|
238
|
-
.replace(/["']/g, '')
|
|
239
|
-
.replace(/[\s_-]+/g, '');
|
|
240
|
-
}
|
|
241
|
-
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import { writeFileSync } from 'fs';
|
|
3
|
+
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import os from 'os';
|
|
6
|
+
import {
|
|
7
|
+
parseJsonc,
|
|
8
|
+
upsertMcpServerEntryInText,
|
|
9
|
+
upsertMcpServerEntryInToml,
|
|
10
|
+
} from '../lib/settings-editor.js';
|
|
11
|
+
|
|
12
|
+
function getUserHomeDir() {
|
|
13
|
+
if (process.platform === 'win32' && process.env.USERPROFILE) {
|
|
14
|
+
return process.env.USERPROFILE;
|
|
15
|
+
}
|
|
16
|
+
return os.homedir();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function detectCurrentIDE() {
|
|
20
|
+
if (process.env.ANTIGRAVITY_AGENT) {
|
|
21
|
+
return 'Antigravity';
|
|
22
|
+
}
|
|
23
|
+
if (process.env.CURSOR_AGENT) {
|
|
24
|
+
return 'Cursor';
|
|
25
|
+
}
|
|
26
|
+
if (
|
|
27
|
+
process.env.CODEX_THREAD_ID ||
|
|
28
|
+
process.env.CODEX_INTERNAL_ORIGINATOR_OVERRIDE ||
|
|
29
|
+
process.env.CODEX_WORKSPACE
|
|
30
|
+
) {
|
|
31
|
+
return 'Codex';
|
|
32
|
+
}
|
|
33
|
+
if (process.env.VSCODE_IPC_HOOK || process.env.TERM_PROGRAM === 'vscode') {
|
|
34
|
+
return 'VS Code';
|
|
35
|
+
}
|
|
36
|
+
if (
|
|
37
|
+
process.env.WARP_SESSION_ID ||
|
|
38
|
+
process.env.TERM_PROGRAM === 'WarpTerminal' ||
|
|
39
|
+
process.env.TERM_PROGRAM === 'Warp'
|
|
40
|
+
) {
|
|
41
|
+
return 'Warp';
|
|
42
|
+
}
|
|
43
|
+
if (process.env.WINDSURF_AGENT || process.env.WINDSURF_WORKSPACE) {
|
|
44
|
+
return 'Windsurf';
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function getConfigPaths() {
|
|
51
|
+
const platform = process.platform;
|
|
52
|
+
const home = getUserHomeDir();
|
|
53
|
+
const currentIDE = detectCurrentIDE();
|
|
54
|
+
const allPaths = [];
|
|
55
|
+
|
|
56
|
+
allPaths.push({
|
|
57
|
+
name: 'Antigravity',
|
|
58
|
+
path: path.join(home, '.gemini', 'antigravity', 'mcp_config.json'),
|
|
59
|
+
format: 'json',
|
|
60
|
+
canCreate: true,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
allPaths.push({
|
|
64
|
+
name: 'Codex',
|
|
65
|
+
path: path.join(home, '.codex', 'config.toml'),
|
|
66
|
+
format: 'toml',
|
|
67
|
+
canCreate: true,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
if (platform === 'darwin') {
|
|
71
|
+
allPaths.push({
|
|
72
|
+
name: 'Claude Desktop',
|
|
73
|
+
path: path.join(
|
|
74
|
+
home,
|
|
75
|
+
'Library',
|
|
76
|
+
'Application Support',
|
|
77
|
+
'Claude',
|
|
78
|
+
'claude_desktop_config.json'
|
|
79
|
+
),
|
|
80
|
+
format: 'json',
|
|
81
|
+
canCreate: false,
|
|
82
|
+
});
|
|
83
|
+
} else if (platform === 'win32') {
|
|
84
|
+
allPaths.push({
|
|
85
|
+
name: 'Claude Desktop',
|
|
86
|
+
path: path.join(process.env.APPDATA || '', 'Claude', 'claude_desktop_config.json'),
|
|
87
|
+
format: 'json',
|
|
88
|
+
canCreate: false,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (platform === 'darwin') {
|
|
93
|
+
allPaths.push({
|
|
94
|
+
name: 'Cursor',
|
|
95
|
+
path: path.join(home, 'Library', 'Application Support', 'Cursor', 'User', 'settings.json'),
|
|
96
|
+
format: 'json',
|
|
97
|
+
canCreate: false,
|
|
98
|
+
});
|
|
99
|
+
} else if (platform === 'win32') {
|
|
100
|
+
allPaths.push({
|
|
101
|
+
name: 'Cursor',
|
|
102
|
+
path: path.join(process.env.APPDATA || '', 'Cursor', 'User', 'settings.json'),
|
|
103
|
+
format: 'json',
|
|
104
|
+
canCreate: false,
|
|
105
|
+
});
|
|
106
|
+
} else {
|
|
107
|
+
allPaths.push({
|
|
108
|
+
name: 'Cursor',
|
|
109
|
+
path: path.join(home, '.config', 'Cursor', 'User', 'settings.json'),
|
|
110
|
+
format: 'json',
|
|
111
|
+
canCreate: false,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Cursor global MCP config (discovered by VS Code MCP Discovery)
|
|
116
|
+
allPaths.push({
|
|
117
|
+
name: 'Cursor Global',
|
|
118
|
+
path: path.join(home, '.cursor', 'mcp.json'),
|
|
119
|
+
format: 'json',
|
|
120
|
+
canCreate: false,
|
|
121
|
+
preferredContainerKey: 'mcpServers',
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// Windsurf global MCP config (discovered by VS Code MCP Discovery)
|
|
125
|
+
allPaths.push({
|
|
126
|
+
name: 'Windsurf',
|
|
127
|
+
path: path.join(home, '.codeium', 'windsurf', 'mcp_config.json'),
|
|
128
|
+
format: 'json',
|
|
129
|
+
canCreate: false,
|
|
130
|
+
preferredContainerKey: 'mcpServers',
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
allPaths.push({
|
|
134
|
+
name: 'Warp',
|
|
135
|
+
path: path.join(home, '.warp', 'mcp_settings.json'),
|
|
136
|
+
format: 'json',
|
|
137
|
+
canCreate: true,
|
|
138
|
+
preferredContainerKey: 'mcpServers',
|
|
139
|
+
});
|
|
140
|
+
if (platform === 'win32') {
|
|
141
|
+
allPaths.push({
|
|
142
|
+
name: 'Warp AppData',
|
|
143
|
+
path: path.join(process.env.APPDATA || '', 'Warp', 'mcp_settings.json'),
|
|
144
|
+
format: 'json',
|
|
145
|
+
canCreate: false,
|
|
146
|
+
preferredContainerKey: 'mcpServers',
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (platform === 'darwin') {
|
|
151
|
+
allPaths.push({
|
|
152
|
+
name: 'VS Code',
|
|
153
|
+
path: path.join(home, 'Library', 'Application Support', 'Code', 'User', 'mcp.json'),
|
|
154
|
+
format: 'json',
|
|
155
|
+
canCreate: false,
|
|
156
|
+
preferredContainerKey: 'servers',
|
|
157
|
+
});
|
|
158
|
+
allPaths.push({
|
|
159
|
+
name: 'VS Code Insiders',
|
|
160
|
+
path: path.join(
|
|
161
|
+
home,
|
|
162
|
+
'Library',
|
|
163
|
+
'Application Support',
|
|
164
|
+
'Code - Insiders',
|
|
165
|
+
'User',
|
|
166
|
+
'mcp.json'
|
|
167
|
+
),
|
|
168
|
+
format: 'json',
|
|
169
|
+
canCreate: false,
|
|
170
|
+
preferredContainerKey: 'servers',
|
|
171
|
+
});
|
|
172
|
+
} else if (platform === 'win32') {
|
|
173
|
+
allPaths.push({
|
|
174
|
+
name: 'VS Code',
|
|
175
|
+
path: path.join(process.env.APPDATA || '', 'Code', 'User', 'mcp.json'),
|
|
176
|
+
format: 'json',
|
|
177
|
+
canCreate: false,
|
|
178
|
+
preferredContainerKey: 'servers',
|
|
179
|
+
});
|
|
180
|
+
allPaths.push({
|
|
181
|
+
name: 'VS Code Insiders',
|
|
182
|
+
path: path.join(process.env.APPDATA || '', 'Code - Insiders', 'User', 'mcp.json'),
|
|
183
|
+
format: 'json',
|
|
184
|
+
canCreate: false,
|
|
185
|
+
preferredContainerKey: 'servers',
|
|
186
|
+
});
|
|
187
|
+
} else {
|
|
188
|
+
allPaths.push({
|
|
189
|
+
name: 'VS Code',
|
|
190
|
+
path: path.join(home, '.config', 'Code', 'User', 'mcp.json'),
|
|
191
|
+
format: 'json',
|
|
192
|
+
canCreate: false,
|
|
193
|
+
preferredContainerKey: 'servers',
|
|
194
|
+
});
|
|
195
|
+
allPaths.push({
|
|
196
|
+
name: 'VS Code Insiders',
|
|
197
|
+
path: path.join(home, '.config', 'Code - Insiders', 'User', 'mcp.json'),
|
|
198
|
+
format: 'json',
|
|
199
|
+
canCreate: false,
|
|
200
|
+
preferredContainerKey: 'servers',
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return allPaths.map((entry) => ({
|
|
205
|
+
...entry,
|
|
206
|
+
canCreate: entry.canCreate || entry.name === currentIDE,
|
|
207
|
+
}));
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function forceLog(message) {
|
|
211
|
+
try {
|
|
212
|
+
if (process.platform !== 'win32') {
|
|
213
|
+
writeFileSync('/dev/tty', message + '\n');
|
|
214
|
+
} else {
|
|
215
|
+
console.error(message);
|
|
216
|
+
}
|
|
217
|
+
} catch (_e) {
|
|
218
|
+
console.error(message);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function normalizeIdeName(name) {
|
|
223
|
+
return String(name || '')
|
|
224
|
+
.toLowerCase()
|
|
225
|
+
.replace(/["']/g, '')
|
|
226
|
+
.replace(/[\s_-]+/g, '');
|
|
227
|
+
}
|
|
228
|
+
|
|
242
229
|
function ideMatchesFilter(name, filter) {
|
|
243
|
-
if (!filter) return true;
|
|
244
|
-
const normalizedName = normalizeIdeName(name);
|
|
245
|
-
const normalizedFilter = normalizeIdeName(filter);
|
|
246
|
-
if (!normalizedFilter) return true;
|
|
247
|
-
|
|
248
|
-
if (normalizedName === normalizedFilter) return true;
|
|
249
|
-
if (normalizedFilter === 'claude') return normalizedName === 'claudedesktop';
|
|
250
|
-
if (normalizedFilter === 'cursor') {
|
|
251
|
-
return normalizedName === 'cursor' || normalizedName === 'cursorglobal';
|
|
252
|
-
}
|
|
253
|
-
if (normalizedFilter === 'windsurf') {
|
|
254
|
-
return normalizedName === 'windsurf';
|
|
255
|
-
}
|
|
256
|
-
if (normalizedFilter === 'warp') {
|
|
257
|
-
return normalizedName === 'warp' || normalizedName === 'warpappdata';
|
|
258
|
-
}
|
|
259
|
-
if (normalizedFilter === 'vscode') {
|
|
260
|
-
return normalizedName === 'vscode' || normalizedName === 'vscodeinsiders';
|
|
261
|
-
}
|
|
262
|
-
|
|
230
|
+
if (!filter) return true;
|
|
231
|
+
const normalizedName = normalizeIdeName(name);
|
|
232
|
+
const normalizedFilter = normalizeIdeName(filter);
|
|
233
|
+
if (!normalizedFilter) return true;
|
|
234
|
+
|
|
235
|
+
if (normalizedName === normalizedFilter) return true;
|
|
236
|
+
if (normalizedFilter === 'claude') return normalizedName === 'claudedesktop';
|
|
237
|
+
if (normalizedFilter === 'cursor') {
|
|
238
|
+
return normalizedName === 'cursor' || normalizedName === 'cursorglobal';
|
|
239
|
+
}
|
|
240
|
+
if (normalizedFilter === 'windsurf') {
|
|
241
|
+
return normalizedName === 'windsurf';
|
|
242
|
+
}
|
|
243
|
+
if (normalizedFilter === 'warp') {
|
|
244
|
+
return normalizedName === 'warp' || normalizedName === 'warpappdata';
|
|
245
|
+
}
|
|
246
|
+
if (normalizedFilter === 'vscode') {
|
|
247
|
+
return normalizedName === 'vscode' || normalizedName === 'vscodeinsiders';
|
|
248
|
+
}
|
|
249
|
+
|
|
263
250
|
return false;
|
|
264
251
|
}
|
|
265
252
|
|
|
@@ -295,51 +282,48 @@ export async function register(filter = null) {
|
|
|
295
282
|
|
|
296
283
|
const configPaths = getConfigPaths();
|
|
297
284
|
let registeredCount = 0;
|
|
298
|
-
|
|
299
|
-
forceLog(`[Auto-Register] Detecting IDE configurations...`);
|
|
300
|
-
|
|
301
|
-
for (const { name, path: configPath, canCreate, format, preferredContainerKey } of configPaths) {
|
|
302
|
-
if (!ideMatchesFilter(name, filter)) {
|
|
303
|
-
continue;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
try {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
forceLog(
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
|
|
285
|
+
|
|
286
|
+
forceLog(`[Auto-Register] Detecting IDE configurations...`);
|
|
287
|
+
|
|
288
|
+
for (const { name, path: configPath, canCreate, format, preferredContainerKey } of configPaths) {
|
|
289
|
+
if (!ideMatchesFilter(name, filter)) {
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
try {
|
|
294
|
+
let fileExists = true;
|
|
295
|
+
|
|
296
|
+
try {
|
|
297
|
+
await fs.access(configPath);
|
|
298
|
+
} catch {
|
|
299
|
+
fileExists = false;
|
|
300
|
+
|
|
301
|
+
if (canCreate) {
|
|
302
|
+
try {
|
|
303
|
+
await fs.mkdir(path.dirname(configPath), { recursive: true });
|
|
304
|
+
forceLog(`[Auto-Register] Creating ${name} config at ${configPath}`);
|
|
305
|
+
} catch (mkdirErr) {
|
|
306
|
+
forceLog(
|
|
307
|
+
`[Auto-Register] Skipped ${name}: Cannot create config directory: ${mkdirErr.message}`
|
|
308
|
+
);
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
} else {
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
332
316
|
let content = '';
|
|
333
317
|
if (fileExists) {
|
|
334
318
|
content = await fs.readFile(configPath, 'utf-8');
|
|
335
|
-
if (format === 'json' && content.trim()) {
|
|
336
|
-
const parsed = parseJsonc(content);
|
|
337
|
-
if (!parsed) {
|
|
338
|
-
forceLog(
|
|
339
|
-
`[Auto-Register] Warning: ${name} config is not valid JSON/JSONC; skipping to avoid data loss.`
|
|
340
|
-
);
|
|
341
|
-
continue;
|
|
342
|
-
}
|
|
319
|
+
if (format === 'json' && content.trim()) {
|
|
320
|
+
const parsed = parseJsonc(content);
|
|
321
|
+
if (!parsed) {
|
|
322
|
+
forceLog(
|
|
323
|
+
`[Auto-Register] Warning: ${name} config is not valid JSON/JSONC; skipping to avoid data loss.`
|
|
324
|
+
);
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
343
327
|
}
|
|
344
328
|
}
|
|
345
329
|
|
|
@@ -347,29 +331,28 @@ export async function register(filter = null) {
|
|
|
347
331
|
const updated =
|
|
348
332
|
format === 'toml'
|
|
349
333
|
? upsertMcpServerEntryInToml(content, 'heuristic-mcp', serverConfig)
|
|
350
|
-
: upsertMcpServerEntryInText(
|
|
351
|
-
content,
|
|
352
|
-
'heuristic-mcp',
|
|
353
|
-
serverConfig,
|
|
354
|
-
preferredContainerKey || 'mcpServers'
|
|
355
|
-
);
|
|
356
|
-
if (!updated) {
|
|
357
|
-
forceLog(
|
|
358
|
-
`[Auto-Register] Warning: Failed to update ${name} config (could not locate root object).`
|
|
359
|
-
);
|
|
360
|
-
continue;
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
334
|
+
: upsertMcpServerEntryInText(
|
|
335
|
+
content,
|
|
336
|
+
'heuristic-mcp',
|
|
337
|
+
serverConfig,
|
|
338
|
+
preferredContainerKey || 'mcpServers'
|
|
339
|
+
);
|
|
340
|
+
if (!updated) {
|
|
341
|
+
forceLog(
|
|
342
|
+
`[Auto-Register] Warning: Failed to update ${name} config (could not locate root object).`
|
|
343
|
+
);
|
|
344
|
+
continue;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
writeFileSync(configPath, updated);
|
|
348
|
+
|
|
349
|
+
forceLog(`\x1b[32m[Auto-Register] ✅ Successfully registered with ${name}\x1b[0m`);
|
|
350
|
+
registeredCount++;
|
|
351
|
+
} catch (err) {
|
|
352
|
+
forceLog(`[Auto-Register] Failed to register with ${name}: ${err.message}`);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
373
356
|
if (registeredCount === 0) {
|
|
374
357
|
const manualServerConfig = {
|
|
375
358
|
command: 'heuristic-mcp',
|
|
@@ -380,47 +363,45 @@ export async function register(filter = null) {
|
|
|
380
363
|
`[Auto-Register] Manual Config:\n${JSON.stringify({ mcpServers: { 'heuristic-mcp': manualServerConfig } }, null, 2)}`
|
|
381
364
|
);
|
|
382
365
|
} else {
|
|
383
|
-
|
|
384
|
-
forceLog('
|
|
385
|
-
forceLog('
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
)
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
\x1b[
|
|
406
|
-
- \x1b[
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
\x1b[
|
|
411
|
-
- \x1b[
|
|
412
|
-
- \x1b[
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
\x1b[
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
}
|
|
426
|
-
}
|
|
366
|
+
forceLog('\n\x1b[36m' + '='.repeat(60));
|
|
367
|
+
forceLog(' 🚀 Heuristic MCP Installed & Configured! ');
|
|
368
|
+
forceLog('='.repeat(60) + '\x1b[0m');
|
|
369
|
+
|
|
370
|
+
const home = getUserHomeDir();
|
|
371
|
+
const cacheRoot =
|
|
372
|
+
process.platform === 'win32'
|
|
373
|
+
? path.join(
|
|
374
|
+
process.env.LOCALAPPDATA || path.join(home, 'AppData', 'Local'),
|
|
375
|
+
'heuristic-mcp'
|
|
376
|
+
)
|
|
377
|
+
: process.platform === 'darwin'
|
|
378
|
+
? path.join(home, 'Library', 'Caches', 'heuristic-mcp')
|
|
379
|
+
: path.join(process.env.XDG_CACHE_HOME || path.join(home, '.cache'), 'heuristic-mcp');
|
|
380
|
+
|
|
381
|
+
forceLog(`
|
|
382
|
+
\x1b[33mACTION REQUIRED:\x1b[0m
|
|
383
|
+
1. \x1b[1mRestart your IDE\x1b[0m (or reload the window) to load the new config.
|
|
384
|
+
2. The server will start automatically in the background.
|
|
385
|
+
|
|
386
|
+
\x1b[32mSTATUS:\x1b[0m
|
|
387
|
+
- \x1b[1mConfig:\x1b[0m Updated ${registeredCount} config file(s).
|
|
388
|
+
- \x1b[1mIndexing:\x1b[0m Will begin immediately after restart.
|
|
389
|
+
- \x1b[1mUsage:\x1b[0m You can work while it indexes (it catches up!).
|
|
390
|
+
|
|
391
|
+
\x1b[90mPATHS:\x1b[0m
|
|
392
|
+
- \x1b[1mMCP Config:\x1b[0m ${configPaths.map((p) => p.path).join(', ')}
|
|
393
|
+
- \x1b[1mCache:\x1b[0m ${cacheRoot}
|
|
394
|
+
- \x1b[1mCheck status:\x1b[0m heuristic-mcp --status
|
|
395
|
+
- \x1b[1mView logs:\x1b[0m heuristic-mcp --logs
|
|
396
|
+
|
|
397
|
+
\x1b[36mHappy Coding! 🤖\x1b[0m
|
|
398
|
+
`);
|
|
399
|
+
forceLog(`\n\x1b[90m(Please wait while npm finalizes the installation...)\x1b[0m`);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
if (currentIDE === 'Warp' && registeredCount === 0) {
|
|
403
|
+
forceLog(
|
|
404
|
+
'[Auto-Register] Warp detected but no local Warp MCP config was writable. Use Warp MCP settings/UI if needed.'
|
|
405
|
+
);
|
|
406
|
+
}
|
|
407
|
+
}
|