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
mcp_vector_search/__init__.py
CHANGED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""Structural code analysis module.
|
|
2
|
+
|
|
3
|
+
This module provides dataclasses and interfaces for collecting and storing
|
|
4
|
+
code quality metrics during semantic code analysis.
|
|
5
|
+
|
|
6
|
+
Key Components:
|
|
7
|
+
- ChunkMetrics: Metrics for individual functions/methods/classes
|
|
8
|
+
- FileMetrics: Aggregated metrics for entire files
|
|
9
|
+
- ProjectMetrics: Project-wide metric aggregates
|
|
10
|
+
- MetricCollector: Abstract base class for metric collection
|
|
11
|
+
- CollectorContext: Shared context during AST traversal
|
|
12
|
+
|
|
13
|
+
Example:
|
|
14
|
+
# Create chunk metrics
|
|
15
|
+
chunk = ChunkMetrics(
|
|
16
|
+
cognitive_complexity=8,
|
|
17
|
+
cyclomatic_complexity=5,
|
|
18
|
+
max_nesting_depth=3,
|
|
19
|
+
parameter_count=2,
|
|
20
|
+
lines_of_code=25
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
# Chunk automatically computes grade
|
|
24
|
+
assert chunk.complexity_grade == "B" # 6-10 range
|
|
25
|
+
|
|
26
|
+
# Store in ChromaDB-compatible format
|
|
27
|
+
metadata = chunk.to_metadata()
|
|
28
|
+
|
|
29
|
+
# Aggregate file metrics
|
|
30
|
+
file_metrics = FileMetrics(
|
|
31
|
+
file_path="src/module.py",
|
|
32
|
+
chunks=[chunk]
|
|
33
|
+
)
|
|
34
|
+
file_metrics.compute_aggregates()
|
|
35
|
+
|
|
36
|
+
# Project-wide analysis
|
|
37
|
+
project = ProjectMetrics(project_root="/path/to/project")
|
|
38
|
+
project.files["src/module.py"] = file_metrics
|
|
39
|
+
project.compute_aggregates()
|
|
40
|
+
hotspots = project.get_hotspots(limit=5)
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
from .collectors.base import CollectorContext, MetricCollector
|
|
44
|
+
from .collectors.complexity import (
|
|
45
|
+
CognitiveComplexityCollector,
|
|
46
|
+
CyclomaticComplexityCollector,
|
|
47
|
+
MethodCountCollector,
|
|
48
|
+
NestingDepthCollector,
|
|
49
|
+
ParameterCountCollector,
|
|
50
|
+
)
|
|
51
|
+
from .metrics import ChunkMetrics, FileMetrics, ProjectMetrics
|
|
52
|
+
|
|
53
|
+
__all__ = [
|
|
54
|
+
"ChunkMetrics",
|
|
55
|
+
"FileMetrics",
|
|
56
|
+
"ProjectMetrics",
|
|
57
|
+
"CollectorContext",
|
|
58
|
+
"MetricCollector",
|
|
59
|
+
"CognitiveComplexityCollector",
|
|
60
|
+
"CyclomaticComplexityCollector",
|
|
61
|
+
"NestingDepthCollector",
|
|
62
|
+
"ParameterCountCollector",
|
|
63
|
+
"MethodCountCollector",
|
|
64
|
+
]
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Metric collector implementations.
|
|
2
|
+
|
|
3
|
+
This module provides the base interface and context for implementing
|
|
4
|
+
metric collectors that traverse AST nodes during code analysis.
|
|
5
|
+
|
|
6
|
+
Example:
|
|
7
|
+
from mcp_vector_search.analysis.collectors import MetricCollector, CollectorContext
|
|
8
|
+
|
|
9
|
+
class MyCollector(MetricCollector):
|
|
10
|
+
@property
|
|
11
|
+
def name(self) -> str:
|
|
12
|
+
return "my_collector"
|
|
13
|
+
|
|
14
|
+
def collect_node(self, node, context, depth):
|
|
15
|
+
# Process node
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
def finalize_function(self, node, context):
|
|
19
|
+
return {"my_metric": 42}
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from .base import CollectorContext, MetricCollector
|
|
23
|
+
from .complexity import (
|
|
24
|
+
CognitiveComplexityCollector,
|
|
25
|
+
CyclomaticComplexityCollector,
|
|
26
|
+
MethodCountCollector,
|
|
27
|
+
NestingDepthCollector,
|
|
28
|
+
ParameterCountCollector,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
__all__ = [
|
|
32
|
+
"CollectorContext",
|
|
33
|
+
"MetricCollector",
|
|
34
|
+
"CognitiveComplexityCollector",
|
|
35
|
+
"CyclomaticComplexityCollector",
|
|
36
|
+
"NestingDepthCollector",
|
|
37
|
+
"ParameterCountCollector",
|
|
38
|
+
"MethodCountCollector",
|
|
39
|
+
]
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"""Base collector interface for metric collection during AST traversal."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from abc import ABC, abstractmethod
|
|
6
|
+
from dataclasses import dataclass, field
|
|
7
|
+
from typing import TYPE_CHECKING, Any
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from tree_sitter import Node
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass
|
|
14
|
+
class CollectorContext:
|
|
15
|
+
"""Shared context passed to all collectors during AST traversal.
|
|
16
|
+
|
|
17
|
+
Provides state management for tracking the current position and scope
|
|
18
|
+
during tree-sitter AST traversal. All collectors receive the same
|
|
19
|
+
context instance and can read/modify it during traversal.
|
|
20
|
+
|
|
21
|
+
Attributes:
|
|
22
|
+
file_path: Path to the file being analyzed
|
|
23
|
+
source_code: Raw source code as bytes (required by tree-sitter)
|
|
24
|
+
language: Programming language identifier (e.g., "python", "javascript")
|
|
25
|
+
current_function: Name of the function currently being analyzed
|
|
26
|
+
current_class: Name of the class currently being analyzed
|
|
27
|
+
nesting_stack: Stack tracking nested scopes (for depth calculation)
|
|
28
|
+
|
|
29
|
+
Example:
|
|
30
|
+
context = CollectorContext(
|
|
31
|
+
file_path="/path/to/file.py",
|
|
32
|
+
source_code=b"def foo(): pass",
|
|
33
|
+
language="python"
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
# During traversal
|
|
37
|
+
context.current_function = "foo"
|
|
38
|
+
context.nesting_stack.append("function")
|
|
39
|
+
depth = len(context.nesting_stack)
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
file_path: str
|
|
43
|
+
source_code: bytes
|
|
44
|
+
language: str
|
|
45
|
+
|
|
46
|
+
# Accumulator for current function being analyzed
|
|
47
|
+
current_function: str | None = None
|
|
48
|
+
current_class: str | None = None
|
|
49
|
+
|
|
50
|
+
# Stack for tracking nesting
|
|
51
|
+
nesting_stack: list[str] = field(default_factory=list)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class MetricCollector(ABC):
|
|
55
|
+
"""Abstract base class for metric collectors.
|
|
56
|
+
|
|
57
|
+
Collectors implement the visitor pattern for AST traversal. Each collector
|
|
58
|
+
is responsible for tracking specific metrics (e.g., complexity, nesting)
|
|
59
|
+
during tree-sitter node traversal.
|
|
60
|
+
|
|
61
|
+
Lifecycle:
|
|
62
|
+
1. collect_node() called for each AST node during traversal
|
|
63
|
+
2. Collector accumulates state during traversal
|
|
64
|
+
3. finalize_function() called when exiting a function/method
|
|
65
|
+
4. reset() called to prepare for next function
|
|
66
|
+
|
|
67
|
+
Subclasses must implement:
|
|
68
|
+
- name: Unique identifier for the collector
|
|
69
|
+
- collect_node(): Process individual AST nodes
|
|
70
|
+
- finalize_function(): Return final metrics for completed function
|
|
71
|
+
|
|
72
|
+
Example Implementation:
|
|
73
|
+
class ComplexityCollector(MetricCollector):
|
|
74
|
+
def __init__(self):
|
|
75
|
+
self._complexity = 0
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
def name(self) -> str:
|
|
79
|
+
return "complexity"
|
|
80
|
+
|
|
81
|
+
def collect_node(self, node: Node, context: CollectorContext, depth: int) -> None:
|
|
82
|
+
if node.type in ("if_statement", "while_statement"):
|
|
83
|
+
self._complexity += 1
|
|
84
|
+
|
|
85
|
+
def finalize_function(self, node: Node, context: CollectorContext) -> dict[str, Any]:
|
|
86
|
+
return {"cognitive_complexity": self._complexity}
|
|
87
|
+
|
|
88
|
+
def reset(self) -> None:
|
|
89
|
+
self._complexity = 0
|
|
90
|
+
"""
|
|
91
|
+
|
|
92
|
+
@property
|
|
93
|
+
@abstractmethod
|
|
94
|
+
def name(self) -> str:
|
|
95
|
+
"""Unique identifier for this collector.
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
Collector name (e.g., "complexity", "nesting", "parameters")
|
|
99
|
+
"""
|
|
100
|
+
pass
|
|
101
|
+
|
|
102
|
+
@abstractmethod
|
|
103
|
+
def collect_node(self, node: Node, context: CollectorContext, depth: int) -> None:
|
|
104
|
+
"""Called for each AST node during traversal.
|
|
105
|
+
|
|
106
|
+
Collectors accumulate state here by examining node properties
|
|
107
|
+
and updating internal counters/state.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
node: Current tree-sitter AST node being visited
|
|
111
|
+
context: Shared context with file info and current scope
|
|
112
|
+
depth: Current nesting depth in the AST
|
|
113
|
+
|
|
114
|
+
Example:
|
|
115
|
+
def collect_node(self, node, context, depth):
|
|
116
|
+
if node.type == "if_statement":
|
|
117
|
+
self._if_count += 1
|
|
118
|
+
elif node.type == "for_statement":
|
|
119
|
+
self._loop_count += 1
|
|
120
|
+
"""
|
|
121
|
+
pass
|
|
122
|
+
|
|
123
|
+
@abstractmethod
|
|
124
|
+
def finalize_function(
|
|
125
|
+
self, node: Node, context: CollectorContext
|
|
126
|
+
) -> dict[str, Any]:
|
|
127
|
+
"""Called when exiting a function/method.
|
|
128
|
+
|
|
129
|
+
Returns final metrics for this function. The returned dictionary
|
|
130
|
+
should contain metric names as keys and their values.
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
node: The function/method definition node
|
|
134
|
+
context: Shared context with file info and scope
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
Dictionary of metric names to values
|
|
138
|
+
Example: {"cognitive_complexity": 5, "max_nesting": 3}
|
|
139
|
+
|
|
140
|
+
Example:
|
|
141
|
+
def finalize_function(self, node, context):
|
|
142
|
+
return {
|
|
143
|
+
"cognitive_complexity": self._complexity,
|
|
144
|
+
"nesting_depth": self._max_depth
|
|
145
|
+
}
|
|
146
|
+
"""
|
|
147
|
+
pass
|
|
148
|
+
|
|
149
|
+
def reset(self) -> None:
|
|
150
|
+
"""Reset collector state for next function.
|
|
151
|
+
|
|
152
|
+
Called after finalize_function() to prepare the collector
|
|
153
|
+
for analyzing the next function/method.
|
|
154
|
+
|
|
155
|
+
Default implementation does nothing. Override if collector
|
|
156
|
+
maintains state that needs clearing.
|
|
157
|
+
|
|
158
|
+
Example:
|
|
159
|
+
def reset(self):
|
|
160
|
+
self._complexity = 0
|
|
161
|
+
self._nesting_stack.clear()
|
|
162
|
+
self._max_depth = 0
|
|
163
|
+
"""
|
|
164
|
+
return # Default no-op implementation - subclasses override if needed
|