@softerist/heuristic-mcp 2.1.3 → 2.1.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 +31 -9
- package/features/lifecycle.js +45 -0
- package/features/register.js +121 -0
- package/index.js +25 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -126,15 +126,7 @@ Install globally via npm:
|
|
|
126
126
|
npm install -g @softerist/heuristic-mcp
|
|
127
127
|
```
|
|
128
128
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
```bash
|
|
132
|
-
npm update -g @softerist/heuristic-mcp
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
## Configuration
|
|
136
|
-
|
|
137
|
-
Add to your MCP configuration file. The location depends on your IDE and OS:
|
|
129
|
+
That's it! The installer will automatically detect your IDE (Antigravity, Claude, Cursor) and configure it for you.
|
|
138
130
|
|
|
139
131
|
| IDE | OS | Config Path |
|
|
140
132
|
| -------------------- | ------- | ----------------------------------------------------------------- |
|
|
@@ -176,6 +168,36 @@ Add the server configuration to the `mcpServers` object in your config file:
|
|
|
176
168
|
}
|
|
177
169
|
```
|
|
178
170
|
|
|
171
|
+
### Troubleshooting
|
|
172
|
+
|
|
173
|
+
If for some reason the server isn't detected automatically, you can trigger the registration manually:
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
heuristic-mcp --register
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Starting and Stopping
|
|
180
|
+
|
|
181
|
+
If you need to restart the server or kill a zombie process:
|
|
182
|
+
|
|
183
|
+
**Stop the server:**
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
heuristic-mcp --stop
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
*(This kills any running instances of the server)*
|
|
190
|
+
|
|
191
|
+
**Start/Enable the server:**
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
heuristic-mcp --start
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
*(This re-runs the configuration step to ensure it is enabled in your IDE)*
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
179
201
|
## Environment Variables
|
|
180
202
|
|
|
181
203
|
Override configuration settings via environment variables in your MCP config:
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { exec } from 'child_process';
|
|
2
|
+
import util from 'util';
|
|
3
|
+
const execPromise = util.promisify(exec);
|
|
4
|
+
|
|
5
|
+
export async function stop() {
|
|
6
|
+
console.log('[Lifecycle] Stopping Heuristic MCP servers...');
|
|
7
|
+
try {
|
|
8
|
+
const platform = process.platform;
|
|
9
|
+
let command = '';
|
|
10
|
+
|
|
11
|
+
if (platform === 'win32') {
|
|
12
|
+
// Windows: Use wmic to find node processes running our script
|
|
13
|
+
command = `wmic process where "CommandLine like '%heuristic-mcp/index.js%'" delete`;
|
|
14
|
+
} else {
|
|
15
|
+
// Unix/Linux/Mac: Use pkill to find the process matching the script path
|
|
16
|
+
// We exclude the current process to avoid suicide if we are running from the same script
|
|
17
|
+
// however, usually the CLI runner is a different PID than the server.
|
|
18
|
+
command = `pkill -f "heuristic-mcp/index.js"`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
await execPromise(command);
|
|
22
|
+
console.log('[Lifecycle] ✅ Stopped all running instances.');
|
|
23
|
+
} catch (error) {
|
|
24
|
+
// pkill returns non-zero if no process found, which is fine
|
|
25
|
+
if (error.code === 1 || error.message.includes('No Instance(s) Available')) {
|
|
26
|
+
console.log('[Lifecycle] No running instances found.');
|
|
27
|
+
} else {
|
|
28
|
+
// Don't fail hard, just warn
|
|
29
|
+
console.warn(`[Lifecycle] Note: Could not stop server (it might not be running). Detail: ${error.message}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function start() {
|
|
35
|
+
console.log('[Lifecycle] Ensuring server is configured...');
|
|
36
|
+
// Re-use the registration logic to ensure the config is present and correct
|
|
37
|
+
try {
|
|
38
|
+
const { register } = await import('./register.js');
|
|
39
|
+
await register();
|
|
40
|
+
console.log('[Lifecycle] ✅ Configuration checked.');
|
|
41
|
+
console.log('[Lifecycle] To start the server, please reload your IDE window or restart the IDE.');
|
|
42
|
+
} catch (err) {
|
|
43
|
+
console.error(`[Lifecycle] Failed to configure server: ${err.message}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import os from 'os';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
|
|
6
|
+
// Helper to expand ~ and %vars%
|
|
7
|
+
function expandPath(p) {
|
|
8
|
+
if (p.startsWith('~/')) {
|
|
9
|
+
return path.join(os.homedir(), p.slice(2));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (process.platform === 'win32') {
|
|
13
|
+
return p.replace(/%([^%]+)%/g, (_, n) => process.env[n] || '%' + n + '%');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return p;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Known config paths for different IDEs
|
|
20
|
+
function getConfigPaths() {
|
|
21
|
+
const platform = process.platform;
|
|
22
|
+
const home = os.homedir();
|
|
23
|
+
const paths = [];
|
|
24
|
+
|
|
25
|
+
// Antigravity
|
|
26
|
+
if (platform === 'win32') {
|
|
27
|
+
paths.push({
|
|
28
|
+
name: 'Antigravity',
|
|
29
|
+
path: expandPath('%USERPROFILE%\\.gemini\\antigravity\\mcp_config.json')
|
|
30
|
+
});
|
|
31
|
+
} else {
|
|
32
|
+
paths.push({
|
|
33
|
+
name: 'Antigravity',
|
|
34
|
+
path: expandPath('~/.gemini/antigravity/mcp_config.json')
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Claude Desktop
|
|
39
|
+
if (platform === 'darwin') {
|
|
40
|
+
paths.push({
|
|
41
|
+
name: 'Claude Desktop',
|
|
42
|
+
path: expandPath('~/Library/Application Support/Claude/claude_desktop_config.json')
|
|
43
|
+
});
|
|
44
|
+
} else if (platform === 'win32') {
|
|
45
|
+
paths.push({
|
|
46
|
+
name: 'Claude Desktop',
|
|
47
|
+
path: expandPath('%APPDATA%\\Claude\\claude_desktop_config.json')
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Cursor (Cascade) - Settings are usually in settings.json but MCP might have a specific spot?
|
|
52
|
+
// Cursor often uses VS Code's settings.json for some things, but explicit MCP support varies.
|
|
53
|
+
// For now, we'll stick to Antigravity and Claude as confirmed targets.
|
|
54
|
+
// NOTE: If Cursor adds a specific mcp_config, add it here.
|
|
55
|
+
|
|
56
|
+
return paths;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export async function register(filter = null) {
|
|
60
|
+
const binaryPath = process.execPath; // The node binary
|
|
61
|
+
const scriptPath = fileURLToPath(new URL('../index.js', import.meta.url)); // Absolute path to index.js
|
|
62
|
+
|
|
63
|
+
const serverConfig = {
|
|
64
|
+
command: binaryPath,
|
|
65
|
+
args: [scriptPath, "--workspace", "${workspaceFolder}"],
|
|
66
|
+
disabled: false,
|
|
67
|
+
autoRegistered: true // Marker to know we did this
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const configPaths = getConfigPaths();
|
|
71
|
+
let registeredCount = 0;
|
|
72
|
+
|
|
73
|
+
console.log(`[Auto-Register] Detecting IDE configurations...`);
|
|
74
|
+
|
|
75
|
+
for (const { name, path: configPath } of configPaths) {
|
|
76
|
+
if (filter && name.toLowerCase() !== filter.toLowerCase()) {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
// Check if file exists
|
|
82
|
+
try {
|
|
83
|
+
await fs.access(configPath);
|
|
84
|
+
} catch {
|
|
85
|
+
console.log(`[Auto-Register] Skipped ${name}: Config file not found at ${configPath}`);
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Read config
|
|
90
|
+
const content = await fs.readFile(configPath, 'utf-8');
|
|
91
|
+
let config = {};
|
|
92
|
+
try {
|
|
93
|
+
config = JSON.parse(content);
|
|
94
|
+
} catch (e) {
|
|
95
|
+
console.error(`[Auto-Register] Error parsing ${name} config: ${e.message}`);
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Init mcpServers if missing
|
|
100
|
+
if (!config.mcpServers) {
|
|
101
|
+
config.mcpServers = {};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Inject configuration
|
|
105
|
+
config.mcpServers['heuristic-mcp'] = serverConfig;
|
|
106
|
+
|
|
107
|
+
// Write back
|
|
108
|
+
await fs.writeFile(configPath, JSON.stringify(config, null, 2));
|
|
109
|
+
console.log(`[Auto-Register] ✅ Successfully registered with ${name}`);
|
|
110
|
+
registeredCount++;
|
|
111
|
+
|
|
112
|
+
} catch (err) {
|
|
113
|
+
console.error(`[Auto-Register] Failed to register with ${name}: ${err.message}`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (registeredCount === 0) {
|
|
118
|
+
console.log(`[Auto-Register] No compatible IDE configurations found to update.`);
|
|
119
|
+
console.log(`[Auto-Register] Manual Config:\n${JSON.stringify({ mcpServers: { "heuristic-mcp": serverConfig } }, null, 2)}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
package/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3
|
+
import { stop, start } from "./features/lifecycle.js";
|
|
3
4
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
5
|
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
5
6
|
import { pipeline } from "@xenova/transformers";
|
|
@@ -19,10 +20,33 @@ import * as IndexCodebaseFeature from "./features/index-codebase.js";
|
|
|
19
20
|
import * as HybridSearchFeature from "./features/hybrid-search.js";
|
|
20
21
|
import * as ClearCacheFeature from "./features/clear-cache.js";
|
|
21
22
|
import * as FindSimilarCodeFeature from "./features/find-similar-code.js";
|
|
22
|
-
import
|
|
23
|
+
import { register } from "./features/register.js";
|
|
23
24
|
|
|
24
25
|
// Parse workspace from command line arguments
|
|
25
26
|
const args = process.argv.slice(2);
|
|
27
|
+
|
|
28
|
+
if (args.includes('--stop')) {
|
|
29
|
+
await stop();
|
|
30
|
+
process.exit(0);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (args.includes('--start')) {
|
|
34
|
+
await start();
|
|
35
|
+
process.exit(0);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Check if --register flag is present
|
|
39
|
+
if (args.includes('--register')) {
|
|
40
|
+
// Extract optional filter (e.g. --register antigravity)
|
|
41
|
+
const filterIndex = args.indexOf('--register');
|
|
42
|
+
const filter = args[filterIndex + 1] && !args[filterIndex + 1].startsWith('-')
|
|
43
|
+
? args[filterIndex + 1]
|
|
44
|
+
: null;
|
|
45
|
+
|
|
46
|
+
await register(filter);
|
|
47
|
+
process.exit(0);
|
|
48
|
+
}
|
|
49
|
+
|
|
26
50
|
const workspaceIndex = args.findIndex(arg => arg.startsWith('--workspace'));
|
|
27
51
|
let workspaceDir = null;
|
|
28
52
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@softerist/heuristic-mcp",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.5",
|
|
4
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
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
"dev": "node --watch index.js",
|
|
13
13
|
"test": "vitest run",
|
|
14
14
|
"test:watch": "vitest",
|
|
15
|
-
"clear-cache": "node scripts/clear-cache.js"
|
|
15
|
+
"clear-cache": "node scripts/clear-cache.js",
|
|
16
|
+
"postinstall": "node index.js --register"
|
|
16
17
|
},
|
|
17
18
|
"keywords": [
|
|
18
19
|
"mcp",
|