mcp-vector-search 0.12.6__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.
Files changed (68) hide show
  1. mcp_vector_search/__init__.py +10 -0
  2. mcp_vector_search/cli/__init__.py +1 -0
  3. mcp_vector_search/cli/commands/__init__.py +1 -0
  4. mcp_vector_search/cli/commands/auto_index.py +397 -0
  5. mcp_vector_search/cli/commands/config.py +393 -0
  6. mcp_vector_search/cli/commands/demo.py +358 -0
  7. mcp_vector_search/cli/commands/index.py +744 -0
  8. mcp_vector_search/cli/commands/init.py +645 -0
  9. mcp_vector_search/cli/commands/install.py +675 -0
  10. mcp_vector_search/cli/commands/install_old.py +696 -0
  11. mcp_vector_search/cli/commands/mcp.py +1182 -0
  12. mcp_vector_search/cli/commands/reset.py +393 -0
  13. mcp_vector_search/cli/commands/search.py +773 -0
  14. mcp_vector_search/cli/commands/status.py +549 -0
  15. mcp_vector_search/cli/commands/uninstall.py +485 -0
  16. mcp_vector_search/cli/commands/visualize.py +1467 -0
  17. mcp_vector_search/cli/commands/watch.py +287 -0
  18. mcp_vector_search/cli/didyoumean.py +500 -0
  19. mcp_vector_search/cli/export.py +320 -0
  20. mcp_vector_search/cli/history.py +295 -0
  21. mcp_vector_search/cli/interactive.py +342 -0
  22. mcp_vector_search/cli/main.py +461 -0
  23. mcp_vector_search/cli/output.py +412 -0
  24. mcp_vector_search/cli/suggestions.py +375 -0
  25. mcp_vector_search/config/__init__.py +1 -0
  26. mcp_vector_search/config/constants.py +24 -0
  27. mcp_vector_search/config/defaults.py +200 -0
  28. mcp_vector_search/config/settings.py +134 -0
  29. mcp_vector_search/core/__init__.py +1 -0
  30. mcp_vector_search/core/auto_indexer.py +298 -0
  31. mcp_vector_search/core/connection_pool.py +360 -0
  32. mcp_vector_search/core/database.py +1214 -0
  33. mcp_vector_search/core/directory_index.py +318 -0
  34. mcp_vector_search/core/embeddings.py +294 -0
  35. mcp_vector_search/core/exceptions.py +89 -0
  36. mcp_vector_search/core/factory.py +318 -0
  37. mcp_vector_search/core/git_hooks.py +345 -0
  38. mcp_vector_search/core/indexer.py +1002 -0
  39. mcp_vector_search/core/models.py +294 -0
  40. mcp_vector_search/core/project.py +333 -0
  41. mcp_vector_search/core/scheduler.py +330 -0
  42. mcp_vector_search/core/search.py +952 -0
  43. mcp_vector_search/core/watcher.py +322 -0
  44. mcp_vector_search/mcp/__init__.py +5 -0
  45. mcp_vector_search/mcp/__main__.py +25 -0
  46. mcp_vector_search/mcp/server.py +733 -0
  47. mcp_vector_search/parsers/__init__.py +8 -0
  48. mcp_vector_search/parsers/base.py +296 -0
  49. mcp_vector_search/parsers/dart.py +605 -0
  50. mcp_vector_search/parsers/html.py +413 -0
  51. mcp_vector_search/parsers/javascript.py +643 -0
  52. mcp_vector_search/parsers/php.py +694 -0
  53. mcp_vector_search/parsers/python.py +502 -0
  54. mcp_vector_search/parsers/registry.py +223 -0
  55. mcp_vector_search/parsers/ruby.py +678 -0
  56. mcp_vector_search/parsers/text.py +186 -0
  57. mcp_vector_search/parsers/utils.py +265 -0
  58. mcp_vector_search/py.typed +1 -0
  59. mcp_vector_search/utils/__init__.py +40 -0
  60. mcp_vector_search/utils/gitignore.py +250 -0
  61. mcp_vector_search/utils/monorepo.py +277 -0
  62. mcp_vector_search/utils/timing.py +334 -0
  63. mcp_vector_search/utils/version.py +47 -0
  64. mcp_vector_search-0.12.6.dist-info/METADATA +754 -0
  65. mcp_vector_search-0.12.6.dist-info/RECORD +68 -0
  66. mcp_vector_search-0.12.6.dist-info/WHEEL +4 -0
  67. mcp_vector_search-0.12.6.dist-info/entry_points.txt +2 -0
  68. mcp_vector_search-0.12.6.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,10 @@
1
+ """MCP Vector Search - CLI-first semantic code search with MCP integration."""
2
+
3
+ __version__ = "0.12.6"
4
+ __build__ = "55"
5
+ __author__ = "Robert Matsuoka"
6
+ __email__ = "bobmatnyc@gmail.com"
7
+
8
+ from .core.exceptions import MCPVectorSearchError
9
+
10
+ __all__ = ["MCPVectorSearchError", "__version__", "__build__"]
@@ -0,0 +1 @@
1
+ """CLI module for MCP Vector Search."""
@@ -0,0 +1 @@
1
+ """CLI commands for MCP Vector Search."""
@@ -0,0 +1,397 @@
1
+ """Auto-indexing management commands."""
2
+
3
+ import asyncio
4
+ from pathlib import Path
5
+
6
+ import click
7
+ import typer
8
+ from rich.console import Console
9
+ from rich.table import Table
10
+
11
+ from ...core.factory import (
12
+ ComponentFactory,
13
+ ConfigurationService,
14
+ DatabaseContext,
15
+ handle_cli_errors,
16
+ )
17
+ from ...core.git_hooks import GitHookManager
18
+ from ...core.scheduler import SchedulerManager
19
+ from ..output import print_error, print_info, print_success, print_warning
20
+
21
+ console = Console()
22
+
23
+ # Create auto-index app
24
+ auto_index_app = typer.Typer(
25
+ name="auto-index",
26
+ help="Manage automatic indexing",
27
+ add_completion=False,
28
+ )
29
+
30
+
31
+ @auto_index_app.command("status")
32
+ @handle_cli_errors("Auto-index status")
33
+ def auto_index_status(
34
+ project_root: Path = typer.Argument(
35
+ Path.cwd(),
36
+ help="Project root directory",
37
+ exists=True,
38
+ file_okay=False,
39
+ dir_okay=True,
40
+ readable=True,
41
+ ),
42
+ ) -> None:
43
+ """Show automatic indexing status and staleness information."""
44
+ asyncio.run(_show_auto_index_status(project_root))
45
+
46
+
47
+ @auto_index_app.command("check")
48
+ @handle_cli_errors("Auto-index check")
49
+ def auto_index_check(
50
+ project_root: Path = typer.Argument(
51
+ Path.cwd(),
52
+ help="Project root directory",
53
+ exists=True,
54
+ file_okay=False,
55
+ dir_okay=True,
56
+ readable=True,
57
+ ),
58
+ auto_reindex: bool = typer.Option(
59
+ True,
60
+ "--auto-reindex/--no-auto-reindex",
61
+ help="Automatically reindex stale files",
62
+ ),
63
+ max_files: int = typer.Option(
64
+ 5,
65
+ "--max-files",
66
+ help="Maximum files to auto-reindex",
67
+ min=1,
68
+ max=50,
69
+ ),
70
+ ) -> None:
71
+ """Check for stale files and optionally auto-reindex them."""
72
+ asyncio.run(_check_and_auto_reindex(project_root, auto_reindex, max_files))
73
+
74
+
75
+ @auto_index_app.command("setup")
76
+ def auto_index_setup(
77
+ project_root: Path = typer.Argument(
78
+ Path.cwd(),
79
+ help="Project root directory",
80
+ exists=True,
81
+ file_okay=False,
82
+ dir_okay=True,
83
+ readable=True,
84
+ ),
85
+ method: str = typer.Option(
86
+ "search",
87
+ "--method",
88
+ help="Auto-indexing method: search, git-hooks, scheduled, or all",
89
+ click_type=click.Choice(["search", "git-hooks", "scheduled", "all"]),
90
+ ),
91
+ interval: int = typer.Option(
92
+ 60,
93
+ "--interval",
94
+ help="Interval in minutes for scheduled tasks",
95
+ min=5,
96
+ max=1440,
97
+ ),
98
+ max_files: int = typer.Option(
99
+ 5,
100
+ "--max-files",
101
+ help="Maximum files to auto-reindex",
102
+ min=1,
103
+ max=50,
104
+ ),
105
+ ) -> None:
106
+ """Setup automatic indexing with various strategies."""
107
+ try:
108
+ asyncio.run(_setup_auto_indexing(project_root, method, interval, max_files))
109
+ except Exception as e:
110
+ print_error(f"Auto-index setup failed: {e}")
111
+ raise typer.Exit(1)
112
+
113
+
114
+ @auto_index_app.command("teardown")
115
+ def auto_index_teardown(
116
+ project_root: Path = typer.Argument(
117
+ Path.cwd(),
118
+ help="Project root directory",
119
+ exists=True,
120
+ file_okay=False,
121
+ dir_okay=True,
122
+ readable=True,
123
+ ),
124
+ method: str = typer.Option(
125
+ "all",
126
+ "--method",
127
+ help="Auto-indexing method to remove: git-hooks, scheduled, or all",
128
+ click_type=click.Choice(["git-hooks", "scheduled", "all"]),
129
+ ),
130
+ ) -> None:
131
+ """Remove automatic indexing setup."""
132
+ try:
133
+ asyncio.run(_teardown_auto_indexing(project_root, method))
134
+ except Exception as e:
135
+ print_error(f"Auto-index teardown failed: {e}")
136
+ raise typer.Exit(1)
137
+
138
+
139
+ async def _show_auto_index_status(project_root: Path) -> None:
140
+ """Show auto-indexing status."""
141
+ print_info(f"๐Ÿ“Š Auto-indexing status for {project_root}")
142
+
143
+ # Check if project is initialized
144
+ config_service = ConfigurationService(project_root)
145
+ if not config_service.ensure_initialized():
146
+ return
147
+
148
+ # Create components using factory
149
+ components = await ComponentFactory.create_standard_components(
150
+ project_root=project_root,
151
+ include_auto_indexer=True,
152
+ )
153
+
154
+ # Get staleness info
155
+ staleness_info = components.auto_indexer.get_staleness_info()
156
+
157
+ # Create status table
158
+ table = Table(title="Auto-Indexing Status")
159
+ table.add_column("Metric", style="cyan")
160
+ table.add_column("Value", style="green")
161
+ table.add_column("Status", style="yellow")
162
+
163
+ # Add rows
164
+ table.add_row(
165
+ "Total Files",
166
+ str(staleness_info["total_files"]),
167
+ "โœ…" if staleness_info["total_files"] > 0 else "โš ๏ธ",
168
+ )
169
+
170
+ table.add_row(
171
+ "Indexed Files",
172
+ str(staleness_info["indexed_files"]),
173
+ "โœ…" if staleness_info["indexed_files"] > 0 else "โŒ",
174
+ )
175
+
176
+ table.add_row(
177
+ "Stale Files",
178
+ str(staleness_info["stale_files"]),
179
+ "โŒ" if staleness_info["stale_files"] > 0 else "โœ…",
180
+ )
181
+
182
+ staleness_minutes = staleness_info["staleness_seconds"] / 60
183
+ table.add_row(
184
+ "Index Age",
185
+ f"{staleness_minutes:.1f} minutes",
186
+ "โŒ" if staleness_info["is_stale"] else "โœ…",
187
+ )
188
+
189
+ console.print(table)
190
+
191
+ # Show recommendations
192
+ if staleness_info["stale_files"] > 0:
193
+ print_warning(f"โš ๏ธ {staleness_info['stale_files']} files need reindexing")
194
+ print_info(
195
+ "Run 'mcp-vector-search auto-index check --auto-reindex' to update them"
196
+ )
197
+ else:
198
+ print_success("โœ… All files are up to date")
199
+
200
+
201
+ async def _check_and_auto_reindex(
202
+ project_root: Path, auto_reindex: bool, max_files: int
203
+ ) -> None:
204
+ """Check for stale files and optionally reindex."""
205
+ print_info(f"๐Ÿ” Checking for stale files in {project_root}")
206
+
207
+ # Check if project is initialized
208
+ config_service = ConfigurationService(project_root)
209
+ if not config_service.ensure_initialized():
210
+ return
211
+
212
+ # Create components using factory
213
+ components = await ComponentFactory.create_standard_components(
214
+ project_root=project_root,
215
+ include_auto_indexer=True,
216
+ auto_reindex_threshold=max_files,
217
+ )
218
+
219
+ async with DatabaseContext(components.database):
220
+ # Check and optionally reindex
221
+ (
222
+ reindexed,
223
+ file_count,
224
+ ) = await components.auto_indexer.check_and_reindex_if_needed(
225
+ force_check=True, interactive=not auto_reindex
226
+ )
227
+
228
+ if reindexed:
229
+ print_success(f"โœ… Auto-reindexed {file_count} files")
230
+ elif file_count > 0:
231
+ print_warning(f"โš ๏ธ Found {file_count} stale files")
232
+ if not auto_reindex:
233
+ print_info("Use --auto-reindex to update them automatically")
234
+ else:
235
+ print_success("โœ… All files are up to date")
236
+
237
+
238
+ async def _configure_auto_index(
239
+ project_root: Path,
240
+ enable: bool | None,
241
+ threshold: int | None,
242
+ staleness: int | None,
243
+ ) -> None:
244
+ """Configure auto-indexing settings."""
245
+ print_info(f"โš™๏ธ Configuring auto-indexing for {project_root}")
246
+
247
+ # Initialize project manager
248
+ project_manager = ProjectManager(project_root)
249
+ if not project_manager.is_initialized():
250
+ print_error("Project not initialized. Run 'mcp-vector-search init' first.")
251
+ return
252
+
253
+ config = project_manager.load_config()
254
+
255
+ # Update settings
256
+ changes_made = False
257
+
258
+ if enable is not None:
259
+ # Add auto_indexing settings to config if they don't exist
260
+ if not hasattr(config, "auto_indexing"):
261
+ config.auto_indexing = {}
262
+
263
+ config.auto_indexing["enabled"] = enable
264
+ changes_made = True
265
+ print_info(f"Auto-indexing {'enabled' if enable else 'disabled'}")
266
+
267
+ if threshold is not None:
268
+ if not hasattr(config, "auto_indexing"):
269
+ config.auto_indexing = {}
270
+
271
+ config.auto_indexing["threshold"] = threshold
272
+ changes_made = True
273
+ print_info(f"Auto-reindex threshold set to {threshold} files")
274
+
275
+ if staleness is not None:
276
+ if not hasattr(config, "auto_indexing"):
277
+ config.auto_indexing = {}
278
+
279
+ config.auto_indexing["staleness_minutes"] = staleness
280
+ changes_made = True
281
+ print_info(f"Staleness threshold set to {staleness} minutes")
282
+
283
+ if changes_made:
284
+ project_manager.save_config(config)
285
+ print_success("โœ… Auto-indexing configuration saved")
286
+ else:
287
+ print_info("No changes specified")
288
+
289
+ # Show current settings
290
+ auto_settings = getattr(config, "auto_indexing", {})
291
+ print_info("Current settings:")
292
+ print_info(f" Enabled: {auto_settings.get('enabled', True)}")
293
+ print_info(f" Threshold: {auto_settings.get('threshold', 5)} files")
294
+ print_info(f" Staleness: {auto_settings.get('staleness_minutes', 5)} minutes")
295
+
296
+
297
+ async def _setup_auto_indexing(
298
+ project_root: Path, method: str, interval: int, max_files: int
299
+ ) -> None:
300
+ """Setup automatic indexing."""
301
+ print_info(f"๐Ÿš€ Setting up auto-indexing for {project_root}")
302
+ print_info(f"Method: {method}, Interval: {interval}min, Max files: {max_files}")
303
+
304
+ success_count = 0
305
+ total_count = 0
306
+
307
+ if method in ["search", "all"]:
308
+ print_info("\n๐Ÿ“Š Setting up search-triggered auto-indexing...")
309
+ # This is enabled by default when using the search engine with auto_indexer
310
+ print_success("โœ… Search-triggered auto-indexing is built-in")
311
+ print_info(" Automatically checks for stale files during searches")
312
+ success_count += 1
313
+ total_count += 1
314
+
315
+ if method in ["git-hooks", "all"]:
316
+ print_info("\n๐Ÿ”— Setting up Git hooks...")
317
+ total_count += 1
318
+
319
+ git_manager = GitHookManager(project_root)
320
+ if git_manager.is_git_repo():
321
+ if git_manager.install_hooks():
322
+ print_success("โœ… Git hooks installed successfully")
323
+ print_info(
324
+ " Auto-reindex will trigger after commits, merges, and checkouts"
325
+ )
326
+ success_count += 1
327
+ else:
328
+ print_error("โŒ Failed to install Git hooks")
329
+ else:
330
+ print_warning("โš ๏ธ Not a Git repository - skipping Git hooks")
331
+
332
+ if method in ["scheduled", "all"]:
333
+ print_info(f"\nโฐ Setting up scheduled task (every {interval} minutes)...")
334
+ total_count += 1
335
+
336
+ scheduler = SchedulerManager(project_root)
337
+ if scheduler.install_scheduled_task(interval):
338
+ print_success("โœ… Scheduled task installed successfully")
339
+ print_info(f" Auto-reindex will run every {interval} minutes")
340
+ success_count += 1
341
+ else:
342
+ print_error("โŒ Failed to install scheduled task")
343
+
344
+ # Summary
345
+ print_info("\n๐Ÿ“‹ Setup Summary:")
346
+ print_info(f" Successful: {success_count}/{total_count}")
347
+
348
+ if success_count > 0:
349
+ print_success("๐ŸŽ‰ Auto-indexing is now active!")
350
+ print_info("\nNext steps:")
351
+ print_info("โ€ข Use 'mcp-vector-search auto-index status' to check status")
352
+ print_info("โ€ข Use 'mcp-vector-search auto-index check' to test manually")
353
+ print_info("โ€ข Search operations will automatically check for stale files")
354
+ else:
355
+ print_error("โŒ No auto-indexing methods were successfully set up")
356
+
357
+
358
+ async def _teardown_auto_indexing(project_root: Path, method: str) -> None:
359
+ """Remove automatic indexing setup."""
360
+ print_info(f"๐Ÿงน Removing auto-indexing setup for {project_root}")
361
+
362
+ success_count = 0
363
+ total_count = 0
364
+
365
+ if method in ["git-hooks", "all"]:
366
+ print_info("\n๐Ÿ”— Removing Git hooks...")
367
+ total_count += 1
368
+
369
+ git_manager = GitHookManager(project_root)
370
+ if git_manager.uninstall_hooks():
371
+ print_success("โœ… Git hooks removed successfully")
372
+ success_count += 1
373
+ else:
374
+ print_error("โŒ Failed to remove Git hooks")
375
+
376
+ if method in ["scheduled", "all"]:
377
+ print_info("\nโฐ Removing scheduled task...")
378
+ total_count += 1
379
+
380
+ scheduler = SchedulerManager(project_root)
381
+ if scheduler.uninstall_scheduled_task():
382
+ print_success("โœ… Scheduled task removed successfully")
383
+ success_count += 1
384
+ else:
385
+ print_error("โŒ Failed to remove scheduled task")
386
+
387
+ # Summary
388
+ print_info("\n๐Ÿ“‹ Teardown Summary:")
389
+ print_info(f" Successful: {success_count}/{total_count}")
390
+
391
+ if success_count > 0:
392
+ print_success("๐Ÿงน Auto-indexing setup removed!")
393
+ print_info(
394
+ "Note: Search-triggered auto-indexing is built-in and cannot be disabled"
395
+ )
396
+ else:
397
+ print_warning("โš ๏ธ No auto-indexing methods were removed")