mcp-vector-search 0.0.3__py3-none-any.whl → 0.4.12__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 (49) hide show
  1. mcp_vector_search/__init__.py +3 -2
  2. mcp_vector_search/cli/commands/auto_index.py +397 -0
  3. mcp_vector_search/cli/commands/config.py +88 -40
  4. mcp_vector_search/cli/commands/index.py +198 -52
  5. mcp_vector_search/cli/commands/init.py +471 -58
  6. mcp_vector_search/cli/commands/install.py +284 -0
  7. mcp_vector_search/cli/commands/mcp.py +495 -0
  8. mcp_vector_search/cli/commands/search.py +241 -87
  9. mcp_vector_search/cli/commands/status.py +184 -58
  10. mcp_vector_search/cli/commands/watch.py +34 -35
  11. mcp_vector_search/cli/didyoumean.py +184 -0
  12. mcp_vector_search/cli/export.py +320 -0
  13. mcp_vector_search/cli/history.py +292 -0
  14. mcp_vector_search/cli/interactive.py +342 -0
  15. mcp_vector_search/cli/main.py +175 -27
  16. mcp_vector_search/cli/output.py +63 -45
  17. mcp_vector_search/config/defaults.py +50 -36
  18. mcp_vector_search/config/settings.py +49 -35
  19. mcp_vector_search/core/auto_indexer.py +298 -0
  20. mcp_vector_search/core/connection_pool.py +322 -0
  21. mcp_vector_search/core/database.py +335 -25
  22. mcp_vector_search/core/embeddings.py +73 -29
  23. mcp_vector_search/core/exceptions.py +19 -2
  24. mcp_vector_search/core/factory.py +310 -0
  25. mcp_vector_search/core/git_hooks.py +345 -0
  26. mcp_vector_search/core/indexer.py +237 -73
  27. mcp_vector_search/core/models.py +21 -19
  28. mcp_vector_search/core/project.py +73 -58
  29. mcp_vector_search/core/scheduler.py +330 -0
  30. mcp_vector_search/core/search.py +574 -86
  31. mcp_vector_search/core/watcher.py +48 -46
  32. mcp_vector_search/mcp/__init__.py +4 -0
  33. mcp_vector_search/mcp/__main__.py +25 -0
  34. mcp_vector_search/mcp/server.py +701 -0
  35. mcp_vector_search/parsers/base.py +30 -31
  36. mcp_vector_search/parsers/javascript.py +74 -48
  37. mcp_vector_search/parsers/python.py +57 -49
  38. mcp_vector_search/parsers/registry.py +47 -32
  39. mcp_vector_search/parsers/text.py +179 -0
  40. mcp_vector_search/utils/__init__.py +40 -0
  41. mcp_vector_search/utils/gitignore.py +229 -0
  42. mcp_vector_search/utils/timing.py +334 -0
  43. mcp_vector_search/utils/version.py +47 -0
  44. {mcp_vector_search-0.0.3.dist-info → mcp_vector_search-0.4.12.dist-info}/METADATA +173 -7
  45. mcp_vector_search-0.4.12.dist-info/RECORD +54 -0
  46. mcp_vector_search-0.0.3.dist-info/RECORD +0 -35
  47. {mcp_vector_search-0.0.3.dist-info → mcp_vector_search-0.4.12.dist-info}/WHEEL +0 -0
  48. {mcp_vector_search-0.0.3.dist-info → mcp_vector_search-0.4.12.dist-info}/entry_points.txt +0 -0
  49. {mcp_vector_search-0.0.3.dist-info → mcp_vector_search-0.4.12.dist-info}/licenses/LICENSE +0 -0
@@ -1,7 +1,6 @@
1
1
  """Init command for MCP Vector Search CLI."""
2
2
 
3
3
  from pathlib import Path
4
- from typing import List, Optional
5
4
 
6
5
  import typer
7
6
  from loguru import logger
@@ -16,16 +15,16 @@ from ..output import (
16
15
  print_info,
17
16
  print_project_info,
18
17
  print_success,
18
+ print_warning,
19
19
  )
20
20
 
21
21
  # Create init subcommand app
22
22
  init_app = typer.Typer(help="Initialize project for semantic search")
23
23
 
24
24
 
25
- @init_app.command()
26
25
  def main(
27
26
  ctx: typer.Context,
28
- config_file: Optional[Path] = typer.Option(
27
+ config_file: Path | None = typer.Option(
29
28
  None,
30
29
  "--config",
31
30
  "-c",
@@ -35,11 +34,11 @@ def main(
35
34
  dir_okay=False,
36
35
  readable=True,
37
36
  ),
38
- extensions: Optional[str] = typer.Option(
37
+ extensions: str | None = typer.Option(
39
38
  None,
40
39
  "--extensions",
41
40
  "-e",
42
- help="Comma-separated list of file extensions to index (e.g., '.py,.js,.ts')",
41
+ help="Comma-separated list of file extensions to index (e.g., '.py,.js,.ts,.txt,.md')",
43
42
  ),
44
43
  embedding_model: str = typer.Option(
45
44
  DEFAULT_EMBEDDING_MODELS["code"],
@@ -48,7 +47,7 @@ def main(
48
47
  help="Embedding model to use for semantic search",
49
48
  ),
50
49
  similarity_threshold: float = typer.Option(
51
- 0.75,
50
+ 0.5,
52
51
  "--similarity-threshold",
53
52
  "-s",
54
53
  help="Similarity threshold for search results (0.0 to 1.0)",
@@ -62,25 +61,40 @@ def main(
62
61
  help="Force re-initialization if project is already initialized",
63
62
  ),
64
63
  auto_index: bool = typer.Option(
65
- False,
66
- "--auto-index",
64
+ True,
65
+ "--auto-index/--no-auto-index",
67
66
  help="Automatically start indexing after initialization",
68
67
  ),
68
+ mcp: bool = typer.Option(
69
+ True,
70
+ "--mcp/--no-mcp",
71
+ help="Install Claude Code MCP integration after initialization",
72
+ ),
73
+ auto_indexing: bool = typer.Option(
74
+ True,
75
+ "--auto-indexing/--no-auto-indexing",
76
+ help="Set up automatic indexing for file changes",
77
+ ),
69
78
  ) -> None:
70
- """Initialize a project for semantic code search.
71
-
72
- This command sets up the necessary configuration and directory structure
73
- for MCP Vector Search in your project. It will:
74
-
75
- - Create a .mcp-vector-search directory for storing the index and configuration
76
- - Detect programming languages in your project
77
- - Set up default configuration based on your project structure
78
- - Optionally start indexing your codebase
79
-
79
+ """🚀 Complete project setup for semantic code search with MCP integration.
80
+
81
+ This command provides a comprehensive one-step installation that:
82
+
83
+ ✅ **Installs** mcp-vector-search in the current project
84
+ **Auto-detects** your project's programming languages and file types
85
+ **Initializes** vector database and configuration
86
+ **Indexes** your codebase automatically
87
+ **Sets up** auto-indexing for file changes
88
+ ✅ **Installs** Claude Code MCP integration with project-scoped .mcp.json
89
+ ✅ **Creates** shareable team configuration
90
+
91
+ Perfect for getting started quickly in any project!
92
+
80
93
  Examples:
81
- mcp-vector-search init
82
- mcp-vector-search init --extensions .py,.js,.ts --auto-index
83
- mcp-vector-search init --embedding-model microsoft/unixcoder-base --force
94
+ mcp-vector-search init # Full setup with smart defaults
95
+ mcp-vector-search init --no-mcp # Setup without MCP integration
96
+ mcp-vector-search init --extensions .py,.js,.ts,.txt # Custom file types
97
+ mcp-vector-search init --force # Re-initialize existing project
84
98
  """
85
99
  try:
86
100
  # Get project root from context or auto-detect
@@ -90,40 +104,103 @@ def main(
90
104
 
91
105
  print_info(f"Initializing project at: {project_root}")
92
106
 
107
+ # Step 1: Install mcp-vector-search in the current project
108
+ console.print("\n[bold blue]📦 Installing mcp-vector-search...[/bold blue]")
109
+
110
+ # Find the development source directory
111
+ import mcp_vector_search
112
+ dev_source_path = Path(mcp_vector_search.__file__).parent.parent.parent
113
+
114
+ try:
115
+ import subprocess
116
+ import sys
117
+ import shutil
118
+
119
+ # Try different installation methods based on available tools
120
+ install_success = False
121
+
122
+ # Method 1: Try pip directly
123
+ if shutil.which("pip"):
124
+ install_cmd = ["pip", "install", "-e", str(dev_source_path)]
125
+ try:
126
+ result = subprocess.run(install_cmd, capture_output=True, text=True, timeout=120)
127
+ if result.returncode == 0:
128
+ install_success = True
129
+ except:
130
+ pass
131
+
132
+ # Method 2: Try python -m pip
133
+ if not install_success:
134
+ install_cmd = [sys.executable, "-m", "pip", "install", "-e", str(dev_source_path)]
135
+ try:
136
+ result = subprocess.run(install_cmd, capture_output=True, text=True, timeout=120)
137
+ if result.returncode == 0:
138
+ install_success = True
139
+ except:
140
+ pass
141
+
142
+ # Method 3: Try uv if available
143
+ if not install_success and shutil.which("uv"):
144
+ install_cmd = ["uv", "add", "--editable", str(dev_source_path)]
145
+ try:
146
+ result = subprocess.run(install_cmd, capture_output=True, text=True, timeout=120)
147
+ if result.returncode == 0:
148
+ install_success = True
149
+ except:
150
+ pass
151
+
152
+ if install_success:
153
+ print_success("✅ mcp-vector-search installed successfully!")
154
+ else:
155
+ print_warning("⚠️ Could not install automatically - you may need to install manually")
156
+ print_info(f"💡 Try: pip install -e {dev_source_path}")
157
+ print_info("Continuing with setup...")
158
+
159
+ except Exception as e:
160
+ print_warning(f"⚠️ Installation encountered an issue: {e}")
161
+ print_info("Continuing with setup...")
162
+
93
163
  # Create project manager
94
164
  project_manager = ProjectManager(project_root)
95
165
 
96
166
  # Check if already initialized
97
167
  if project_manager.is_initialized() and not force:
98
- print_error("Project is already initialized")
168
+ print_success("Project is already initialized and ready to use!")
169
+ print_info("Your project has vector search capabilities enabled.")
99
170
  print_info("Use --force to re-initialize or run 'mcp-vector-search status' to see current configuration")
100
- raise typer.Exit(1)
171
+ return # Exit gracefully without raising an exception
101
172
 
102
173
  # Parse file extensions
103
174
  file_extensions = None
104
175
  if extensions:
105
176
  file_extensions = [ext.strip() for ext in extensions.split(",")]
106
177
  # Ensure extensions start with dot
107
- file_extensions = [ext if ext.startswith(".") else f".{ext}" for ext in file_extensions]
178
+ file_extensions = [
179
+ ext if ext.startswith(".") else f".{ext}" for ext in file_extensions
180
+ ]
108
181
  else:
109
182
  file_extensions = DEFAULT_FILE_EXTENSIONS
110
183
 
111
184
  # Show what will be initialized
112
- console.print("\n[bold blue]Initialization Settings:[/bold blue]")
113
- console.print(f" Project Root: {project_root}")
114
- console.print(f" File Extensions: {', '.join(file_extensions)}")
115
- console.print(f" Embedding Model: {embedding_model}")
116
- console.print(f" Similarity Threshold: {similarity_threshold}")
185
+ console.print("\n[bold blue]🚀 MCP Vector Search Setup:[/bold blue]")
186
+ console.print(f" 📁 Project Root: {project_root}")
187
+ console.print(f" 📄 File Extensions: {', '.join(file_extensions)}")
188
+ console.print(f" 🧠 Embedding Model: {embedding_model}")
189
+ console.print(f" 🎯 Similarity Threshold: {similarity_threshold}")
190
+ console.print(f" 🔍 Auto-indexing: {'✅ Enabled' if auto_index else '❌ Disabled'}")
191
+ console.print(f" ⚡ File watching: {'✅ Enabled' if auto_indexing else '❌ Disabled'}")
192
+ console.print(f" 🔗 Claude Code MCP: {'✅ Enabled' if mcp else '❌ Disabled'}")
117
193
 
118
- # Confirm initialization
119
- if not force and not confirm_action("\nProceed with initialization?", default=True):
120
- print_info("Initialization cancelled")
121
- raise typer.Exit(0)
194
+ # Confirm initialization (only if not using defaults)
195
+ if not force and (not auto_index or not mcp or not auto_indexing):
196
+ if not confirm_action("\nProceed with setup?", default=True):
197
+ print_info("Setup cancelled")
198
+ raise typer.Exit(0)
122
199
 
123
200
  # Initialize project
124
201
  console.print("\n[bold]Initializing project...[/bold]")
125
-
126
- config = project_manager.initialize(
202
+
203
+ project_manager.initialize(
127
204
  file_extensions=file_extensions,
128
205
  embedding_model=embedding_model,
129
206
  similarity_threshold=similarity_threshold,
@@ -137,32 +214,110 @@ def main(
137
214
  project_info = project_manager.get_project_info()
138
215
  print_project_info(project_info)
139
216
 
140
- # Offer to start indexing
141
- if auto_index or confirm_action("\nStart indexing your codebase now?", default=True):
142
- console.print("\n[bold]Starting indexing...[/bold]")
217
+ # Start indexing if requested
218
+ if auto_index:
219
+ console.print("\n[bold]🔍 Indexing your codebase...[/bold]")
143
220
 
144
221
  # Import and run indexing (avoid circular imports)
145
222
  import asyncio
223
+
146
224
  from .index import run_indexing
147
225
 
148
226
  try:
149
- asyncio.run(run_indexing(
150
- project_root=project_root,
151
- force_reindex=False,
152
- show_progress=True,
153
- ))
154
- print_success("Indexing completed!")
227
+ asyncio.run(
228
+ run_indexing(
229
+ project_root=project_root,
230
+ force_reindex=False,
231
+ show_progress=True,
232
+ )
233
+ )
234
+ print_success("✅ Indexing completed!")
155
235
  except Exception as e:
156
- print_error(f"Indexing failed: {e}")
157
- print_info("You can run 'mcp-vector-search index' later to index your codebase")
236
+ print_error(f"Indexing failed: {e}")
237
+ print_info(
238
+ "You can run 'mcp-vector-search index' later to index your codebase"
239
+ )
158
240
  else:
159
- print_info("Run 'mcp-vector-search index' to index your codebase")
241
+ print_info("💡 Run 'mcp-vector-search index' to index your codebase when ready")
242
+
243
+ # Install MCP integration if requested
244
+ if mcp:
245
+ console.print("\n[bold]🔗 Installing Claude Code MCP integration...[/bold]")
246
+
247
+ try:
248
+ # Import MCP functionality
249
+ from .mcp import check_claude_code_available, get_claude_command, get_mcp_server_command
250
+ import subprocess
251
+
252
+ # Check if Claude Code is available
253
+ if not check_claude_code_available():
254
+ print_warning("Claude Code not found. Skipping MCP integration.")
255
+ print_info("Install Claude Code from: https://claude.ai/download")
256
+ else:
257
+ claude_cmd = get_claude_command()
258
+ server_command = get_mcp_server_command(project_root)
259
+
260
+ # Install MCP server with project scope for team sharing
261
+ cmd_args = [
262
+ claude_cmd, "mcp", "add",
263
+ "--scope=project", # Use project scope for team sharing
264
+ "mcp-vector-search",
265
+ "--",
266
+ ] + server_command.split()
267
+
268
+ result = subprocess.run(
269
+ cmd_args,
270
+ capture_output=True,
271
+ text=True,
272
+ timeout=30
273
+ )
160
274
 
161
- # Show next steps
162
- console.print("\n[bold green]Next Steps:[/bold green]")
163
- console.print(" 1. Run [code]mcp-vector-search index[/code] to index your codebase (if not done)")
164
- console.print(" 2. Run [code]mcp-vector-search search 'your query'[/code] to search your code")
165
- console.print(" 3. Run [code]mcp-vector-search status[/code] to check indexing status")
275
+ if result.returncode == 0:
276
+ print_success(" Claude Code MCP integration installed!")
277
+ print_info("📁 Created .mcp.json for team sharing - commit this file to your repo")
278
+
279
+ # Also set up auto-indexing if requested
280
+ if auto_indexing:
281
+ try:
282
+ import asyncio
283
+ from .auto_index import _setup_auto_indexing
284
+ asyncio.run(_setup_auto_indexing(project_root, "search", 60, 5))
285
+ print_success("⚡ Auto-indexing configured for file changes")
286
+ except Exception as e:
287
+ print_warning(f"Auto-indexing setup failed: {e}")
288
+ print_info("You can set it up later with: mcp-vector-search auto-index setup")
289
+ else:
290
+ print_warning(f"MCP integration failed: {result.stderr}")
291
+ print_info("You can install it later with: mcp-vector-search mcp install")
292
+
293
+ except Exception as e:
294
+ print_warning(f"MCP integration failed: {e}")
295
+ print_info("You can install it later with: mcp-vector-search mcp install")
296
+
297
+ # Show completion status and next steps
298
+ console.print("\n[bold green]🎉 Setup Complete![/bold green]")
299
+
300
+ if auto_index and mcp:
301
+ console.print("\n[bold blue]✨ Your project is fully configured:[/bold blue]")
302
+ console.print(" ✅ Vector database initialized")
303
+ console.print(" ✅ Codebase indexed and searchable")
304
+ console.print(" ✅ Auto-indexing enabled for file changes")
305
+ console.print(" ✅ Claude Code MCP integration installed")
306
+ console.print(" ✅ Team configuration saved in .mcp.json")
307
+
308
+ console.print("\n[bold green]🚀 Ready to use:[/bold green]")
309
+ console.print(" • Search your code: [code]mcp-vector-search search 'your query'[/code]")
310
+ console.print(" • Use in Claude Code with MCP tools")
311
+ console.print(" • Check status: [code]mcp-vector-search status[/code]")
312
+ console.print("\n[dim]💡 Tip: Commit .mcp.json to share MCP integration with your team![/dim]")
313
+ else:
314
+ console.print("\n[bold blue]Next steps:[/bold blue]")
315
+ if not auto_index:
316
+ console.print(" 1. Run [code]mcp-vector-search index[/code] to index your codebase")
317
+ console.print(" 2. Run [code]mcp-vector-search search 'your query'[/code] to search your code")
318
+ console.print(" 3. Run [code]mcp-vector-search status[/code] to check status")
319
+ if not mcp:
320
+ console.print(" 4. Run [code]mcp-vector-search mcp install[/code] for Claude Code integration")
166
321
 
167
322
  except ProjectInitializationError as e:
168
323
  print_error(f"Initialization failed: {e}")
@@ -179,10 +334,10 @@ def check_initialization(ctx: typer.Context) -> None:
179
334
  try:
180
335
  project_root = ctx.obj.get("project_root") or Path.cwd()
181
336
  project_manager = ProjectManager(project_root)
182
-
337
+
183
338
  if project_manager.is_initialized():
184
339
  print_success(f"Project is initialized at {project_root}")
185
-
340
+
186
341
  # Show project info
187
342
  project_info = project_manager.get_project_info()
188
343
  print_project_info(project_info)
@@ -190,22 +345,280 @@ def check_initialization(ctx: typer.Context) -> None:
190
345
  print_error(f"Project is not initialized at {project_root}")
191
346
  print_info("Run 'mcp-vector-search init' to initialize the project")
192
347
  raise typer.Exit(1)
193
-
348
+
194
349
  except Exception as e:
195
350
  logger.error(f"Error checking initialization: {e}")
196
351
  print_error(f"Error: {e}")
197
352
  raise typer.Exit(1)
198
353
 
199
354
 
355
+ async def run_init_setup(
356
+ project_root: Path,
357
+ file_extensions: list[str] | None = None,
358
+ embedding_model: str = "sentence-transformers/all-MiniLM-L6-v2",
359
+ similarity_threshold: float = 0.5,
360
+ mcp: bool = True,
361
+ auto_index: bool = True,
362
+ auto_indexing: bool = True,
363
+ force: bool = False,
364
+ ) -> None:
365
+ """Reusable initialization setup function.
366
+
367
+ This function contains the core initialization logic that can be used
368
+ by both the init command and the install command.
369
+ """
370
+ from ...config.defaults import DEFAULT_FILE_EXTENSIONS
371
+ from ...core.project import ProjectManager
372
+ from ..output import print_project_info
373
+
374
+ # Create project manager
375
+ project_manager = ProjectManager(project_root)
376
+
377
+ # Parse file extensions
378
+ if not file_extensions:
379
+ file_extensions = DEFAULT_FILE_EXTENSIONS
380
+
381
+ # Initialize project
382
+ project_manager.initialize(
383
+ file_extensions=file_extensions,
384
+ embedding_model=embedding_model,
385
+ similarity_threshold=similarity_threshold,
386
+ force=force,
387
+ )
388
+
389
+ print_success("Project initialized successfully!")
390
+
391
+ # Show project information
392
+ project_info = project_manager.get_project_info()
393
+ print_project_info(project_info)
394
+
395
+ # Start indexing if requested
396
+ if auto_index:
397
+ console.print("\n[bold]🔍 Indexing your codebase...[/bold]")
398
+
399
+ # Import and run indexing (avoid circular imports)
400
+ from .index import run_indexing
401
+
402
+ try:
403
+ await run_indexing(
404
+ project_root=project_root,
405
+ force_reindex=False,
406
+ show_progress=True,
407
+ )
408
+ print_success("✅ Indexing completed!")
409
+ except Exception as e:
410
+ print_error(f"❌ Indexing failed: {e}")
411
+ print_info(
412
+ "You can run 'mcp-vector-search index' later to index your codebase"
413
+ )
414
+ else:
415
+ print_info("💡 Run 'mcp-vector-search index' to index your codebase when ready")
416
+
417
+ # Install MCP integration if requested
418
+ if mcp:
419
+ console.print("\n[bold]🔗 Installing Claude Code MCP integration...[/bold]")
420
+
421
+ try:
422
+ # Import MCP functionality
423
+ from .mcp import check_claude_code_available, get_claude_command, get_mcp_server_command
424
+ import subprocess
425
+
426
+ # Check if Claude Code is available
427
+ if not check_claude_code_available():
428
+ print_warning("Claude Code not found. Skipping MCP integration.")
429
+ print_info("Install Claude Code from: https://claude.ai/download")
430
+ else:
431
+ claude_cmd = get_claude_command()
432
+ server_command = get_mcp_server_command(project_root)
433
+
434
+ # Install MCP server with project scope for team sharing
435
+ cmd_args = [
436
+ claude_cmd, "mcp", "add",
437
+ "--scope=project", # Use project scope for team sharing
438
+ "mcp-vector-search",
439
+ "--",
440
+ ] + server_command.split()
441
+
442
+ result = subprocess.run(
443
+ cmd_args,
444
+ capture_output=True,
445
+ text=True,
446
+ timeout=30
447
+ )
448
+
449
+ if result.returncode == 0:
450
+ print_success("✅ Claude Code MCP integration installed!")
451
+ print_info("📁 Created .mcp.json for team sharing - commit this file to your repo")
452
+
453
+ # Also set up auto-indexing if requested
454
+ if auto_indexing:
455
+ try:
456
+ from .auto_index import _setup_auto_indexing
457
+ await _setup_auto_indexing(project_root, "search", 60, 5)
458
+ print_success("⚡ Auto-indexing configured for file changes")
459
+ except Exception as e:
460
+ print_warning(f"Auto-indexing setup failed: {e}")
461
+ print_info("You can set it up later with: mcp-vector-search auto-index setup")
462
+ else:
463
+ print_warning(f"MCP integration failed: {result.stderr}")
464
+ print_info("You can install it later with: mcp-vector-search mcp install")
465
+
466
+ except Exception as e:
467
+ print_warning(f"MCP integration failed: {e}")
468
+ print_info("You can install it later with: mcp-vector-search mcp install")
469
+
470
+
471
+ @init_app.command("mcp")
472
+ def init_mcp_integration(
473
+ ctx: typer.Context,
474
+ server_name: str = typer.Option(
475
+ "mcp-vector-search",
476
+ "--name",
477
+ help="Name for the MCP server"
478
+ ),
479
+ force: bool = typer.Option(
480
+ False,
481
+ "--force",
482
+ "-f",
483
+ help="Force installation even if server already exists"
484
+ )
485
+ ) -> None:
486
+ """Install/fix Claude Code MCP integration for the current project.
487
+
488
+ This command sets up MCP integration by:
489
+ ✅ Creating project-level .claude.json configuration
490
+ ✅ Testing server startup and connectivity
491
+ ✅ Providing troubleshooting information if needed
492
+
493
+ Perfect for fixing MCP integration issues or setting up team-shared configuration.
494
+ """
495
+ try:
496
+ # Import MCP functions
497
+ from .mcp import (
498
+ check_claude_code_available,
499
+ create_project_claude_config,
500
+ get_mcp_server_command,
501
+ )
502
+ import subprocess
503
+ import json
504
+
505
+ # Get project root
506
+ project_root = ctx.obj.get("project_root") or Path.cwd()
507
+
508
+ # Check if project is initialized
509
+ project_manager = ProjectManager(project_root)
510
+ if not project_manager.is_initialized():
511
+ print_error("Project not initialized. Run 'mcp-vector-search init' first.")
512
+ raise typer.Exit(1)
513
+
514
+ print_info(f"Setting up MCP integration for project: {project_root}")
515
+
516
+ # Check if project-level .claude.json already has the server
517
+ claude_json_path = project_root / ".claude.json"
518
+ if claude_json_path.exists() and not force:
519
+ with open(claude_json_path, 'r') as f:
520
+ config = json.load(f)
521
+ if config.get("mcpServers", {}).get(server_name):
522
+ print_warning(f"MCP server '{server_name}' already exists in project config.")
523
+ print_info("Use --force to overwrite or try a different --name")
524
+
525
+ # Still test the existing configuration
526
+ print_info("Testing existing configuration...")
527
+ _test_mcp_server(project_root)
528
+ return
529
+
530
+ # Create project-level configuration
531
+ create_project_claude_config(project_root, server_name)
532
+
533
+ print_success(f"✅ MCP server '{server_name}' installed in project configuration")
534
+ print_info("📁 Created .claude.json for team sharing - commit this file to your repo")
535
+
536
+ # Test the server
537
+ print_info("Testing server startup...")
538
+ _test_mcp_server(project_root)
539
+
540
+ # Check if Claude Code is available and provide guidance
541
+ if not check_claude_code_available():
542
+ print_warning("⚠️ Claude Code not detected on this system")
543
+ print_info("📥 Install Claude Code from: https://claude.ai/download")
544
+ print_info("🔄 After installation, restart Claude Code to detect the MCP server")
545
+ else:
546
+ print_success("✅ Claude Code detected - server should be available automatically")
547
+ print_info("🔄 If Claude Code is running, restart it to detect the new server")
548
+
549
+ print_info("\n📋 Next steps:")
550
+ print_info(" 1. Restart Claude Code if it's currently running")
551
+ print_info(" 2. Open this project in Claude Code")
552
+ print_info(" 3. The MCP server should appear automatically in the tools list")
553
+ print_info(" 4. Test with: 'Search for functions that handle user authentication'")
554
+
555
+ except Exception as e:
556
+ logger.error(f"MCP integration setup failed: {e}")
557
+ print_error(f"MCP integration setup failed: {e}")
558
+ raise typer.Exit(1)
559
+
560
+
561
+ def _test_mcp_server(project_root: Path) -> None:
562
+ """Test MCP server startup and basic functionality."""
563
+ try:
564
+ from .mcp import get_mcp_server_command
565
+ import subprocess
566
+ import json
567
+
568
+ server_command = get_mcp_server_command(project_root)
569
+ test_process = subprocess.Popen(
570
+ server_command.split(),
571
+ stdin=subprocess.PIPE,
572
+ stdout=subprocess.PIPE,
573
+ stderr=subprocess.PIPE,
574
+ text=True
575
+ )
576
+
577
+ # Send a simple initialization request
578
+ init_request = {
579
+ "jsonrpc": "2.0",
580
+ "id": 1,
581
+ "method": "initialize",
582
+ "params": {
583
+ "protocolVersion": "2024-11-05",
584
+ "capabilities": {},
585
+ "clientInfo": {"name": "test", "version": "1.0.0"}
586
+ }
587
+ }
588
+
589
+ try:
590
+ stdout, stderr = test_process.communicate(
591
+ input=json.dumps(init_request) + "\n",
592
+ timeout=10
593
+ )
594
+
595
+ if test_process.returncode == 0:
596
+ print_success("✅ Server startup test passed")
597
+ else:
598
+ print_warning(f"⚠️ Server test failed with return code {test_process.returncode}")
599
+ if stderr:
600
+ print_info(f"Error output: {stderr}")
601
+
602
+ except subprocess.TimeoutExpired:
603
+ test_process.kill()
604
+ print_warning("⚠️ Server test timed out (this may be normal)")
605
+
606
+ except Exception as e:
607
+ print_warning(f"⚠️ Server test failed: {e}")
608
+ print_info("This may be normal - the server should still work with Claude Code")
609
+
610
+
200
611
  @init_app.command("models")
201
612
  def list_embedding_models() -> None:
202
613
  """List available embedding models."""
203
614
  console.print("[bold blue]Available Embedding Models:[/bold blue]\n")
204
-
615
+
205
616
  for category, model in DEFAULT_EMBEDDING_MODELS.items():
206
617
  console.print(f"[cyan]{category.title()}:[/cyan] {model}")
207
-
208
- console.print("\n[dim]You can also use any model from Hugging Face that's compatible with sentence-transformers[/dim]")
618
+
619
+ console.print(
620
+ "\n[dim]You can also use any model from Hugging Face that's compatible with sentence-transformers[/dim]"
621
+ )
209
622
 
210
623
 
211
624
  if __name__ == "__main__":