mcp-code-indexer 1.0.1__tar.gz → 1.0.4__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.
- {mcp_code_indexer-1.0.1/src/mcp_code_indexer.egg-info → mcp_code_indexer-1.0.4}/PKG-INFO +3 -2
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/README.md +1 -0
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/pyproject.toml +2 -2
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/src/mcp_code_indexer/__init__.py +1 -1
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/src/mcp_code_indexer/main.py +8 -3
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/src/mcp_code_indexer/server/mcp_server.py +139 -10
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4/src/mcp_code_indexer.egg-info}/PKG-INFO +3 -2
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/src/mcp_code_indexer.egg-info/requires.txt +1 -1
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/LICENSE +0 -0
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/MANIFEST.in +0 -0
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/docs/api-reference.md +0 -0
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/docs/architecture.md +0 -0
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/docs/configuration.md +0 -0
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/docs/contributing.md +0 -0
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/migrations/001_initial.sql +0 -0
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/migrations/002_performance_indexes.sql +0 -0
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/requirements.txt +0 -0
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/setup.cfg +0 -0
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/setup.py +0 -0
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/src/mcp_code_indexer/database/__init__.py +0 -0
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/src/mcp_code_indexer/database/database.py +0 -0
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/src/mcp_code_indexer/database/models.py +0 -0
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/src/mcp_code_indexer/error_handler.py +0 -0
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/src/mcp_code_indexer/file_scanner.py +0 -0
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/src/mcp_code_indexer/logging_config.py +0 -0
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/src/mcp_code_indexer/merge_handler.py +0 -0
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/src/mcp_code_indexer/middleware/__init__.py +0 -0
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/src/mcp_code_indexer/middleware/error_middleware.py +0 -0
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/src/mcp_code_indexer/server/__init__.py +0 -0
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/src/mcp_code_indexer/tiktoken_cache/9b5ad71b2ce5302211f9c61530b329a4922fc6a4 +0 -0
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/src/mcp_code_indexer/token_counter.py +0 -0
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/src/mcp_code_indexer/tools/__init__.py +0 -0
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/src/mcp_code_indexer.egg-info/SOURCES.txt +0 -0
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/src/mcp_code_indexer.egg-info/dependency_links.txt +0 -0
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/src/mcp_code_indexer.egg-info/entry_points.txt +0 -0
- {mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/src/mcp_code_indexer.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: mcp-code-indexer
|
3
|
-
Version: 1.0.
|
3
|
+
Version: 1.0.4
|
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
|
Author: MCP Code Indexer Contributors
|
6
6
|
Maintainer: MCP Code Indexer Contributors
|
@@ -30,7 +30,7 @@ Requires-Python: >=3.9
|
|
30
30
|
Description-Content-Type: text/markdown
|
31
31
|
License-File: LICENSE
|
32
32
|
Requires-Dist: tiktoken>=0.9.0
|
33
|
-
Requires-Dist: mcp
|
33
|
+
Requires-Dist: mcp>=1.9.0
|
34
34
|
Requires-Dist: gitignore_parser==0.1.11
|
35
35
|
Requires-Dist: pydantic>=2.8.0
|
36
36
|
Requires-Dist: aiofiles==23.2.0
|
@@ -187,6 +187,7 @@ The server provides **8 powerful MCP tools** for intelligent codebase management
|
|
187
187
|
### Production Ready
|
188
188
|
- **Comprehensive error handling** with structured JSON logging
|
189
189
|
- **Async-first design** with proper resource cleanup
|
190
|
+
- **MCP protocol compliant** with clean stdio streams
|
190
191
|
- **Upstream inheritance** for fork workflows
|
191
192
|
- **Git integration** with .gitignore support
|
192
193
|
|
@@ -132,6 +132,7 @@ The server provides **8 powerful MCP tools** for intelligent codebase management
|
|
132
132
|
### Production Ready
|
133
133
|
- **Comprehensive error handling** with structured JSON logging
|
134
134
|
- **Async-first design** with proper resource cleanup
|
135
|
+
- **MCP protocol compliant** with clean stdio streams
|
135
136
|
- **Upstream inheritance** for fork workflows
|
136
137
|
- **Git integration** with .gitignore support
|
137
138
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = "mcp-code-indexer"
|
7
|
-
version = "1.0.
|
7
|
+
version = "1.0.4"
|
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
|
readme = "README.md"
|
10
10
|
license = {text = "MIT"}
|
@@ -44,7 +44,7 @@ classifiers = [
|
|
44
44
|
requires-python = ">=3.9"
|
45
45
|
dependencies = [
|
46
46
|
"tiktoken>=0.9.0",
|
47
|
-
"mcp
|
47
|
+
"mcp>=1.9.0",
|
48
48
|
"gitignore_parser==0.1.11",
|
49
49
|
"pydantic>=2.8.0",
|
50
50
|
"aiofiles==23.2.0",
|
@@ -6,7 +6,7 @@ intelligent codebase navigation through searchable file descriptions,
|
|
6
6
|
token-aware overviews, and advanced merge capabilities.
|
7
7
|
"""
|
8
8
|
|
9
|
-
__version__ = "1.0.
|
9
|
+
__version__ = "1.0.4"
|
10
10
|
__author__ = "MCP Code Indexer Contributors"
|
11
11
|
__email__ = ""
|
12
12
|
__license__ = "MIT"
|
@@ -84,7 +84,7 @@ async def main() -> None:
|
|
84
84
|
db_path.parent.mkdir(parents=True, exist_ok=True)
|
85
85
|
cache_dir.mkdir(parents=True, exist_ok=True)
|
86
86
|
|
87
|
-
# Log startup information
|
87
|
+
# Log startup information to stderr (stdout reserved for MCP JSON-RPC)
|
88
88
|
logger.info("Starting MCP Code Index Server", extra={
|
89
89
|
"structured_data": {
|
90
90
|
"startup": {
|
@@ -119,9 +119,14 @@ def cli_main():
|
|
119
119
|
try:
|
120
120
|
asyncio.run(main())
|
121
121
|
except KeyboardInterrupt:
|
122
|
-
|
122
|
+
# For MCP servers, we should avoid stdout completely
|
123
|
+
# The server will log shutdown through stderr
|
124
|
+
pass
|
123
125
|
except Exception as e:
|
124
|
-
|
126
|
+
# Log critical errors to stderr, not stdout
|
127
|
+
import traceback
|
128
|
+
print(f"Server failed to start: {e}", file=sys.stderr)
|
129
|
+
print(f"Traceback: {traceback.format_exc()}", file=sys.stderr)
|
125
130
|
sys.exit(1)
|
126
131
|
|
127
132
|
|
@@ -16,6 +16,7 @@ from typing import Any, Dict, List, Optional
|
|
16
16
|
from mcp import types
|
17
17
|
from mcp.server import Server
|
18
18
|
from mcp.server.stdio import stdio_server
|
19
|
+
from pydantic import ValidationError
|
19
20
|
|
20
21
|
from mcp_code_indexer.database.database import DatabaseManager
|
21
22
|
from mcp_code_indexer.file_scanner import FileScanner
|
@@ -75,6 +76,9 @@ class MCPCodeIndexServer:
|
|
75
76
|
# Register handlers
|
76
77
|
self._register_handlers()
|
77
78
|
|
79
|
+
# Add debug logging for server events
|
80
|
+
self.logger.debug("MCP server instance created and handlers registered")
|
81
|
+
|
78
82
|
self.logger.info(
|
79
83
|
"MCP Code Index Server initialized",
|
80
84
|
extra={"structured_data": {"initialization": {"token_limit": token_limit}}}
|
@@ -648,21 +652,146 @@ class MCPCodeIndexServer:
|
|
648
652
|
**result
|
649
653
|
}
|
650
654
|
|
651
|
-
async def
|
652
|
-
"""Run
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
655
|
+
async def _run_session_with_retry(self, read_stream, write_stream, initialization_options) -> None:
|
656
|
+
"""Run a single MCP session with error handling and retry logic."""
|
657
|
+
max_retries = 3
|
658
|
+
base_delay = 1.0 # seconds
|
659
|
+
|
660
|
+
for attempt in range(max_retries + 1):
|
661
|
+
try:
|
662
|
+
logger.info(f"Starting MCP server protocol session (attempt {attempt + 1})...")
|
658
663
|
await self.server.run(
|
659
664
|
read_stream,
|
660
665
|
write_stream,
|
661
666
|
initialization_options
|
662
667
|
)
|
663
|
-
|
664
|
-
|
665
|
-
|
668
|
+
logger.info("MCP server session completed normally")
|
669
|
+
return # Success, exit retry loop
|
670
|
+
|
671
|
+
except ValidationError as e:
|
672
|
+
# Handle malformed requests gracefully
|
673
|
+
logger.warning(f"Received malformed request (attempt {attempt + 1}): {e}", extra={
|
674
|
+
"structured_data": {
|
675
|
+
"error_type": "ValidationError",
|
676
|
+
"validation_errors": e.errors() if hasattr(e, 'errors') else str(e),
|
677
|
+
"attempt": attempt + 1,
|
678
|
+
"max_retries": max_retries
|
679
|
+
}
|
680
|
+
})
|
681
|
+
|
682
|
+
if attempt < max_retries:
|
683
|
+
delay = base_delay * (2 ** attempt) # Exponential backoff
|
684
|
+
logger.info(f"Retrying in {delay} seconds...")
|
685
|
+
await asyncio.sleep(delay)
|
686
|
+
else:
|
687
|
+
logger.error("Max retries exceeded for validation errors. Server will continue but this session failed.")
|
688
|
+
return
|
689
|
+
|
690
|
+
except (ConnectionError, BrokenPipeError, EOFError) as e:
|
691
|
+
# Handle client disconnection gracefully
|
692
|
+
logger.info(f"Client disconnected: {e}")
|
693
|
+
return
|
694
|
+
|
695
|
+
except Exception as e:
|
696
|
+
# Handle other exceptions with full logging
|
697
|
+
import traceback
|
698
|
+
if "unhandled errors in a TaskGroup" in str(e) and "ValidationError" in str(e):
|
699
|
+
# This is likely a ValidationError wrapped in a TaskGroup exception
|
700
|
+
logger.warning(f"Detected wrapped validation error (attempt {attempt + 1}): {e}", extra={
|
701
|
+
"structured_data": {
|
702
|
+
"error_type": type(e).__name__,
|
703
|
+
"error_message": str(e),
|
704
|
+
"attempt": attempt + 1,
|
705
|
+
"max_retries": max_retries,
|
706
|
+
"likely_validation_error": True
|
707
|
+
}
|
708
|
+
})
|
709
|
+
|
710
|
+
if attempt < max_retries:
|
711
|
+
delay = base_delay * (2 ** attempt)
|
712
|
+
logger.info(f"Retrying in {delay} seconds...")
|
713
|
+
await asyncio.sleep(delay)
|
714
|
+
else:
|
715
|
+
logger.error("Max retries exceeded for validation errors. Server will continue but this session failed.")
|
716
|
+
return
|
717
|
+
else:
|
718
|
+
# This is a genuine error, log and re-raise
|
719
|
+
logger.error(f"MCP server session error: {e}", extra={
|
720
|
+
"structured_data": {
|
721
|
+
"error_type": type(e).__name__,
|
722
|
+
"error_message": str(e),
|
723
|
+
"traceback": traceback.format_exc()
|
724
|
+
}
|
725
|
+
})
|
726
|
+
raise
|
727
|
+
|
728
|
+
async def run(self) -> None:
|
729
|
+
"""Run the MCP server with robust error handling."""
|
730
|
+
logger.info("Starting server initialization...")
|
731
|
+
await self.initialize()
|
732
|
+
logger.info("Server initialization completed, starting MCP protocol...")
|
733
|
+
|
734
|
+
max_retries = 5
|
735
|
+
base_delay = 2.0 # seconds
|
736
|
+
|
737
|
+
for attempt in range(max_retries + 1):
|
738
|
+
try:
|
739
|
+
async with stdio_server() as (read_stream, write_stream):
|
740
|
+
logger.info(f"stdio_server context established (attempt {attempt + 1})")
|
741
|
+
initialization_options = self.server.create_initialization_options()
|
742
|
+
logger.debug(f"Initialization options: {initialization_options}")
|
743
|
+
|
744
|
+
await self._run_session_with_retry(read_stream, write_stream, initialization_options)
|
745
|
+
return # Success, exit retry loop
|
746
|
+
|
747
|
+
except KeyboardInterrupt:
|
748
|
+
logger.info("Server stopped by user interrupt")
|
749
|
+
return
|
750
|
+
|
751
|
+
except Exception as e:
|
752
|
+
import traceback
|
753
|
+
|
754
|
+
# Check if this is a wrapped validation error
|
755
|
+
error_str = str(e)
|
756
|
+
is_validation_error = (
|
757
|
+
"ValidationError" in error_str or
|
758
|
+
"Field required" in error_str or
|
759
|
+
"Input should be" in error_str or
|
760
|
+
"pydantic_core._pydantic_core.ValidationError" in error_str
|
761
|
+
)
|
762
|
+
|
763
|
+
if is_validation_error:
|
764
|
+
logger.warning(f"Detected validation error in session (attempt {attempt + 1}): Malformed client request", extra={
|
765
|
+
"structured_data": {
|
766
|
+
"error_type": "ValidationError",
|
767
|
+
"error_message": "Client sent malformed request (likely missing clientInfo)",
|
768
|
+
"attempt": attempt + 1,
|
769
|
+
"max_retries": max_retries,
|
770
|
+
"will_retry": attempt < max_retries
|
771
|
+
}
|
772
|
+
})
|
773
|
+
|
774
|
+
if attempt < max_retries:
|
775
|
+
delay = base_delay * (2 ** min(attempt, 3)) # Cap exponential growth
|
776
|
+
logger.info(f"Retrying server in {delay} seconds...")
|
777
|
+
await asyncio.sleep(delay)
|
778
|
+
continue
|
779
|
+
else:
|
780
|
+
logger.warning("Max retries exceeded for validation errors. Server is robust against malformed requests.")
|
781
|
+
return
|
782
|
+
else:
|
783
|
+
# This is a genuine fatal error
|
784
|
+
logger.error(f"Fatal server error: {e}", extra={
|
785
|
+
"structured_data": {
|
786
|
+
"error_type": type(e).__name__,
|
787
|
+
"error_message": str(e),
|
788
|
+
"traceback": traceback.format_exc()
|
789
|
+
}
|
790
|
+
})
|
791
|
+
raise
|
792
|
+
|
793
|
+
# Clean shutdown
|
794
|
+
await self.shutdown()
|
666
795
|
|
667
796
|
async def shutdown(self) -> None:
|
668
797
|
"""Clean shutdown of server resources."""
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: mcp-code-indexer
|
3
|
-
Version: 1.0.
|
3
|
+
Version: 1.0.4
|
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
|
Author: MCP Code Indexer Contributors
|
6
6
|
Maintainer: MCP Code Indexer Contributors
|
@@ -30,7 +30,7 @@ Requires-Python: >=3.9
|
|
30
30
|
Description-Content-Type: text/markdown
|
31
31
|
License-File: LICENSE
|
32
32
|
Requires-Dist: tiktoken>=0.9.0
|
33
|
-
Requires-Dist: mcp
|
33
|
+
Requires-Dist: mcp>=1.9.0
|
34
34
|
Requires-Dist: gitignore_parser==0.1.11
|
35
35
|
Requires-Dist: pydantic>=2.8.0
|
36
36
|
Requires-Dist: aiofiles==23.2.0
|
@@ -187,6 +187,7 @@ The server provides **8 powerful MCP tools** for intelligent codebase management
|
|
187
187
|
### Production Ready
|
188
188
|
- **Comprehensive error handling** with structured JSON logging
|
189
189
|
- **Async-first design** with proper resource cleanup
|
190
|
+
- **MCP protocol compliant** with clean stdio streams
|
190
191
|
- **Upstream inheritance** for fork workflows
|
191
192
|
- **Git integration** with .gitignore support
|
192
193
|
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/src/mcp_code_indexer/middleware/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/src/mcp_code_indexer.egg-info/dependency_links.txt
RENAMED
File without changes
|
{mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/src/mcp_code_indexer.egg-info/entry_points.txt
RENAMED
File without changes
|
{mcp_code_indexer-1.0.1 → mcp_code_indexer-1.0.4}/src/mcp_code_indexer.egg-info/top_level.txt
RENAMED
File without changes
|