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