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.
Files changed (39) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/README.md +74 -33
  3. package/dist/app.d.ts +1 -1
  4. package/dist/app.js +67 -16
  5. package/dist/src/commands/BackfillCommand.js +15 -5
  6. package/dist/src/commands/ConfigCommand.d.ts +12 -0
  7. package/dist/src/commands/ConfigCommand.js +98 -0
  8. package/dist/src/commands/IndexCommand.js +1 -1
  9. package/dist/src/config-store.d.ts +53 -0
  10. package/dist/src/config-store.js +197 -0
  11. package/dist/src/config.d.ts +22 -8
  12. package/dist/src/config.js +103 -58
  13. package/dist/src/container.d.ts +1 -1
  14. package/dist/src/container.js +8 -7
  15. package/dist/src/db/index.d.ts +2 -3
  16. package/dist/src/db/index.js +6 -7
  17. package/dist/src/db/schema.d.ts +577 -0
  18. package/dist/src/db/schema.js +47 -0
  19. package/dist/src/help.js +28 -12
  20. package/dist/src/interfaces/IAstParser.d.ts +19 -0
  21. package/dist/src/interfaces/IEmbedder.d.ts +1 -0
  22. package/dist/src/project-selector.d.ts +14 -5
  23. package/dist/src/project-selector.js +74 -60
  24. package/dist/src/services/AstParserService.d.ts +7 -0
  25. package/dist/src/services/AstParserService.js +191 -28
  26. package/dist/src/services/DatabaseService.d.ts +11 -4
  27. package/dist/src/services/DatabaseService.js +107 -48
  28. package/dist/src/services/IndexerService.d.ts +9 -0
  29. package/dist/src/services/IndexerService.js +224 -60
  30. package/dist/src/services/LoggerService.d.ts +5 -1
  31. package/dist/src/services/LoggerService.js +8 -5
  32. package/dist/src/services/McpServer.d.ts +1 -0
  33. package/dist/src/services/McpServer.js +74 -4
  34. package/dist/src/services/OllamaEmbedder.d.ts +2 -0
  35. package/dist/src/services/OllamaEmbedder.js +29 -0
  36. package/dist/src/services/SearcherService.d.ts +13 -0
  37. package/dist/src/services/SearcherService.js +118 -22
  38. package/dist/src/setup.js +57 -62
  39. 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 CONFIG_DIR = path.join(os.homedir(), '.config', 'codesearch-mcp');
44
- const DEFAULT_LOG_DIR = path.join(CONFIG_DIR, 'logs');
45
- const CONFIG_FILE = path.join(CONFIG_DIR, '.env');
46
- const DOCKER_COMPOSE_SRC = path.join(__dirname, '..', '..', 'docker', 'docker-compose.yml');
47
- const DOCKER_COMPOSE_DST = path.join(CONFIG_DIR, 'docker-compose.yml');
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 setupLocalDocker(ollamaHost, dbPort, dbUser, dbPass, logger, steps) {
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('setupLocalDocker: docker startup failed', { reason, steps });
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('setupLocalDocker: ollama container not found', { reason, steps });
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(`\nWorkspace root — full path to the directory that contains all your projects`);
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
- const dbVars = useDocker
231
- ? await setupLocalDocker(ollamaHost, await loggedPrompt('DB port', '5433'), await loggedPrompt('DB user', 'dev'), await loggedPrompt('DB password', 'dev'), logger, steps)
232
- : await setupRemoteDb(rl, logger, steps, logStep);
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 envVars = {
247
- ...dbVars,
248
- WORKSPACE_ROOT: workspaceRoot,
249
- OLLAMA_HOST: ollamaHost,
250
- LOG_LEVEL: logLevel,
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
- envVars['LOG_DIR'] = logDir;
254
- writeEnv(envVars);
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(config);
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.15-alpha",
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
- "dotenv": "^17.4.2",
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": {