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.
Files changed (65) hide show
  1. mcp_vector_search/__init__.py +2 -2
  2. mcp_vector_search/analysis/__init__.py +64 -0
  3. mcp_vector_search/analysis/collectors/__init__.py +39 -0
  4. mcp_vector_search/analysis/collectors/base.py +164 -0
  5. mcp_vector_search/analysis/collectors/complexity.py +743 -0
  6. mcp_vector_search/analysis/metrics.py +341 -0
  7. mcp_vector_search/analysis/reporters/__init__.py +5 -0
  8. mcp_vector_search/analysis/reporters/console.py +222 -0
  9. mcp_vector_search/cli/commands/analyze.py +408 -0
  10. mcp_vector_search/cli/commands/chat.py +1262 -0
  11. mcp_vector_search/cli/commands/index.py +21 -3
  12. mcp_vector_search/cli/commands/init.py +13 -0
  13. mcp_vector_search/cli/commands/install.py +597 -335
  14. mcp_vector_search/cli/commands/install_old.py +8 -4
  15. mcp_vector_search/cli/commands/mcp.py +78 -6
  16. mcp_vector_search/cli/commands/reset.py +68 -26
  17. mcp_vector_search/cli/commands/search.py +30 -7
  18. mcp_vector_search/cli/commands/setup.py +1133 -0
  19. mcp_vector_search/cli/commands/status.py +37 -2
  20. mcp_vector_search/cli/commands/uninstall.py +276 -357
  21. mcp_vector_search/cli/commands/visualize/__init__.py +39 -0
  22. mcp_vector_search/cli/commands/visualize/cli.py +276 -0
  23. mcp_vector_search/cli/commands/visualize/exporters/__init__.py +12 -0
  24. mcp_vector_search/cli/commands/visualize/exporters/html_exporter.py +33 -0
  25. mcp_vector_search/cli/commands/visualize/exporters/json_exporter.py +29 -0
  26. mcp_vector_search/cli/commands/visualize/graph_builder.py +714 -0
  27. mcp_vector_search/cli/commands/visualize/layout_engine.py +469 -0
  28. mcp_vector_search/cli/commands/visualize/server.py +311 -0
  29. mcp_vector_search/cli/commands/visualize/state_manager.py +428 -0
  30. mcp_vector_search/cli/commands/visualize/templates/__init__.py +16 -0
  31. mcp_vector_search/cli/commands/visualize/templates/base.py +180 -0
  32. mcp_vector_search/cli/commands/visualize/templates/scripts.py +2507 -0
  33. mcp_vector_search/cli/commands/visualize/templates/styles.py +1313 -0
  34. mcp_vector_search/cli/commands/visualize.py.original +2536 -0
  35. mcp_vector_search/cli/didyoumean.py +22 -2
  36. mcp_vector_search/cli/main.py +115 -159
  37. mcp_vector_search/cli/output.py +24 -8
  38. mcp_vector_search/config/__init__.py +4 -0
  39. mcp_vector_search/config/default_thresholds.yaml +52 -0
  40. mcp_vector_search/config/settings.py +12 -0
  41. mcp_vector_search/config/thresholds.py +185 -0
  42. mcp_vector_search/core/auto_indexer.py +3 -3
  43. mcp_vector_search/core/boilerplate.py +186 -0
  44. mcp_vector_search/core/config_utils.py +394 -0
  45. mcp_vector_search/core/database.py +369 -94
  46. mcp_vector_search/core/exceptions.py +11 -0
  47. mcp_vector_search/core/git_hooks.py +4 -4
  48. mcp_vector_search/core/indexer.py +221 -4
  49. mcp_vector_search/core/llm_client.py +751 -0
  50. mcp_vector_search/core/models.py +3 -0
  51. mcp_vector_search/core/project.py +17 -0
  52. mcp_vector_search/core/scheduler.py +11 -11
  53. mcp_vector_search/core/search.py +179 -29
  54. mcp_vector_search/mcp/server.py +24 -5
  55. mcp_vector_search/utils/__init__.py +2 -0
  56. mcp_vector_search/utils/gitignore_updater.py +212 -0
  57. mcp_vector_search/utils/monorepo.py +66 -4
  58. mcp_vector_search/utils/timing.py +10 -6
  59. {mcp_vector_search-0.12.6.dist-info → mcp_vector_search-1.0.3.dist-info}/METADATA +182 -52
  60. mcp_vector_search-1.0.3.dist-info/RECORD +97 -0
  61. {mcp_vector_search-0.12.6.dist-info → mcp_vector_search-1.0.3.dist-info}/WHEEL +1 -1
  62. {mcp_vector_search-0.12.6.dist-info → mcp_vector_search-1.0.3.dist-info}/entry_points.txt +1 -0
  63. mcp_vector_search/cli/commands/visualize.py +0 -1467
  64. mcp_vector_search-0.12.6.dist-info/RECORD +0 -68
  65. {mcp_vector_search-0.12.6.dist-info → mcp_vector_search-1.0.3.dist-info}/licenses/LICENSE +0 -0
@@ -1,7 +1,7 @@
1
1
  """MCP Vector Search - CLI-first semantic code search with MCP integration."""
2
2
 
3
- __version__ = "0.12.6"
4
- __build__ = "55"
3
+ __version__ = "1.0.3"
4
+ __build__ = "93"
5
5
  __author__ = "Robert Matsuoka"
6
6
  __email__ = "bobmatnyc@gmail.com"
7
7
 
@@ -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