mcp-vector-search 0.15.7__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 (86) 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/chat.py +534 -0
  6. mcp_vector_search/cli/commands/config.py +393 -0
  7. mcp_vector_search/cli/commands/demo.py +358 -0
  8. mcp_vector_search/cli/commands/index.py +762 -0
  9. mcp_vector_search/cli/commands/init.py +658 -0
  10. mcp_vector_search/cli/commands/install.py +869 -0
  11. mcp_vector_search/cli/commands/install_old.py +700 -0
  12. mcp_vector_search/cli/commands/mcp.py +1254 -0
  13. mcp_vector_search/cli/commands/reset.py +393 -0
  14. mcp_vector_search/cli/commands/search.py +796 -0
  15. mcp_vector_search/cli/commands/setup.py +1133 -0
  16. mcp_vector_search/cli/commands/status.py +584 -0
  17. mcp_vector_search/cli/commands/uninstall.py +404 -0
  18. mcp_vector_search/cli/commands/visualize/__init__.py +39 -0
  19. mcp_vector_search/cli/commands/visualize/cli.py +265 -0
  20. mcp_vector_search/cli/commands/visualize/exporters/__init__.py +12 -0
  21. mcp_vector_search/cli/commands/visualize/exporters/html_exporter.py +33 -0
  22. mcp_vector_search/cli/commands/visualize/exporters/json_exporter.py +29 -0
  23. mcp_vector_search/cli/commands/visualize/graph_builder.py +709 -0
  24. mcp_vector_search/cli/commands/visualize/layout_engine.py +469 -0
  25. mcp_vector_search/cli/commands/visualize/server.py +201 -0
  26. mcp_vector_search/cli/commands/visualize/state_manager.py +428 -0
  27. mcp_vector_search/cli/commands/visualize/templates/__init__.py +16 -0
  28. mcp_vector_search/cli/commands/visualize/templates/base.py +218 -0
  29. mcp_vector_search/cli/commands/visualize/templates/scripts.py +3670 -0
  30. mcp_vector_search/cli/commands/visualize/templates/styles.py +779 -0
  31. mcp_vector_search/cli/commands/visualize.py.original +2536 -0
  32. mcp_vector_search/cli/commands/watch.py +287 -0
  33. mcp_vector_search/cli/didyoumean.py +520 -0
  34. mcp_vector_search/cli/export.py +320 -0
  35. mcp_vector_search/cli/history.py +295 -0
  36. mcp_vector_search/cli/interactive.py +342 -0
  37. mcp_vector_search/cli/main.py +484 -0
  38. mcp_vector_search/cli/output.py +414 -0
  39. mcp_vector_search/cli/suggestions.py +375 -0
  40. mcp_vector_search/config/__init__.py +1 -0
  41. mcp_vector_search/config/constants.py +24 -0
  42. mcp_vector_search/config/defaults.py +200 -0
  43. mcp_vector_search/config/settings.py +146 -0
  44. mcp_vector_search/core/__init__.py +1 -0
  45. mcp_vector_search/core/auto_indexer.py +298 -0
  46. mcp_vector_search/core/config_utils.py +394 -0
  47. mcp_vector_search/core/connection_pool.py +360 -0
  48. mcp_vector_search/core/database.py +1237 -0
  49. mcp_vector_search/core/directory_index.py +318 -0
  50. mcp_vector_search/core/embeddings.py +294 -0
  51. mcp_vector_search/core/exceptions.py +89 -0
  52. mcp_vector_search/core/factory.py +318 -0
  53. mcp_vector_search/core/git_hooks.py +345 -0
  54. mcp_vector_search/core/indexer.py +1002 -0
  55. mcp_vector_search/core/llm_client.py +453 -0
  56. mcp_vector_search/core/models.py +294 -0
  57. mcp_vector_search/core/project.py +350 -0
  58. mcp_vector_search/core/scheduler.py +330 -0
  59. mcp_vector_search/core/search.py +952 -0
  60. mcp_vector_search/core/watcher.py +322 -0
  61. mcp_vector_search/mcp/__init__.py +5 -0
  62. mcp_vector_search/mcp/__main__.py +25 -0
  63. mcp_vector_search/mcp/server.py +752 -0
  64. mcp_vector_search/parsers/__init__.py +8 -0
  65. mcp_vector_search/parsers/base.py +296 -0
  66. mcp_vector_search/parsers/dart.py +605 -0
  67. mcp_vector_search/parsers/html.py +413 -0
  68. mcp_vector_search/parsers/javascript.py +643 -0
  69. mcp_vector_search/parsers/php.py +694 -0
  70. mcp_vector_search/parsers/python.py +502 -0
  71. mcp_vector_search/parsers/registry.py +223 -0
  72. mcp_vector_search/parsers/ruby.py +678 -0
  73. mcp_vector_search/parsers/text.py +186 -0
  74. mcp_vector_search/parsers/utils.py +265 -0
  75. mcp_vector_search/py.typed +1 -0
  76. mcp_vector_search/utils/__init__.py +42 -0
  77. mcp_vector_search/utils/gitignore.py +250 -0
  78. mcp_vector_search/utils/gitignore_updater.py +212 -0
  79. mcp_vector_search/utils/monorepo.py +339 -0
  80. mcp_vector_search/utils/timing.py +338 -0
  81. mcp_vector_search/utils/version.py +47 -0
  82. mcp_vector_search-0.15.7.dist-info/METADATA +884 -0
  83. mcp_vector_search-0.15.7.dist-info/RECORD +86 -0
  84. mcp_vector_search-0.15.7.dist-info/WHEEL +4 -0
  85. mcp_vector_search-0.15.7.dist-info/entry_points.txt +3 -0
  86. mcp_vector_search-0.15.7.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,869 @@
1
+ """Install and integration commands for MCP Vector Search CLI.
2
+
3
+ This module provides installation commands for:
4
+ 1. Project initialization (main command)
5
+ 2. Platform-specific MCP integrations using py-mcp-installer library
6
+
7
+ Examples:
8
+ # Install in current project
9
+ $ mcp-vector-search install
10
+
11
+ # Install MCP integration (auto-detect platforms)
12
+ $ mcp-vector-search install mcp
13
+
14
+ # Install to specific platform
15
+ $ mcp-vector-search install mcp --platform cursor
16
+
17
+ # Install to all detected platforms
18
+ $ mcp-vector-search install mcp --all
19
+ """
20
+
21
+ import asyncio
22
+ from pathlib import Path
23
+
24
+ import typer
25
+ from loguru import logger
26
+
27
+ # Import from py-mcp-installer library
28
+ from py_mcp_installer import (
29
+ MCPInspector,
30
+ MCPInstaller,
31
+ MCPServerConfig,
32
+ Platform,
33
+ PlatformDetector,
34
+ PlatformInfo,
35
+ )
36
+ from rich.console import Console
37
+ from rich.panel import Panel
38
+ from rich.table import Table
39
+
40
+ from ...config.defaults import DEFAULT_EMBEDDING_MODELS, DEFAULT_FILE_EXTENSIONS
41
+ from ...core.exceptions import ProjectInitializationError
42
+ from ...core.project import ProjectManager
43
+ from ..didyoumean import create_enhanced_typer
44
+ from ..output import (
45
+ print_error,
46
+ print_info,
47
+ print_next_steps,
48
+ print_success,
49
+ print_warning,
50
+ )
51
+
52
+ # Create console for rich output
53
+ console = Console()
54
+
55
+ # Create install app with subcommands
56
+ install_app = create_enhanced_typer(
57
+ help="""📦 Install mcp-vector-search and MCP integrations
58
+
59
+ [bold cyan]Usage Patterns:[/bold cyan]
60
+
61
+ [green]1. Project Installation (Primary)[/green]
62
+ Install mcp-vector-search in the current project:
63
+ [code]$ mcp-vector-search install[/code]
64
+
65
+ [green]2. MCP Platform Integration[/green]
66
+ Add MCP integration with auto-detection:
67
+ [code]$ mcp-vector-search install mcp[/code]
68
+ [code]$ mcp-vector-search install mcp --platform cursor[/code]
69
+ [code]$ mcp-vector-search install mcp --all[/code]
70
+
71
+ [green]3. Complete Setup[/green]
72
+ Install project + all MCP integrations:
73
+ [code]$ mcp-vector-search install --with-mcp[/code]
74
+
75
+ [bold cyan]Supported Platforms:[/bold cyan]
76
+ • [green]claude-code[/green] - Claude Code
77
+ • [green]claude-desktop[/green] - Claude Desktop
78
+ • [green]cursor[/green] - Cursor IDE
79
+ • [green]auggie[/green] - Auggie
80
+ • [green]codex[/green] - Codex
81
+ • [green]windsurf[/green] - Windsurf IDE
82
+ • [green]gemini-cli[/green] - Gemini CLI
83
+
84
+ [dim]💡 Use 'mcp-vector-search uninstall mcp' to remove integrations[/dim]
85
+ """,
86
+ invoke_without_command=True,
87
+ no_args_is_help=False,
88
+ )
89
+
90
+
91
+ # ==============================================================================
92
+ # Helper Functions
93
+ # ==============================================================================
94
+
95
+
96
+ def detect_project_root(start_path: Path | None = None) -> Path:
97
+ """Auto-detect project root directory.
98
+
99
+ Detection priority:
100
+ 1. Directory with .mcp-vector-search/ (project initialized)
101
+ 2. Git repository root
102
+ 3. Current working directory (fallback)
103
+
104
+ Args:
105
+ start_path: Starting path for detection (default: current directory)
106
+
107
+ Returns:
108
+ Path to detected project root
109
+ """
110
+ current = start_path or Path.cwd()
111
+
112
+ # Check for .mcp-vector-search directory (initialized project)
113
+ if (current / ".mcp-vector-search").exists():
114
+ logger.debug(f"Detected project root via .mcp-vector-search: {current}")
115
+ return current
116
+
117
+ # Check if we're in a git repository
118
+ git_root = find_git_root(current)
119
+ if git_root and (git_root / ".mcp-vector-search").exists():
120
+ logger.debug(f"Detected project root via git + .mcp-vector-search: {git_root}")
121
+ return git_root
122
+
123
+ # Fallback to current directory
124
+ logger.debug(f"Using current directory as project root: {current}")
125
+ return current
126
+
127
+
128
+ def find_git_root(path: Path) -> Path | None:
129
+ """Find git repository root by walking up directory tree.
130
+
131
+ Args:
132
+ path: Starting path
133
+
134
+ Returns:
135
+ Path to git root or None if not in a git repo
136
+ """
137
+ current = path.resolve()
138
+ while current != current.parent:
139
+ if (current / ".git").exists():
140
+ logger.debug(f"Found git root: {current}")
141
+ return current
142
+ current = current.parent
143
+ return None
144
+
145
+
146
+ def _get_claude_desktop_config_path() -> Path | None:
147
+ """Get the default config path for Claude Desktop based on OS.
148
+
149
+ Returns:
150
+ Path to Claude Desktop config or None if unknown OS
151
+ """
152
+ import sys
153
+
154
+ if sys.platform == "darwin":
155
+ # macOS
156
+ return (
157
+ Path.home()
158
+ / "Library"
159
+ / "Application Support"
160
+ / "Claude"
161
+ / "claude_desktop_config.json"
162
+ )
163
+ elif sys.platform == "win32":
164
+ # Windows
165
+ import os
166
+
167
+ appdata = os.environ.get("APPDATA", "")
168
+ if appdata:
169
+ return Path(appdata) / "Claude" / "claude_desktop_config.json"
170
+ else:
171
+ # Linux
172
+ return Path.home() / ".config" / "Claude" / "claude_desktop_config.json"
173
+ return None
174
+
175
+
176
+ def detect_all_platforms() -> list[PlatformInfo]:
177
+ """Detect all available platforms on the system.
178
+
179
+ Returns:
180
+ List of detected platforms with confidence scores
181
+ """
182
+ detector = PlatformDetector()
183
+ detected_platforms = []
184
+
185
+ # Try to detect each platform
186
+ platform_detectors = {
187
+ Platform.CLAUDE_CODE: detector.detect_claude_code,
188
+ Platform.CLAUDE_DESKTOP: detector.detect_claude_desktop,
189
+ Platform.CURSOR: detector.detect_cursor,
190
+ Platform.AUGGIE: detector.detect_auggie,
191
+ Platform.CODEX: detector.detect_codex,
192
+ Platform.WINDSURF: detector.detect_windsurf,
193
+ Platform.GEMINI_CLI: detector.detect_gemini_cli,
194
+ }
195
+
196
+ for platform_enum, detector_func in platform_detectors.items():
197
+ try:
198
+ confidence, config_path = detector_func()
199
+
200
+ # Determine CLI availability
201
+ cli_available = False
202
+ from py_mcp_installer.utils import resolve_command_path
203
+
204
+ if platform_enum in (Platform.CLAUDE_CODE, Platform.CLAUDE_DESKTOP):
205
+ cli_available = resolve_command_path("claude") is not None
206
+ elif platform_enum == Platform.CURSOR:
207
+ cli_available = resolve_command_path("cursor") is not None
208
+
209
+ # Include platform if:
210
+ # 1. Has config file with confidence > 0, OR
211
+ # 2. Has CLI available (can create config)
212
+ # For CLI-based platforms, we can configure even without existing config
213
+ if confidence > 0.0 and config_path:
214
+ # Has existing config file
215
+ platform_info = PlatformInfo(
216
+ platform=platform_enum,
217
+ confidence=confidence,
218
+ config_path=config_path,
219
+ cli_available=cli_available,
220
+ )
221
+ detected_platforms.append(platform_info)
222
+ elif cli_available and platform_enum in (
223
+ Platform.CLAUDE_CODE,
224
+ Platform.CLAUDE_DESKTOP,
225
+ Platform.CURSOR,
226
+ ):
227
+ # CLI available but no config yet - we can still configure it
228
+ # Use default config path for the platform
229
+ default_config_paths = {
230
+ Platform.CLAUDE_CODE: Path.home()
231
+ / ".config"
232
+ / "claude"
233
+ / "mcp.json",
234
+ Platform.CLAUDE_DESKTOP: _get_claude_desktop_config_path(),
235
+ Platform.CURSOR: Path.home() / ".cursor" / "mcp.json",
236
+ }
237
+ platform_info = PlatformInfo(
238
+ platform=platform_enum,
239
+ confidence=0.2, # Low confidence since no config exists yet
240
+ config_path=default_config_paths.get(platform_enum),
241
+ cli_available=cli_available,
242
+ )
243
+ detected_platforms.append(platform_info)
244
+ except Exception as e:
245
+ logger.debug(f"Failed to detect {platform_enum.value}: {e}")
246
+ continue
247
+
248
+ return detected_platforms
249
+
250
+
251
+ def platform_name_to_enum(name: str) -> Platform | None:
252
+ """Convert platform name to enum.
253
+
254
+ Args:
255
+ name: Platform name (e.g., "cursor", "claude-code")
256
+
257
+ Returns:
258
+ Platform enum or None if not found
259
+ """
260
+ name_map = {
261
+ "claude-code": Platform.CLAUDE_CODE,
262
+ "claude-desktop": Platform.CLAUDE_DESKTOP,
263
+ "cursor": Platform.CURSOR,
264
+ "auggie": Platform.AUGGIE,
265
+ "codex": Platform.CODEX,
266
+ "windsurf": Platform.WINDSURF,
267
+ "gemini-cli": Platform.GEMINI_CLI,
268
+ }
269
+ return name_map.get(name.lower())
270
+
271
+
272
+ # ==============================================================================
273
+ # Main Install Command (Project Installation)
274
+ # ==============================================================================
275
+
276
+
277
+ @install_app.callback()
278
+ def main(
279
+ ctx: typer.Context,
280
+ extensions: str | None = typer.Option(
281
+ None,
282
+ "--extensions",
283
+ "-e",
284
+ help="Comma-separated file extensions (e.g., .py,.js,.ts)",
285
+ rich_help_panel="📁 Configuration",
286
+ ),
287
+ embedding_model: str = typer.Option(
288
+ DEFAULT_EMBEDDING_MODELS["code"],
289
+ "--embedding-model",
290
+ "-m",
291
+ help="Embedding model for semantic search",
292
+ rich_help_panel="🧠 Model Settings",
293
+ ),
294
+ similarity_threshold: float = typer.Option(
295
+ 0.5,
296
+ "--similarity-threshold",
297
+ "-s",
298
+ help="Similarity threshold (0.0-1.0)",
299
+ min=0.0,
300
+ max=1.0,
301
+ rich_help_panel="🧠 Model Settings",
302
+ ),
303
+ auto_index: bool = typer.Option(
304
+ True,
305
+ "--auto-index/--no-auto-index",
306
+ help="Automatically index after initialization",
307
+ rich_help_panel="🚀 Workflow",
308
+ ),
309
+ with_mcp: bool = typer.Option(
310
+ False,
311
+ "--with-mcp",
312
+ help="Install all available MCP integrations",
313
+ rich_help_panel="🚀 Workflow",
314
+ ),
315
+ force: bool = typer.Option(
316
+ False,
317
+ "--force",
318
+ "-f",
319
+ help="Force re-initialization",
320
+ rich_help_panel="⚙️ Advanced",
321
+ ),
322
+ ) -> None:
323
+ """📦 Install mcp-vector-search in the current project.
324
+
325
+ This command initializes mcp-vector-search with:
326
+ ✅ Vector database setup
327
+ ✅ Configuration file creation
328
+ ✅ Automatic code indexing
329
+ ✅ Ready-to-use semantic search
330
+
331
+ [bold cyan]Examples:[/bold cyan]
332
+
333
+ [green]Basic installation:[/green]
334
+ $ mcp-vector-search install
335
+
336
+ [green]Custom file types:[/green]
337
+ $ mcp-vector-search install --extensions .py,.js,.ts
338
+
339
+ [green]Install with MCP integrations:[/green]
340
+ $ mcp-vector-search install --with-mcp
341
+
342
+ [green]Skip auto-indexing:[/green]
343
+ $ mcp-vector-search install --no-auto-index
344
+
345
+ [dim]💡 After installation, use 'mcp-vector-search search' to search your code[/dim]
346
+ """
347
+ # Only run main logic if no subcommand was invoked
348
+ if ctx.invoked_subcommand is not None:
349
+ return
350
+
351
+ try:
352
+ project_root = ctx.obj.get("project_root") or Path.cwd()
353
+
354
+ console.print(
355
+ Panel.fit(
356
+ f"[bold cyan]Installing mcp-vector-search[/bold cyan]\n"
357
+ f"📁 Project: {project_root}",
358
+ border_style="cyan",
359
+ )
360
+ )
361
+
362
+ # Check if already initialized
363
+ project_manager = ProjectManager(project_root)
364
+ if project_manager.is_initialized() and not force:
365
+ print_success("✅ Project already initialized!")
366
+ print_info(" Use --force to re-initialize")
367
+ raise typer.Exit(0)
368
+
369
+ # Parse file extensions
370
+ file_extensions = None
371
+ if extensions:
372
+ file_extensions = [
373
+ ext.strip() if ext.startswith(".") else f".{ext.strip()}"
374
+ for ext in extensions.split(",")
375
+ ]
376
+ else:
377
+ file_extensions = DEFAULT_FILE_EXTENSIONS
378
+
379
+ # Show configuration
380
+ console.print("\n[bold blue]Configuration:[/bold blue]")
381
+ console.print(f" 📄 Extensions: {', '.join(file_extensions)}")
382
+ console.print(f" 🧠 Model: {embedding_model}")
383
+ console.print(f" 🎯 Threshold: {similarity_threshold}")
384
+ console.print(f" 🔍 Auto-index: {'✅' if auto_index else '❌'}")
385
+ console.print(f" 🔗 With MCP: {'✅' if with_mcp else '❌'}")
386
+
387
+ # Initialize project
388
+ console.print("\n[bold]Initializing project...[/bold]")
389
+ project_manager.initialize(
390
+ file_extensions=file_extensions,
391
+ embedding_model=embedding_model,
392
+ similarity_threshold=similarity_threshold,
393
+ force=force,
394
+ )
395
+ print_success("✅ Project initialized")
396
+
397
+ # Auto-index if requested
398
+ if auto_index:
399
+ console.print("\n[bold]🔍 Indexing codebase...[/bold]")
400
+ from .index import run_indexing
401
+
402
+ try:
403
+ asyncio.run(
404
+ run_indexing(
405
+ project_root=project_root,
406
+ force_reindex=False,
407
+ show_progress=True,
408
+ )
409
+ )
410
+ print_success("✅ Indexing completed")
411
+ except Exception as e:
412
+ print_error(f"❌ Indexing failed: {e}")
413
+ print_info(" Run 'mcp-vector-search index' to index later")
414
+
415
+ # Install MCP integrations if requested
416
+ if with_mcp:
417
+ console.print("\n[bold blue]🔗 Installing MCP integrations...[/bold blue]")
418
+ detected = detect_all_platforms()
419
+
420
+ if detected:
421
+ for platform_info in detected:
422
+ _install_to_platform(platform_info, project_root)
423
+ else:
424
+ print_warning("No MCP platforms detected")
425
+ print_info("Install platforms manually using:")
426
+ print_info(" mcp-vector-search install mcp --platform <platform>")
427
+
428
+ # Success message
429
+ console.print("\n[bold green]🎉 Installation Complete![/bold green]")
430
+
431
+ next_steps = [
432
+ "[cyan]mcp-vector-search search 'your query'[/cyan] - Search your code",
433
+ "[cyan]mcp-vector-search status[/cyan] - View project status",
434
+ ]
435
+
436
+ if not with_mcp:
437
+ next_steps.append(
438
+ "[cyan]mcp-vector-search install mcp[/cyan] - Add MCP integration"
439
+ )
440
+
441
+ print_next_steps(next_steps, title="Ready to Use")
442
+
443
+ except typer.Exit:
444
+ # Re-raise typer.Exit to allow proper exit handling
445
+ raise
446
+ except ProjectInitializationError as e:
447
+ print_error(f"Installation failed: {e}")
448
+ raise typer.Exit(1)
449
+ except Exception as e:
450
+ logger.error(f"Unexpected error during installation: {e}")
451
+ print_error(f"Unexpected error: {e}")
452
+ raise typer.Exit(1)
453
+
454
+
455
+ # ==============================================================================
456
+ # MCP Installation Command
457
+ # ==============================================================================
458
+
459
+
460
+ def _install_to_platform(platform_info: PlatformInfo, project_root: Path) -> bool:
461
+ """Install to a specific platform.
462
+
463
+ Args:
464
+ platform_info: Platform information
465
+ project_root: Project root directory
466
+
467
+ Returns:
468
+ True if installation succeeded
469
+ """
470
+ try:
471
+ # Create installer for this platform
472
+ installer = MCPInstaller(platform=platform_info.platform)
473
+
474
+ # Detect installation method (uv vs direct command)
475
+ import shutil
476
+
477
+ use_uv = shutil.which("uv") is not None
478
+ mcp_cmd = shutil.which("mcp-vector-search")
479
+
480
+ if use_uv:
481
+ # Development mode with uv
482
+ command = "uv"
483
+ args = ["run", "--directory", str(project_root), "mcp-vector-search", "mcp"]
484
+ elif mcp_cmd:
485
+ # Production mode with installed package
486
+ command = "mcp-vector-search"
487
+ args = ["mcp"]
488
+ else:
489
+ # Fallback to uv (will fail if not available)
490
+ command = "uv"
491
+ args = ["run", "mcp-vector-search", "mcp"]
492
+
493
+ # Create server configuration
494
+ server_config = MCPServerConfig(
495
+ name="mcp-vector-search",
496
+ command=command,
497
+ args=args,
498
+ env={
499
+ "PROJECT_ROOT": str(project_root.resolve()),
500
+ "MCP_PROJECT_ROOT": str(project_root.resolve()),
501
+ },
502
+ description=f"Semantic code search for {project_root.name}",
503
+ )
504
+
505
+ # Install server
506
+ result = installer.install_server(
507
+ name=server_config.name,
508
+ command=server_config.command,
509
+ args=server_config.args,
510
+ env=server_config.env,
511
+ description=server_config.description,
512
+ )
513
+
514
+ if result.success:
515
+ print_success(f" ✅ Installed to {platform_info.platform.value}")
516
+ if result.config_path:
517
+ print_info(f" Config: {result.config_path}")
518
+
519
+ # Validate installation
520
+ inspector = MCPInspector(platform_info)
521
+ report = inspector.inspect()
522
+
523
+ if report.has_errors():
524
+ print_warning(" ⚠️ Configuration has issues:")
525
+ for issue in report.issues:
526
+ if issue.severity == "error":
527
+ print_warning(f" • {issue.message}")
528
+
529
+ return True
530
+ else:
531
+ print_error(
532
+ f" ❌ Failed to install to {platform_info.platform.value}: {result.message}"
533
+ )
534
+ return False
535
+
536
+ except Exception as e:
537
+ logger.exception(f"Installation to {platform_info.platform.value} failed")
538
+ print_error(f" ❌ Installation failed: {e}")
539
+ return False
540
+
541
+
542
+ @install_app.command(name="mcp")
543
+ def install_mcp(
544
+ ctx: typer.Context,
545
+ platform: str | None = typer.Option(
546
+ None,
547
+ "--platform",
548
+ "-p",
549
+ help="Specific platform to install to (e.g., cursor, claude-code)",
550
+ ),
551
+ all_platforms: bool = typer.Option(
552
+ False,
553
+ "--all",
554
+ "-a",
555
+ help="Install to all detected platforms",
556
+ ),
557
+ auto: bool = typer.Option(
558
+ True,
559
+ "--auto/--no-auto",
560
+ help="Auto-detect project root (default: enabled)",
561
+ ),
562
+ dry_run: bool = typer.Option(
563
+ False,
564
+ "--dry-run",
565
+ help="Preview changes without applying them",
566
+ ),
567
+ ) -> None:
568
+ """Install MCP integration to platforms.
569
+
570
+ Auto-detects available platforms and installs mcp-vector-search as an MCP server.
571
+ Automatically detects project root from current directory or git repository.
572
+
573
+ [bold cyan]Examples:[/bold cyan]
574
+
575
+ [green]Auto-detect and install (recommended):[/green]
576
+ $ mcp-vector-search install mcp
577
+ $ mcp-vector-search install mcp --auto
578
+
579
+ [green]Install to specific platform:[/green]
580
+ $ mcp-vector-search install mcp --platform cursor
581
+
582
+ [green]Install to all detected platforms:[/green]
583
+ $ mcp-vector-search install mcp --all
584
+
585
+ [green]Preview changes (dry run):[/green]
586
+ $ mcp-vector-search install mcp --dry-run
587
+
588
+ [green]Use current directory as project root (no auto-detection):[/green]
589
+ $ mcp-vector-search install mcp --no-auto
590
+ """
591
+ # Auto-detect project root if enabled
592
+ if auto:
593
+ project_root = detect_project_root()
594
+ console.print(f"[dim]🔍 Auto-detected project root: {project_root}[/dim]\n")
595
+ else:
596
+ project_root = ctx.obj.get("project_root") or Path.cwd()
597
+ console.print(f"[dim]📁 Using project root: {project_root}[/dim]\n")
598
+
599
+ console.print(
600
+ Panel.fit(
601
+ "[bold cyan]Installing MCP Integration[/bold cyan]\n"
602
+ f"📁 Project: {project_root}",
603
+ border_style="cyan",
604
+ )
605
+ )
606
+
607
+ try:
608
+ # Detect available platforms
609
+ print_info("🔍 Detecting available MCP platforms...")
610
+ detected = detect_all_platforms()
611
+
612
+ if not detected:
613
+ print_warning("No MCP platforms detected.")
614
+ print_info(
615
+ "Supported platforms: claude-code, claude-desktop, cursor, auggie, codex, windsurf, gemini-cli"
616
+ )
617
+ raise typer.Exit(0)
618
+
619
+ # Display detected platforms
620
+ table = Table(title="Detected MCP Platforms")
621
+ table.add_column("Platform", style="cyan")
622
+ table.add_column("Config Path", style="green")
623
+ table.add_column("Confidence", style="yellow")
624
+ table.add_column("CLI", style="magenta")
625
+
626
+ for p in detected:
627
+ table.add_row(
628
+ p.platform.value,
629
+ str(p.config_path) if p.config_path else "N/A",
630
+ f"{p.confidence:.2f}",
631
+ "✅" if p.cli_available else "❌",
632
+ )
633
+
634
+ console.print(table)
635
+
636
+ # Filter platforms
637
+ target_platforms = detected
638
+
639
+ if platform:
640
+ # Install to specific platform
641
+ platform_enum = platform_name_to_enum(platform)
642
+ if not platform_enum:
643
+ print_error(f"Unknown platform: {platform}")
644
+ print_info(
645
+ "Supported: claude-code, claude-desktop, cursor, auggie, codex, windsurf, gemini-cli"
646
+ )
647
+ raise typer.Exit(1)
648
+
649
+ target_platforms = [p for p in detected if p.platform == platform_enum]
650
+
651
+ if not target_platforms:
652
+ print_error(f"Platform '{platform}' not detected on this system")
653
+ raise typer.Exit(1)
654
+
655
+ elif not all_platforms:
656
+ # By default, install to highest confidence platform only
657
+ if detected:
658
+ max_confidence_platform = max(detected, key=lambda p: p.confidence)
659
+ target_platforms = [max_confidence_platform]
660
+ print_info(
661
+ f"Installing to highest confidence platform: {max_confidence_platform.platform.value}"
662
+ )
663
+ print_info("Use --all to install to all detected platforms")
664
+
665
+ # Show what will be installed
666
+ console.print("\n[bold]Target platforms:[/bold]")
667
+ for p in target_platforms:
668
+ console.print(f" • {p.platform.value}")
669
+
670
+ if dry_run:
671
+ console.print("\n[bold yellow]🔍 DRY RUN MODE[/bold yellow]")
672
+ print_info("No changes will be applied")
673
+ return
674
+
675
+ # Install to each platform
676
+ console.print("\n[bold]Installing...[/bold]")
677
+ successful = 0
678
+ failed = 0
679
+
680
+ for platform_info in target_platforms:
681
+ if _install_to_platform(platform_info, project_root):
682
+ successful += 1
683
+ else:
684
+ failed += 1
685
+
686
+ # Summary
687
+ console.print("\n[bold green]✨ Installation Summary[/bold green]")
688
+ console.print(f" ✅ Successful: {successful}")
689
+ if failed > 0:
690
+ console.print(f" ❌ Failed: {failed}")
691
+
692
+ console.print("\n[bold blue]Next Steps:[/bold blue]")
693
+ console.print(" 1. Restart your AI coding tool")
694
+ console.print(" 2. The MCP server will be available automatically")
695
+ console.print(" 3. Try: 'Search my code for authentication functions'")
696
+
697
+ except typer.Exit:
698
+ raise
699
+ except Exception as e:
700
+ logger.exception("MCP installation failed")
701
+ print_error(f"Installation failed: {e}")
702
+ raise typer.Exit(1)
703
+
704
+
705
+ # ==============================================================================
706
+ # MCP Status Command
707
+ # ==============================================================================
708
+
709
+
710
+ @install_app.command("mcp-status")
711
+ def mcp_status(ctx: typer.Context) -> None:
712
+ """Show MCP integration status for all platforms.
713
+
714
+ Displays which platforms have mcp-vector-search configured,
715
+ the detected project root, and configuration details.
716
+
717
+ [bold cyan]Examples:[/bold cyan]
718
+
719
+ [green]Check status:[/green]
720
+ $ mcp-vector-search install mcp-status
721
+ """
722
+ # Auto-detect project root
723
+ project_root = detect_project_root()
724
+
725
+ console.print(
726
+ Panel.fit(
727
+ f"[bold cyan]MCP Integration Status[/bold cyan]\n"
728
+ f"📁 Detected Project: {project_root}",
729
+ border_style="cyan",
730
+ )
731
+ )
732
+
733
+ try:
734
+ # Detect all platforms
735
+ detected = detect_all_platforms()
736
+
737
+ if not detected:
738
+ print_warning("No MCP platforms detected")
739
+ return
740
+
741
+ # Create status table
742
+ table = Table(show_header=True, header_style="bold cyan")
743
+ table.add_column("Platform", style="cyan")
744
+ table.add_column("Status", style="green")
745
+ table.add_column("Config Path")
746
+ table.add_column("Project Root")
747
+
748
+ for platform_info in detected:
749
+ try:
750
+ # Check if mcp-vector-search is configured
751
+ installer = MCPInstaller(platform=platform_info.platform)
752
+ server = installer.get_server("mcp-vector-search")
753
+
754
+ if server:
755
+ status = "✅ Configured"
756
+ # Extract project root from env
757
+ env = server.get("env", {})
758
+ configured_root = env.get("MCP_PROJECT_ROOT") or env.get(
759
+ "PROJECT_ROOT", "N/A"
760
+ )
761
+
762
+ # Check if it matches current project
763
+ if configured_root != "N/A":
764
+ configured_path = Path(configured_root)
765
+ if configured_path == project_root:
766
+ status = "✅ Configured (current project)"
767
+ else:
768
+ status = "⚠️ Configured (different project)"
769
+ else:
770
+ status = "❌ Not configured"
771
+ configured_root = "N/A"
772
+
773
+ except Exception as e:
774
+ logger.debug(f"Failed to check {platform_info.platform.value}: {e}")
775
+ status = "❓ Unknown"
776
+ configured_root = "N/A"
777
+
778
+ table.add_row(
779
+ platform_info.platform.value,
780
+ status,
781
+ str(platform_info.config_path) if platform_info.config_path else "N/A",
782
+ configured_root,
783
+ )
784
+
785
+ console.print(table)
786
+
787
+ # Show next steps
788
+ console.print("\n[bold blue]Quick Actions:[/bold blue]")
789
+ console.print(
790
+ " mcp-vector-search install mcp # Install to auto-detected platform"
791
+ )
792
+ console.print(
793
+ " mcp-vector-search install mcp --all # Install to all platforms"
794
+ )
795
+ console.print(
796
+ " mcp-vector-search install mcp --platform <name> # Install to specific platform"
797
+ )
798
+
799
+ except Exception as e:
800
+ logger.exception("Failed to check MCP status")
801
+ print_error(f"Status check failed: {e}")
802
+ raise typer.Exit(1)
803
+
804
+
805
+ # ==============================================================================
806
+ # List Platforms Command
807
+ # ==============================================================================
808
+
809
+
810
+ @install_app.command("list-platforms")
811
+ def list_platforms(ctx: typer.Context) -> None:
812
+ """List all detected MCP platforms and their status."""
813
+ console.print(
814
+ Panel.fit("[bold cyan]MCP Platform Status[/bold cyan]", border_style="cyan")
815
+ )
816
+
817
+ try:
818
+ detected = detect_all_platforms()
819
+
820
+ if not detected:
821
+ print_warning("No MCP platforms detected")
822
+ print_info(
823
+ "Supported platforms: claude-code, claude-desktop, cursor, auggie, codex, windsurf, gemini-cli"
824
+ )
825
+ return
826
+
827
+ table = Table(show_header=True, header_style="bold cyan")
828
+ table.add_column("Platform", style="cyan")
829
+ table.add_column("Status", style="green")
830
+ table.add_column("Config Path")
831
+ table.add_column("Confidence", style="yellow")
832
+
833
+ for platform_info in detected:
834
+ # Check if mcp-vector-search is configured
835
+ try:
836
+ installer = MCPInstaller(platform=platform_info.platform)
837
+ server = installer.get_server("mcp-vector-search")
838
+ status = "✅ Configured" if server else "⚠️ Available"
839
+ except Exception:
840
+ status = "⚠️ Available"
841
+
842
+ table.add_row(
843
+ platform_info.platform.value,
844
+ status,
845
+ str(platform_info.config_path) if platform_info.config_path else "N/A",
846
+ f"{platform_info.confidence:.2f}",
847
+ )
848
+
849
+ console.print(table)
850
+
851
+ console.print("\n[bold blue]Installation Commands:[/bold blue]")
852
+ console.print(
853
+ " mcp-vector-search install mcp # Auto-detect"
854
+ )
855
+ console.print(
856
+ " mcp-vector-search install mcp --platform <name> # Specific platform"
857
+ )
858
+ console.print(
859
+ " mcp-vector-search install mcp --all # All platforms"
860
+ )
861
+
862
+ except Exception as e:
863
+ logger.exception("Failed to list platforms")
864
+ print_error(f"Failed to list platforms: {e}")
865
+ raise typer.Exit(1)
866
+
867
+
868
+ if __name__ == "__main__":
869
+ install_app()