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