codesearch-mcp 0.0.15-alpha → 0.0.17-alpha
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/CHANGELOG.md +53 -0
- package/README.md +74 -33
- package/dist/app.d.ts +1 -1
- package/dist/app.js +67 -16
- package/dist/src/commands/BackfillCommand.js +15 -5
- package/dist/src/commands/ConfigCommand.d.ts +12 -0
- package/dist/src/commands/ConfigCommand.js +98 -0
- package/dist/src/commands/IndexCommand.js +1 -1
- package/dist/src/config-store.d.ts +53 -0
- package/dist/src/config-store.js +197 -0
- package/dist/src/config.d.ts +22 -8
- package/dist/src/config.js +103 -58
- package/dist/src/container.d.ts +1 -1
- package/dist/src/container.js +8 -7
- package/dist/src/db/index.d.ts +2 -3
- package/dist/src/db/index.js +6 -7
- package/dist/src/db/schema.d.ts +577 -0
- package/dist/src/db/schema.js +47 -0
- package/dist/src/help.js +28 -12
- package/dist/src/interfaces/IAstParser.d.ts +19 -0
- package/dist/src/interfaces/IEmbedder.d.ts +1 -0
- package/dist/src/project-selector.d.ts +14 -5
- package/dist/src/project-selector.js +74 -60
- package/dist/src/services/AstParserService.d.ts +7 -0
- package/dist/src/services/AstParserService.js +191 -28
- package/dist/src/services/DatabaseService.d.ts +11 -4
- package/dist/src/services/DatabaseService.js +107 -48
- package/dist/src/services/IndexerService.d.ts +9 -0
- package/dist/src/services/IndexerService.js +224 -60
- package/dist/src/services/LoggerService.d.ts +5 -1
- package/dist/src/services/LoggerService.js +8 -5
- package/dist/src/services/McpServer.d.ts +1 -0
- package/dist/src/services/McpServer.js +74 -4
- package/dist/src/services/OllamaEmbedder.d.ts +2 -0
- package/dist/src/services/OllamaEmbedder.js +29 -0
- package/dist/src/services/SearcherService.d.ts +13 -0
- package/dist/src/services/SearcherService.js +118 -22
- package/dist/src/setup.js +57 -62
- package/package.json +4 -5
package/dist/src/setup.js
CHANGED
|
@@ -40,11 +40,14 @@ const path = __importStar(require("path"));
|
|
|
40
40
|
const os = __importStar(require("os"));
|
|
41
41
|
const child_process_1 = require("child_process");
|
|
42
42
|
const constants_1 = require("./constants");
|
|
43
|
-
const
|
|
44
|
-
const
|
|
45
|
-
const
|
|
46
|
-
const
|
|
47
|
-
|
|
43
|
+
const config_store_1 = require("./config-store");
|
|
44
|
+
const config_1 = require("./config");
|
|
45
|
+
const DEFAULT_LOG_DIR = path.join(config_store_1.CONFIG_DIR, 'logs');
|
|
46
|
+
const _projectRoot = fs.existsSync(path.join(__dirname, '..', 'package.json'))
|
|
47
|
+
? path.join(__dirname, '..')
|
|
48
|
+
: path.join(__dirname, '..', '..');
|
|
49
|
+
const DOCKER_COMPOSE_SRC = path.join(_projectRoot, 'docker', 'docker-compose.yml');
|
|
50
|
+
const DOCKER_COMPOSE_DST = path.join(config_store_1.CONFIG_DIR, 'docker-compose.yml');
|
|
48
51
|
function ask(rl, question) {
|
|
49
52
|
return new Promise(resolve => rl.question(question, resolve));
|
|
50
53
|
}
|
|
@@ -57,14 +60,6 @@ function expandHome(p) {
|
|
|
57
60
|
return path.join(os.homedir(), p.slice(2));
|
|
58
61
|
return p;
|
|
59
62
|
}
|
|
60
|
-
function writeEnv(vars) {
|
|
61
|
-
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
62
|
-
const content = Object.entries(vars)
|
|
63
|
-
.map(([k, v]) => `${k}=${v}`)
|
|
64
|
-
.join('\n') + '\n';
|
|
65
|
-
fs.writeFileSync(CONFIG_FILE, content, { mode: 0o600 });
|
|
66
|
-
console.log(`\nConfig saved to ${CONFIG_FILE}`);
|
|
67
|
-
}
|
|
68
63
|
async function waitForDb(host, port, user, pass, db, maxWaitSec = 60, logger, steps) {
|
|
69
64
|
const { Client } = await Promise.resolve().then(() => __importStar(require('pg')));
|
|
70
65
|
const deadline = Date.now() + maxWaitSec * 1000;
|
|
@@ -129,7 +124,7 @@ async function checkRemoteDb(host, port, user, pass, db, logger, steps) {
|
|
|
129
124
|
return false;
|
|
130
125
|
}
|
|
131
126
|
}
|
|
132
|
-
async function
|
|
127
|
+
async function startDockerContainers(ollamaHost, dbPort, dbUser, dbPass, logger, steps) {
|
|
133
128
|
console.log('\nWriting docker-compose.yml to', DOCKER_COMPOSE_DST);
|
|
134
129
|
const yamlQuote = (s) => `"${s.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
|
|
135
130
|
let composeContent = fs.readFileSync(DOCKER_COMPOSE_SRC, 'utf-8');
|
|
@@ -137,57 +132,29 @@ async function setupLocalDocker(ollamaHost, dbPort, dbUser, dbPass, logger, step
|
|
|
137
132
|
.replace('POSTGRES_USER: dev', `POSTGRES_USER: ${yamlQuote(dbUser)}`)
|
|
138
133
|
.replace('POSTGRES_PASSWORD: dev', `POSTGRES_PASSWORD: ${yamlQuote(dbPass)}`)
|
|
139
134
|
.replace('"5433:5432"', `"${dbPort}:5432"`);
|
|
140
|
-
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
135
|
+
fs.mkdirSync(config_store_1.CONFIG_DIR, { recursive: true });
|
|
141
136
|
fs.writeFileSync(DOCKER_COMPOSE_DST, composeContent, 'utf-8');
|
|
142
137
|
console.log('\nStarting Docker containers...');
|
|
143
138
|
const upResult = (0, child_process_1.spawnSync)('docker', ['compose', '-f', DOCKER_COMPOSE_DST, 'up', '-d'], { stdio: 'inherit' });
|
|
144
139
|
if (upResult.status !== 0) {
|
|
145
140
|
const reason = 'Failed to start Docker containers. Make sure Docker is running.';
|
|
146
141
|
console.error(reason);
|
|
147
|
-
logger?.error('
|
|
142
|
+
logger?.error('startDockerContainers: docker startup failed', { reason, steps });
|
|
148
143
|
process.exit(1);
|
|
149
144
|
}
|
|
150
145
|
await waitForDb('localhost', parseInt(dbPort), dbUser, dbPass, 'postgres', 60, logger, steps);
|
|
151
146
|
await waitForOllama(ollamaHost, 60, logger, steps);
|
|
152
|
-
// Resolve the ollama container ID via compose — compose project name (and thus the
|
|
153
|
-
// default container name) depends on the parent directory, so hardcoding it breaks when
|
|
154
|
-
// users install via npm -g or move the compose file around.
|
|
155
147
|
const ollamaId = (0, child_process_1.spawnSync)('docker', ['compose', '-f', DOCKER_COMPOSE_DST, 'ps', '-q', 'ollama'], { encoding: 'utf-8' })
|
|
156
148
|
.stdout?.trim();
|
|
157
149
|
if (!ollamaId) {
|
|
158
150
|
const reason = 'Could not resolve ollama container ID from compose. Pull the model manually:';
|
|
159
151
|
console.error(reason);
|
|
160
152
|
console.error(` docker exec <ollama-container> ollama pull ${constants_1.DEFAULT_EMBED_MODEL}`);
|
|
161
|
-
logger?.error('
|
|
153
|
+
logger?.error('startDockerContainers: ollama container not found', { reason, steps });
|
|
162
154
|
process.exit(1);
|
|
163
155
|
}
|
|
164
156
|
console.log(`Pulling ${constants_1.DEFAULT_EMBED_MODEL} model (this may take a while)...`);
|
|
165
157
|
(0, child_process_1.spawnSync)('docker', ['exec', ollamaId, 'ollama', 'pull', constants_1.DEFAULT_EMBED_MODEL], { stdio: 'inherit' });
|
|
166
|
-
return { DB_HOST: 'localhost', DB_PORT: dbPort, DB_USER: dbUser, DB_PASS: dbPass };
|
|
167
|
-
}
|
|
168
|
-
async function setupRemoteDb(rl, logger, steps, logStep) {
|
|
169
|
-
const lp = async (label, def) => {
|
|
170
|
-
const answer = await prompt(rl, label, def);
|
|
171
|
-
logStep?.(label, answer);
|
|
172
|
-
return answer;
|
|
173
|
-
};
|
|
174
|
-
let vars = {};
|
|
175
|
-
while (true) {
|
|
176
|
-
vars.DB_HOST = await lp('DB host', 'localhost');
|
|
177
|
-
vars.DB_PORT = await lp('DB port', '5432');
|
|
178
|
-
vars.DB_USER = await lp('DB user', 'postgres');
|
|
179
|
-
vars.DB_PASS = await lp('DB password', '');
|
|
180
|
-
console.log('\nTesting connection...');
|
|
181
|
-
const ok = await checkRemoteDb(vars.DB_HOST, vars.DB_PORT, vars.DB_USER, vars.DB_PASS, 'postgres', logger, steps);
|
|
182
|
-
if (ok) {
|
|
183
|
-
console.log('Connection successful.');
|
|
184
|
-
break;
|
|
185
|
-
}
|
|
186
|
-
const retry = await ask(rl, 'Retry? (y/n): ');
|
|
187
|
-
if (retry.trim().toLowerCase() !== 'y')
|
|
188
|
-
break;
|
|
189
|
-
}
|
|
190
|
-
return vars;
|
|
191
158
|
}
|
|
192
159
|
async function runSetup(logger) {
|
|
193
160
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
@@ -210,14 +177,12 @@ async function runSetup(logger) {
|
|
|
210
177
|
};
|
|
211
178
|
console.log('=== codesearch-mcp setup ===');
|
|
212
179
|
console.log('Press Enter to keep the default value shown in parentheses.\n');
|
|
213
|
-
const dbChoice = await loggedAsk('Infrastructure:\n 1. Local Docker (auto-start PostgreSQL + Ollama)\n 2. Remote (Supabase, Railway, self-hosted DB + local Ollama)\n\nEnter choice (1): ');
|
|
214
|
-
const useDocker = (dbChoice.trim() || '1') === '1';
|
|
215
180
|
const workspaceExample = (() => {
|
|
216
181
|
const candidates = ['Projects', 'projects', 'workspace', 'code', 'Code', 'dev', 'Development'];
|
|
217
182
|
const found = candidates.find(d => fs.existsSync(path.join(os.homedir(), d)));
|
|
218
183
|
return path.join(os.homedir(), found ?? 'projects');
|
|
219
184
|
})();
|
|
220
|
-
console.log(
|
|
185
|
+
console.log(`Workspace root — full path to the directory that contains all your projects`);
|
|
221
186
|
console.log(` (e.g. ${workspaceExample})`);
|
|
222
187
|
let workspaceInput;
|
|
223
188
|
do {
|
|
@@ -227,12 +192,39 @@ async function runSetup(logger) {
|
|
|
227
192
|
} while (!workspaceInput.trim());
|
|
228
193
|
const workspaceRoot = expandHome(workspaceInput.trim());
|
|
229
194
|
const ollamaHost = await loggedPrompt('Ollama API URL', 'http://localhost:11434');
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
195
|
+
console.log('\n--- Database ---');
|
|
196
|
+
const dbHost = await loggedPrompt('DB host', 'localhost');
|
|
197
|
+
const dbPort = await loggedPrompt('DB port', '5433');
|
|
198
|
+
const dbUser = await loggedPrompt('DB user', 'dev');
|
|
199
|
+
const dbPass = await loggedPrompt('DB password', 'dev');
|
|
200
|
+
process.stdout.write('\nTesting connection...');
|
|
201
|
+
const alreadyConnected = await checkRemoteDb(dbHost, dbPort, dbUser, dbPass, 'postgres', logger, steps);
|
|
202
|
+
if (alreadyConnected)
|
|
203
|
+
console.log(' Database is already reachable.');
|
|
204
|
+
const dockerDefault = alreadyConnected ? 'n' : 'y';
|
|
205
|
+
const startDockerRaw = await loggedAsk(`Start Docker containers automatically? (y/n) (${dockerDefault}): `);
|
|
206
|
+
const startDocker = (startDockerRaw.trim().toLowerCase() || dockerDefault) === 'y';
|
|
207
|
+
if (startDocker) {
|
|
208
|
+
await startDockerContainers(ollamaHost, dbPort, dbUser, dbPass, logger, steps);
|
|
209
|
+
}
|
|
210
|
+
else if (!alreadyConnected) {
|
|
211
|
+
while (true) {
|
|
212
|
+
console.log('\nTesting connection...');
|
|
213
|
+
const ok = await checkRemoteDb(dbHost, dbPort, dbUser, dbPass, 'postgres', logger, steps);
|
|
214
|
+
if (ok) {
|
|
215
|
+
console.log('Connection successful.');
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
const retry = await ask(rl, 'Retry? (y/n): ');
|
|
219
|
+
if (retry.trim().toLowerCase() !== 'y')
|
|
220
|
+
break;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
const dbVars = { host: dbHost, port: parseInt(dbPort, 10), user: dbUser, password: dbPass };
|
|
233
224
|
console.log('\n--- Logging ---');
|
|
234
225
|
console.log(' error — failures only (recommended)');
|
|
235
226
|
console.log(' warn — + recoverable issues');
|
|
227
|
+
console.log(' info — + general progress messages');
|
|
236
228
|
console.log(' debug — full diagnostic output (verbose)');
|
|
237
229
|
const validLevels = ['error', 'warn', 'info', 'debug'];
|
|
238
230
|
let logLevel;
|
|
@@ -243,22 +235,25 @@ async function runSetup(logger) {
|
|
|
243
235
|
} while (!validLevels.includes(logLevel));
|
|
244
236
|
const logDirInput = await loggedAsk(`Log dir (leave blank for default: ${DEFAULT_LOG_DIR}, or "false" to disable): `);
|
|
245
237
|
const logDir = logDirInput.trim();
|
|
246
|
-
const
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
238
|
+
const cfg = {
|
|
239
|
+
db: {
|
|
240
|
+
host: dbVars.host,
|
|
241
|
+
port: dbVars.port,
|
|
242
|
+
user: dbVars.user,
|
|
243
|
+
password: dbVars.password,
|
|
244
|
+
},
|
|
245
|
+
ollama: { host: ollamaHost },
|
|
246
|
+
logging: { level: logLevel },
|
|
247
|
+
workspaceRoot,
|
|
251
248
|
};
|
|
252
249
|
if (logDir)
|
|
253
|
-
|
|
254
|
-
|
|
250
|
+
cfg.logging.dir = logDir;
|
|
251
|
+
(0, config_store_1.writeConfigJson)(cfg);
|
|
252
|
+
console.log(`\nConfig saved to ${config_store_1.CONFIG_FILE}`);
|
|
255
253
|
rl.close();
|
|
256
254
|
console.log('\nInitializing database schema...');
|
|
257
|
-
const dotenv = await Promise.resolve().then(() => __importStar(require('dotenv')));
|
|
258
|
-
dotenv.config({ path: CONFIG_FILE, override: true });
|
|
259
|
-
const { config } = await Promise.resolve().then(() => __importStar(require('./config')));
|
|
260
255
|
const { DatabaseService } = await Promise.resolve().then(() => __importStar(require('./services/DatabaseService')));
|
|
261
|
-
const dbService = new DatabaseService(
|
|
256
|
+
const dbService = new DatabaseService(new config_1.Config());
|
|
262
257
|
let initError = null;
|
|
263
258
|
try {
|
|
264
259
|
await dbService.initDbWithSchema();
|
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codesearch-mcp",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.17-alpha",
|
|
4
4
|
"description": "Local semantic codebase search via MCP — indexes projects into pgvector, exposes search to Claude",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/app.js",
|
|
7
7
|
"bin": {
|
|
8
8
|
"rag-index": "dist/app.js",
|
|
9
9
|
"rag-mcp": "dist/app.js",
|
|
10
|
-
"rag-setup": "dist/app.js"
|
|
10
|
+
"rag-setup": "dist/app.js",
|
|
11
|
+
"rag-config": "dist/app.js"
|
|
11
12
|
},
|
|
12
13
|
"files": [
|
|
13
14
|
"dist/",
|
|
@@ -33,15 +34,13 @@
|
|
|
33
34
|
"@langchain/textsplitters": "^1.0.1",
|
|
34
35
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
35
36
|
"cli-progress": "^3.12.0",
|
|
36
|
-
"
|
|
37
|
+
"drizzle-orm": "^0.45.2",
|
|
37
38
|
"ignore": "^7.0.5",
|
|
38
39
|
"ollama": "^0.5.0",
|
|
39
40
|
"pg": "^8.13.0",
|
|
40
41
|
"pino": "^10.3.1",
|
|
41
42
|
"pino-roll": "^4.0.0",
|
|
42
|
-
"reflect-metadata": "^0.2.2",
|
|
43
43
|
"ts-morph": "^28.0.0",
|
|
44
|
-
"typeorm": "^0.3.20",
|
|
45
44
|
"zod": "^4.3.6"
|
|
46
45
|
},
|
|
47
46
|
"devDependencies": {
|