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