mcp-code-indexer 1.6.5__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.
Files changed (41) hide show
  1. {mcp_code_indexer-1.6.5/src/mcp_code_indexer.egg-info → mcp_code_indexer-1.8.0}/PKG-INFO +3 -3
  2. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/README.md +2 -2
  3. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/pyproject.toml +1 -1
  4. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/git_hook_handler.py +145 -95
  5. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/logging_config.py +53 -0
  6. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/main.py +1 -1
  7. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0/src/mcp_code_indexer.egg-info}/PKG-INFO +3 -3
  8. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/LICENSE +0 -0
  9. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/MANIFEST.in +0 -0
  10. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/docs/api-reference.md +0 -0
  11. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/docs/architecture.md +0 -0
  12. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/docs/configuration.md +0 -0
  13. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/docs/contributing.md +0 -0
  14. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/docs/git-hook-setup.md +0 -0
  15. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/migrations/001_initial.sql +0 -0
  16. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/migrations/002_performance_indexes.sql +0 -0
  17. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/migrations/003_project_overviews.sql +0 -0
  18. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/requirements.txt +0 -0
  19. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/setup.cfg +0 -0
  20. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/setup.py +0 -0
  21. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/__init__.py +0 -0
  22. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/__main__.py +0 -0
  23. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/data/stop_words_english.txt +0 -0
  24. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/database/__init__.py +0 -0
  25. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/database/database.py +0 -0
  26. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/database/models.py +0 -0
  27. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/error_handler.py +0 -0
  28. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/file_scanner.py +0 -0
  29. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/merge_handler.py +0 -0
  30. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/middleware/__init__.py +0 -0
  31. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/middleware/error_middleware.py +0 -0
  32. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/server/__init__.py +0 -0
  33. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/server/mcp_server.py +0 -0
  34. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/tiktoken_cache/9b5ad71b2ce5302211f9c61530b329a4922fc6a4 +0 -0
  35. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/token_counter.py +0 -0
  36. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer/tools/__init__.py +0 -0
  37. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer.egg-info/SOURCES.txt +0 -0
  38. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer.egg-info/dependency_links.txt +0 -0
  39. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer.egg-info/entry_points.txt +0 -0
  40. {mcp_code_indexer-1.6.5 → mcp_code_indexer-1.8.0}/src/mcp_code_indexer.egg-info/requires.txt +0 -0
  41. {mcp_code_indexer-1.6.5 → 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.6.5
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
- [![PyPI version](https://badge.fury.io/py/mcp-code-indexer.svg?8)](https://badge.fury.io/py/mcp-code-indexer)
63
- [![Python](https://img.shields.io/pypi/pyversions/mcp-code-indexer.svg?8)](https://pypi.org/project/mcp-code-indexer/)
62
+ [![PyPI version](https://badge.fury.io/py/mcp-code-indexer.svg?10)](https://badge.fury.io/py/mcp-code-indexer)
63
+ [![Python](https://img.shields.io/pypi/pyversions/mcp-code-indexer.svg?10)](https://pypi.org/project/mcp-code-indexer/)
64
64
  [![License](https://img.shields.io/badge/License-MIT-blue.svg)](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
- [![PyPI version](https://badge.fury.io/py/mcp-code-indexer.svg?8)](https://badge.fury.io/py/mcp-code-indexer)
4
- [![Python](https://img.shields.io/pypi/pyversions/mcp-code-indexer.svg?8)](https://pypi.org/project/mcp-code-indexer/)
3
+ [![PyPI version](https://badge.fury.io/py/mcp-code-indexer.svg?10)](https://badge.fury.io/py/mcp-code-indexer)
4
+ [![Python](https://img.shields.io/pypi/pyversions/mcp-code-indexer.svg?10)](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. 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.6.5"
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"}
@@ -49,17 +49,18 @@ class GitHookHandler:
49
49
  OPENROUTER_API_URL = "https://openrouter.ai/api/v1/chat/completions"
50
50
  OPENROUTER_MODEL = "anthropic/claude-sonnet-4"
51
51
 
52
- def __init__(self, db_manager: DatabaseManager, cache_dir: Path):
52
+ def __init__(self, db_manager: DatabaseManager, cache_dir: Path, logger: Optional[logging.Logger] = None):
53
53
  """
54
54
  Initialize GitHookHandler.
55
55
 
56
56
  Args:
57
57
  db_manager: Database manager instance
58
58
  cache_dir: Cache directory for temporary files
59
+ logger: Logger instance to use (optional, creates default if not provided)
59
60
  """
60
61
  self.db_manager = db_manager
61
62
  self.cache_dir = cache_dir
62
- self.logger = logging.getLogger(__name__)
63
+ self.logger = logger if logger is not None else logging.getLogger(__name__)
63
64
  self.token_counter = TokenCounter()
64
65
 
65
66
  # Git hook specific settings
@@ -136,32 +137,26 @@ class GitHookHandler:
136
137
  self.logger.info(f"Current overview length: {len(current_overview) if current_overview else 0} characters")
137
138
  self.logger.info(f"Current descriptions count: {len(current_descriptions)}")
138
139
 
139
- # Build prompt for OpenRouter
140
- self.logger.info("Building analysis prompt...")
141
- prompt = self._build_githook_prompt(
142
- git_diff,
143
- commit_message,
144
- current_overview,
145
- current_descriptions,
146
- changed_files
147
- )
148
-
149
- # Log prompt details
150
- prompt_chars = len(prompt)
151
- prompt_tokens = self.token_counter.count_tokens(prompt)
152
- 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...")
153
142
 
154
- # Check total prompt token count
155
- if prompt_tokens > self.config["max_diff_tokens"]:
156
- self.logger.info(f"Skipping git hook update - prompt too large ({prompt_tokens} tokens > {self.config['max_diff_tokens']} limit)")
157
- return
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
+ )
158
147
 
159
- self.logger.info(f"Prompt size OK ({prompt_tokens} <= {self.config['max_diff_tokens']} tokens), calling OpenRouter...")
148
+ # Stage 2: Update file descriptions
149
+ file_updates = await self._analyze_file_updates(
150
+ git_diff, commit_message, current_descriptions, changed_files
151
+ )
160
152
 
161
- # Call OpenRouter API
162
- updates = await self._call_openrouter(prompt)
153
+ # Combine updates
154
+ updates = {
155
+ "file_updates": file_updates.get("file_updates", {}),
156
+ "overview_update": overview_updates.get("overview_update")
157
+ }
163
158
 
164
- self.logger.info(f"OpenRouter response received, processing updates...")
159
+ self.logger.info(f"Two-stage analysis completed, processing updates...")
165
160
 
166
161
  # Apply updates to database
167
162
  await self._apply_updates(project_info, updates)
@@ -440,101 +435,143 @@ class GitHookHandler:
440
435
  self.logger.warning(f"Failed to get file descriptions: {e}")
441
436
  return {}
442
437
 
443
- def _build_githook_prompt(
444
- self,
445
- git_diff: str,
446
- commit_message: str,
447
- overview: str,
448
- descriptions: Dict[str, str],
438
+ async def _analyze_overview_updates(
439
+ self,
440
+ git_diff: str,
441
+ commit_message: str,
442
+ current_overview: str,
449
443
  changed_files: List[str]
450
- ) -> str:
444
+ ) -> Dict[str, Any]:
451
445
  """
452
- Build prompt for OpenRouter API to analyze git changes.
446
+ Stage 1: Analyze if project overview needs updating.
453
447
 
454
448
  Args:
455
449
  git_diff: Git diff content
456
450
  commit_message: Commit message explaining the changes
457
- overview: Current project overview
458
- descriptions: Current file descriptions
451
+ current_overview: Current project overview
459
452
  changed_files: List of changed file paths
460
453
 
461
454
  Returns:
462
- Formatted prompt for the API
455
+ Dict with overview_update key
463
456
  """
464
- return f"""Analyze this git commit and update the file descriptions and project overview as needed.
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.
465
460
 
466
461
  COMMIT MESSAGE:
467
462
  {commit_message or "No commit message available"}
468
463
 
469
464
  CURRENT PROJECT OVERVIEW:
470
- {overview or "No overview available"}
465
+ {current_overview or "No overview available"}
471
466
 
472
- CURRENT FILE DESCRIPTIONS:
473
- {json.dumps(descriptions, indent=2)}
467
+ CHANGED FILES:
468
+ {', '.join(changed_files)}
474
469
 
475
470
  GIT DIFF:
476
471
  {git_diff}
477
472
 
478
- CHANGED FILES:
479
- {', '.join(changed_files)}
480
-
481
473
  INSTRUCTIONS:
482
474
 
483
- Use the COMMIT MESSAGE to understand the intent and context of the changes. The commit message explains what the developer was trying to accomplish.
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.
484
485
 
485
- 1. **File Descriptions**: Update descriptions for any files that have changed significantly. Consider both the diff content and the commit message context. Only include files that need actual description updates.
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
486
505
 
487
- 2. **Project Overview**: Update ONLY if there are major structural changes like:
488
- - New major features or components (which may be indicated by commit message)
489
- - Architectural changes (new patterns, frameworks, or approaches)
490
- - Significant dependency additions
491
- - New API endpoints or workflows
492
- - Changes to build/deployment processes
493
-
494
- Do NOT update overview for minor changes like bug fixes, small refactors, or documentation updates.
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.
495
534
 
496
- 3. **Overview Format**: If updating the overview, follow this structure with comprehensive narrative (10-20 pages of text):
535
+ COMMIT MESSAGE:
536
+ {commit_message or "No commit message available"}
497
537
 
498
- ````
499
- ## Directory Structure
500
- ```
501
- src/
502
- ├── api/ # REST API endpoints and middleware
503
- ├── models/ # Database models and business logic
504
- ├── services/ # External service integrations
505
- ├── utils/ # Shared utilities and helpers
506
- └── tests/ # Test suites
507
- ```
538
+ CURRENT FILE DESCRIPTIONS (for changed files only):
539
+ {json.dumps(relevant_descriptions, indent=2)}
508
540
 
509
- ## Architecture Overview
510
- [Describe how components interact, data flow, key design decisions]
541
+ CHANGED FILES:
542
+ {', '.join(changed_files)}
511
543
 
512
- ## Core Components
513
- ### API Layer
514
- [Details about API structure, authentication, routing]
544
+ GIT DIFF:
545
+ {git_diff}
515
546
 
516
- ### Data Model
517
- [Key entities, relationships, database design]
547
+ INSTRUCTIONS:
518
548
 
519
- ## Key Workflows
520
- 1. User Authentication Flow
521
- [Step-by-step description]
522
- 2. Data Processing Pipeline
523
- [How data moves through the system]
549
+ Use the COMMIT MESSAGE to understand the intent and context of the changes.
524
550
 
525
- [Continue with other sections...]
526
- ````
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.
527
552
 
528
- Return ONLY a JSON object in this exact format:
553
+ Return ONLY a JSON object:
529
554
  {{
530
555
  "file_updates": {{
531
556
  "path/to/file1.py": "Updated description for file1",
532
557
  "path/to/file2.js": "Updated description for file2"
533
- }},
534
- "overview_update": "Updated project overview text (or null if no update needed)"
535
- }}
558
+ }}
559
+ }}"""
536
560
 
537
- Return ONLY the JSON, no other text."""
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
538
575
 
539
576
  @retry(
540
577
  wait=wait_exponential(multiplier=1, min=4, max=60),
@@ -633,19 +670,32 @@ Return ONLY the JSON, no other text."""
633
670
  try:
634
671
  data = json.loads(response_text.strip())
635
672
 
636
- # Validate structure
637
- if "file_updates" not in data:
638
- raise ValueError("Missing 'file_updates' field")
639
- if "overview_update" not in data:
640
- raise ValueError("Missing 'overview_update' field")
641
-
642
- if not isinstance(data["file_updates"], dict):
643
- raise ValueError("'file_updates' must be a dictionary")
644
-
645
- # Validate descriptions
646
- for path, desc in data["file_updates"].items():
647
- if not isinstance(desc, str) or not desc.strip():
648
- raise ValueError(f"Invalid description for {path}")
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'")
649
699
 
650
700
  return data
651
701
 
@@ -163,6 +163,9 @@ def setup_command_logger(
163
163
 
164
164
  logger.addHandler(file_handler)
165
165
 
166
+ # Set up component loggers to also log to this command's log file
167
+ _setup_component_loggers_for_command(command_name, file_handler, structured_formatter)
168
+
166
169
  logger.info(f"=== {command_name.upper()} SESSION STARTED ===")
167
170
 
168
171
  except (OSError, PermissionError) as e:
@@ -175,6 +178,56 @@ def setup_command_logger(
175
178
  return logger
176
179
 
177
180
 
181
+ def _setup_component_loggers_for_command(
182
+ command_name: str,
183
+ file_handler: logging.Handler,
184
+ formatter: logging.Formatter
185
+ ) -> None:
186
+ """
187
+ Set up component loggers to also send logs to the command's log file.
188
+
189
+ Args:
190
+ command_name: Name of the command
191
+ file_handler: File handler to add to component loggers
192
+ formatter: Formatter to use for the handler
193
+ """
194
+ # List of component logger names that should also log to command files
195
+ component_loggers = [
196
+ "mcp_code_indexer.database.database",
197
+ "mcp_code_indexer.server.mcp_server",
198
+ "mcp_code_indexer.token_counter",
199
+ "mcp_code_indexer.file_scanner",
200
+ "mcp_code_indexer.error_handler",
201
+ "mcp_code_indexer.merge_handler"
202
+ ]
203
+
204
+ for component_logger_name in component_loggers:
205
+ component_logger = logging.getLogger(component_logger_name)
206
+
207
+ # Create a separate handler for this command to avoid interference
208
+ command_handler = logging.handlers.RotatingFileHandler(
209
+ file_handler.baseFilename,
210
+ maxBytes=file_handler.maxBytes,
211
+ backupCount=file_handler.backupCount,
212
+ encoding='utf-8'
213
+ )
214
+ command_handler.setLevel(logging.DEBUG)
215
+ command_handler.setFormatter(formatter)
216
+
217
+ # Add a marker to identify which command this handler belongs to
218
+ command_handler._command_name = command_name
219
+
220
+ # Remove any existing handlers for this command (in case of multiple calls)
221
+ existing_handlers = [h for h in component_logger.handlers if hasattr(h, '_command_name') and h._command_name == command_name]
222
+ for handler in existing_handlers:
223
+ component_logger.removeHandler(handler)
224
+ handler.close()
225
+
226
+ # Add the new handler
227
+ component_logger.addHandler(command_handler)
228
+ component_logger.setLevel(logging.DEBUG) # Ensure component loggers capture all levels
229
+
230
+
178
231
  def log_performance_metrics(
179
232
  logger: logging.Logger,
180
233
  operation: str,
@@ -499,7 +499,7 @@ async def handle_githook(args: argparse.Namespace) -> None:
499
499
  logger.debug("Database initialized successfully")
500
500
 
501
501
  # Initialize git hook handler
502
- git_handler = GitHookHandler(db_manager, cache_dir)
502
+ git_handler = GitHookHandler(db_manager, cache_dir, logger)
503
503
  logger.debug("Git hook handler initialized")
504
504
 
505
505
  # Run git hook analysis
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcp-code-indexer
3
- Version: 1.6.5
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
- [![PyPI version](https://badge.fury.io/py/mcp-code-indexer.svg?8)](https://badge.fury.io/py/mcp-code-indexer)
63
- [![Python](https://img.shields.io/pypi/pyversions/mcp-code-indexer.svg?8)](https://pypi.org/project/mcp-code-indexer/)
62
+ [![PyPI version](https://badge.fury.io/py/mcp-code-indexer.svg?10)](https://badge.fury.io/py/mcp-code-indexer)
63
+ [![Python](https://img.shields.io/pypi/pyversions/mcp-code-indexer.svg?10)](https://pypi.org/project/mcp-code-indexer/)
64
64
  [![License](https://img.shields.io/badge/License-MIT-blue.svg)](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.