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.

Files changed (29) hide show
  1. mcp_vector_search/__init__.py +2 -2
  2. mcp_vector_search/cli/commands/index.py +73 -31
  3. mcp_vector_search/cli/commands/init.py +189 -113
  4. mcp_vector_search/cli/commands/install.py +525 -113
  5. mcp_vector_search/cli/commands/mcp.py +201 -151
  6. mcp_vector_search/cli/commands/reset.py +41 -41
  7. mcp_vector_search/cli/commands/search.py +73 -14
  8. mcp_vector_search/cli/commands/status.py +51 -17
  9. mcp_vector_search/cli/didyoumean.py +254 -246
  10. mcp_vector_search/cli/main.py +171 -52
  11. mcp_vector_search/cli/output.py +152 -0
  12. mcp_vector_search/cli/suggestions.py +246 -197
  13. mcp_vector_search/core/database.py +81 -49
  14. mcp_vector_search/core/indexer.py +10 -4
  15. mcp_vector_search/core/search.py +17 -6
  16. mcp_vector_search/mcp/__main__.py +1 -1
  17. mcp_vector_search/mcp/server.py +211 -203
  18. mcp_vector_search/parsers/__init__.py +6 -0
  19. mcp_vector_search/parsers/dart.py +605 -0
  20. mcp_vector_search/parsers/php.py +694 -0
  21. mcp_vector_search/parsers/registry.py +16 -1
  22. mcp_vector_search/parsers/ruby.py +678 -0
  23. mcp_vector_search/parsers/text.py +31 -25
  24. mcp_vector_search/utils/gitignore.py +72 -71
  25. {mcp_vector_search-0.4.13.dist-info → mcp_vector_search-0.5.0.dist-info}/METADATA +59 -2
  26. {mcp_vector_search-0.4.13.dist-info → mcp_vector_search-0.5.0.dist-info}/RECORD +29 -26
  27. {mcp_vector_search-0.4.13.dist-info → mcp_vector_search-0.5.0.dist-info}/WHEEL +0 -0
  28. {mcp_vector_search-0.4.13.dist-info → mcp_vector_search-0.5.0.dist-info}/entry_points.txt +0 -0
  29. {mcp_vector_search-0.4.13.dist-info → mcp_vector_search-0.5.0.dist-info}/licenses/LICENSE +0 -0
@@ -12,14 +12,17 @@ from .commands.auto_index import auto_index_app
12
12
  from .commands.config import config_app
13
13
  from .commands.index import index_app
14
14
  from .commands.init import (
15
- init_app,
16
- main as init_main,
17
15
  check_initialization as init_check,
16
+ )
17
+ from .commands.init import (
18
18
  init_mcp_integration,
19
19
  list_embedding_models,
20
20
  )
21
- from .commands.install import install_app
21
+ from .commands.init import (
22
+ main as init_main,
23
+ )
22
24
  from .commands.mcp import mcp_app
25
+ from .commands.reset import health_main, reset_app
23
26
  from .commands.search import (
24
27
  search_app,
25
28
  search_context_cmd,
@@ -28,10 +31,9 @@ from .commands.search import (
28
31
  )
29
32
  from .commands.status import status_app
30
33
  from .commands.watch import app as watch_app
31
- from .commands.reset import reset_app, health_main
32
- from .didyoumean import create_enhanced_typer, add_common_suggestions
33
- from .suggestions import get_contextual_suggestions, ContextualSuggestionProvider
34
+ from .didyoumean import add_common_suggestions, create_enhanced_typer
34
35
  from .output import print_error, setup_logging
36
+ from .suggestions import get_contextual_suggestions
35
37
 
36
38
  # Install rich traceback handler
37
39
  install(show_locals=True)
@@ -42,15 +44,41 @@ console = Console()
42
44
  # Create main Typer app with "did you mean" functionality
43
45
  app = create_enhanced_typer(
44
46
  name="mcp-vector-search",
45
- help="CLI-first semantic code search with MCP integration",
47
+ help="""
48
+ 🔍 [bold]CLI-first semantic code search with MCP integration[/bold]
49
+
50
+ Semantic search finds code by meaning, not just keywords. Perfect for exploring
51
+ unfamiliar codebases, finding similar patterns, and integrating with AI tools.
52
+
53
+ [bold cyan]Quick Start:[/bold cyan]
54
+ 1. Initialize: [green]mcp-vector-search init[/green]
55
+ 2. Search code: [green]mcp-vector-search search "your query"[/green]
56
+ 3. Check status: [green]mcp-vector-search status[/green]
57
+
58
+ [bold cyan]Key Features:[/bold cyan]
59
+ 🤖 MCP Integration: Works with Claude Code, Cursor, and AI tools
60
+ ⚡ Fast Indexing: Incremental updates with file watching
61
+ 🎯 Semantic Search: Find code by meaning, not just keywords
62
+ 📊 Rich Output: Beautiful terminal formatting with syntax highlighting
63
+
64
+ [bold cyan]Configuration Files:[/bold cyan]
65
+ • Project: .mcp-vector-search/config.json
66
+ • Claude Code: .claude/settings.local.json
67
+ • Global cache: ~/.cache/mcp-vector-search/
68
+
69
+ [dim]For detailed help on any command: [cyan]mcp-vector-search COMMAND --help[/cyan][/dim]
70
+ [dim]Documentation: [cyan]https://github.com/yourusername/mcp-vector-search[/cyan][/dim]
71
+ """,
46
72
  add_completion=False,
47
73
  rich_markup_mode="rich",
48
74
  )
49
75
 
50
76
  # Import command functions for direct registration and aliases
51
- from .commands.install import main as install_main, demo as install_demo
52
- from .commands.status import main as status_main
53
77
  from .commands.index import main as index_main
78
+ from .commands.install import demo as install_demo
79
+ from .commands.install import main as install_main
80
+ from .commands.status import main as status_main
81
+
54
82
  # Note: config doesn't have a main function, it uses subcommands via config_app
55
83
  app.command("install", help="🚀 Install mcp-vector-search in projects")(install_main)
56
84
  app.command("demo", help="🎬 Run installation demo with sample project")(install_demo)
@@ -59,8 +87,12 @@ app.command("status", help="📊 Show project status and statistics")(status_mai
59
87
  app.command("init", help="🔧 Initialize project for semantic search")(init_main)
60
88
  # Add init subcommands as separate commands
61
89
  app.command("init-check", help="Check if project is initialized")(init_check)
62
- app.command("init-mcp", help="Install/fix Claude Code MCP integration")(init_mcp_integration)
63
- app.command("init-models", help="List available embedding models")(list_embedding_models)
90
+ app.command("init-mcp", help="Install/fix Claude Code MCP integration")(
91
+ init_mcp_integration
92
+ )
93
+ app.command("init-models", help="List available embedding models")(
94
+ list_embedding_models
95
+ )
64
96
  app.add_typer(index_app, name="index", help="Index codebase for semantic search")
65
97
  app.add_typer(config_app, name="config", help="Manage project configuration")
66
98
  app.add_typer(watch_app, name="watch", help="Watch for file changes and update index")
@@ -72,23 +104,43 @@ app.add_typer(reset_app, name="reset", help="Reset and recovery operations")
72
104
  app.command("search", help="Search code semantically")(search_main)
73
105
 
74
106
  # Keep old nested structure for backward compatibility
75
- app.add_typer(search_app, name="search-legacy", help="Legacy search commands", hidden=True)
76
- app.add_typer(status_app, name="status-legacy", help="Legacy status commands", hidden=True)
107
+ app.add_typer(
108
+ search_app, name="search-legacy", help="Legacy search commands", hidden=True
109
+ )
110
+ app.add_typer(
111
+ status_app, name="status-legacy", help="Legacy status commands", hidden=True
112
+ )
77
113
 
78
114
  # Add command aliases for better user experience
79
115
  app.command("find", help="Search code semantically (alias for search)")(search_main)
80
- app.command("f", help="Search code semantically (short alias)", hidden=True)(search_main) # Hidden short alias
81
- app.command("s", help="Search code semantically (short alias)", hidden=True)(search_main) # Hidden short alias
82
- app.command("query", help="Search code semantically (alias for search)", hidden=True)(search_main) # Hidden alias
116
+ app.command("f", help="Search code semantically (short alias)", hidden=True)(
117
+ search_main
118
+ ) # Hidden short alias
119
+ app.command("s", help="Search code semantically (short alias)", hidden=True)(
120
+ search_main
121
+ ) # Hidden short alias
122
+ app.command("query", help="Search code semantically (alias for search)", hidden=True)(
123
+ search_main
124
+ ) # Hidden alias
83
125
 
84
126
  # Index aliases
85
- app.command("i", help="Index codebase (short alias)", hidden=True)(index_main) # Hidden short alias
86
- app.command("build", help="Index codebase (alias for index)", hidden=True)(index_main) # Hidden alias
87
- app.command("scan", help="Index codebase (alias for index)", hidden=True)(index_main) # Hidden alias
88
-
89
- # Status aliases
90
- app.command("st", help="Show status (short alias)", hidden=True)(status_main) # Hidden short alias
91
- app.command("info", help="Show project information (alias for status)", hidden=True)(status_main) # Hidden alias
127
+ app.command("i", help="Index codebase (short alias)", hidden=True)(
128
+ index_main
129
+ ) # Hidden short alias
130
+ app.command("build", help="Index codebase (alias for index)", hidden=True)(
131
+ index_main
132
+ ) # Hidden alias
133
+ app.command("scan", help="Index codebase (alias for index)", hidden=True)(
134
+ index_main
135
+ ) # Hidden alias
136
+
137
+ # Status aliases
138
+ app.command("st", help="Show status (short alias)", hidden=True)(
139
+ status_main
140
+ ) # Hidden short alias
141
+ app.command("info", help="Show project information (alias for status)", hidden=True)(
142
+ status_main
143
+ ) # Hidden alias
92
144
 
93
145
  # Config aliases - Since config uses subcommands, these will be handled by the enhanced typer error resolution
94
146
  # app.command("c", help="Manage configuration (short alias)", hidden=True) # Will be handled by typo resolution
@@ -112,7 +164,15 @@ def interactive_search(
112
164
  None, "--project-root", "-p", help="Project root directory"
113
165
  ),
114
166
  ) -> None:
115
- """Start an interactive search session with filtering and refinement."""
167
+ """Start an interactive search session with filtering and refinement.
168
+
169
+ The interactive mode provides a rich terminal interface for searching your codebase
170
+ with real-time filtering, query refinement, and result navigation.
171
+
172
+ Examples:
173
+ mcp-vector-search interactive
174
+ mcp-vector-search interactive --project-root /path/to/project
175
+ """
116
176
  import asyncio
117
177
 
118
178
  from .interactive import start_interactive_search
@@ -137,7 +197,15 @@ def show_history(
137
197
  None, "--project-root", "-p", help="Project root directory"
138
198
  ),
139
199
  ) -> None:
140
- """Show search history."""
200
+ """Show search history.
201
+
202
+ Displays your recent search queries with timestamps and result counts.
203
+ Use this to revisit previous searches or track your search patterns.
204
+
205
+ Examples:
206
+ mcp-vector-search history
207
+ mcp-vector-search history --limit 50
208
+ """
141
209
  from .history import show_search_history
142
210
 
143
211
  root = project_root or ctx.obj.get("project_root") or Path.cwd()
@@ -151,7 +219,14 @@ def show_favorites_cmd(
151
219
  None, "--project-root", "-p", help="Project root directory"
152
220
  ),
153
221
  ) -> None:
154
- """Show favorite queries."""
222
+ """Show favorite queries.
223
+
224
+ Displays your saved favorite search queries. Favorites allow you to quickly
225
+ access frequently used searches without typing them again.
226
+
227
+ Examples:
228
+ mcp-vector-search favorites
229
+ """
155
230
  from .history import show_favorites
156
231
 
157
232
  root = project_root or ctx.obj.get("project_root") or Path.cwd()
@@ -167,7 +242,15 @@ def add_favorite(
167
242
  None, "--project-root", "-p", help="Project root directory"
168
243
  ),
169
244
  ) -> None:
170
- """Add a query to favorites."""
245
+ """Add a query to favorites.
246
+
247
+ Save a search query to your favorites list for quick access later.
248
+ Optionally include a description to help remember what the query is for.
249
+
250
+ Examples:
251
+ mcp-vector-search add-favorite "authentication functions"
252
+ mcp-vector-search add-favorite "error handling" --desc "Error handling patterns"
253
+ """
171
254
  from .history import SearchHistory
172
255
 
173
256
  root = project_root or ctx.obj.get("project_root") or Path.cwd()
@@ -183,7 +266,13 @@ def remove_favorite(
183
266
  None, "--project-root", "-p", help="Project root directory"
184
267
  ),
185
268
  ) -> None:
186
- """Remove a query from favorites."""
269
+ """Remove a query from favorites.
270
+
271
+ Remove a previously saved favorite query from your favorites list.
272
+
273
+ Examples:
274
+ mcp-vector-search remove-favorite "authentication functions"
275
+ """
187
276
  from .history import SearchHistory
188
277
 
189
278
  root = project_root or ctx.obj.get("project_root") or Path.cwd()
@@ -195,10 +284,24 @@ def remove_favorite(
195
284
  def main(
196
285
  ctx: typer.Context,
197
286
  version: bool = typer.Option(
198
- False, "--version", "-v", help="Show version and exit"
287
+ False,
288
+ "--version",
289
+ "-v",
290
+ help="Show version and exit",
291
+ rich_help_panel="ℹ️ Information",
292
+ ),
293
+ verbose: bool = typer.Option(
294
+ False,
295
+ "--verbose",
296
+ help="Enable verbose logging",
297
+ rich_help_panel="🔧 Global Options",
298
+ ),
299
+ quiet: bool = typer.Option(
300
+ False,
301
+ "--quiet",
302
+ help="Suppress non-error output",
303
+ rich_help_panel="🔧 Global Options",
199
304
  ),
200
- verbose: bool = typer.Option(False, "--verbose", help="Enable verbose logging"),
201
- quiet: bool = typer.Option(False, "--quiet", help="Suppress non-error output"),
202
305
  project_root: Path | None = typer.Option(
203
306
  None,
204
307
  "--project-root",
@@ -208,6 +311,7 @@ def main(
208
311
  file_okay=False,
209
312
  dir_okay=True,
210
313
  readable=True,
314
+ rich_help_panel="🔧 Global Options",
211
315
  ),
212
316
  ) -> None:
213
317
  """MCP Vector Search - CLI-first semantic code search with MCP integration.
@@ -254,19 +358,21 @@ def handle_command_error(ctx, param, value):
254
358
 
255
359
  # This will be called when a command is not found
256
360
  import click
361
+
257
362
  try:
258
363
  return value
259
364
  except click.UsageError as e:
260
365
  if "No such command" in str(e):
261
366
  # Extract the command name from the error
262
367
  import re
368
+
263
369
  match = re.search(r"No such command '([^']+)'", str(e))
264
370
  if match:
265
371
  command_name = match.group(1)
266
-
372
+
267
373
  # Use both the original suggestions and contextual suggestions
268
374
  add_common_suggestions(ctx, command_name)
269
-
375
+
270
376
  # Add contextual suggestions based on project state
271
377
  try:
272
378
  project_root = ctx.obj.get("project_root") if ctx.obj else None
@@ -277,23 +383,32 @@ def handle_command_error(ctx, param, value):
277
383
  raise
278
384
 
279
385
 
280
-
281
-
282
386
  @app.command()
283
387
  def help_contextual() -> None:
284
388
  """Show contextual help and suggestions based on project state."""
285
389
  try:
286
390
  project_root = Path.cwd()
287
- console.print(f"[bold blue]mcp-vector-search[/bold blue] version [green]{__version__}[/green]")
391
+ console.print(
392
+ f"[bold blue]mcp-vector-search[/bold blue] version [green]{__version__}[/green]"
393
+ )
288
394
  console.print("[dim]CLI-first semantic code search with MCP integration[/dim]")
289
395
  get_contextual_suggestions(project_root)
290
- except Exception as e:
291
- console.print("\n[dim]Use [bold]mcp-vector-search --help[/bold] for more information.[/dim]")
396
+ except Exception:
397
+ console.print(
398
+ "\n[dim]Use [bold]mcp-vector-search --help[/bold] for more information.[/dim]"
399
+ )
292
400
 
293
401
 
294
402
  @app.command()
295
403
  def doctor() -> None:
296
- """Check system dependencies and configuration."""
404
+ """Check system dependencies and configuration.
405
+
406
+ Runs diagnostic checks to ensure all required dependencies are installed
407
+ and properly configured. Use this command to troubleshoot installation issues.
408
+
409
+ Examples:
410
+ mcp-vector-search doctor
411
+ """
297
412
  from .commands.status import check_dependencies
298
413
 
299
414
  console.print("[bold blue]MCP Vector Search - System Check[/bold blue]\n")
@@ -310,14 +425,12 @@ def doctor() -> None:
310
425
  )
311
426
 
312
427
 
313
-
314
-
315
-
316
428
  def cli_with_suggestions():
317
429
  """CLI wrapper that catches errors and provides suggestions."""
318
430
  import sys
431
+
319
432
  import click
320
-
433
+
321
434
  try:
322
435
  # Call the app with standalone_mode=False to get exceptions instead of sys.exit
323
436
  app(standalone_mode=False)
@@ -326,40 +439,46 @@ def cli_with_suggestions():
326
439
  if "No such command" in str(e):
327
440
  # Extract the command name from the error
328
441
  import re
442
+
329
443
  match = re.search(r"No such command '([^']+)'", str(e))
330
444
  if match:
331
445
  command_name = match.group(1)
332
-
446
+
333
447
  # Show enhanced suggestions
334
448
  from rich.console import Console
449
+
335
450
  console = Console(stderr=True)
336
451
  console.print(f"\\n[red]Error:[/red] {e}")
337
-
452
+
338
453
  # Show enhanced suggestions
339
454
  add_common_suggestions(None, command_name)
340
-
455
+
341
456
  # Show contextual suggestions too
342
457
  try:
343
458
  project_root = Path.cwd()
344
459
  get_contextual_suggestions(project_root, command_name)
345
460
  except Exception:
346
461
  pass
347
-
462
+
348
463
  sys.exit(2) # Exit with error code
349
-
464
+
350
465
  # For other usage errors, show the default message and exit
351
466
  click.echo(f"Error: {e}", err=True)
352
467
  sys.exit(2)
353
468
  except click.Abort:
354
469
  # User interrupted (Ctrl+C)
355
470
  sys.exit(1)
356
- except SystemExit as e:
471
+ except SystemExit:
357
472
  # Re-raise system exits
358
473
  raise
359
474
  except Exception as e:
360
- # For other exceptions, show error and exit
361
- click.echo(f"Unexpected error: {e}", err=True)
362
- sys.exit(1)
475
+ # For other exceptions, show error and exit if verbose logging is enabled
476
+ # Suppress internal framework errors in normal operation
477
+ if "--verbose" in sys.argv or "-v" in sys.argv:
478
+ click.echo(f"Unexpected error: {e}", err=True)
479
+ sys.exit(1)
480
+ # Otherwise, just exit silently to avoid confusing error messages
481
+ pass
363
482
 
364
483
 
365
484
  if __name__ == "__main__":
@@ -258,3 +258,155 @@ def print_json(data: Any, title: str | None = None) -> None:
258
258
  console.print(Panel(syntax, title=title, border_style="blue"))
259
259
  else:
260
260
  console.print(syntax)
261
+
262
+
263
+ def print_panel(
264
+ content: str,
265
+ title: str | None = None,
266
+ border_style: str = "blue",
267
+ padding: tuple[int, int] = (1, 2),
268
+ ) -> None:
269
+ """Print content in a Rich panel.
270
+
271
+ Args:
272
+ content: The content to display in the panel
273
+ title: Optional title for the panel
274
+ border_style: Border color/style (default: "blue")
275
+ padding: Tuple of (vertical, horizontal) padding
276
+ """
277
+ console.print(
278
+ Panel(
279
+ content,
280
+ title=title,
281
+ border_style=border_style,
282
+ padding=padding,
283
+ )
284
+ )
285
+
286
+
287
+ def print_next_steps(steps: list[str], title: str = "Next Steps") -> None:
288
+ """Print next step hints after a command execution.
289
+
290
+ Args:
291
+ steps: List of next step descriptions
292
+ title: Panel title (default: "Next Steps")
293
+ """
294
+ content = "\n".join(f" {i}. {step}" for i, step in enumerate(steps, 1))
295
+ print_panel(content, title=f"🚀 {title}", border_style="blue")
296
+
297
+
298
+ def print_tip(message: str) -> None:
299
+ """Print a helpful tip message.
300
+
301
+ Args:
302
+ message: The tip message to display
303
+ """
304
+ console.print(f"[dim]💡 Tip: {message}[/dim]")
305
+
306
+
307
+ def print_completion_status(
308
+ title: str,
309
+ completed_items: list[str],
310
+ pending_items: list[str] | None = None,
311
+ ) -> None:
312
+ """Print completion status with checkmarks.
313
+
314
+ Args:
315
+ title: Status title
316
+ completed_items: List of completed items
317
+ pending_items: Optional list of pending items
318
+ """
319
+ content_lines = []
320
+
321
+ if completed_items:
322
+ content_lines.append("[bold green]✨ Completed:[/bold green]")
323
+ for item in completed_items:
324
+ content_lines.append(f" ✅ {item}")
325
+
326
+ if pending_items:
327
+ content_lines.append("\n[bold yellow]📋 Pending:[/bold yellow]")
328
+ for item in pending_items:
329
+ content_lines.append(f" ☐ {item}")
330
+
331
+ print_panel("\n".join(content_lines), title=title, border_style="green")
332
+
333
+
334
+ def print_setup_progress(
335
+ completed_steps: list[str],
336
+ all_steps: list[tuple[str, str]] | None = None,
337
+ ) -> None:
338
+ """Display setup workflow progress.
339
+
340
+ Args:
341
+ completed_steps: List of completed step IDs
342
+ all_steps: Optional list of (step_id, step_name) tuples
343
+ """
344
+ if all_steps is None:
345
+ all_steps = [
346
+ ("initialize", "Initialize project"),
347
+ ("configure", "Configure settings"),
348
+ ("index", "Index codebase"),
349
+ ("mcp_setup", "Setup MCP integration"),
350
+ ("verify", "Verify installation"),
351
+ ]
352
+
353
+ completed = len([s for s, _ in all_steps if s in completed_steps])
354
+ total = len(all_steps)
355
+ percentage = (completed / total) * 100
356
+
357
+ console.print(f"\n🚀 Setup Progress: {completed}/{total} ({percentage:.0f}%)")
358
+
359
+ for step_id, step_name in all_steps:
360
+ status = "✓" if step_id in completed_steps else "☐"
361
+ style = "green" if step_id in completed_steps else "dim"
362
+ console.print(f" {status} {step_name}", style=style)
363
+
364
+
365
+ def print_error_with_recovery(error_message: str, recovery_steps: list[str]) -> None:
366
+ """Print error message with recovery hints.
367
+
368
+ Args:
369
+ error_message: The error message
370
+ recovery_steps: List of recovery step descriptions
371
+ """
372
+ print_error(error_message)
373
+
374
+ console.print("\n[bold]How to fix:[/bold]")
375
+ for i, step in enumerate(recovery_steps, 1):
376
+ console.print(f" {i}. {step}")
377
+
378
+ console.print("\n[dim]For more help: mcp-vector-search --help[/dim]")
379
+
380
+
381
+ def print_command_examples(
382
+ command: str,
383
+ examples: list[tuple[str, str]],
384
+ ) -> None:
385
+ """Print command examples in a formatted table.
386
+
387
+ Args:
388
+ command: Base command name
389
+ examples: List of (description, example) tuples
390
+ """
391
+ table = Table(
392
+ title=f"Examples: {command}",
393
+ show_header=True,
394
+ header_style="bold cyan",
395
+ )
396
+ table.add_column("Description", style="white", no_wrap=False)
397
+ table.add_column("Command", style="green", no_wrap=False)
398
+
399
+ for description, example in examples:
400
+ table.add_row(description, example)
401
+
402
+ console.print(table)
403
+
404
+
405
+ def print_config_hint(config_type: str, config_path: str) -> None:
406
+ """Print configuration file location hint.
407
+
408
+ Args:
409
+ config_type: Type of configuration (e.g., "Claude Code", "Project")
410
+ config_path: Path to the configuration file
411
+ """
412
+ console.print(f"[dim]💡 {config_type} config: {config_path}[/dim]")