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
@@ -1,6 +1,8 @@
1
1
  """Install command for MCP Vector Search CLI."""
2
2
 
3
3
  import asyncio
4
+ import json
5
+ import shutil
4
6
  import subprocess
5
7
  import sys
6
8
  from pathlib import Path
@@ -9,9 +11,15 @@ import typer
9
11
  from loguru import logger
10
12
  from rich.console import Console
11
13
  from rich.panel import Panel
14
+ from rich.progress import Progress, SpinnerColumn, TextColumn
12
15
 
13
16
  from ...core.project import ProjectManager
14
- from ..output import print_error, print_info, print_success, print_warning
17
+ from ..output import (
18
+ print_error,
19
+ print_info,
20
+ print_success,
21
+ print_warning,
22
+ )
15
23
 
16
24
  # Create console for rich output
17
25
  console = Console()
@@ -20,28 +28,326 @@ console = Console()
20
28
  install_app = typer.Typer(help="Install mcp-vector-search in projects")
21
29
 
22
30
 
23
- @install_app.command()
31
+ # ============================================================================
32
+ # MCP Multi-Tool Integration Helpers
33
+ # ============================================================================
34
+
35
+
36
+ def detect_ai_tools() -> dict[str, Path]:
37
+ """Detect installed AI coding tools by checking config file existence.
38
+
39
+ Returns:
40
+ Dictionary mapping tool names to their config file paths.
41
+ For Claude Code, returns a placeholder path since it uses project-scoped .mcp.json
42
+ """
43
+ HOME = Path.home()
44
+
45
+ CONFIG_LOCATIONS = {
46
+ "claude-desktop": HOME
47
+ / "Library"
48
+ / "Application Support"
49
+ / "Claude"
50
+ / "claude_desktop_config.json",
51
+ "cursor": HOME / ".cursor" / "mcp.json",
52
+ "windsurf": HOME / ".codeium" / "windsurf" / "mcp_config.json",
53
+ "vscode": HOME / ".vscode" / "mcp.json",
54
+ }
55
+
56
+ # Return only tools with existing config files
57
+ detected_tools = {}
58
+ for tool_name, config_path in CONFIG_LOCATIONS.items():
59
+ if config_path.exists():
60
+ detected_tools[tool_name] = config_path
61
+
62
+ # Always include Claude Code as an option (it uses project-scoped .mcp.json)
63
+ detected_tools["claude-code"] = Path(
64
+ ".mcp.json"
65
+ ) # Placeholder - will be project-scoped
66
+
67
+ return detected_tools
68
+
69
+
70
+ def get_mcp_server_config(
71
+ project_root: Path, enable_watch: bool = True, tool_name: str = ""
72
+ ) -> dict:
73
+ """Generate MCP server configuration dict.
74
+
75
+ Args:
76
+ project_root: Path to the project root directory
77
+ enable_watch: Whether to enable file watching (default: True)
78
+ tool_name: Name of the tool (for tool-specific config adjustments)
79
+
80
+ Returns:
81
+ Dictionary containing MCP server configuration.
82
+ """
83
+ # Base configuration
84
+ config = {
85
+ "command": "uv",
86
+ "args": ["run", "mcp-vector-search", "mcp"],
87
+ "env": {"MCP_ENABLE_FILE_WATCHING": "true" if enable_watch else "false"},
88
+ }
89
+
90
+ # Add "type": "stdio" for Claude Code and other tools that require it
91
+ if tool_name in ("claude-code", "cursor", "windsurf", "vscode"):
92
+ config["type"] = "stdio"
93
+
94
+ # Add cwd only for tools that support it (not Claude Code)
95
+ if tool_name not in ("claude-code",):
96
+ config["cwd"] = str(project_root.absolute())
97
+
98
+ return config
99
+
100
+
101
+ def configure_mcp_for_tool(
102
+ tool_name: str,
103
+ config_path: Path,
104
+ project_root: Path,
105
+ server_name: str = "mcp-vector-search",
106
+ enable_watch: bool = True,
107
+ ) -> bool:
108
+ """Add MCP server configuration to a tool's config file.
109
+
110
+ Args:
111
+ tool_name: Name of the AI tool (e.g., "claude-code", "cursor")
112
+ config_path: Path to the tool's configuration file
113
+ project_root: Path to the project root directory
114
+ server_name: Name for the MCP server entry
115
+ enable_watch: Whether to enable file watching
116
+
117
+ Returns:
118
+ True if configuration was successful, False otherwise.
119
+ """
120
+ try:
121
+ # For Claude Code, we create .mcp.json in project root instead of ~/.claude.json
122
+ if tool_name == "claude-code":
123
+ # Override config_path to project-scoped .mcp.json
124
+ config_path = project_root / ".mcp.json"
125
+
126
+ # Create backup of existing config
127
+ backup_path = config_path.with_suffix(config_path.suffix + ".backup")
128
+
129
+ # Load existing config or create new one
130
+ if config_path.exists():
131
+ shutil.copy2(config_path, backup_path)
132
+ with open(config_path) as f:
133
+ config = json.load(f)
134
+ else:
135
+ # Create parent directory if it doesn't exist
136
+ config_path.parent.mkdir(parents=True, exist_ok=True)
137
+ config = {}
138
+
139
+ # Ensure mcpServers section exists
140
+ if "mcpServers" not in config:
141
+ config["mcpServers"] = {}
142
+
143
+ # Get the MCP server configuration with tool-specific settings
144
+ server_config = get_mcp_server_config(project_root, enable_watch, tool_name)
145
+
146
+ # Add server configuration
147
+ config["mcpServers"][server_name] = server_config
148
+
149
+ # Write the updated config
150
+ with open(config_path, "w") as f:
151
+ json.dump(config, f, indent=2)
152
+
153
+ print_success(f" ✅ Configured {tool_name} at {config_path}")
154
+ return True
155
+
156
+ except Exception as e:
157
+ print_error(f" ❌ Failed to configure {tool_name}: {e}")
158
+ # Restore backup if it exists
159
+ if backup_path.exists():
160
+ shutil.copy2(backup_path, config_path)
161
+ return False
162
+
163
+
164
+ def setup_mcp_integration(
165
+ project_root: Path,
166
+ mcp_tool: str | None = None,
167
+ enable_watch: bool = True,
168
+ interactive: bool = True,
169
+ ) -> dict[str, bool]:
170
+ """Setup MCP integration for one or more AI tools.
171
+
172
+ Args:
173
+ project_root: Path to the project root directory
174
+ mcp_tool: Specific tool to configure (None for interactive selection)
175
+ enable_watch: Whether to enable file watching
176
+ interactive: Whether to prompt user for tool selection
177
+
178
+ Returns:
179
+ Dictionary mapping tool names to success status.
180
+ """
181
+ detected_tools = detect_ai_tools()
182
+
183
+ if not detected_tools:
184
+ print_warning("No AI coding tools detected on this system.")
185
+ print_info(
186
+ "Supported tools: Claude Code, Claude Desktop, Cursor, Windsurf, VS Code"
187
+ )
188
+ print_info("Install one of these tools and try again.")
189
+ return {}
190
+
191
+ # Determine which tools to configure
192
+ tools_to_configure = {}
193
+
194
+ if mcp_tool:
195
+ # Specific tool requested
196
+ if mcp_tool in detected_tools:
197
+ tools_to_configure[mcp_tool] = detected_tools[mcp_tool]
198
+ else:
199
+ print_error(f"Tool '{mcp_tool}' not found or not installed.")
200
+ print_info(f"Detected tools: {', '.join(detected_tools.keys())}")
201
+ return {}
202
+ elif interactive and len(detected_tools) > 1:
203
+ # Multiple tools detected, prompt user
204
+ console.print("\n[bold blue]🔍 Detected AI coding tools:[/bold blue]")
205
+ for i, tool_name in enumerate(detected_tools.keys(), 1):
206
+ console.print(f" {i}. {tool_name}")
207
+
208
+ console.print("\n[bold]Configure MCP integration for:[/bold]")
209
+ console.print(" [1] All detected tools")
210
+ console.print(" [2] Choose specific tool(s)")
211
+ console.print(" [3] Skip MCP setup")
212
+
213
+ choice = typer.prompt("\nSelect option", type=int, default=1)
214
+
215
+ if choice == 1:
216
+ # Configure all tools
217
+ tools_to_configure = detected_tools
218
+ elif choice == 2:
219
+ # Let user choose specific tools
220
+ console.print(
221
+ "\n[bold]Select tools to configure (comma-separated numbers):[/bold]"
222
+ )
223
+ tool_list = list(detected_tools.keys())
224
+ for i, tool_name in enumerate(tool_list, 1):
225
+ console.print(f" {i}. {tool_name}")
226
+
227
+ selections = typer.prompt("Tool numbers").strip()
228
+ for num_str in selections.split(","):
229
+ try:
230
+ idx = int(num_str.strip()) - 1
231
+ if 0 <= idx < len(tool_list):
232
+ tool_name = tool_list[idx]
233
+ tools_to_configure[tool_name] = detected_tools[tool_name]
234
+ except ValueError:
235
+ print_warning(f"Invalid selection: {num_str}")
236
+ else:
237
+ # Skip MCP setup
238
+ print_info("Skipping MCP setup")
239
+ return {}
240
+ else:
241
+ # Single tool or non-interactive mode - configure all
242
+ tools_to_configure = detected_tools
243
+
244
+ # Configure selected tools
245
+ results = {}
246
+
247
+ if tools_to_configure:
248
+ console.print("\n[bold blue]🔗 Configuring MCP integration...[/bold blue]")
249
+
250
+ for tool_name, config_path in tools_to_configure.items():
251
+ results[tool_name] = configure_mcp_for_tool(
252
+ tool_name=tool_name,
253
+ config_path=config_path,
254
+ project_root=project_root,
255
+ server_name="mcp-vector-search",
256
+ enable_watch=enable_watch,
257
+ )
258
+
259
+ return results
260
+
261
+
262
+ def print_next_steps(
263
+ project_root: Path,
264
+ indexed: bool,
265
+ mcp_results: dict[str, bool],
266
+ ) -> None:
267
+ """Print helpful next steps after installation.
268
+
269
+ Args:
270
+ project_root: Path to the project root
271
+ indexed: Whether the codebase was indexed
272
+ mcp_results: Results of MCP integration (tool_name -> success)
273
+ """
274
+ console.print("\n[bold green]🎉 Installation Complete![/bold green]")
275
+
276
+ # Show what was completed
277
+ console.print("\n[bold blue]✨ Setup Summary:[/bold blue]")
278
+ console.print(" ✅ Vector database initialized")
279
+ if indexed:
280
+ console.print(" ✅ Codebase indexed and searchable")
281
+ else:
282
+ console.print(" ⏭️ Indexing skipped (use --no-index flag)")
283
+
284
+ if mcp_results:
285
+ successful_tools = [tool for tool, success in mcp_results.items() if success]
286
+ if successful_tools:
287
+ console.print(
288
+ f" ✅ MCP integration configured for: {', '.join(successful_tools)}"
289
+ )
290
+
291
+ # Next steps
292
+ console.print("\n[bold green]🚀 Ready to use:[/bold green]")
293
+ console.print(
294
+ " • Search your code: [code]mcp-vector-search search 'your query'[/code]"
295
+ )
296
+ console.print(" • Check status: [code]mcp-vector-search status[/code]")
297
+
298
+ if mcp_results:
299
+ console.print("\n[bold blue]🤖 Using MCP Integration:[/bold blue]")
300
+ if "claude-code" in mcp_results and mcp_results["claude-code"]:
301
+ console.print(" • Open Claude Code in this project directory")
302
+ console.print(" • Use: 'Search my code for authentication functions'")
303
+ if "cursor" in mcp_results and mcp_results["cursor"]:
304
+ console.print(" • Open Cursor in this project directory")
305
+ console.print(" • MCP tools should be available automatically")
306
+ if "claude-desktop" in mcp_results and mcp_results["claude-desktop"]:
307
+ console.print(" • Restart Claude Desktop")
308
+ console.print(" • The mcp-vector-search server will be available")
309
+
310
+ console.print(
311
+ "\n[dim]💡 Tip: Run 'mcp-vector-search --help' for more commands[/dim]"
312
+ )
313
+
314
+
315
+ # ============================================================================
316
+ # Main Install Command
317
+ # ============================================================================
318
+
319
+
24
320
  def main(
25
321
  ctx: typer.Context,
26
- target_directory: Path = typer.Argument(
27
- None,
28
- help="Target directory to install in (default: current directory)",
29
- ),
30
- project_root: Path | None = typer.Option(
31
- None,
32
- "--project-root",
33
- "-p",
34
- help="Project root directory (auto-detected if not specified)",
35
- exists=True,
36
- file_okay=False,
37
- dir_okay=True,
38
- readable=True,
322
+ project_path: Path = typer.Argument(
323
+ ...,
324
+ help="Project directory to initialize and index",
39
325
  ),
40
326
  extensions: str | None = typer.Option(
41
327
  None,
42
328
  "--extensions",
43
329
  "-e",
44
- help="Comma-separated list of file extensions to index (e.g., '.py,.js,.ts,.txt,.md')",
330
+ help="Comma-separated file extensions (e.g., .py,.js,.ts,.dart)",
331
+ ),
332
+ no_index: bool = typer.Option(
333
+ False,
334
+ "--no-index",
335
+ help="Skip initial indexing",
336
+ ),
337
+ no_mcp: bool = typer.Option(
338
+ False,
339
+ "--no-mcp",
340
+ help="Skip MCP integration setup",
341
+ ),
342
+ mcp_tool: str | None = typer.Option(
343
+ None,
344
+ "--mcp-tool",
345
+ help="Specific AI tool for MCP integration (claude-code, cursor, etc.)",
346
+ ),
347
+ no_watch: bool = typer.Option(
348
+ False,
349
+ "--no-watch",
350
+ help="Disable file watching for MCP integration",
45
351
  ),
46
352
  embedding_model: str = typer.Option(
47
353
  "sentence-transformers/all-MiniLM-L6-v2",
@@ -57,16 +363,6 @@ def main(
57
363
  min=0.0,
58
364
  max=1.0,
59
365
  ),
60
- no_mcp: bool = typer.Option(
61
- False,
62
- "--no-mcp",
63
- help="Skip MCP integration setup",
64
- ),
65
- no_auto_index: bool = typer.Option(
66
- False,
67
- "--no-auto-index",
68
- help="Skip automatic indexing after setup",
69
- ),
70
366
  force: bool = typer.Option(
71
367
  False,
72
368
  "--force",
@@ -74,47 +370,59 @@ def main(
74
370
  help="Force re-installation if project is already initialized",
75
371
  ),
76
372
  ) -> None:
77
- """Install mcp-vector-search in a project directory.
373
+ """Install mcp-vector-search with complete setup including MCP integration.
374
+
375
+ This command provides a comprehensive one-step installation that:
78
376
 
79
- This command sets up mcp-vector-search in the specified directory (or current directory)
80
- with full initialization, indexing, and optional MCP integration.
377
+ Initializes mcp-vector-search in the project directory
378
+ Auto-detects programming languages and file types
379
+ ✅ Indexes the codebase for semantic search
380
+ ✅ Configures MCP integration for multiple AI tools
381
+ ✅ Sets up file watching for automatic updates
382
+
383
+ Perfect for getting started quickly with semantic code search!
81
384
 
82
385
  Examples:
83
- mcp-vector-search install # Install in current directory
84
- mcp-vector-search install ~/my-project # Install in specific directory
85
- mcp-vector-search install --no-mcp # Install without MCP integration
86
- mcp-vector-search install --force # Force re-installation
87
- mcp-vector-search install --extensions .py,.js,.ts,.txt # Custom file extensions
386
+ mcp-vector-search install . # Install in current directory
387
+ mcp-vector-search install ~/my-project # Install in specific directory
388
+ mcp-vector-search install . --no-mcp # Skip MCP integration
389
+ mcp-vector-search install . --mcp-tool claude-code # Configure specific tool
390
+ mcp-vector-search install . --extensions .py,.js,.ts # Custom file types
391
+ mcp-vector-search install . --force # Force re-initialization
88
392
  """
89
393
  try:
90
- # Determine target directory - prioritize target_directory, then project_root, then context, then cwd
91
- target_dir = target_directory or project_root or ctx.obj.get("project_root") or Path.cwd()
92
- target_dir = target_dir.resolve()
394
+ # Resolve project path
395
+ project_root = project_path.resolve()
93
396
 
94
397
  # Show installation header
95
- console.print(Panel.fit(
96
- f"[bold blue]🚀 MCP Vector Search - Project Installation[/bold blue]\n\n"
97
- f"📁 Target project: [cyan]{target_dir}[/cyan]\n"
98
- f"🔧 Installing with full setup and configuration",
99
- border_style="blue"
100
- ))
101
-
102
- # Check if target directory exists
103
- if not target_dir.exists():
104
- print_error(f"Target directory does not exist: {target_dir}")
398
+ console.print(
399
+ Panel.fit(
400
+ f"[bold blue]🚀 MCP Vector Search - Complete Installation[/bold blue]\n\n"
401
+ f"📁 Project: [cyan]{project_root}[/cyan]\n"
402
+ f"🔧 Setting up with full initialization and MCP integration",
403
+ border_style="blue",
404
+ )
405
+ )
406
+
407
+ # Check if project directory exists
408
+ if not project_root.exists():
409
+ print_error(f"Project directory does not exist: {project_root}")
105
410
  raise typer.Exit(1)
106
411
 
107
412
  # Check if already initialized
108
- project_manager = ProjectManager(target_dir)
413
+ project_manager = ProjectManager(project_root)
109
414
  if project_manager.is_initialized() and not force:
110
- print_success("Project is already initialized and ready to use!")
111
- print_info("Your project has vector search capabilities enabled.")
112
- print_info(f"Use --force to re-initialize or run 'mcp-vector-search --project-root {target_dir} status main' to see current configuration")
113
-
114
- console.print("\n[bold green]🔍 Ready to use:[/bold green]")
115
- console.print(f" • Search your code: [code]cd {target_dir} && mcp-vector-search search 'your query'[/code]")
116
- console.print(f" Check status: [code]cd {target_dir} && mcp-vector-search status main[/code]")
117
- console.print(" • Use [code]--force[/code] to re-initialize if needed")
415
+ print_success("Project is already initialized!")
416
+ print_info("Vector search capabilities are enabled.")
417
+ print_info("Use --force to re-initialize if needed.")
418
+
419
+ # Show MCP configuration option
420
+ if not no_mcp:
421
+ console.print("\n[bold blue]💡 MCP Integration:[/bold blue]")
422
+ console.print(
423
+ " Run install again with --force to reconfigure MCP integration"
424
+ )
425
+
118
426
  return
119
427
 
120
428
  # Parse file extensions
@@ -126,41 +434,122 @@ def main(
126
434
  ext if ext.startswith(".") else f".{ext}" for ext in file_extensions
127
435
  ]
128
436
 
129
- # Run initialization
130
- print_info("Initializing project...")
131
-
132
- # Import init functionality
133
- from .init import run_init_setup
437
+ # ========================================================================
438
+ # STEP 1: Initialize Project
439
+ # ========================================================================
440
+ with Progress(
441
+ SpinnerColumn(),
442
+ TextColumn("[progress.description]{task.description}"),
443
+ console=console,
444
+ ) as progress:
445
+ task = progress.add_task("📁 Initializing project...", total=None)
134
446
 
135
- asyncio.run(
136
- run_init_setup(
137
- project_root=target_dir,
447
+ # Initialize the project
448
+ project_manager.initialize(
138
449
  file_extensions=file_extensions,
139
450
  embedding_model=embedding_model,
140
451
  similarity_threshold=similarity_threshold,
141
- mcp=not no_mcp,
142
- auto_index=not no_auto_index,
143
452
  force=force,
144
453
  )
145
- )
146
454
 
147
- # Show completion message
148
- console.print(Panel.fit(
149
- f"[bold green]🎉 Installation Complete![/bold green]\n\n"
150
- f"✅ Project initialized at [cyan]{target_dir}[/cyan]\n"
151
- f"✅ Vector database configured\n"
152
- f"✅ {'Codebase indexed' if not no_auto_index else 'Ready for indexing'}\n"
153
- f"✅ {'MCP integration enabled' if not no_mcp else 'MCP integration skipped'}\n\n"
154
- f"[bold blue]🔍 Next steps:[/bold blue]\n"
155
- f" • [code]cd {target_dir}[/code]\n"
156
- f" • [code]mcp-vector-search search 'your query'[/code]\n"
157
- f"[code]mcp-vector-search status main[/code]",
158
- border_style="green"
159
- ))
455
+ progress.update(task, completed=True)
456
+ print_success("✅ Project initialized successfully")
457
+
458
+ # ========================================================================
459
+ # STEP 2: Index Codebase (unless --no-index)
460
+ # ========================================================================
461
+ indexed = False
462
+ if not no_index:
463
+ with Progress(
464
+ SpinnerColumn(),
465
+ TextColumn("[progress.description]{task.description}"),
466
+ console=console,
467
+ ) as progress:
468
+ task = progress.add_task("🔍 Indexing codebase...", total=None)
469
+
470
+ # Import and run indexing
471
+ from .index import run_indexing
472
+
473
+ try:
474
+ asyncio.run(
475
+ run_indexing(
476
+ project_root=project_root,
477
+ force_reindex=False,
478
+ show_progress=False, # We handle progress here
479
+ )
480
+ )
481
+ indexed = True
482
+ progress.update(task, completed=True)
483
+ print_success("✅ Codebase indexed successfully")
484
+ except Exception as e:
485
+ print_error(f"❌ Indexing failed: {e}")
486
+ print_info("You can run 'mcp-vector-search index' later")
487
+ else:
488
+ print_info("⏭️ Indexing skipped (--no-index)")
489
+
490
+ # ========================================================================
491
+ # STEP 3: Configure MCP Integration (unless --no-mcp)
492
+ # ========================================================================
493
+ mcp_results = {}
494
+ if not no_mcp:
495
+ enable_watch = not no_watch
496
+ mcp_results = setup_mcp_integration(
497
+ project_root=project_root,
498
+ mcp_tool=mcp_tool,
499
+ enable_watch=enable_watch,
500
+ interactive=True, # Allow interactive tool selection
501
+ )
502
+
503
+ if not mcp_results:
504
+ print_info("⏭️ MCP integration skipped")
505
+ else:
506
+ print_info("⏭️ MCP integration skipped (--no-mcp)")
507
+
508
+ # ========================================================================
509
+ # STEP 4: Verification
510
+ # ========================================================================
511
+ console.print("\n[bold blue]✅ Verifying installation...[/bold blue]")
512
+
513
+ # Check project initialized
514
+ if project_manager.is_initialized():
515
+ print_success(" ✅ Project configuration created")
516
+
517
+ # Check index created
518
+ if indexed:
519
+ print_success(" ✅ Index created and populated")
520
+
521
+ # Check MCP configured
522
+ if mcp_results:
523
+ successful_tools = [
524
+ tool for tool, success in mcp_results.items() if success
525
+ ]
526
+ if successful_tools:
527
+ print_success(f" ✅ MCP configured for: {', '.join(successful_tools)}")
528
+
529
+ # ========================================================================
530
+ # STEP 5: Print Next Steps
531
+ # ========================================================================
532
+ print_next_steps(
533
+ project_root=project_root,
534
+ indexed=indexed,
535
+ mcp_results=mcp_results,
536
+ )
160
537
 
161
538
  except Exception as e:
162
539
  logger.error(f"Installation failed: {e}")
163
- print_error(f"Installation failed: {e}")
540
+ print_error(f"Installation failed: {e}")
541
+
542
+ # Provide recovery instructions
543
+ console.print("\n[bold]Recovery steps:[/bold]")
544
+ console.print(" 1. Check that the project directory exists and is writable")
545
+ console.print(
546
+ " 2. Ensure required dependencies are installed: [code]pip install mcp-vector-search[/code]"
547
+ )
548
+ console.print(
549
+ " 3. Try running with --force to override existing configuration"
550
+ )
551
+ console.print(" 4. Check logs with --verbose flag for more details")
552
+
164
553
  raise typer.Exit(1)
165
554
 
166
555
 
@@ -180,15 +569,14 @@ def demo(
180
569
  """Run installation demo with sample project."""
181
570
  try:
182
571
  import tempfile
183
- import shutil
184
-
572
+
185
573
  print_info("🎬 Running mcp-vector-search installation demo...")
186
-
574
+
187
575
  # Create temporary demo directory
188
576
  with tempfile.TemporaryDirectory(prefix="mcp-demo-") as temp_dir:
189
577
  demo_dir = Path(temp_dir) / "demo-project"
190
578
  demo_dir.mkdir()
191
-
579
+
192
580
  # Create sample files
193
581
  (demo_dir / "main.py").write_text("""
194
582
  def main():
@@ -213,7 +601,7 @@ class UserService:
213
601
  if __name__ == "__main__":
214
602
  main()
215
603
  """)
216
-
604
+
217
605
  (demo_dir / "utils.py").write_text("""
218
606
  import json
219
607
  from typing import Dict, Any
@@ -232,48 +620,72 @@ def hash_password(password: str) -> str:
232
620
  import hashlib
233
621
  return hashlib.sha256(password.encode()).hexdigest()
234
622
  """)
235
-
236
- console.print(f"\n[bold blue]📁 Created demo project at:[/bold blue] {demo_dir}")
237
-
623
+
624
+ console.print(
625
+ f"\n[bold blue]📁 Created demo project at:[/bold blue] {demo_dir}"
626
+ )
627
+
238
628
  # Run installation
239
629
  print_info("Installing mcp-vector-search in demo project...")
240
-
630
+
241
631
  # Use subprocess to run the install command
242
- result = subprocess.run([
243
- sys.executable, "-m", "mcp_vector_search.cli.main",
244
- "--project-root", str(demo_dir),
245
- "install", str(demo_dir),
246
- "--extensions", ".py",
247
- "--no-mcp" # Skip MCP for demo
248
- ], capture_output=True, text=True)
249
-
632
+ result = subprocess.run(
633
+ [
634
+ sys.executable,
635
+ "-m",
636
+ "mcp_vector_search.cli.main",
637
+ "--project-root",
638
+ str(demo_dir),
639
+ "install",
640
+ str(demo_dir),
641
+ "--extensions",
642
+ ".py",
643
+ "--no-mcp", # Skip MCP for demo
644
+ ],
645
+ capture_output=True,
646
+ text=True,
647
+ )
648
+
250
649
  if result.returncode == 0:
251
650
  print_success("✅ Demo installation completed!")
252
-
651
+
253
652
  # Run a sample search
254
653
  print_info("Running sample search: 'user authentication'...")
255
-
256
- search_result = subprocess.run([
257
- sys.executable, "-m", "mcp_vector_search.cli.main",
258
- "--project-root", str(demo_dir),
259
- "search", "user authentication",
260
- "--limit", "3"
261
- ], capture_output=True, text=True)
262
-
654
+
655
+ search_result = subprocess.run(
656
+ [
657
+ sys.executable,
658
+ "-m",
659
+ "mcp_vector_search.cli.main",
660
+ "--project-root",
661
+ str(demo_dir),
662
+ "search",
663
+ "user authentication",
664
+ "--limit",
665
+ "3",
666
+ ],
667
+ capture_output=True,
668
+ text=True,
669
+ )
670
+
263
671
  if search_result.returncode == 0:
264
- console.print("\n[bold green]🔍 Sample search results:[/bold green]")
672
+ console.print(
673
+ "\n[bold green]🔍 Sample search results:[/bold green]"
674
+ )
265
675
  console.print(search_result.stdout)
266
676
  else:
267
677
  print_warning("Search demo failed, but installation was successful")
268
-
269
- console.print(f"\n[bold blue]🎉 Demo completed![/bold blue]")
678
+
679
+ console.print("\n[bold blue]🎉 Demo completed![/bold blue]")
270
680
  console.print(f"Demo project was created at: [cyan]{demo_dir}[/cyan]")
271
- console.print("The temporary directory will be cleaned up automatically.")
272
-
681
+ console.print(
682
+ "The temporary directory will be cleaned up automatically."
683
+ )
684
+
273
685
  else:
274
686
  print_error(f"Demo installation failed: {result.stderr}")
275
687
  raise typer.Exit(1)
276
-
688
+
277
689
  except Exception as e:
278
690
  logger.error(f"Demo failed: {e}")
279
691
  print_error(f"Demo failed: {e}")