mcp-code-indexer 1.7.0__tar.gz → 1.8.0__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.7.0/src/mcp_code_indexer.egg-info → mcp_code_indexer-1.8.0}/PKG-INFO +3 -3
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/README.md +2 -2
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/pyproject.toml +1 -1
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/git_hook_handler.py +142 -93
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0/src/mcp_code_indexer.egg-info}/PKG-INFO +3 -3
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/LICENSE +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/MANIFEST.in +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/docs/api-reference.md +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/docs/architecture.md +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/docs/configuration.md +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/docs/contributing.md +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/docs/git-hook-setup.md +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/migrations/001_initial.sql +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/migrations/002_performance_indexes.sql +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/migrations/003_project_overviews.sql +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/requirements.txt +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/setup.cfg +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/setup.py +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/__init__.py +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/__main__.py +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/data/stop_words_english.txt +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/database/__init__.py +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/database/database.py +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/database/models.py +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/error_handler.py +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/file_scanner.py +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/logging_config.py +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/main.py +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/merge_handler.py +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/middleware/__init__.py +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/middleware/error_middleware.py +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/server/__init__.py +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/server/mcp_server.py +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/tiktoken_cache/9b5ad71b2ce5302211f9c61530b329a4922fc6a4 +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/token_counter.py +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/tools/__init__.py +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer.egg-info/SOURCES.txt +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer.egg-info/dependency_links.txt +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer.egg-info/entry_points.txt +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer.egg-info/requires.txt +0 -0
- {mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/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.
|
3
|
+
Version: 1.8.0
|
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
|
@@ -59,8 +59,8 @@ Dynamic: requires-python
|
|
59
59
|
|
60
60
|
# MCP Code Indexer 🚀
|
61
61
|
|
62
|
-
[](https://badge.fury.io/py/mcp-code-indexer)
|
63
|
+
[](https://pypi.org/project/mcp-code-indexer/)
|
64
64
|
[](https://opensource.org/licenses/MIT)
|
65
65
|
|
66
66
|
A production-ready **Model Context Protocol (MCP) server** that revolutionizes how AI agents navigate and understand codebases. Instead of repeatedly scanning files, agents get instant access to intelligent descriptions, semantic search, and context-aware recommendations.
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# MCP Code Indexer 🚀
|
2
2
|
|
3
|
-
[](https://badge.fury.io/py/mcp-code-indexer)
|
4
|
+
[](https://pypi.org/project/mcp-code-indexer/)
|
5
5
|
[](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. Instead of repeatedly scanning files, agents get instant access to intelligent descriptions, semantic search, and context-aware recommendations.
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = "mcp-code-indexer"
|
7
|
-
version = "1.
|
7
|
+
version = "1.8.0"
|
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"}
|
@@ -137,32 +137,26 @@ class GitHookHandler:
|
|
137
137
|
self.logger.info(f"Current overview length: {len(current_overview) if current_overview else 0} characters")
|
138
138
|
self.logger.info(f"Current descriptions count: {len(current_descriptions)}")
|
139
139
|
|
140
|
-
#
|
141
|
-
self.logger.info("
|
142
|
-
prompt = self._build_githook_prompt(
|
143
|
-
git_diff,
|
144
|
-
commit_message,
|
145
|
-
current_overview,
|
146
|
-
current_descriptions,
|
147
|
-
changed_files
|
148
|
-
)
|
149
|
-
|
150
|
-
# Log prompt details
|
151
|
-
prompt_chars = len(prompt)
|
152
|
-
prompt_tokens = self.token_counter.count_tokens(prompt)
|
153
|
-
self.logger.info(f"Analysis prompt: {prompt_chars} characters, {prompt_tokens} tokens")
|
140
|
+
# Use two-stage approach for large codebases
|
141
|
+
self.logger.info("Starting two-stage analysis approach...")
|
154
142
|
|
155
|
-
# Check
|
156
|
-
|
157
|
-
|
158
|
-
|
143
|
+
# Stage 1: Check if overview needs updating
|
144
|
+
overview_updates = await self._analyze_overview_updates(
|
145
|
+
git_diff, commit_message, current_overview, changed_files
|
146
|
+
)
|
159
147
|
|
160
|
-
|
148
|
+
# Stage 2: Update file descriptions
|
149
|
+
file_updates = await self._analyze_file_updates(
|
150
|
+
git_diff, commit_message, current_descriptions, changed_files
|
151
|
+
)
|
161
152
|
|
162
|
-
#
|
163
|
-
updates =
|
153
|
+
# Combine updates
|
154
|
+
updates = {
|
155
|
+
"file_updates": file_updates.get("file_updates", {}),
|
156
|
+
"overview_update": overview_updates.get("overview_update")
|
157
|
+
}
|
164
158
|
|
165
|
-
self.logger.info(f"
|
159
|
+
self.logger.info(f"Two-stage analysis completed, processing updates...")
|
166
160
|
|
167
161
|
# Apply updates to database
|
168
162
|
await self._apply_updates(project_info, updates)
|
@@ -441,101 +435,143 @@ class GitHookHandler:
|
|
441
435
|
self.logger.warning(f"Failed to get file descriptions: {e}")
|
442
436
|
return {}
|
443
437
|
|
444
|
-
def
|
445
|
-
self,
|
446
|
-
git_diff: str,
|
447
|
-
commit_message: str,
|
448
|
-
|
449
|
-
descriptions: Dict[str, str],
|
438
|
+
async def _analyze_overview_updates(
|
439
|
+
self,
|
440
|
+
git_diff: str,
|
441
|
+
commit_message: str,
|
442
|
+
current_overview: str,
|
450
443
|
changed_files: List[str]
|
451
|
-
) -> str:
|
444
|
+
) -> Dict[str, Any]:
|
452
445
|
"""
|
453
|
-
|
446
|
+
Stage 1: Analyze if project overview needs updating.
|
454
447
|
|
455
448
|
Args:
|
456
449
|
git_diff: Git diff content
|
457
450
|
commit_message: Commit message explaining the changes
|
458
|
-
|
459
|
-
descriptions: Current file descriptions
|
451
|
+
current_overview: Current project overview
|
460
452
|
changed_files: List of changed file paths
|
461
453
|
|
462
454
|
Returns:
|
463
|
-
|
455
|
+
Dict with overview_update key
|
464
456
|
"""
|
465
|
-
|
457
|
+
self.logger.info("Stage 1: Analyzing overview updates...")
|
458
|
+
|
459
|
+
prompt = f"""Analyze this git commit to determine if the project overview needs updating.
|
466
460
|
|
467
461
|
COMMIT MESSAGE:
|
468
462
|
{commit_message or "No commit message available"}
|
469
463
|
|
470
464
|
CURRENT PROJECT OVERVIEW:
|
471
|
-
{
|
465
|
+
{current_overview or "No overview available"}
|
472
466
|
|
473
|
-
|
474
|
-
{
|
467
|
+
CHANGED FILES:
|
468
|
+
{', '.join(changed_files)}
|
475
469
|
|
476
470
|
GIT DIFF:
|
477
471
|
{git_diff}
|
478
472
|
|
479
|
-
CHANGED FILES:
|
480
|
-
{', '.join(changed_files)}
|
481
|
-
|
482
473
|
INSTRUCTIONS:
|
483
474
|
|
484
|
-
|
475
|
+
Update project overview ONLY if there are major structural changes like:
|
476
|
+
- New major features or components (indicated by commit message or new directories)
|
477
|
+
- Architectural changes (new patterns, frameworks, or approaches)
|
478
|
+
- Significant dependency additions (Cargo.toml, package.json, requirements.txt changes)
|
479
|
+
- New API endpoints or workflows
|
480
|
+
- Changes to build/deployment processes
|
481
|
+
|
482
|
+
Do NOT update for: bug fixes, small refactors, documentation updates, version bumps.
|
483
|
+
|
484
|
+
If updating, provide comprehensive narrative (10-20 pages of text) with directory structure, architecture, components, and workflows.
|
485
485
|
|
486
|
-
|
486
|
+
Return ONLY a JSON object:
|
487
|
+
{{
|
488
|
+
"overview_update": "Updated overview text" or null
|
489
|
+
}}"""
|
490
|
+
|
491
|
+
# Log prompt details
|
492
|
+
prompt_chars = len(prompt)
|
493
|
+
prompt_tokens = self.token_counter.count_tokens(prompt)
|
494
|
+
self.logger.info(f"Stage 1 prompt: {prompt_chars} characters, {prompt_tokens} tokens")
|
495
|
+
|
496
|
+
if prompt_tokens > self.config["max_diff_tokens"]:
|
497
|
+
self.logger.warning(f"Stage 1 prompt too large ({prompt_tokens} tokens), skipping overview analysis")
|
498
|
+
return {"overview_update": None}
|
499
|
+
|
500
|
+
# Call OpenRouter API
|
501
|
+
result = await self._call_openrouter(prompt)
|
502
|
+
self.logger.info("Stage 1 completed: overview analysis")
|
503
|
+
|
504
|
+
return result
|
487
505
|
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
506
|
+
async def _analyze_file_updates(
|
507
|
+
self,
|
508
|
+
git_diff: str,
|
509
|
+
commit_message: str,
|
510
|
+
current_descriptions: Dict[str, str],
|
511
|
+
changed_files: List[str]
|
512
|
+
) -> Dict[str, Any]:
|
513
|
+
"""
|
514
|
+
Stage 2: Analyze file description updates.
|
515
|
+
|
516
|
+
Args:
|
517
|
+
git_diff: Git diff content
|
518
|
+
commit_message: Commit message explaining the changes
|
519
|
+
current_descriptions: Current file descriptions for changed files only
|
520
|
+
changed_files: List of changed file paths
|
521
|
+
|
522
|
+
Returns:
|
523
|
+
Dict with file_updates key
|
524
|
+
"""
|
525
|
+
self.logger.info("Stage 2: Analyzing file description updates...")
|
526
|
+
|
527
|
+
# Only include descriptions for changed files to reduce token usage
|
528
|
+
relevant_descriptions = {
|
529
|
+
path: desc for path, desc in current_descriptions.items()
|
530
|
+
if path in changed_files
|
531
|
+
}
|
532
|
+
|
533
|
+
prompt = f"""Analyze this git commit and update file descriptions for changed files.
|
496
534
|
|
497
|
-
|
535
|
+
COMMIT MESSAGE:
|
536
|
+
{commit_message or "No commit message available"}
|
498
537
|
|
499
|
-
|
500
|
-
|
501
|
-
```
|
502
|
-
src/
|
503
|
-
├── api/ # REST API endpoints and middleware
|
504
|
-
├── models/ # Database models and business logic
|
505
|
-
├── services/ # External service integrations
|
506
|
-
├── utils/ # Shared utilities and helpers
|
507
|
-
└── tests/ # Test suites
|
508
|
-
```
|
538
|
+
CURRENT FILE DESCRIPTIONS (for changed files only):
|
539
|
+
{json.dumps(relevant_descriptions, indent=2)}
|
509
540
|
|
510
|
-
|
511
|
-
|
541
|
+
CHANGED FILES:
|
542
|
+
{', '.join(changed_files)}
|
512
543
|
|
513
|
-
|
514
|
-
|
515
|
-
[Details about API structure, authentication, routing]
|
544
|
+
GIT DIFF:
|
545
|
+
{git_diff}
|
516
546
|
|
517
|
-
|
518
|
-
[Key entities, relationships, database design]
|
547
|
+
INSTRUCTIONS:
|
519
548
|
|
520
|
-
|
521
|
-
1. User Authentication Flow
|
522
|
-
[Step-by-step description]
|
523
|
-
2. Data Processing Pipeline
|
524
|
-
[How data moves through the system]
|
549
|
+
Use the COMMIT MESSAGE to understand the intent and context of the changes.
|
525
550
|
|
526
|
-
|
527
|
-
````
|
551
|
+
Update descriptions for files that have changed significantly. Consider both the diff content and commit message context. Only include files that need actual description updates.
|
528
552
|
|
529
|
-
Return ONLY a JSON object
|
553
|
+
Return ONLY a JSON object:
|
530
554
|
{{
|
531
555
|
"file_updates": {{
|
532
556
|
"path/to/file1.py": "Updated description for file1",
|
533
557
|
"path/to/file2.js": "Updated description for file2"
|
534
|
-
}}
|
535
|
-
|
536
|
-
}}
|
558
|
+
}}
|
559
|
+
}}"""
|
537
560
|
|
538
|
-
|
561
|
+
# Log prompt details
|
562
|
+
prompt_chars = len(prompt)
|
563
|
+
prompt_tokens = self.token_counter.count_tokens(prompt)
|
564
|
+
self.logger.info(f"Stage 2 prompt: {prompt_chars} characters, {prompt_tokens} tokens")
|
565
|
+
|
566
|
+
if prompt_tokens > self.config["max_diff_tokens"]:
|
567
|
+
self.logger.warning(f"Stage 2 prompt too large ({prompt_tokens} tokens), skipping file analysis")
|
568
|
+
return {"file_updates": {}}
|
569
|
+
|
570
|
+
# Call OpenRouter API
|
571
|
+
result = await self._call_openrouter(prompt)
|
572
|
+
self.logger.info("Stage 2 completed: file description analysis")
|
573
|
+
|
574
|
+
return result
|
539
575
|
|
540
576
|
@retry(
|
541
577
|
wait=wait_exponential(multiplier=1, min=4, max=60),
|
@@ -634,19 +670,32 @@ Return ONLY the JSON, no other text."""
|
|
634
670
|
try:
|
635
671
|
data = json.loads(response_text.strip())
|
636
672
|
|
637
|
-
#
|
638
|
-
if "file_updates"
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
673
|
+
# Handle both single-stage and two-stage responses
|
674
|
+
if "file_updates" in data and "overview_update" in data:
|
675
|
+
# Original single-stage format
|
676
|
+
if not isinstance(data["file_updates"], dict):
|
677
|
+
raise ValueError("'file_updates' must be a dictionary")
|
678
|
+
|
679
|
+
# Validate descriptions
|
680
|
+
for path, desc in data["file_updates"].items():
|
681
|
+
if not isinstance(desc, str) or not desc.strip():
|
682
|
+
raise ValueError(f"Invalid description for {path}")
|
683
|
+
|
684
|
+
elif "file_updates" in data:
|
685
|
+
# Stage 2 format (file updates only)
|
686
|
+
if not isinstance(data["file_updates"], dict):
|
687
|
+
raise ValueError("'file_updates' must be a dictionary")
|
688
|
+
|
689
|
+
# Validate descriptions
|
690
|
+
for path, desc in data["file_updates"].items():
|
691
|
+
if not isinstance(desc, str) or not desc.strip():
|
692
|
+
raise ValueError(f"Invalid description for {path}")
|
693
|
+
|
694
|
+
elif "overview_update" in data:
|
695
|
+
# Stage 1 format (overview only) - overview_update can be null
|
696
|
+
pass
|
697
|
+
else:
|
698
|
+
raise ValueError("Response must contain 'file_updates' and/or 'overview_update'")
|
650
699
|
|
651
700
|
return data
|
652
701
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: mcp-code-indexer
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.8.0
|
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
|
@@ -59,8 +59,8 @@ Dynamic: requires-python
|
|
59
59
|
|
60
60
|
# MCP Code Indexer 🚀
|
61
61
|
|
62
|
-
[](https://badge.fury.io/py/mcp-code-indexer)
|
63
|
+
[](https://pypi.org/project/mcp-code-indexer/)
|
64
64
|
[](https://opensource.org/licenses/MIT)
|
65
65
|
|
66
66
|
A production-ready **Model Context Protocol (MCP) server** that revolutionizes how AI agents navigate and understand codebases. Instead of repeatedly scanning files, agents get instant access to intelligent descriptions, semantic search, and context-aware recommendations.
|
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.7.0 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/data/stop_words_english.txt
RENAMED
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.7.0 → mcp_code_indexer-1.8.0}/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
|
File without changes
|
{mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer.egg-info/dependency_links.txt
RENAMED
File without changes
|
{mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer.egg-info/entry_points.txt
RENAMED
File without changes
|
{mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer.egg-info/requires.txt
RENAMED
File without changes
|
{mcp_code_indexer-1.7.0 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer.egg-info/top_level.txt
RENAMED
File without changes
|