mcp-vector-search 0.4.13__py3-none-any.whl → 0.5.0__py3-none-any.whl
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.
Potentially problematic release.
This version of mcp-vector-search might be problematic. Click here for more details.
- mcp_vector_search/__init__.py +2 -2
- mcp_vector_search/cli/commands/index.py +73 -31
- mcp_vector_search/cli/commands/init.py +189 -113
- mcp_vector_search/cli/commands/install.py +525 -113
- mcp_vector_search/cli/commands/mcp.py +201 -151
- mcp_vector_search/cli/commands/reset.py +41 -41
- mcp_vector_search/cli/commands/search.py +73 -14
- mcp_vector_search/cli/commands/status.py +51 -17
- mcp_vector_search/cli/didyoumean.py +254 -246
- mcp_vector_search/cli/main.py +171 -52
- mcp_vector_search/cli/output.py +152 -0
- mcp_vector_search/cli/suggestions.py +246 -197
- mcp_vector_search/core/database.py +81 -49
- mcp_vector_search/core/indexer.py +10 -4
- mcp_vector_search/core/search.py +17 -6
- mcp_vector_search/mcp/__main__.py +1 -1
- mcp_vector_search/mcp/server.py +211 -203
- mcp_vector_search/parsers/__init__.py +6 -0
- mcp_vector_search/parsers/dart.py +605 -0
- mcp_vector_search/parsers/php.py +694 -0
- mcp_vector_search/parsers/registry.py +16 -1
- mcp_vector_search/parsers/ruby.py +678 -0
- mcp_vector_search/parsers/text.py +31 -25
- mcp_vector_search/utils/gitignore.py +72 -71
- {mcp_vector_search-0.4.13.dist-info → mcp_vector_search-0.5.0.dist-info}/METADATA +59 -2
- {mcp_vector_search-0.4.13.dist-info → mcp_vector_search-0.5.0.dist-info}/RECORD +29 -26
- {mcp_vector_search-0.4.13.dist-info → mcp_vector_search-0.5.0.dist-info}/WHEEL +0 -0
- {mcp_vector_search-0.4.13.dist-info → mcp_vector_search-0.5.0.dist-info}/entry_points.txt +0 -0
- {mcp_vector_search-0.4.13.dist-info → mcp_vector_search-0.5.0.dist-info}/licenses/LICENSE +0 -0
mcp_vector_search/__init__.py
CHANGED
|
@@ -17,7 +17,9 @@ from ..output import (
|
|
|
17
17
|
print_error,
|
|
18
18
|
print_index_stats,
|
|
19
19
|
print_info,
|
|
20
|
+
print_next_steps,
|
|
20
21
|
print_success,
|
|
22
|
+
print_tip,
|
|
21
23
|
)
|
|
22
24
|
|
|
23
25
|
# Create index subcommand app
|
|
@@ -32,23 +34,27 @@ def main(
|
|
|
32
34
|
"--watch",
|
|
33
35
|
"-w",
|
|
34
36
|
help="Watch for file changes and update index incrementally",
|
|
37
|
+
rich_help_panel="⚙️ Advanced Options",
|
|
35
38
|
),
|
|
36
39
|
incremental: bool = typer.Option(
|
|
37
40
|
True,
|
|
38
41
|
"--incremental/--full",
|
|
39
42
|
help="Use incremental indexing (skip unchanged files)",
|
|
43
|
+
rich_help_panel="📊 Indexing Options",
|
|
40
44
|
),
|
|
41
45
|
extensions: str | None = typer.Option(
|
|
42
46
|
None,
|
|
43
47
|
"--extensions",
|
|
44
48
|
"-e",
|
|
45
49
|
help="Override file extensions to index (comma-separated)",
|
|
50
|
+
rich_help_panel="📁 Configuration",
|
|
46
51
|
),
|
|
47
52
|
force: bool = typer.Option(
|
|
48
53
|
False,
|
|
49
54
|
"--force",
|
|
50
55
|
"-f",
|
|
51
56
|
help="Force reindexing of all files",
|
|
57
|
+
rich_help_panel="📊 Indexing Options",
|
|
52
58
|
),
|
|
53
59
|
batch_size: int = typer.Option(
|
|
54
60
|
32,
|
|
@@ -57,17 +63,37 @@ def main(
|
|
|
57
63
|
help="Batch size for embedding generation",
|
|
58
64
|
min=1,
|
|
59
65
|
max=128,
|
|
66
|
+
rich_help_panel="⚡ Performance",
|
|
60
67
|
),
|
|
61
68
|
) -> None:
|
|
62
|
-
"""Index your codebase for semantic search.
|
|
69
|
+
"""📑 Index your codebase for semantic search.
|
|
63
70
|
|
|
64
|
-
|
|
65
|
-
|
|
71
|
+
Parses code files, generates semantic embeddings, and stores them in ChromaDB.
|
|
72
|
+
Supports incremental indexing to skip unchanged files for faster updates.
|
|
66
73
|
|
|
67
|
-
Examples:
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
mcp-vector-search index
|
|
74
|
+
[bold cyan]Basic Examples:[/bold cyan]
|
|
75
|
+
|
|
76
|
+
[green]Index entire project:[/green]
|
|
77
|
+
$ mcp-vector-search index
|
|
78
|
+
|
|
79
|
+
[green]Force full reindex:[/green]
|
|
80
|
+
$ mcp-vector-search index --force
|
|
81
|
+
|
|
82
|
+
[green]Custom file extensions:[/green]
|
|
83
|
+
$ mcp-vector-search index --extensions .py,.js,.ts,.md
|
|
84
|
+
|
|
85
|
+
[bold cyan]Advanced Usage:[/bold cyan]
|
|
86
|
+
|
|
87
|
+
[green]Watch mode (experimental):[/green]
|
|
88
|
+
$ mcp-vector-search index --watch
|
|
89
|
+
|
|
90
|
+
[green]Full reindex (no incremental):[/green]
|
|
91
|
+
$ mcp-vector-search index --full
|
|
92
|
+
|
|
93
|
+
[green]Optimize for large projects:[/green]
|
|
94
|
+
$ mcp-vector-search index --batch-size 64
|
|
95
|
+
|
|
96
|
+
[dim]💡 Tip: Use incremental indexing (default) for faster updates on subsequent runs.[/dim]
|
|
71
97
|
"""
|
|
72
98
|
try:
|
|
73
99
|
project_root = ctx.obj.get("project_root") or Path.cwd()
|
|
@@ -190,6 +216,21 @@ async def _run_batch_indexing(
|
|
|
190
216
|
stats = await indexer.get_indexing_stats()
|
|
191
217
|
print_index_stats(stats)
|
|
192
218
|
|
|
219
|
+
# Add next-step hints
|
|
220
|
+
if indexed_count > 0:
|
|
221
|
+
steps = [
|
|
222
|
+
"[cyan]mcp-vector-search search 'your query'[/cyan] - Try semantic search",
|
|
223
|
+
"[cyan]mcp-vector-search status[/cyan] - View detailed statistics",
|
|
224
|
+
]
|
|
225
|
+
print_next_steps(steps, title="Ready to Search")
|
|
226
|
+
else:
|
|
227
|
+
print_info("\n[bold]No files were indexed. Possible reasons:[/bold]")
|
|
228
|
+
print_info(" • No matching files found for configured extensions")
|
|
229
|
+
print_info(" • All files already indexed (use --force to reindex)")
|
|
230
|
+
print_tip(
|
|
231
|
+
"Check configured extensions with [cyan]mcp-vector-search status[/cyan]"
|
|
232
|
+
)
|
|
233
|
+
|
|
193
234
|
|
|
194
235
|
async def _run_watch_mode(indexer: SemanticIndexer, show_progress: bool) -> None:
|
|
195
236
|
"""Run indexing in watch mode."""
|
|
@@ -228,12 +269,12 @@ def reindex_file(
|
|
|
228
269
|
),
|
|
229
270
|
) -> None:
|
|
230
271
|
"""Reindex files in the project.
|
|
231
|
-
|
|
272
|
+
|
|
232
273
|
Can reindex a specific file or the entire project:
|
|
233
274
|
- Without arguments: reindexes entire project (with confirmation)
|
|
234
275
|
- With file path: reindexes specific file
|
|
235
276
|
- With --all flag: explicitly reindexes entire project
|
|
236
|
-
|
|
277
|
+
|
|
237
278
|
Examples:
|
|
238
279
|
mcp-vector-search index reindex # Reindex entire project
|
|
239
280
|
mcp-vector-search index reindex --all # Explicitly reindex entire project
|
|
@@ -247,7 +288,7 @@ def reindex_file(
|
|
|
247
288
|
if file_path is not None and all:
|
|
248
289
|
print_error("Cannot specify both a file path and --all flag")
|
|
249
290
|
raise typer.Exit(1)
|
|
250
|
-
|
|
291
|
+
|
|
251
292
|
if file_path is not None:
|
|
252
293
|
# Reindex specific file
|
|
253
294
|
asyncio.run(_reindex_single_file(project_root, file_path))
|
|
@@ -255,14 +296,13 @@ def reindex_file(
|
|
|
255
296
|
# Reindex entire project
|
|
256
297
|
if not force and not all:
|
|
257
298
|
from ..output import confirm_action
|
|
258
|
-
|
|
299
|
+
|
|
259
300
|
if not confirm_action(
|
|
260
|
-
"This will reindex the entire project. Continue?",
|
|
261
|
-
default=False
|
|
301
|
+
"This will reindex the entire project. Continue?", default=False
|
|
262
302
|
):
|
|
263
303
|
print_info("Reindex operation cancelled")
|
|
264
304
|
raise typer.Exit(0)
|
|
265
|
-
|
|
305
|
+
|
|
266
306
|
# Use the full project reindexing
|
|
267
307
|
asyncio.run(_reindex_entire_project(project_root))
|
|
268
308
|
|
|
@@ -278,21 +318,21 @@ def reindex_file(
|
|
|
278
318
|
async def _reindex_entire_project(project_root: Path) -> None:
|
|
279
319
|
"""Reindex the entire project."""
|
|
280
320
|
print_info("Starting full project reindex...")
|
|
281
|
-
|
|
321
|
+
|
|
282
322
|
# Load project configuration
|
|
283
323
|
project_manager = ProjectManager(project_root)
|
|
284
|
-
|
|
324
|
+
|
|
285
325
|
if not project_manager.is_initialized():
|
|
286
326
|
raise ProjectNotFoundError(
|
|
287
327
|
f"Project not initialized at {project_root}. Run 'mcp-vector-search init' first."
|
|
288
328
|
)
|
|
289
|
-
|
|
329
|
+
|
|
290
330
|
config = project_manager.load_config()
|
|
291
|
-
|
|
331
|
+
|
|
292
332
|
print_info(f"Project: {project_root}")
|
|
293
333
|
print_info(f"File extensions: {', '.join(config.file_extensions)}")
|
|
294
334
|
print_info(f"Embedding model: {config.embedding_model}")
|
|
295
|
-
|
|
335
|
+
|
|
296
336
|
# Setup embedding function and cache
|
|
297
337
|
cache_dir = (
|
|
298
338
|
get_default_cache_path(project_root) if config.cache_embeddings else None
|
|
@@ -302,44 +342,44 @@ async def _reindex_entire_project(project_root: Path) -> None:
|
|
|
302
342
|
cache_dir=cache_dir,
|
|
303
343
|
cache_size=config.max_cache_size,
|
|
304
344
|
)
|
|
305
|
-
|
|
345
|
+
|
|
306
346
|
# Setup database
|
|
307
347
|
database = ChromaVectorDatabase(
|
|
308
348
|
persist_directory=config.index_path,
|
|
309
349
|
embedding_function=embedding_function,
|
|
310
350
|
)
|
|
311
|
-
|
|
351
|
+
|
|
312
352
|
# Setup indexer
|
|
313
353
|
indexer = SemanticIndexer(
|
|
314
354
|
database=database,
|
|
315
355
|
project_root=project_root,
|
|
316
356
|
file_extensions=config.file_extensions,
|
|
317
357
|
)
|
|
318
|
-
|
|
358
|
+
|
|
319
359
|
try:
|
|
320
360
|
async with database:
|
|
321
361
|
# First, clean the existing index
|
|
322
362
|
print_info("Clearing existing index...")
|
|
323
363
|
await database.reset()
|
|
324
|
-
|
|
364
|
+
|
|
325
365
|
# Then reindex everything with progress
|
|
326
366
|
with create_progress() as progress:
|
|
327
367
|
task = progress.add_task("Reindexing files...", total=None)
|
|
328
|
-
|
|
368
|
+
|
|
329
369
|
# Force reindex all files
|
|
330
370
|
indexed_count = await indexer.index_project(
|
|
331
371
|
force_reindex=True, # Force reindexing
|
|
332
372
|
show_progress=False, # We handle progress here
|
|
333
373
|
)
|
|
334
|
-
|
|
374
|
+
|
|
335
375
|
progress.update(task, completed=indexed_count, total=indexed_count)
|
|
336
|
-
|
|
376
|
+
|
|
337
377
|
print_success(f"Successfully reindexed {indexed_count} files")
|
|
338
|
-
|
|
378
|
+
|
|
339
379
|
# Show statistics
|
|
340
380
|
stats = await indexer.get_indexing_stats()
|
|
341
381
|
print_index_stats(stats)
|
|
342
|
-
|
|
382
|
+
|
|
343
383
|
except Exception as e:
|
|
344
384
|
logger.error(f"Full reindex error: {e}")
|
|
345
385
|
raise
|
|
@@ -354,12 +394,12 @@ async def _reindex_single_file(project_root: Path, file_path: Path) -> None:
|
|
|
354
394
|
# Make file path absolute if it's not already
|
|
355
395
|
if not file_path.is_absolute():
|
|
356
396
|
file_path = file_path.resolve()
|
|
357
|
-
|
|
397
|
+
|
|
358
398
|
# Check if file exists
|
|
359
399
|
if not file_path.exists():
|
|
360
400
|
print_error(f"File not found: {file_path}")
|
|
361
401
|
return
|
|
362
|
-
|
|
402
|
+
|
|
363
403
|
# Check if file is within project root
|
|
364
404
|
try:
|
|
365
405
|
file_path.relative_to(project_root)
|
|
@@ -395,7 +435,9 @@ async def _reindex_single_file(project_root: Path, file_path: Path) -> None:
|
|
|
395
435
|
print_error(f"Failed to reindex: {file_path}")
|
|
396
436
|
# Check if file extension is in the list of indexable extensions
|
|
397
437
|
if file_path.suffix not in config.file_extensions:
|
|
398
|
-
print_info(
|
|
438
|
+
print_info(
|
|
439
|
+
f"Note: {file_path.suffix} is not in the configured file extensions: {', '.join(config.file_extensions)}"
|
|
440
|
+
)
|
|
399
441
|
|
|
400
442
|
|
|
401
443
|
@index_app.command("clean")
|