mcp-vector-search 0.12.6__py3-none-any.whl → 1.0.3__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.
- mcp_vector_search/__init__.py +2 -2
- mcp_vector_search/analysis/__init__.py +64 -0
- mcp_vector_search/analysis/collectors/__init__.py +39 -0
- mcp_vector_search/analysis/collectors/base.py +164 -0
- mcp_vector_search/analysis/collectors/complexity.py +743 -0
- mcp_vector_search/analysis/metrics.py +341 -0
- mcp_vector_search/analysis/reporters/__init__.py +5 -0
- mcp_vector_search/analysis/reporters/console.py +222 -0
- mcp_vector_search/cli/commands/analyze.py +408 -0
- mcp_vector_search/cli/commands/chat.py +1262 -0
- mcp_vector_search/cli/commands/index.py +21 -3
- mcp_vector_search/cli/commands/init.py +13 -0
- mcp_vector_search/cli/commands/install.py +597 -335
- mcp_vector_search/cli/commands/install_old.py +8 -4
- mcp_vector_search/cli/commands/mcp.py +78 -6
- mcp_vector_search/cli/commands/reset.py +68 -26
- mcp_vector_search/cli/commands/search.py +30 -7
- mcp_vector_search/cli/commands/setup.py +1133 -0
- mcp_vector_search/cli/commands/status.py +37 -2
- mcp_vector_search/cli/commands/uninstall.py +276 -357
- mcp_vector_search/cli/commands/visualize/__init__.py +39 -0
- mcp_vector_search/cli/commands/visualize/cli.py +276 -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 +714 -0
- mcp_vector_search/cli/commands/visualize/layout_engine.py +469 -0
- mcp_vector_search/cli/commands/visualize/server.py +311 -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 +180 -0
- mcp_vector_search/cli/commands/visualize/templates/scripts.py +2507 -0
- mcp_vector_search/cli/commands/visualize/templates/styles.py +1313 -0
- mcp_vector_search/cli/commands/visualize.py.original +2536 -0
- mcp_vector_search/cli/didyoumean.py +22 -2
- mcp_vector_search/cli/main.py +115 -159
- mcp_vector_search/cli/output.py +24 -8
- mcp_vector_search/config/__init__.py +4 -0
- mcp_vector_search/config/default_thresholds.yaml +52 -0
- mcp_vector_search/config/settings.py +12 -0
- mcp_vector_search/config/thresholds.py +185 -0
- mcp_vector_search/core/auto_indexer.py +3 -3
- mcp_vector_search/core/boilerplate.py +186 -0
- mcp_vector_search/core/config_utils.py +394 -0
- mcp_vector_search/core/database.py +369 -94
- mcp_vector_search/core/exceptions.py +11 -0
- mcp_vector_search/core/git_hooks.py +4 -4
- mcp_vector_search/core/indexer.py +221 -4
- mcp_vector_search/core/llm_client.py +751 -0
- mcp_vector_search/core/models.py +3 -0
- mcp_vector_search/core/project.py +17 -0
- mcp_vector_search/core/scheduler.py +11 -11
- mcp_vector_search/core/search.py +179 -29
- mcp_vector_search/mcp/server.py +24 -5
- mcp_vector_search/utils/__init__.py +2 -0
- mcp_vector_search/utils/gitignore_updater.py +212 -0
- mcp_vector_search/utils/monorepo.py +66 -4
- mcp_vector_search/utils/timing.py +10 -6
- {mcp_vector_search-0.12.6.dist-info → mcp_vector_search-1.0.3.dist-info}/METADATA +182 -52
- mcp_vector_search-1.0.3.dist-info/RECORD +97 -0
- {mcp_vector_search-0.12.6.dist-info → mcp_vector_search-1.0.3.dist-info}/WHEEL +1 -1
- {mcp_vector_search-0.12.6.dist-info → mcp_vector_search-1.0.3.dist-info}/entry_points.txt +1 -0
- mcp_vector_search/cli/commands/visualize.py +0 -1467
- mcp_vector_search-0.12.6.dist-info/RECORD +0 -68
- {mcp_vector_search-0.12.6.dist-info → mcp_vector_search-1.0.3.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Modular visualization package for code graphs.
|
|
2
|
+
|
|
3
|
+
This package provides D3.js-based interactive visualization of code relationships,
|
|
4
|
+
organized into modular components for maintainability.
|
|
5
|
+
|
|
6
|
+
Structure:
|
|
7
|
+
- graph_builder.py: Graph data construction logic
|
|
8
|
+
- server.py: HTTP server for serving visualization
|
|
9
|
+
- templates/: HTML, CSS, and JavaScript generation
|
|
10
|
+
- exporters/: Export functionality (JSON, HTML)
|
|
11
|
+
- cli.py: Typer CLI commands (imported for backwards compatibility)
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from .cli import app
|
|
15
|
+
from .exporters import export_to_html, export_to_json
|
|
16
|
+
from .graph_builder import (
|
|
17
|
+
build_graph_data,
|
|
18
|
+
get_subproject_color,
|
|
19
|
+
parse_project_dependencies,
|
|
20
|
+
)
|
|
21
|
+
from .server import find_free_port, start_visualization_server
|
|
22
|
+
from .templates import generate_html_template
|
|
23
|
+
|
|
24
|
+
__all__ = [
|
|
25
|
+
# CLI
|
|
26
|
+
"app",
|
|
27
|
+
# Graph building
|
|
28
|
+
"build_graph_data",
|
|
29
|
+
"get_subproject_color",
|
|
30
|
+
"parse_project_dependencies",
|
|
31
|
+
# Server
|
|
32
|
+
"find_free_port",
|
|
33
|
+
"start_visualization_server",
|
|
34
|
+
# Templates
|
|
35
|
+
"generate_html_template",
|
|
36
|
+
# Exporters
|
|
37
|
+
"export_to_html",
|
|
38
|
+
"export_to_json",
|
|
39
|
+
]
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
"""Visualization commands for MCP Vector Search.
|
|
2
|
+
|
|
3
|
+
This module provides a backwards-compatible interface to the refactored
|
|
4
|
+
modular visualization components.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
import shutil
|
|
9
|
+
from fnmatch import fnmatch
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
import typer
|
|
13
|
+
from loguru import logger
|
|
14
|
+
from rich.console import Console
|
|
15
|
+
from rich.panel import Panel
|
|
16
|
+
|
|
17
|
+
from ....core.database import ChromaVectorDatabase
|
|
18
|
+
from ....core.embeddings import create_embedding_function
|
|
19
|
+
from ....core.project import ProjectManager
|
|
20
|
+
|
|
21
|
+
# Import from refactored modules (same directory)
|
|
22
|
+
from .exporters import export_to_html, export_to_json
|
|
23
|
+
from .graph_builder import build_graph_data
|
|
24
|
+
from .server import find_free_port, start_visualization_server
|
|
25
|
+
|
|
26
|
+
app = typer.Typer(
|
|
27
|
+
help="Visualize code chunk relationships",
|
|
28
|
+
)
|
|
29
|
+
console = Console()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@app.callback(invoke_without_command=True)
|
|
33
|
+
def visualize_callback(ctx: typer.Context) -> None:
|
|
34
|
+
"""Visualize code chunk relationships.
|
|
35
|
+
|
|
36
|
+
When called without a subcommand, automatically starts the visualization server.
|
|
37
|
+
"""
|
|
38
|
+
# If no subcommand was invoked, run serve with defaults
|
|
39
|
+
if ctx.invoked_subcommand is None:
|
|
40
|
+
# Call serve directly with default parameters
|
|
41
|
+
serve(port=8080, graph_file=Path("chunk-graph.json"), code_only=False)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@app.command()
|
|
45
|
+
def export(
|
|
46
|
+
output: Path = typer.Option(
|
|
47
|
+
Path("chunk-graph.json"),
|
|
48
|
+
"--output",
|
|
49
|
+
"-o",
|
|
50
|
+
help="Output file for chunk relationship data",
|
|
51
|
+
),
|
|
52
|
+
file_path: str | None = typer.Option(
|
|
53
|
+
None,
|
|
54
|
+
"--file",
|
|
55
|
+
"-f",
|
|
56
|
+
help="Export only chunks from specific file (supports wildcards)",
|
|
57
|
+
),
|
|
58
|
+
code_only: bool = typer.Option(
|
|
59
|
+
False,
|
|
60
|
+
"--code-only",
|
|
61
|
+
help="Exclude documentation chunks (text, comment, docstring)",
|
|
62
|
+
),
|
|
63
|
+
) -> None:
|
|
64
|
+
"""Export chunk relationships as JSON for D3.js visualization.
|
|
65
|
+
|
|
66
|
+
Examples:
|
|
67
|
+
# Export all chunks
|
|
68
|
+
mcp-vector-search visualize export
|
|
69
|
+
|
|
70
|
+
# Export from specific file
|
|
71
|
+
mcp-vector-search visualize export --file src/main.py
|
|
72
|
+
|
|
73
|
+
# Custom output location
|
|
74
|
+
mcp-vector-search visualize export -o graph.json
|
|
75
|
+
|
|
76
|
+
# Export only code chunks (exclude documentation)
|
|
77
|
+
mcp-vector-search visualize export --code-only
|
|
78
|
+
"""
|
|
79
|
+
asyncio.run(_export_chunks(output, file_path, code_only))
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
async def _export_chunks(
|
|
83
|
+
output: Path, file_filter: str | None, code_only: bool = False
|
|
84
|
+
) -> None:
|
|
85
|
+
"""Export chunk relationship data.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
output: Path to output JSON file
|
|
89
|
+
file_filter: Optional file pattern to filter chunks
|
|
90
|
+
code_only: If True, exclude documentation chunks (text, comment, docstring)
|
|
91
|
+
"""
|
|
92
|
+
try:
|
|
93
|
+
# Load project
|
|
94
|
+
project_manager = ProjectManager(Path.cwd())
|
|
95
|
+
|
|
96
|
+
if not project_manager.is_initialized():
|
|
97
|
+
console.print(
|
|
98
|
+
"[red]Project not initialized. Run 'mcp-vector-search init' first.[/red]"
|
|
99
|
+
)
|
|
100
|
+
raise typer.Exit(1)
|
|
101
|
+
|
|
102
|
+
config = project_manager.load_config()
|
|
103
|
+
|
|
104
|
+
# Get database
|
|
105
|
+
embedding_function, _ = create_embedding_function(config.embedding_model)
|
|
106
|
+
database = ChromaVectorDatabase(
|
|
107
|
+
persist_directory=config.index_path,
|
|
108
|
+
embedding_function=embedding_function,
|
|
109
|
+
)
|
|
110
|
+
await database.initialize()
|
|
111
|
+
|
|
112
|
+
# Get all chunks with metadata
|
|
113
|
+
console.print("[cyan]Fetching chunks from database...[/cyan]")
|
|
114
|
+
chunks = await database.get_all_chunks()
|
|
115
|
+
|
|
116
|
+
if len(chunks) == 0:
|
|
117
|
+
console.print(
|
|
118
|
+
"[yellow]No chunks found in index. Run 'mcp-vector-search index' first.[/yellow]"
|
|
119
|
+
)
|
|
120
|
+
raise typer.Exit(1)
|
|
121
|
+
|
|
122
|
+
console.print(f"[green]✓[/green] Retrieved {len(chunks)} chunks")
|
|
123
|
+
|
|
124
|
+
# Apply file filter if specified
|
|
125
|
+
if file_filter:
|
|
126
|
+
chunks = [c for c in chunks if fnmatch(str(c.file_path), file_filter)]
|
|
127
|
+
console.print(
|
|
128
|
+
f"[cyan]Filtered to {len(chunks)} chunks matching '{file_filter}'[/cyan]"
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
# Apply code-only filter if requested
|
|
132
|
+
if code_only:
|
|
133
|
+
original_count = len(chunks)
|
|
134
|
+
chunks = [
|
|
135
|
+
c
|
|
136
|
+
for c in chunks
|
|
137
|
+
if c.chunk_type not in ["text", "comment", "docstring"]
|
|
138
|
+
]
|
|
139
|
+
filtered_count = len(chunks)
|
|
140
|
+
console.print(
|
|
141
|
+
f"[dim]Filtered out {original_count - filtered_count} documentation chunks "
|
|
142
|
+
f"({original_count} → {filtered_count} chunks)[/dim]"
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
# Build graph data using refactored module
|
|
146
|
+
graph_data = await build_graph_data(
|
|
147
|
+
chunks=chunks,
|
|
148
|
+
database=database,
|
|
149
|
+
project_manager=project_manager,
|
|
150
|
+
code_only=code_only,
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
# Export to JSON using refactored module
|
|
154
|
+
export_to_json(graph_data, output)
|
|
155
|
+
|
|
156
|
+
await database.close()
|
|
157
|
+
|
|
158
|
+
console.print()
|
|
159
|
+
# Count cycles from graph_data links
|
|
160
|
+
cycles = [link for link in graph_data["links"] if link.get("is_cycle", False)]
|
|
161
|
+
cycle_warning = f"[yellow]Cycles: {len(cycles)} ⚠️[/yellow]\n" if cycles else ""
|
|
162
|
+
|
|
163
|
+
# Count subprojects
|
|
164
|
+
subprojects_count = len(graph_data["metadata"].get("subprojects", []))
|
|
165
|
+
|
|
166
|
+
console.print(
|
|
167
|
+
Panel.fit(
|
|
168
|
+
f"[green]✓[/green] Exported graph data to [cyan]{output}[/cyan]\n\n"
|
|
169
|
+
f"Nodes: {len(graph_data['nodes'])}\n"
|
|
170
|
+
f"Links: {len(graph_data['links'])}\n"
|
|
171
|
+
f"{cycle_warning}"
|
|
172
|
+
f"{'Subprojects: ' + str(subprojects_count) if subprojects_count else ''}\n\n"
|
|
173
|
+
f"[dim]Next: Run 'mcp-vector-search visualize serve' to view[/dim]",
|
|
174
|
+
title="Export Complete",
|
|
175
|
+
border_style="green",
|
|
176
|
+
)
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
except Exception as e:
|
|
180
|
+
logger.error(f"Export failed: {e}")
|
|
181
|
+
console.print(f"[red]✗ Export failed: {e}[/red]")
|
|
182
|
+
raise typer.Exit(1)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
@app.command()
|
|
186
|
+
def serve(
|
|
187
|
+
port: int = typer.Option(
|
|
188
|
+
8080, "--port", "-p", help="Port for visualization server"
|
|
189
|
+
),
|
|
190
|
+
graph_file: Path = typer.Option(
|
|
191
|
+
Path("chunk-graph.json"),
|
|
192
|
+
"--graph",
|
|
193
|
+
"-g",
|
|
194
|
+
help="Graph JSON file to visualize",
|
|
195
|
+
),
|
|
196
|
+
code_only: bool = typer.Option(
|
|
197
|
+
False,
|
|
198
|
+
"--code-only",
|
|
199
|
+
help="Exclude documentation chunks (text, comment, docstring)",
|
|
200
|
+
),
|
|
201
|
+
) -> None:
|
|
202
|
+
"""Start local HTTP server for D3.js visualization.
|
|
203
|
+
|
|
204
|
+
Examples:
|
|
205
|
+
# Start server on default port 8080
|
|
206
|
+
mcp-vector-search visualize serve
|
|
207
|
+
|
|
208
|
+
# Custom port
|
|
209
|
+
mcp-vector-search visualize serve --port 3000
|
|
210
|
+
|
|
211
|
+
# Custom graph file
|
|
212
|
+
mcp-vector-search visualize serve --graph my-graph.json
|
|
213
|
+
|
|
214
|
+
# Serve with code-only filter
|
|
215
|
+
mcp-vector-search visualize serve --code-only
|
|
216
|
+
"""
|
|
217
|
+
# Use specified port or find free one
|
|
218
|
+
if port == 8080: # Default port, try to find free one
|
|
219
|
+
try:
|
|
220
|
+
port = find_free_port(8080, 8099)
|
|
221
|
+
except OSError as e:
|
|
222
|
+
console.print(f"[red]✗ {e}[/red]")
|
|
223
|
+
raise typer.Exit(1)
|
|
224
|
+
|
|
225
|
+
# Get visualization directory - use project-local storage
|
|
226
|
+
project_manager = ProjectManager(Path.cwd())
|
|
227
|
+
if not project_manager.is_initialized():
|
|
228
|
+
console.print(
|
|
229
|
+
"[red]Project not initialized. Run 'mcp-vector-search init' first.[/red]"
|
|
230
|
+
)
|
|
231
|
+
raise typer.Exit(1)
|
|
232
|
+
|
|
233
|
+
viz_dir = project_manager.project_root / ".mcp-vector-search" / "visualization"
|
|
234
|
+
|
|
235
|
+
if not viz_dir.exists():
|
|
236
|
+
console.print(
|
|
237
|
+
f"[yellow]Visualization directory not found. Creating at {viz_dir}...[/yellow]"
|
|
238
|
+
)
|
|
239
|
+
viz_dir.mkdir(parents=True, exist_ok=True)
|
|
240
|
+
|
|
241
|
+
# Always ensure index.html exists (regenerate if missing)
|
|
242
|
+
html_file = viz_dir / "index.html"
|
|
243
|
+
if not html_file.exists():
|
|
244
|
+
console.print("[yellow]Creating visualization HTML file...[/yellow]")
|
|
245
|
+
export_to_html(html_file)
|
|
246
|
+
|
|
247
|
+
# Check if we need to regenerate the graph file
|
|
248
|
+
needs_regeneration = not graph_file.exists() or code_only
|
|
249
|
+
|
|
250
|
+
if graph_file.exists() and not needs_regeneration:
|
|
251
|
+
# Use existing unfiltered file
|
|
252
|
+
dest = viz_dir / "chunk-graph.json"
|
|
253
|
+
shutil.copy(graph_file, dest)
|
|
254
|
+
console.print(f"[green]✓[/green] Copied graph data to {dest}")
|
|
255
|
+
else:
|
|
256
|
+
# Generate new file (with filter if requested)
|
|
257
|
+
if graph_file.exists() and code_only:
|
|
258
|
+
console.print(
|
|
259
|
+
"[yellow]Regenerating filtered graph data (--code-only)...[/yellow]"
|
|
260
|
+
)
|
|
261
|
+
elif not graph_file.exists():
|
|
262
|
+
console.print(
|
|
263
|
+
f"[yellow]Graph file {graph_file} not found. Generating it now...[/yellow]"
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
asyncio.run(_export_chunks(graph_file, None, code_only))
|
|
267
|
+
console.print()
|
|
268
|
+
|
|
269
|
+
# Copy the newly generated graph to visualization directory
|
|
270
|
+
if graph_file.exists():
|
|
271
|
+
dest = viz_dir / "chunk-graph.json"
|
|
272
|
+
shutil.copy(graph_file, dest)
|
|
273
|
+
console.print(f"[green]✓[/green] Copied graph data to {dest}")
|
|
274
|
+
|
|
275
|
+
# Start server using refactored module
|
|
276
|
+
start_visualization_server(port, viz_dir, auto_open=True)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""Export functionality for graph visualization data.
|
|
2
|
+
|
|
3
|
+
This package contains modules for exporting graph data to various formats.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from .html_exporter import export_to_html
|
|
7
|
+
from .json_exporter import export_to_json
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"export_to_html",
|
|
11
|
+
"export_to_json",
|
|
12
|
+
]
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""HTML export functionality for visualization.
|
|
2
|
+
|
|
3
|
+
This module handles creating standalone HTML files for the visualization.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from rich.console import Console
|
|
9
|
+
|
|
10
|
+
from ..templates.base import generate_html_template
|
|
11
|
+
|
|
12
|
+
console = Console()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def export_to_html(output_path: Path) -> None:
|
|
16
|
+
"""Export visualization to standalone HTML file.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
output_path: Path to output HTML file
|
|
20
|
+
"""
|
|
21
|
+
# Generate HTML template
|
|
22
|
+
html_content = generate_html_template()
|
|
23
|
+
|
|
24
|
+
# Ensure output directory exists
|
|
25
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
26
|
+
|
|
27
|
+
# Write to file
|
|
28
|
+
with open(output_path, "w") as f:
|
|
29
|
+
f.write(html_content)
|
|
30
|
+
|
|
31
|
+
console.print(
|
|
32
|
+
f"[green]✓[/green] Created visualization HTML at [cyan]{output_path}[/cyan]"
|
|
33
|
+
)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""JSON export functionality for graph data.
|
|
2
|
+
|
|
3
|
+
This module handles exporting graph data to JSON format.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import json
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from rich.console import Console
|
|
11
|
+
|
|
12
|
+
console = Console()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def export_to_json(graph_data: dict[str, Any], output_path: Path) -> None:
|
|
16
|
+
"""Export graph data to JSON file.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
graph_data: Graph data dictionary containing nodes, links, and metadata
|
|
20
|
+
output_path: Path to output JSON file
|
|
21
|
+
"""
|
|
22
|
+
# Ensure output directory exists
|
|
23
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
24
|
+
|
|
25
|
+
# Write to file
|
|
26
|
+
with open(output_path, "w") as f:
|
|
27
|
+
json.dump(graph_data, f, indent=2)
|
|
28
|
+
|
|
29
|
+
console.print(f"[green]✓[/green] Exported graph data to [cyan]{output_path}[/cyan]")
|