mcp-code-indexer 4.2.15__py3-none-any.whl → 4.2.17__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_code_indexer/database/database.py +334 -115
- mcp_code_indexer/database/database_factory.py +1 -1
- mcp_code_indexer/database/exceptions.py +1 -1
- mcp_code_indexer/database/models.py +66 -24
- mcp_code_indexer/database/retry_executor.py +15 -5
- mcp_code_indexer/file_scanner.py +107 -12
- mcp_code_indexer/main.py +43 -30
- mcp_code_indexer/server/mcp_server.py +201 -7
- mcp_code_indexer/vector_mode/chunking/ast_chunker.py +103 -84
- mcp_code_indexer/vector_mode/chunking/chunk_optimizer.py +1 -0
- mcp_code_indexer/vector_mode/config.py +113 -45
- mcp_code_indexer/vector_mode/const.py +24 -0
- mcp_code_indexer/vector_mode/daemon.py +860 -98
- mcp_code_indexer/vector_mode/monitoring/change_detector.py +113 -97
- mcp_code_indexer/vector_mode/monitoring/file_watcher.py +175 -121
- mcp_code_indexer/vector_mode/providers/turbopuffer_client.py +291 -98
- mcp_code_indexer/vector_mode/providers/voyage_client.py +140 -38
- mcp_code_indexer/vector_mode/services/__init__.py +9 -0
- mcp_code_indexer/vector_mode/services/embedding_service.py +389 -0
- mcp_code_indexer/vector_mode/services/vector_mode_tools_service.py +459 -0
- mcp_code_indexer/vector_mode/services/vector_storage_service.py +580 -0
- mcp_code_indexer/vector_mode/types.py +46 -0
- mcp_code_indexer/vector_mode/utils.py +50 -0
- {mcp_code_indexer-4.2.15.dist-info → mcp_code_indexer-4.2.17.dist-info}/METADATA +13 -10
- {mcp_code_indexer-4.2.15.dist-info → mcp_code_indexer-4.2.17.dist-info}/RECORD +28 -21
- {mcp_code_indexer-4.2.15.dist-info → mcp_code_indexer-4.2.17.dist-info}/WHEEL +1 -1
- {mcp_code_indexer-4.2.15.dist-info → mcp_code_indexer-4.2.17.dist-info}/entry_points.txt +0 -0
- {mcp_code_indexer-4.2.15.dist-info → mcp_code_indexer-4.2.17.dist-info/licenses}/LICENSE +0 -0
|
@@ -13,7 +13,7 @@ import random
|
|
|
13
13
|
import re
|
|
14
14
|
import time
|
|
15
15
|
import uuid
|
|
16
|
-
from datetime import datetime
|
|
16
|
+
from datetime import datetime, timedelta
|
|
17
17
|
from pathlib import Path
|
|
18
18
|
from typing import Any, Dict, List, Optional, Callable, cast
|
|
19
19
|
|
|
@@ -56,7 +56,7 @@ class MCPCodeIndexServer:
|
|
|
56
56
|
cache_dir: Optional[Path] = None,
|
|
57
57
|
db_pool_size: int = 3,
|
|
58
58
|
db_retry_count: int = 5,
|
|
59
|
-
db_timeout: float =
|
|
59
|
+
db_timeout: float = 30.0,
|
|
60
60
|
enable_wal_mode: bool = True,
|
|
61
61
|
health_check_interval: float = 30.0,
|
|
62
62
|
retry_min_wait: float = 0.1,
|
|
@@ -684,6 +684,104 @@ class MCPCodeIndexServer:
|
|
|
684
684
|
"additionalProperties": False,
|
|
685
685
|
},
|
|
686
686
|
),
|
|
687
|
+
types.Tool(
|
|
688
|
+
name="enabled_vector_mode",
|
|
689
|
+
description=(
|
|
690
|
+
"Enables or disables vector mode for a project. Vector mode "
|
|
691
|
+
"provides semantic search capabilities with embeddings for "
|
|
692
|
+
"enhanced code navigation and discovery."
|
|
693
|
+
),
|
|
694
|
+
inputSchema={
|
|
695
|
+
"type": "object",
|
|
696
|
+
"properties": {
|
|
697
|
+
"projectName": {
|
|
698
|
+
"type": "string",
|
|
699
|
+
"description": "The name of the project",
|
|
700
|
+
},
|
|
701
|
+
"folderPath": {
|
|
702
|
+
"type": "string",
|
|
703
|
+
"description": (
|
|
704
|
+
"Absolute path to the project folder on disk"
|
|
705
|
+
),
|
|
706
|
+
},
|
|
707
|
+
"enabled": {
|
|
708
|
+
"type": "boolean",
|
|
709
|
+
"description": (
|
|
710
|
+
"Whether to enable (true) or disable (false) vector mode"
|
|
711
|
+
),
|
|
712
|
+
},
|
|
713
|
+
},
|
|
714
|
+
"required": ["projectName", "folderPath", "enabled"],
|
|
715
|
+
"additionalProperties": False,
|
|
716
|
+
},
|
|
717
|
+
),
|
|
718
|
+
types.Tool(
|
|
719
|
+
name="find_similar_code",
|
|
720
|
+
description=(
|
|
721
|
+
"Find code similar to a given code snippet or file section using "
|
|
722
|
+
"vector-based semantic search. This tool uses AI embeddings to "
|
|
723
|
+
"understand code context and meaning, providing more intelligent "
|
|
724
|
+
"similarity detection than text-based matching. Requires vector "
|
|
725
|
+
"mode to be enabled for the project."
|
|
726
|
+
),
|
|
727
|
+
inputSchema={
|
|
728
|
+
"type": "object",
|
|
729
|
+
"properties": {
|
|
730
|
+
"projectName": {
|
|
731
|
+
"type": "string",
|
|
732
|
+
"description": "The name of the project",
|
|
733
|
+
},
|
|
734
|
+
"folderPath": {
|
|
735
|
+
"type": "string",
|
|
736
|
+
"description": (
|
|
737
|
+
"Absolute path to the project folder on disk"
|
|
738
|
+
),
|
|
739
|
+
},
|
|
740
|
+
"code_snippet": {
|
|
741
|
+
"type": "string",
|
|
742
|
+
"description": (
|
|
743
|
+
"Direct code snippet to search for similarities (mutually "
|
|
744
|
+
"exclusive with file_path)"
|
|
745
|
+
),
|
|
746
|
+
},
|
|
747
|
+
"file_path": {
|
|
748
|
+
"type": "string",
|
|
749
|
+
"description": (
|
|
750
|
+
"Path to file containing code to analyze (mutually "
|
|
751
|
+
"exclusive with code_snippet)"
|
|
752
|
+
),
|
|
753
|
+
},
|
|
754
|
+
"line_start": {
|
|
755
|
+
"type": "integer",
|
|
756
|
+
"description": (
|
|
757
|
+
"Starting line number for file section (1-indexed, "
|
|
758
|
+
"used with file_path)"
|
|
759
|
+
),
|
|
760
|
+
},
|
|
761
|
+
"line_end": {
|
|
762
|
+
"type": "integer",
|
|
763
|
+
"description": (
|
|
764
|
+
"Ending line number for file section (1-indexed, "
|
|
765
|
+
"used with file_path)"
|
|
766
|
+
),
|
|
767
|
+
},
|
|
768
|
+
"similarity_threshold": {
|
|
769
|
+
"type": "number",
|
|
770
|
+
"description": (
|
|
771
|
+
"Minimum similarity score (0.0-1.0, optional)"
|
|
772
|
+
),
|
|
773
|
+
},
|
|
774
|
+
"max_results": {
|
|
775
|
+
"type": "integer",
|
|
776
|
+
"description": (
|
|
777
|
+
"Maximum number of results to return (optional)"
|
|
778
|
+
),
|
|
779
|
+
},
|
|
780
|
+
},
|
|
781
|
+
"required": ["projectName", "folderPath"],
|
|
782
|
+
"additionalProperties": False,
|
|
783
|
+
},
|
|
784
|
+
),
|
|
687
785
|
]
|
|
688
786
|
|
|
689
787
|
@self.server.call_tool() # type: ignore[misc]
|
|
@@ -711,6 +809,8 @@ class MCPCodeIndexServer:
|
|
|
711
809
|
"get_word_frequency": self._handle_get_word_frequency,
|
|
712
810
|
"check_database_health": self._handle_check_database_health,
|
|
713
811
|
"search_codebase_overview": self._handle_search_codebase_overview,
|
|
812
|
+
"enabled_vector_mode": self._handle_enabled_vector_mode,
|
|
813
|
+
"find_similar_code": self._handle_find_similar_code,
|
|
714
814
|
}
|
|
715
815
|
|
|
716
816
|
if name not in tool_handlers:
|
|
@@ -782,8 +882,11 @@ class MCPCodeIndexServer:
|
|
|
782
882
|
all_projects = await db_manager.get_all_projects()
|
|
783
883
|
if all_projects:
|
|
784
884
|
project = all_projects[0] # Use the first (and should be only) project
|
|
785
|
-
|
|
786
|
-
|
|
885
|
+
|
|
886
|
+
# Update last accessed time only if older than 5 minutes
|
|
887
|
+
if datetime.utcnow() - project.last_accessed > timedelta(minutes=5):
|
|
888
|
+
await db_manager.update_project_access_time(project.id)
|
|
889
|
+
|
|
787
890
|
logger.info(
|
|
788
891
|
f"Using existing local project: {project.name} (ID: {project.id})"
|
|
789
892
|
)
|
|
@@ -834,7 +937,9 @@ class MCPCodeIndexServer:
|
|
|
834
937
|
)
|
|
835
938
|
|
|
836
939
|
if project is None:
|
|
837
|
-
raise RuntimeError(
|
|
940
|
+
raise RuntimeError(
|
|
941
|
+
"Project should always be set in if/else branches above"
|
|
942
|
+
)
|
|
838
943
|
return project.id
|
|
839
944
|
|
|
840
945
|
async def _find_matching_project(
|
|
@@ -938,8 +1043,9 @@ class MCPCodeIndexServer:
|
|
|
938
1043
|
db_manager: DatabaseManager,
|
|
939
1044
|
) -> None:
|
|
940
1045
|
"""Update an existing project with new metadata and folder alias."""
|
|
941
|
-
# Update last accessed time
|
|
942
|
-
|
|
1046
|
+
# Update last accessed time only if older than 5 minutes
|
|
1047
|
+
if datetime.utcnow() - project.last_accessed > timedelta(minutes=5):
|
|
1048
|
+
await db_manager.update_project_access_time(project.id)
|
|
943
1049
|
|
|
944
1050
|
should_update = False
|
|
945
1051
|
|
|
@@ -1103,6 +1209,7 @@ class MCPCodeIndexServer:
|
|
|
1103
1209
|
"isLarge": is_large,
|
|
1104
1210
|
"recommendation": recommendation,
|
|
1105
1211
|
"tokenLimit": token_limit,
|
|
1212
|
+
"totalTokens": total_tokens,
|
|
1106
1213
|
"totalFiles": len(file_descriptions),
|
|
1107
1214
|
"cleanedUpCount": cleaned_up_count,
|
|
1108
1215
|
}
|
|
@@ -1481,6 +1588,93 @@ class MCPCodeIndexServer:
|
|
|
1481
1588
|
"status_summary": self._generate_health_summary(comprehensive_diagnostics),
|
|
1482
1589
|
}
|
|
1483
1590
|
|
|
1591
|
+
async def _handle_enabled_vector_mode(
|
|
1592
|
+
self, arguments: Dict[str, Any]
|
|
1593
|
+
) -> Dict[str, Any]:
|
|
1594
|
+
"""Handle enabled_vector_mode tool calls."""
|
|
1595
|
+
folder_path = arguments["folderPath"]
|
|
1596
|
+
db_manager = await self.db_factory.get_database_manager(folder_path)
|
|
1597
|
+
project_id = await self._get_or_create_project_id(arguments)
|
|
1598
|
+
enabled = arguments["enabled"]
|
|
1599
|
+
|
|
1600
|
+
try:
|
|
1601
|
+
await db_manager.set_project_vector_mode(project_id, enabled)
|
|
1602
|
+
|
|
1603
|
+
return {
|
|
1604
|
+
"success": True,
|
|
1605
|
+
"message": f"Vector mode {'enabled' if enabled else 'disabled'} for project",
|
|
1606
|
+
"project_id": project_id,
|
|
1607
|
+
"vector_mode": enabled,
|
|
1608
|
+
}
|
|
1609
|
+
except ValueError as e:
|
|
1610
|
+
return {
|
|
1611
|
+
"success": False,
|
|
1612
|
+
"error": str(e),
|
|
1613
|
+
"project_id": project_id,
|
|
1614
|
+
"vector_mode": None,
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
async def _handle_find_similar_code(
|
|
1618
|
+
self, arguments: Dict[str, Any]
|
|
1619
|
+
) -> Dict[str, Any]:
|
|
1620
|
+
"""Handle find_similar_code tool calls."""
|
|
1621
|
+
try:
|
|
1622
|
+
from mcp_code_indexer.vector_mode.services.vector_mode_tools_service import (
|
|
1623
|
+
VectorModeToolsService,
|
|
1624
|
+
)
|
|
1625
|
+
|
|
1626
|
+
# Initialize the tools service (handles all vector mode setup internally)
|
|
1627
|
+
tools_service = VectorModeToolsService()
|
|
1628
|
+
|
|
1629
|
+
# Extract project info
|
|
1630
|
+
project_name = arguments["projectName"]
|
|
1631
|
+
folder_path = arguments["folderPath"]
|
|
1632
|
+
|
|
1633
|
+
logger.info(
|
|
1634
|
+
"Processing find_similar_code request",
|
|
1635
|
+
extra={
|
|
1636
|
+
"structured_data": {
|
|
1637
|
+
"project_name": project_name,
|
|
1638
|
+
"has_code_snippet": "code_snippet" in arguments,
|
|
1639
|
+
"has_file_path": "file_path" in arguments,
|
|
1640
|
+
}
|
|
1641
|
+
},
|
|
1642
|
+
)
|
|
1643
|
+
|
|
1644
|
+
# Call the service method
|
|
1645
|
+
result = await tools_service.find_similar_code(
|
|
1646
|
+
project_name=project_name,
|
|
1647
|
+
folder_path=folder_path,
|
|
1648
|
+
code_snippet=arguments.get("code_snippet"),
|
|
1649
|
+
file_path=arguments.get("file_path"),
|
|
1650
|
+
line_start=arguments.get("line_start"),
|
|
1651
|
+
line_end=arguments.get("line_end"),
|
|
1652
|
+
similarity_threshold=arguments.get("similarity_threshold"),
|
|
1653
|
+
max_results=arguments.get("max_results"),
|
|
1654
|
+
)
|
|
1655
|
+
|
|
1656
|
+
# Add success indicator to the result
|
|
1657
|
+
result["success"] = True
|
|
1658
|
+
return result
|
|
1659
|
+
|
|
1660
|
+
except Exception as e:
|
|
1661
|
+
logger.error(
|
|
1662
|
+
"Failed to execute find_similar_code",
|
|
1663
|
+
extra={
|
|
1664
|
+
"structured_data": {
|
|
1665
|
+
"error": str(e),
|
|
1666
|
+
"project_name": arguments.get("projectName", "unknown"),
|
|
1667
|
+
}
|
|
1668
|
+
},
|
|
1669
|
+
exc_info=True,
|
|
1670
|
+
)
|
|
1671
|
+
return {
|
|
1672
|
+
"success": False,
|
|
1673
|
+
"error": str(e),
|
|
1674
|
+
"results": [],
|
|
1675
|
+
"total_results": 0,
|
|
1676
|
+
}
|
|
1677
|
+
|
|
1484
1678
|
def _generate_health_summary(self, diagnostics: Dict[str, Any]) -> Dict[str, Any]:
|
|
1485
1679
|
"""Generate a concise health summary from comprehensive diagnostics."""
|
|
1486
1680
|
if "resilience_indicators" not in diagnostics:
|