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,584 @@
1
+ """Status command for MCP Vector Search CLI."""
2
+
3
+ import asyncio
4
+ import json
5
+ import subprocess
6
+ from pathlib import Path
7
+ from typing import Any
8
+
9
+ import typer
10
+ from loguru import logger
11
+
12
+ from ... import __version__
13
+ from ...core.database import ChromaVectorDatabase
14
+ from ...core.embeddings import create_embedding_function
15
+ from ...core.exceptions import ProjectNotFoundError
16
+ from ...core.indexer import SemanticIndexer
17
+ from ...core.project import ProjectManager
18
+ from ..output import (
19
+ console,
20
+ print_dependency_status,
21
+ print_error,
22
+ print_info,
23
+ print_json,
24
+ )
25
+
26
+ # Create status subcommand app
27
+ status_app = typer.Typer(help="Show project status and statistics")
28
+
29
+
30
+ @status_app.command()
31
+ def main(
32
+ ctx: typer.Context,
33
+ project_root: Path | None = typer.Option(
34
+ None,
35
+ "--project-root",
36
+ "-p",
37
+ help="Project root directory (auto-detected if not specified)",
38
+ exists=True,
39
+ file_okay=False,
40
+ dir_okay=True,
41
+ readable=True,
42
+ rich_help_panel="🔧 Global Options",
43
+ ),
44
+ verbose: bool = typer.Option(
45
+ False,
46
+ "--verbose",
47
+ "-v",
48
+ help="Show detailed information including paths and patterns",
49
+ rich_help_panel="📊 Display Options",
50
+ ),
51
+ health_check: bool = typer.Option(
52
+ False,
53
+ "--health-check",
54
+ help="Perform comprehensive health check of all components",
55
+ rich_help_panel="🔍 Diagnostics",
56
+ ),
57
+ mcp: bool = typer.Option(
58
+ False,
59
+ "--mcp",
60
+ help="Check Claude Code MCP integration status",
61
+ rich_help_panel="🔍 Diagnostics",
62
+ ),
63
+ json_output: bool = typer.Option(
64
+ False,
65
+ "--json",
66
+ help="Output status in JSON format",
67
+ rich_help_panel="📊 Display Options",
68
+ ),
69
+ ) -> None:
70
+ """📊 Show project status and indexing statistics.
71
+
72
+ Displays comprehensive information about your project including configuration,
73
+ indexing statistics, and system health. Use this to verify setup and monitor
74
+ indexing progress.
75
+
76
+ [bold cyan]Basic Examples:[/bold cyan]
77
+
78
+ [green]Quick status check:[/green]
79
+ $ mcp-vector-search status
80
+
81
+ [green]Detailed status with all information:[/green]
82
+ $ mcp-vector-search status --verbose
83
+
84
+ [green]Check MCP integration:[/green]
85
+ $ mcp-vector-search status --mcp
86
+
87
+ [bold cyan]Diagnostics:[/bold cyan]
88
+
89
+ [green]Full health check:[/green]
90
+ $ mcp-vector-search status --health-check
91
+
92
+ [green]Export status to JSON:[/green]
93
+ $ mcp-vector-search status --json > status.json
94
+
95
+ [green]Combined diagnostics:[/green]
96
+ $ mcp-vector-search status --verbose --health-check --mcp
97
+
98
+ [dim]💡 Tip: Use --health-check to diagnose issues with dependencies or database.[/dim]
99
+ """
100
+ try:
101
+ # Use provided project_root or current working directory
102
+ if project_root is None:
103
+ project_root = Path.cwd()
104
+
105
+ async def run_status_with_timeout():
106
+ """Run status command with timeout protection."""
107
+ try:
108
+ await asyncio.wait_for(
109
+ show_status(
110
+ project_root=project_root,
111
+ verbose=verbose,
112
+ health_check=health_check,
113
+ mcp=mcp,
114
+ json_output=json_output,
115
+ ),
116
+ timeout=30.0, # 30 second timeout
117
+ )
118
+ except TimeoutError:
119
+ logger.error("Status check timed out after 30 seconds")
120
+ print_error(
121
+ "Status check timed out after 30 seconds. "
122
+ "Try running with --verbose for more details."
123
+ )
124
+ raise typer.Exit(1)
125
+
126
+ asyncio.run(run_status_with_timeout())
127
+
128
+ except Exception as e:
129
+ logger.error(f"Status check failed: {e}")
130
+ print_error(f"Status check failed: {e}")
131
+ raise typer.Exit(1)
132
+
133
+
134
+ async def show_status(
135
+ project_root: Path,
136
+ verbose: bool = False,
137
+ health_check: bool = False,
138
+ mcp: bool = False,
139
+ json_output: bool = False,
140
+ ) -> None:
141
+ """Show comprehensive project status."""
142
+ status_data = {}
143
+
144
+ try:
145
+ # Check if project is initialized - use the specified project root
146
+ project_manager = ProjectManager(project_root)
147
+
148
+ if not project_manager.is_initialized():
149
+ if json_output:
150
+ status_data = {
151
+ "initialized": False,
152
+ "project_root": str(project_root),
153
+ "error": "Project not initialized",
154
+ }
155
+ print_json(status_data)
156
+ else:
157
+ print_error(f"Project not initialized at {project_root}")
158
+ print_info("Run 'mcp-vector-search init' to initialize the project")
159
+ return
160
+
161
+ # Get configuration first
162
+ config = project_manager.load_config()
163
+
164
+ # Get indexing statistics from database (fast, no filesystem scan)
165
+ embedding_function, _ = create_embedding_function(config.embedding_model)
166
+ database = ChromaVectorDatabase(
167
+ persist_directory=config.index_path,
168
+ embedding_function=embedding_function,
169
+ )
170
+
171
+ indexer = SemanticIndexer(
172
+ database=database,
173
+ project_root=project_root,
174
+ config=config,
175
+ )
176
+
177
+ # Get indexing stats (using database stats only, no filesystem scan)
178
+ async with database:
179
+ db_stats = await database.get_stats()
180
+ index_stats = await indexer.get_indexing_stats(db_stats=db_stats)
181
+
182
+ # Get project information with pre-computed file count (avoids filesystem scan)
183
+ project_info = project_manager.get_project_info(file_count=db_stats.total_files)
184
+
185
+ # Get version information
186
+ index_version = indexer.get_index_version()
187
+ needs_reindex = indexer.needs_reindex_for_version()
188
+
189
+ # Compile status data
190
+ status_data = {
191
+ "project": {
192
+ "name": project_info.name,
193
+ "root_path": str(project_info.root_path),
194
+ "initialized": project_info.is_initialized,
195
+ "languages": project_info.languages,
196
+ "file_count": project_info.file_count,
197
+ },
198
+ "configuration": {
199
+ "embedding_model": config.embedding_model,
200
+ "similarity_threshold": config.similarity_threshold,
201
+ "file_extensions": config.file_extensions,
202
+ "max_chunk_size": config.max_chunk_size,
203
+ "cache_embeddings": config.cache_embeddings,
204
+ "watch_files": config.watch_files,
205
+ "auto_reindex_on_upgrade": config.auto_reindex_on_upgrade,
206
+ },
207
+ "index": {
208
+ "total_files": index_stats.get("total_indexable_files", 0),
209
+ "indexed_files": index_stats.get("indexed_files", 0),
210
+ "total_chunks": index_stats.get("total_chunks", 0),
211
+ "languages": index_stats.get("languages", {}),
212
+ "index_size_mb": db_stats.index_size_mb,
213
+ "last_updated": db_stats.last_updated,
214
+ "index_version": index_version,
215
+ "current_version": __version__,
216
+ "needs_reindex": needs_reindex,
217
+ },
218
+ }
219
+
220
+ # Add health check if requested
221
+ if health_check:
222
+ health_status = await perform_health_check(project_root, config)
223
+ status_data["health"] = health_status
224
+
225
+ # Add MCP integration check if requested
226
+ if mcp:
227
+ mcp_status = await check_mcp_integration(project_root)
228
+ status_data["mcp"] = mcp_status
229
+
230
+ # Add verbose information
231
+ if verbose:
232
+ status_data["verbose"] = {
233
+ "config_path": str(project_info.config_path),
234
+ "index_path": str(project_info.index_path),
235
+ "ignore_patterns": list(indexer.get_ignore_patterns()),
236
+ "parser_info": index_stats.get("parser_info", {}),
237
+ }
238
+
239
+ # Output results
240
+ if json_output:
241
+ print_json(status_data)
242
+ else:
243
+ _display_status(status_data, verbose, mcp)
244
+
245
+ except ProjectNotFoundError:
246
+ if json_output:
247
+ print_json({"initialized": False, "error": "Project not initialized"})
248
+ else:
249
+ print_error("Project not initialized")
250
+ print_info("Run 'mcp-vector-search init' to initialize the project")
251
+ except Exception as e:
252
+ if json_output:
253
+ print_json({"error": str(e)})
254
+ else:
255
+ print_error(f"Failed to get status: {e}")
256
+ raise
257
+
258
+
259
+ def _display_status(
260
+ status_data: dict[str, Any], verbose: bool, mcp: bool = False
261
+ ) -> None:
262
+ """Display status in human-readable format."""
263
+ project_data = status_data["project"]
264
+ config_data = status_data["configuration"]
265
+ index_data = status_data["index"]
266
+
267
+ # Project information
268
+ console.print("[bold blue]Project Information[/bold blue]")
269
+ console.print(f" Name: {project_data['name']}")
270
+ console.print(f" Root: {project_data['root_path']}")
271
+ console.print(
272
+ f" Languages: {', '.join(project_data['languages']) if project_data['languages'] else 'None detected'}"
273
+ )
274
+ console.print(f" Indexable Files: {project_data['file_count']}")
275
+ console.print()
276
+
277
+ # Configuration
278
+ console.print("[bold blue]Configuration[/bold blue]")
279
+ console.print(f" Embedding Model: {config_data['embedding_model']}")
280
+ console.print(f" Similarity Threshold: {config_data['similarity_threshold']}")
281
+ console.print(f" File Extensions: {', '.join(config_data['file_extensions'])}")
282
+ console.print(
283
+ f" Cache Embeddings: {'✓' if config_data['cache_embeddings'] else '✗'}"
284
+ )
285
+ console.print()
286
+
287
+ # Index statistics
288
+ console.print("[bold blue]Index Statistics[/bold blue]")
289
+ console.print(
290
+ f" Indexed Files: {index_data['indexed_files']}/{index_data['total_files']}"
291
+ )
292
+ console.print(f" Total Chunks: {index_data['total_chunks']}")
293
+ console.print(f" Index Size: {index_data['index_size_mb']:.2f} MB")
294
+
295
+ # Version information
296
+ index_version = index_data.get("index_version")
297
+ current_version = index_data.get("current_version", __version__)
298
+ needs_reindex = index_data.get("needs_reindex", False)
299
+
300
+ if index_version:
301
+ if needs_reindex:
302
+ console.print(
303
+ f" Version: [yellow]{index_version}[/yellow] (current: {current_version}) [yellow]⚠️ Reindex recommended[/yellow]"
304
+ )
305
+ else:
306
+ console.print(f" Version: [green]{index_version}[/green] (up to date)")
307
+ else:
308
+ console.print(
309
+ f" Version: [yellow]Not tracked[/yellow] (current: {current_version}) [yellow]⚠️ Reindex recommended[/yellow]"
310
+ )
311
+
312
+ if index_data["languages"]:
313
+ console.print(" Language Distribution:")
314
+ for lang, count in index_data["languages"].items():
315
+ console.print(f" {lang}: {count} chunks")
316
+ console.print()
317
+
318
+ # Show reindex recommendation if needed
319
+ if needs_reindex:
320
+ console.print(
321
+ "[yellow]💡 Tip: Run 'mcp-vector-search index' to reindex with the latest improvements[/yellow]"
322
+ )
323
+ console.print()
324
+
325
+ # Health check results
326
+ if "health" in status_data:
327
+ health_data = status_data["health"]
328
+ console.print("[bold blue]Health Check[/bold blue]")
329
+
330
+ overall_health = health_data.get("overall", "unknown")
331
+ if overall_health == "healthy":
332
+ console.print("[green]✓ System is healthy[/green]")
333
+ elif overall_health == "warning":
334
+ console.print("[yellow]⚠ System has warnings[/yellow]")
335
+ else:
336
+ console.print("[red]✗ System has issues[/red]")
337
+
338
+ for component, status in health_data.get("components", {}).items():
339
+ if status == "ok":
340
+ console.print(f" [green]✓[/green] {component}")
341
+ elif status == "warning":
342
+ console.print(f" [yellow]⚠[/yellow] {component}")
343
+ else:
344
+ console.print(f" [red]✗[/red] {component}")
345
+ console.print()
346
+
347
+ # MCP integration status
348
+ if "mcp" in status_data:
349
+ mcp_data = status_data["mcp"]
350
+ console.print("[bold blue]MCP Integration[/bold blue]")
351
+
352
+ if mcp_data.get("claude_available"):
353
+ console.print("[green]✓[/green] Claude Code: Available")
354
+ else:
355
+ console.print("[red]✗[/red] Claude Code: Not available")
356
+
357
+ server_status = mcp_data.get("server_status", "unknown")
358
+ server_name = mcp_data.get("server_name", "mcp-vector-search")
359
+
360
+ if server_status == "installed":
361
+ console.print(f"[green]✓[/green] MCP Server '{server_name}': Installed")
362
+ elif server_status == "not_installed":
363
+ console.print(f"[red]✗[/red] MCP Server '{server_name}': Not installed")
364
+ else:
365
+ console.print(
366
+ f"[yellow]⚠[/yellow] MCP Server '{server_name}': {server_status}"
367
+ )
368
+
369
+ if mcp_data.get("project_config"):
370
+ console.print("[green]✓[/green] Project Configuration: Found")
371
+ else:
372
+ console.print("[red]✗[/red] Project Configuration: Missing")
373
+
374
+ console.print()
375
+
376
+ # Verbose information
377
+ if verbose and "verbose" in status_data:
378
+ verbose_data = status_data["verbose"]
379
+ console.print("[bold blue]Detailed Information[/bold blue]")
380
+ console.print(f" Config Path: {verbose_data['config_path']}")
381
+ console.print(f" Index Path: {verbose_data['index_path']}")
382
+ console.print(
383
+ f" Ignore Patterns: {', '.join(verbose_data['ignore_patterns'])}"
384
+ )
385
+
386
+
387
+ async def perform_health_check(project_root: Path, config) -> dict[str, Any]:
388
+ """Perform comprehensive health check."""
389
+ health_status = {
390
+ "overall": "healthy",
391
+ "components": {},
392
+ "issues": [],
393
+ }
394
+
395
+ try:
396
+ # Check dependencies
397
+ deps_ok = check_dependencies()
398
+ health_status["components"]["dependencies"] = "ok" if deps_ok else "error"
399
+ if not deps_ok:
400
+ health_status["issues"].append("Missing dependencies")
401
+
402
+ # Check configuration
403
+ try:
404
+ # Validate embedding model
405
+ embedding_function, _ = create_embedding_function(config.embedding_model)
406
+ health_status["components"]["embedding_model"] = "ok"
407
+ except Exception as e:
408
+ health_status["components"]["embedding_model"] = "error"
409
+ health_status["issues"].append(f"Embedding model error: {e}")
410
+
411
+ # Check database
412
+ try:
413
+ database = ChromaVectorDatabase(
414
+ persist_directory=config.index_path,
415
+ embedding_function=embedding_function,
416
+ )
417
+ async with database:
418
+ await database.get_stats()
419
+ health_status["components"]["database"] = "ok"
420
+ except Exception as e:
421
+ health_status["components"]["database"] = "error"
422
+ health_status["issues"].append(f"Database error: {e}")
423
+
424
+ # Check file system permissions
425
+ try:
426
+ config.index_path.mkdir(parents=True, exist_ok=True)
427
+ test_file = config.index_path / ".test_write"
428
+ test_file.write_text("test")
429
+ test_file.unlink()
430
+ health_status["components"]["file_permissions"] = "ok"
431
+ except Exception as e:
432
+ health_status["components"]["file_permissions"] = "error"
433
+ health_status["issues"].append(f"File permission error: {e}")
434
+
435
+ # Determine overall health
436
+ if any(status == "error" for status in health_status["components"].values()):
437
+ health_status["overall"] = "error"
438
+ elif any(
439
+ status == "warning" for status in health_status["components"].values()
440
+ ):
441
+ health_status["overall"] = "warning"
442
+
443
+ except Exception as e:
444
+ health_status["overall"] = "error"
445
+ health_status["issues"].append(f"Health check failed: {e}")
446
+
447
+ return health_status
448
+
449
+
450
+ async def check_mcp_integration(
451
+ project_root: Path, server_name: str = "mcp-vector-search"
452
+ ) -> dict[str, Any]:
453
+ """Check MCP integration status."""
454
+ mcp_status = {
455
+ "claude_available": False,
456
+ "server_status": "unknown",
457
+ "server_name": server_name,
458
+ "project_config": False,
459
+ "issues": [],
460
+ }
461
+
462
+ try:
463
+ # Import MCP functions from the mcp command module
464
+ from .mcp import check_claude_code_available, get_claude_command
465
+
466
+ # Check if Claude Code is available
467
+ mcp_status["claude_available"] = check_claude_code_available()
468
+
469
+ if mcp_status["claude_available"]:
470
+ claude_cmd = get_claude_command()
471
+
472
+ # Check if MCP server is installed
473
+ try:
474
+ result = subprocess.run(
475
+ [claude_cmd, "mcp", "get", server_name],
476
+ capture_output=True,
477
+ text=True,
478
+ timeout=10,
479
+ )
480
+
481
+ if result.returncode == 0:
482
+ mcp_status["server_status"] = "installed"
483
+ else:
484
+ mcp_status["server_status"] = "not_installed"
485
+ mcp_status["issues"].append(
486
+ f"MCP server '{server_name}' not found in Claude Code"
487
+ )
488
+
489
+ except subprocess.TimeoutExpired:
490
+ mcp_status["server_status"] = "timeout"
491
+ mcp_status["issues"].append("Timeout checking MCP server status")
492
+ except Exception as e:
493
+ mcp_status["server_status"] = "error"
494
+ mcp_status["issues"].append(f"Error checking MCP server: {e}")
495
+ else:
496
+ mcp_status["issues"].append("Claude Code not available")
497
+
498
+ # Check for project-level .claude.json configuration
499
+ claude_json_path = project_root / ".claude.json"
500
+ if claude_json_path.exists():
501
+ try:
502
+ with open(claude_json_path) as f:
503
+ config = json.load(f)
504
+ if config.get("mcpServers", {}).get(server_name):
505
+ mcp_status["project_config"] = True
506
+ else:
507
+ mcp_status["issues"].append(
508
+ f"MCP server '{server_name}' not found in project .claude.json"
509
+ )
510
+ except Exception as e:
511
+ mcp_status["issues"].append(f"Error reading project .claude.json: {e}")
512
+ else:
513
+ mcp_status["issues"].append("Project .claude.json not found")
514
+
515
+ except Exception as e:
516
+ mcp_status["issues"].append(f"MCP integration check failed: {e}")
517
+
518
+ return mcp_status
519
+
520
+
521
+ def check_dependencies() -> bool:
522
+ """Check if all required dependencies are available.
523
+
524
+ Returns:
525
+ bool: True if all dependencies are available, False otherwise.
526
+ """
527
+ dependencies = [
528
+ ("chromadb", "ChromaDB"),
529
+ ("sentence_transformers", "Sentence Transformers"),
530
+ ("tree_sitter", "Tree-sitter"),
531
+ ("tree_sitter_language_pack", "Tree-sitter Languages"),
532
+ ("typer", "Typer"),
533
+ ("rich", "Rich"),
534
+ ("pydantic", "Pydantic"),
535
+ ("watchdog", "Watchdog"),
536
+ ("loguru", "Loguru"),
537
+ ]
538
+
539
+ all_available = True
540
+ missing_deps = []
541
+
542
+ for module_name, display_name in dependencies:
543
+ try:
544
+ __import__(module_name)
545
+ print_dependency_status(display_name, True)
546
+ except ImportError:
547
+ print_dependency_status(display_name, False)
548
+ all_available = False
549
+ missing_deps.append(module_name)
550
+
551
+ # Print helpful installation instructions if dependencies are missing
552
+ if not all_available:
553
+ console.print()
554
+ console.print("[yellow]💡 Installation Help:[/yellow]")
555
+ console.print()
556
+ console.print("[bold]To install missing dependencies:[/bold]")
557
+ console.print()
558
+ console.print(" [cyan]# Using pip (recommended):[/cyan]")
559
+ console.print(" pip install mcp-vector-search")
560
+ console.print()
561
+ console.print(" [cyan]# Using uv (faster):[/cyan]")
562
+ console.print(" uv pip install mcp-vector-search")
563
+ console.print()
564
+ console.print(" [cyan]# Install from source:[/cyan]")
565
+ console.print(" pip install -e .")
566
+ console.print()
567
+
568
+ if "tree_sitter_language_pack" in missing_deps:
569
+ console.print(
570
+ "[yellow]⚠️ Tree-sitter Language Pack Issue Detected[/yellow]"
571
+ )
572
+ console.print()
573
+ console.print("If you installed via Homebrew, you may need to reinstall:")
574
+ console.print(" brew reinstall mcp-vector-search")
575
+ console.print()
576
+ console.print("Or install the dependency manually:")
577
+ console.print(" pip install tree-sitter-language-pack")
578
+ console.print()
579
+
580
+ return all_available
581
+
582
+
583
+ if __name__ == "__main__":
584
+ status_app()