mcp-code-indexer 3.5.1__tar.gz → 3.5.3__tar.gz

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 (39) hide show
  1. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/PKG-INFO +3 -3
  2. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/README.md +2 -2
  3. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/pyproject.toml +1 -1
  4. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/commands/makelocal.py +23 -9
  5. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/database/database_factory.py +0 -9
  6. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/database/path_resolver.py +16 -33
  7. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/LICENSE +0 -0
  8. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/__init__.py +0 -0
  9. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/__main__.py +0 -0
  10. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/ask_handler.py +0 -0
  11. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/claude_api_handler.py +0 -0
  12. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/cleanup_manager.py +0 -0
  13. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/commands/__init__.py +0 -0
  14. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/data/stop_words_english.txt +0 -0
  15. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/database/__init__.py +0 -0
  16. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/database/connection_health.py +0 -0
  17. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/database/database.py +0 -0
  18. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/database/exceptions.py +0 -0
  19. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/database/models.py +0 -0
  20. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/database/retry_executor.py +0 -0
  21. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/deepask_handler.py +0 -0
  22. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/error_handler.py +0 -0
  23. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/file_scanner.py +0 -0
  24. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/git_hook_handler.py +0 -0
  25. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/logging_config.py +0 -0
  26. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/main.py +0 -0
  27. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/middleware/__init__.py +0 -0
  28. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/middleware/error_middleware.py +0 -0
  29. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/migrations/001_initial.sql +0 -0
  30. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/migrations/002_performance_indexes.sql +0 -0
  31. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/migrations/003_project_overviews.sql +0 -0
  32. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/migrations/004_remove_branch_dependency.sql +0 -0
  33. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/migrations/005_remove_git_remotes.sql +0 -0
  34. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/query_preprocessor.py +0 -0
  35. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/server/__init__.py +0 -0
  36. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/server/mcp_server.py +0 -0
  37. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/tiktoken_cache/9b5ad71b2ce5302211f9c61530b329a4922fc6a4 +0 -0
  38. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/token_counter.py +0 -0
  39. {mcp_code_indexer-3.5.1 → mcp_code_indexer-3.5.3}/src/mcp_code_indexer/tools/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: mcp-code-indexer
3
- Version: 3.5.1
3
+ Version: 3.5.3
4
4
  Summary: MCP server that tracks file descriptions across codebases, enabling AI agents to efficiently navigate and understand code through searchable summaries and token-aware overviews.
5
5
  License: MIT
6
6
  Keywords: mcp,model-context-protocol,code-indexer,ai-tools,codebase-navigation,file-descriptions,llm-tools
@@ -40,8 +40,8 @@ Description-Content-Type: text/markdown
40
40
 
41
41
  # MCP Code Indexer 🚀
42
42
 
43
- [![PyPI version](https://badge.fury.io/py/mcp-code-indexer.svg?36)](https://badge.fury.io/py/mcp-code-indexer)
44
- [![Python](https://img.shields.io/pypi/pyversions/mcp-code-indexer.svg?36)](https://pypi.org/project/mcp-code-indexer/)
43
+ [![PyPI version](https://badge.fury.io/py/mcp-code-indexer.svg?38)](https://badge.fury.io/py/mcp-code-indexer)
44
+ [![Python](https://img.shields.io/pypi/pyversions/mcp-code-indexer.svg?38)](https://pypi.org/project/mcp-code-indexer/)
45
45
  [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
46
46
 
47
47
  A production-ready **Model Context Protocol (MCP) server** that revolutionizes how AI agents navigate and understand codebases. Built for high-concurrency environments with advanced database resilience, the server provides instant access to intelligent descriptions, semantic search, and context-aware recommendations while maintaining 800+ writes/sec throughput.
@@ -1,7 +1,7 @@
1
1
  # MCP Code Indexer 🚀
2
2
 
3
- [![PyPI version](https://badge.fury.io/py/mcp-code-indexer.svg?36)](https://badge.fury.io/py/mcp-code-indexer)
4
- [![Python](https://img.shields.io/pypi/pyversions/mcp-code-indexer.svg?36)](https://pypi.org/project/mcp-code-indexer/)
3
+ [![PyPI version](https://badge.fury.io/py/mcp-code-indexer.svg?38)](https://badge.fury.io/py/mcp-code-indexer)
4
+ [![Python](https://img.shields.io/pypi/pyversions/mcp-code-indexer.svg?38)](https://pypi.org/project/mcp-code-indexer/)
5
5
  [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
6
6
 
7
7
  A production-ready **Model Context Protocol (MCP) server** that revolutionizes how AI agents navigate and understand codebases. Built for high-concurrency environments with advanced database resilience, the server provides instant access to intelligent descriptions, semantic search, and context-aware recommendations while maintaining 800+ writes/sec throughput.
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
4
4
 
5
5
  [tool.poetry]
6
6
  name = "mcp-code-indexer"
7
- version = "3.5.1"
7
+ version = "3.5.3"
8
8
  description = "MCP server that tracks file descriptions across codebases, enabling AI agents to efficiently navigate and understand code through searchable summaries and token-aware overviews."
9
9
  authors = ["MCP Code Indexer Contributors"]
10
10
  maintainers = ["MCP Code Indexer Contributors"]
@@ -52,10 +52,23 @@ class MakeLocalCommand:
52
52
  if not folder_path_obj.is_dir():
53
53
  raise ValueError(f"Path is not a directory: {folder_path}")
54
54
 
55
- # Check if local database already exists
56
- local_db_path = folder_path_obj / ".code-index.db"
57
- if local_db_path.exists() and local_db_path.stat().st_size > 0:
58
- raise ValueError(f"Local database already exists: {local_db_path}")
55
+ # Get local database folder and path
56
+ local_db_folder = self.db_factory.get_path_resolver().get_local_database_folder(folder_path)
57
+ local_db_path = self.db_factory.get_path_resolver().get_local_database_path(folder_path)
58
+
59
+ # Check if local database already exists and has data
60
+ if local_db_folder.exists() and local_db_path.exists() and local_db_path.stat().st_size > 0:
61
+ # Check if it actually has project data (not just schema)
62
+ from sqlite3 import connect
63
+ try:
64
+ with connect(local_db_path) as conn:
65
+ cursor = conn.execute("SELECT COUNT(*) FROM projects")
66
+ project_count = cursor.fetchone()[0]
67
+ if project_count > 0:
68
+ raise ValueError(f"Local database already contains {project_count} project(s): {local_db_path}")
69
+ except Exception:
70
+ # If we can't check, assume it has data to be safe
71
+ raise ValueError(f"Local database already exists: {local_db_path}")
59
72
 
60
73
  # Get global database manager
61
74
  global_db_manager = await self.db_factory.get_database_manager()
@@ -78,11 +91,11 @@ class MakeLocalCommand:
78
91
  if project_overview:
79
92
  logger.info("Found project overview to migrate")
80
93
 
81
- # Create local database (remove empty file if it exists)
82
- if local_db_path.exists():
83
- local_db_path.unlink()
84
-
85
- # Create local database manager
94
+ # Create local database folder (this ensures it exists)
95
+ local_db_folder.mkdir(parents=True, exist_ok=True)
96
+ logger.info(f"Created local database folder: {local_db_folder}")
97
+
98
+ # Create local database manager (this will initialize schema)
86
99
  local_db_manager = await self.db_factory.get_database_manager(str(folder_path_obj))
87
100
 
88
101
  # Migrate data
@@ -98,6 +111,7 @@ class MakeLocalCommand:
98
111
  "project_name": project.name,
99
112
  "project_id": project.id,
100
113
  "local_database_path": str(local_db_path),
114
+ "local_database_folder": str(local_db_folder),
101
115
  "migrated_files": len(file_descriptions),
102
116
  "migrated_overview": project_overview is not None,
103
117
  }
@@ -82,15 +82,6 @@ class DatabaseFactory:
82
82
  if db_key in self._database_managers:
83
83
  return self._database_managers[db_key]
84
84
 
85
- # Check if we need to initialize an empty local database
86
- if (folder_path and
87
- self.path_resolver.is_local_database(folder_path) and
88
- self.path_resolver.should_initialize_local_database(folder_path)):
89
- logger.info(f"Initializing empty local database: {db_path}")
90
- # Remove the empty file so DatabaseManager can create it properly
91
- if db_path.exists():
92
- db_path.unlink()
93
-
94
85
  # Create new database manager
95
86
  db_manager = DatabaseManager(
96
87
  db_path=db_path,
@@ -17,8 +17,8 @@ class DatabasePathResolver:
17
17
  """
18
18
  Resolves database paths, determining whether to use local or global databases.
19
19
 
20
- Local databases are stored as .code-index.db in project folders.
21
- If a local database file exists, it takes precedence over the global database.
20
+ Local databases are stored as tracker.db in .code-index folders.
21
+ If a .code-index folder exists, it takes precedence over the global database.
22
22
  """
23
23
 
24
24
  def __init__(self, global_db_path: Path):
@@ -46,13 +46,14 @@ class DatabasePathResolver:
46
46
 
47
47
  try:
48
48
  folder_path_obj = Path(folder_path).resolve()
49
- local_db_path = folder_path_obj / ".code-index.db"
49
+ local_db_folder = folder_path_obj / ".code-index"
50
50
 
51
- if local_db_path.exists():
52
- logger.debug(f"Found local database: {local_db_path}")
51
+ if local_db_folder.exists() and local_db_folder.is_dir():
52
+ local_db_path = local_db_folder / "tracker.db"
53
+ logger.debug(f"Found local database folder: {local_db_path}")
53
54
  return local_db_path
54
55
  else:
55
- logger.debug(f"No local database found at {local_db_path}, using global database")
56
+ logger.debug(f"No local database folder found at {local_db_folder}, using global database")
56
57
  return self.global_db_path
57
58
 
58
59
  except (OSError, ValueError) as e:
@@ -61,21 +62,21 @@ class DatabasePathResolver:
61
62
 
62
63
  def is_local_database(self, folder_path: Optional[str] = None) -> bool:
63
64
  """
64
- Check if a local database exists for the given folder path.
65
+ Check if a local database folder exists for the given folder path.
65
66
 
66
67
  Args:
67
68
  folder_path: Project folder path to check
68
69
 
69
70
  Returns:
70
- True if a local database exists, False otherwise
71
+ True if a local database folder exists, False otherwise
71
72
  """
72
73
  if not folder_path:
73
74
  return False
74
75
 
75
76
  try:
76
77
  folder_path_obj = Path(folder_path).resolve()
77
- local_db_path = folder_path_obj / ".code-index.db"
78
- return local_db_path.exists()
78
+ local_db_folder = folder_path_obj / ".code-index"
79
+ return local_db_folder.exists() and local_db_folder.is_dir()
79
80
  except (OSError, ValueError):
80
81
  return False
81
82
 
@@ -89,34 +90,16 @@ class DatabasePathResolver:
89
90
  Returns:
90
91
  Path where the local database would be located
91
92
  """
92
- return Path(folder_path).resolve() / ".code-index.db"
93
+ return Path(folder_path).resolve() / ".code-index" / "tracker.db"
93
94
 
94
- def is_empty_database_file(self, db_path: Path) -> bool:
95
+ def get_local_database_folder(self, folder_path: str) -> Path:
95
96
  """
96
- Check if a database file is empty (0 bytes).
97
-
98
- Args:
99
- db_path: Path to the database file
100
-
101
- Returns:
102
- True if the file exists and is empty, False otherwise
103
- """
104
- try:
105
- return db_path.exists() and db_path.stat().st_size == 0
106
- except (OSError, ValueError):
107
- return False
108
-
109
- def should_initialize_local_database(self, folder_path: str) -> bool:
110
- """
111
- Check if a local database should be initialized.
112
-
113
- This returns True if .code-index.db exists and is empty.
97
+ Get the local database folder for a project folder.
114
98
 
115
99
  Args:
116
100
  folder_path: Project folder path
117
101
 
118
102
  Returns:
119
- True if local database should be initialized, False otherwise
103
+ Path where the local database folder would be located
120
104
  """
121
- local_db_path = self.get_local_database_path(folder_path)
122
- return self.is_empty_database_file(local_db_path)
105
+ return Path(folder_path).resolve() / ".code-index"