mcp-code-indexer 4.0.1__tar.gz → 4.0.2__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 (46) hide show
  1. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/PKG-INFO +24 -24
  2. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/README.md +23 -23
  3. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/pyproject.toml +18 -6
  4. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/__init__.py +7 -5
  5. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/ask_handler.py +2 -2
  6. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/claude_api_handler.py +10 -5
  7. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/cleanup_manager.py +20 -12
  8. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/commands/makelocal.py +85 -63
  9. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/data/stop_words_english.txt +1 -1
  10. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/database/connection_health.py +29 -20
  11. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/database/database.py +44 -31
  12. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/database/database_factory.py +19 -20
  13. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/database/exceptions.py +10 -10
  14. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/database/models.py +1 -0
  15. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/database/path_resolver.py +22 -21
  16. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/database/retry_executor.py +37 -19
  17. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/deepask_handler.py +3 -3
  18. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/error_handler.py +46 -20
  19. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/file_scanner.py +15 -12
  20. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/git_hook_handler.py +71 -76
  21. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/logging_config.py +13 -5
  22. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/main.py +25 -22
  23. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/middleware/auth.py +47 -43
  24. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/middleware/error_middleware.py +15 -15
  25. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/middleware/logging.py +44 -42
  26. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/middleware/security.py +84 -76
  27. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/migrations/002_performance_indexes.sql +1 -1
  28. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/migrations/004_remove_branch_dependency.sql +14 -14
  29. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/query_preprocessor.py +2 -2
  30. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/server/mcp_server.py +155 -94
  31. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/transport/base.py +19 -17
  32. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/transport/http_transport.py +89 -76
  33. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/transport/stdio_transport.py +12 -8
  34. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/LICENSE +0 -0
  35. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/__main__.py +0 -0
  36. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/commands/__init__.py +0 -0
  37. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/database/__init__.py +0 -0
  38. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/middleware/__init__.py +1 -1
  39. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/migrations/001_initial.sql +0 -0
  40. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/migrations/003_project_overviews.sql +0 -0
  41. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/migrations/005_remove_git_remotes.sql +0 -0
  42. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/server/__init__.py +0 -0
  43. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/tiktoken_cache/9b5ad71b2ce5302211f9c61530b329a4922fc6a4 +0 -0
  44. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/token_counter.py +0 -0
  45. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/tools/__init__.py +0 -0
  46. {mcp_code_indexer-4.0.1 → mcp_code_indexer-4.0.2}/src/mcp_code_indexer/transport/__init__.py +1 -1
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: mcp-code-indexer
3
- Version: 4.0.1
3
+ Version: 4.0.2
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
@@ -43,8 +43,8 @@ Description-Content-Type: text/markdown
43
43
 
44
44
  # MCP Code Indexer 🚀
45
45
 
46
- [![PyPI version](https://badge.fury.io/py/mcp-code-indexer.svg?44)](https://badge.fury.io/py/mcp-code-indexer)
47
- [![Python](https://img.shields.io/pypi/pyversions/mcp-code-indexer.svg?44)](https://pypi.org/project/mcp-code-indexer/)
46
+ [![PyPI version](https://badge.fury.io/py/mcp-code-indexer.svg?45)](https://badge.fury.io/py/mcp-code-indexer)
47
+ [![Python](https://img.shields.io/pypi/pyversions/mcp-code-indexer.svg?45)](https://pypi.org/project/mcp-code-indexer/)
48
48
  [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
49
49
 
50
50
  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.
@@ -183,17 +183,17 @@ The git hook integration provides intelligent automation:
183
183
 
184
184
  - **📊 Git Analysis**: Automatically analyzes git diffs after commits/merges
185
185
  - **🤖 AI Processing**: Uses OpenRouter API with Anthropic's Claude Sonnet 4
186
- - **⚡ Smart Updates**: Only processes files that actually changed
186
+ - **⚡ Smart Updates**: Only processes files that actually changed
187
187
  - **🔄 Overview Maintenance**: Updates project overview when structure changes
188
188
  - **🛡️ Error Isolation**: Git operations continue even if indexing fails
189
189
  - **⏱️ Rate Limiting**: Built-in retry logic with exponential backoff
190
190
 
191
191
  ### 🎯 Key Benefits
192
192
 
193
- 💡 **Zero Manual Work**: Descriptions stay current without any effort
194
- ⚡ **Performance**: Only analyzes changed files, not entire codebase
195
- 🔒 **Reliability**: Robust error handling ensures git operations never fail
196
- 🎛️ **Configurable**: Support for custom models and timeout settings
193
+ 💡 **Zero Manual Work**: Descriptions stay current without any effort
194
+ ⚡ **Performance**: Only analyzes changed files, not entire codebase
195
+ 🔒 **Reliability**: Robust error handling ensures git operations never fail
196
+ 🎛️ **Configurable**: Support for custom models and timeout settings
197
197
 
198
198
  **Learn More**: See [Git Hook Setup Guide](docs/git-hook-setup.md) for complete configuration options and troubleshooting.
199
199
 
@@ -369,14 +369,14 @@ Comprehensive documentation organized by user journey and expertise level.
369
369
 
370
370
  ### 📋 Quick References
371
371
  - **[Examples & Integrations](examples/)** - Ready-to-use configurations
372
- - **[Troubleshooting](#🚨-troubleshooting)** - Common issues & solutions
372
+ - **[Troubleshooting](#🚨-troubleshooting)** - Common issues & solutions
373
373
  - **[API Tools Summary](#🛠️-mcp-tools-available)** - All 11 tools at a glance
374
374
 
375
375
  **📚 Reading Paths:**
376
376
  - **New to MCP Code Indexer?** Quick Start → API Reference → HTTP API → Q&A Interface
377
377
  - **Web developers?** Quick Start → HTTP API Reference → Q&A Interface → Git Hooks
378
378
  - **AI/ML engineers?** Quick Start → Q&A Interface → API Reference → Git Hooks
379
- - **Setting up for a team?** CLI Reference → Configuration → Administrative Commands → Monitoring
379
+ - **Setting up for a team?** CLI Reference → Configuration → Administrative Commands → Monitoring
380
380
  - **Contributing to the project?** Architecture → Contributing → API Reference
381
381
 
382
382
  ## 🚦 System Requirements
@@ -390,7 +390,7 @@ Comprehensive documentation organized by user journey and expertise level.
390
390
 
391
391
  Tested with codebases up to **10,000 files**:
392
392
  - File description retrieval: **< 10ms**
393
- - Full-text search: **< 100ms**
393
+ - Full-text search: **< 100ms**
394
394
  - Codebase overview generation: **< 2s**
395
395
  - Merge conflict detection: **< 5s**
396
396
 
@@ -460,11 +460,11 @@ async def analyze_codebase(project_path):
460
460
  "projectName": "my-project",
461
461
  "folderPath": project_path
462
462
  })
463
-
463
+
464
464
  if size_info["isLarge"]:
465
465
  # Use search for large codebases
466
466
  results = await mcp_client.call_tool("search_descriptions", {
467
- "projectName": "my-project",
467
+ "projectName": "my-project",
468
468
  "folderPath": project_path,
469
469
  "query": "authentication logic"
470
470
  })
@@ -484,18 +484,18 @@ async def analyze_codebase(project_path):
484
484
  python -c "
485
485
  import asyncio
486
486
  from mcp_client import MCPClient
487
-
487
+
488
488
  async def update_descriptions():
489
489
  client = MCPClient('mcp-code-indexer')
490
-
490
+
491
491
  # Find files without descriptions
492
492
  missing = await client.call_tool('find_missing_descriptions', {
493
493
  'projectName': '${{ github.repository }}',
494
494
  'folderPath': '.'
495
495
  })
496
-
496
+
497
497
  # Process with AI and update...
498
-
498
+
499
499
  asyncio.run(update_descriptions())
500
500
  "
501
501
  ```
@@ -606,7 +606,7 @@ mcp-code-indexer --map PROJECT_NAME
606
606
  ## 🛡️ Security Features
607
607
 
608
608
  - **Input validation** on all MCP tool parameters
609
- - **SQL injection protection** via parameterized queries
609
+ - **SQL injection protection** via parameterized queries
610
610
  - **File system sandboxing** with .gitignore respect
611
611
  - **Error sanitization** to prevent information leakage
612
612
  - **Async resource cleanup** to prevent memory leaks
@@ -638,7 +638,7 @@ Ready to supercharge your AI agents with intelligent codebase navigation?
638
638
  2. **[Master the API tools](docs/api-reference.md)** - Learn all 11 tools with examples
639
639
  3. **[Try HTTP API access](docs/http-api.md)** - REST API for web applications
640
640
  4. **[Explore AI-powered Q&A](docs/qa-interface.md)** - Ask questions about your code
641
- 5. **[Set up git hooks](docs/git-hook-setup.md)** - Automate your workflow
641
+ 5. **[Set up git hooks](docs/git-hook-setup.md)** - Automate your workflow
642
642
 
643
643
  **👥 Setting up for a team?**
644
644
  1. **[Learn all CLI commands](docs/cli-reference.md)** - Complete command reference
@@ -661,7 +661,7 @@ Ready to supercharge your AI agents with intelligent codebase navigation?
661
661
 
662
662
  We welcome contributions! See our **[Contributing Guide](docs/contributing.md)** for:
663
663
  - Development setup
664
- - Code style guidelines
664
+ - Code style guidelines
665
665
  - Testing requirements
666
666
  - Pull request process
667
667
 
@@ -672,7 +672,7 @@ MIT License - see **[LICENSE](LICENSE)** for details.
672
672
  ## 🙏 Built With
673
673
 
674
674
  - **[Model Context Protocol](https://github.com/modelcontextprotocol/python-sdk)** - The foundation for tool integration
675
- - **[tiktoken](https://pypi.org/project/tiktoken/)** - Fast BPE tokenization
675
+ - **[tiktoken](https://pypi.org/project/tiktoken/)** - Fast BPE tokenization
676
676
  - **[aiosqlite](https://pypi.org/project/aiosqlite/)** - Async SQLite operations
677
677
  - **[aiohttp](https://pypi.org/project/aiohttp/)** - Async HTTP client for OpenRouter API
678
678
  - **[tenacity](https://pypi.org/project/tenacity/)** - Robust retry logic and rate limiting
@@ -680,9 +680,9 @@ MIT License - see **[LICENSE](LICENSE)** for details.
680
680
 
681
681
  ---
682
682
 
683
- **Transform how your AI agents understand code!** 🚀
683
+ **Transform how your AI agents understand code!** 🚀
684
684
 
685
- 🎯 **New User?** [Get started in 2 minutes](#-quick-start)
686
- 👨‍💻 **Developer?** [Explore the complete API](docs/api-reference.md)
685
+ 🎯 **New User?** [Get started in 2 minutes](#-quick-start)
686
+ 👨‍💻 **Developer?** [Explore the complete API](docs/api-reference.md)
687
687
  🔧 **Production?** [Deploy with confidence](docs/configuration.md)
688
688
 
@@ -1,7 +1,7 @@
1
1
  # MCP Code Indexer 🚀
2
2
 
3
- [![PyPI version](https://badge.fury.io/py/mcp-code-indexer.svg?44)](https://badge.fury.io/py/mcp-code-indexer)
4
- [![Python](https://img.shields.io/pypi/pyversions/mcp-code-indexer.svg?44)](https://pypi.org/project/mcp-code-indexer/)
3
+ [![PyPI version](https://badge.fury.io/py/mcp-code-indexer.svg?45)](https://badge.fury.io/py/mcp-code-indexer)
4
+ [![Python](https://img.shields.io/pypi/pyversions/mcp-code-indexer.svg?45)](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.
@@ -140,17 +140,17 @@ The git hook integration provides intelligent automation:
140
140
 
141
141
  - **📊 Git Analysis**: Automatically analyzes git diffs after commits/merges
142
142
  - **🤖 AI Processing**: Uses OpenRouter API with Anthropic's Claude Sonnet 4
143
- - **⚡ Smart Updates**: Only processes files that actually changed
143
+ - **⚡ Smart Updates**: Only processes files that actually changed
144
144
  - **🔄 Overview Maintenance**: Updates project overview when structure changes
145
145
  - **🛡️ Error Isolation**: Git operations continue even if indexing fails
146
146
  - **⏱️ Rate Limiting**: Built-in retry logic with exponential backoff
147
147
 
148
148
  ### 🎯 Key Benefits
149
149
 
150
- 💡 **Zero Manual Work**: Descriptions stay current without any effort
151
- ⚡ **Performance**: Only analyzes changed files, not entire codebase
152
- 🔒 **Reliability**: Robust error handling ensures git operations never fail
153
- 🎛️ **Configurable**: Support for custom models and timeout settings
150
+ 💡 **Zero Manual Work**: Descriptions stay current without any effort
151
+ ⚡ **Performance**: Only analyzes changed files, not entire codebase
152
+ 🔒 **Reliability**: Robust error handling ensures git operations never fail
153
+ 🎛️ **Configurable**: Support for custom models and timeout settings
154
154
 
155
155
  **Learn More**: See [Git Hook Setup Guide](docs/git-hook-setup.md) for complete configuration options and troubleshooting.
156
156
 
@@ -326,14 +326,14 @@ Comprehensive documentation organized by user journey and expertise level.
326
326
 
327
327
  ### 📋 Quick References
328
328
  - **[Examples & Integrations](examples/)** - Ready-to-use configurations
329
- - **[Troubleshooting](#🚨-troubleshooting)** - Common issues & solutions
329
+ - **[Troubleshooting](#🚨-troubleshooting)** - Common issues & solutions
330
330
  - **[API Tools Summary](#🛠️-mcp-tools-available)** - All 11 tools at a glance
331
331
 
332
332
  **📚 Reading Paths:**
333
333
  - **New to MCP Code Indexer?** Quick Start → API Reference → HTTP API → Q&A Interface
334
334
  - **Web developers?** Quick Start → HTTP API Reference → Q&A Interface → Git Hooks
335
335
  - **AI/ML engineers?** Quick Start → Q&A Interface → API Reference → Git Hooks
336
- - **Setting up for a team?** CLI Reference → Configuration → Administrative Commands → Monitoring
336
+ - **Setting up for a team?** CLI Reference → Configuration → Administrative Commands → Monitoring
337
337
  - **Contributing to the project?** Architecture → Contributing → API Reference
338
338
 
339
339
  ## 🚦 System Requirements
@@ -347,7 +347,7 @@ Comprehensive documentation organized by user journey and expertise level.
347
347
 
348
348
  Tested with codebases up to **10,000 files**:
349
349
  - File description retrieval: **< 10ms**
350
- - Full-text search: **< 100ms**
350
+ - Full-text search: **< 100ms**
351
351
  - Codebase overview generation: **< 2s**
352
352
  - Merge conflict detection: **< 5s**
353
353
 
@@ -417,11 +417,11 @@ async def analyze_codebase(project_path):
417
417
  "projectName": "my-project",
418
418
  "folderPath": project_path
419
419
  })
420
-
420
+
421
421
  if size_info["isLarge"]:
422
422
  # Use search for large codebases
423
423
  results = await mcp_client.call_tool("search_descriptions", {
424
- "projectName": "my-project",
424
+ "projectName": "my-project",
425
425
  "folderPath": project_path,
426
426
  "query": "authentication logic"
427
427
  })
@@ -441,18 +441,18 @@ async def analyze_codebase(project_path):
441
441
  python -c "
442
442
  import asyncio
443
443
  from mcp_client import MCPClient
444
-
444
+
445
445
  async def update_descriptions():
446
446
  client = MCPClient('mcp-code-indexer')
447
-
447
+
448
448
  # Find files without descriptions
449
449
  missing = await client.call_tool('find_missing_descriptions', {
450
450
  'projectName': '${{ github.repository }}',
451
451
  'folderPath': '.'
452
452
  })
453
-
453
+
454
454
  # Process with AI and update...
455
-
455
+
456
456
  asyncio.run(update_descriptions())
457
457
  "
458
458
  ```
@@ -563,7 +563,7 @@ mcp-code-indexer --map PROJECT_NAME
563
563
  ## 🛡️ Security Features
564
564
 
565
565
  - **Input validation** on all MCP tool parameters
566
- - **SQL injection protection** via parameterized queries
566
+ - **SQL injection protection** via parameterized queries
567
567
  - **File system sandboxing** with .gitignore respect
568
568
  - **Error sanitization** to prevent information leakage
569
569
  - **Async resource cleanup** to prevent memory leaks
@@ -595,7 +595,7 @@ Ready to supercharge your AI agents with intelligent codebase navigation?
595
595
  2. **[Master the API tools](docs/api-reference.md)** - Learn all 11 tools with examples
596
596
  3. **[Try HTTP API access](docs/http-api.md)** - REST API for web applications
597
597
  4. **[Explore AI-powered Q&A](docs/qa-interface.md)** - Ask questions about your code
598
- 5. **[Set up git hooks](docs/git-hook-setup.md)** - Automate your workflow
598
+ 5. **[Set up git hooks](docs/git-hook-setup.md)** - Automate your workflow
599
599
 
600
600
  **👥 Setting up for a team?**
601
601
  1. **[Learn all CLI commands](docs/cli-reference.md)** - Complete command reference
@@ -618,7 +618,7 @@ Ready to supercharge your AI agents with intelligent codebase navigation?
618
618
 
619
619
  We welcome contributions! See our **[Contributing Guide](docs/contributing.md)** for:
620
620
  - Development setup
621
- - Code style guidelines
621
+ - Code style guidelines
622
622
  - Testing requirements
623
623
  - Pull request process
624
624
 
@@ -629,7 +629,7 @@ MIT License - see **[LICENSE](LICENSE)** for details.
629
629
  ## 🙏 Built With
630
630
 
631
631
  - **[Model Context Protocol](https://github.com/modelcontextprotocol/python-sdk)** - The foundation for tool integration
632
- - **[tiktoken](https://pypi.org/project/tiktoken/)** - Fast BPE tokenization
632
+ - **[tiktoken](https://pypi.org/project/tiktoken/)** - Fast BPE tokenization
633
633
  - **[aiosqlite](https://pypi.org/project/aiosqlite/)** - Async SQLite operations
634
634
  - **[aiohttp](https://pypi.org/project/aiohttp/)** - Async HTTP client for OpenRouter API
635
635
  - **[tenacity](https://pypi.org/project/tenacity/)** - Robust retry logic and rate limiting
@@ -637,8 +637,8 @@ MIT License - see **[LICENSE](LICENSE)** for details.
637
637
 
638
638
  ---
639
639
 
640
- **Transform how your AI agents understand code!** 🚀
640
+ **Transform how your AI agents understand code!** 🚀
641
641
 
642
- 🎯 **New User?** [Get started in 2 minutes](#-quick-start)
643
- 👨‍💻 **Developer?** [Explore the complete API](docs/api-reference.md)
642
+ 🎯 **New User?** [Get started in 2 minutes](#-quick-start)
643
+ 👨‍💻 **Developer?** [Explore the complete API](docs/api-reference.md)
644
644
  🔧 **Production?** [Deploy with confidence](docs/configuration.md)
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
4
4
 
5
5
  [tool.poetry]
6
6
  name = "mcp-code-indexer"
7
- version = "4.0.1"
7
+ version = "4.0.2"
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"]
@@ -14,10 +14,10 @@ homepage = "https://github.com/fluffypony/mcp-code-indexer"
14
14
  repository = "https://github.com/fluffypony/mcp-code-indexer"
15
15
  documentation = "https://github.com/fluffypony/mcp-code-indexer/blob/main/README.md"
16
16
  keywords = [
17
- "mcp",
18
- "model-context-protocol",
19
- "code-indexer",
20
- "ai-tools",
17
+ "mcp",
18
+ "model-context-protocol",
19
+ "code-indexer",
20
+ "ai-tools",
21
21
  "codebase-navigation",
22
22
  "file-descriptions",
23
23
  "llm-tools"
@@ -111,7 +111,7 @@ known_first_party = ["src", "mcp_code_indexer"]
111
111
 
112
112
  # MyPy configuration
113
113
  [tool.mypy]
114
- python_version = "3.9"
114
+ python_version = "3.10"
115
115
  warn_return_any = true
116
116
  warn_unused_configs = true
117
117
  disallow_untyped_defs = true
@@ -171,3 +171,15 @@ exclude_lines = [
171
171
  "class .*\\bProtocol\\):",
172
172
  "@(abc\\.)?abstractmethod"
173
173
  ]
174
+
175
+ # Ruff configuration
176
+ [tool.ruff]
177
+ exclude = [
178
+ ".vulture_whitelist.py",
179
+ "venv",
180
+ ".git",
181
+ "__pycache__",
182
+ ".mypy_cache",
183
+ ".pytest_cache",
184
+ ".ruff_cache"
185
+ ]
@@ -6,10 +6,12 @@ intelligent codebase navigation through searchable file descriptions,
6
6
  token-aware overviews, and advanced merge capabilities.
7
7
  """
8
8
 
9
+
9
10
  # Delay import to avoid dependency issues during testing
10
- def get_server():
11
+ def get_server() -> type:
11
12
  """Get MCPCodeIndexServer (lazy import)."""
12
13
  from .server.mcp_server import MCPCodeIndexServer
14
+
13
15
  return MCPCodeIndexServer
14
16
 
15
17
 
@@ -27,15 +29,15 @@ def _get_version() -> str:
27
29
  for pkg_name in ["mcp-code-indexer", "mcp_code_indexer"]:
28
30
  try:
29
31
  return version(pkg_name)
30
- except Exception:
32
+ except Exception: # nosec B112
31
33
  continue
32
- except Exception:
34
+ except Exception: # nosec B110
33
35
  pass
34
36
 
35
37
  # Fallback to reading from pyproject.toml (for development)
36
38
  try:
37
- from pathlib import Path
38
39
  import sys
40
+ from pathlib import Path
39
41
 
40
42
  if sys.version_info >= (3, 11):
41
43
  import tomllib
@@ -48,7 +50,7 @@ def _get_version() -> str:
48
50
  pyproject_path = Path(__file__).parent.parent.parent / "pyproject.toml"
49
51
  with open(pyproject_path, "rb") as f:
50
52
  data = tomllib.load(f)
51
- return data["project"]["version"]
53
+ return str(data["project"]["version"])
52
54
  except Exception:
53
55
  return "dev"
54
56
 
@@ -8,9 +8,9 @@ and sending them to Claude via OpenRouter API for direct responses.
8
8
 
9
9
  import logging
10
10
  from pathlib import Path
11
- from typing import Dict, Optional, Any
11
+ from typing import Any, Dict, Optional
12
12
 
13
- from .claude_api_handler import ClaudeAPIHandler, ClaudeAPIError
13
+ from .claude_api_handler import ClaudeAPIError, ClaudeAPIHandler
14
14
  from .database.database import DatabaseManager
15
15
 
16
16
 
@@ -11,15 +11,15 @@ import json
11
11
  import logging
12
12
  import os
13
13
  from dataclasses import dataclass
14
- from typing import Dict, List, Optional, Any
15
14
  from pathlib import Path
15
+ from typing import Any, Dict, List, Optional
16
16
 
17
17
  import aiohttp
18
18
  from tenacity import (
19
19
  retry,
20
- wait_exponential,
21
- stop_after_attempt,
22
20
  retry_if_exception_type,
21
+ stop_after_attempt,
22
+ wait_exponential,
23
23
  )
24
24
 
25
25
  from .database.database import DatabaseManager
@@ -194,7 +194,6 @@ class ClaudeAPIHandler:
194
194
  async with session.post(
195
195
  self.OPENROUTER_API_URL, headers=headers, json=payload
196
196
  ) as response:
197
-
198
197
  self.logger.info(f"Claude API response status: {response.status}")
199
198
 
200
199
  if response.status == 429:
@@ -240,7 +239,7 @@ class ClaudeAPIHandler:
240
239
  raise ClaudeAPIError("Claude API request timed out")
241
240
 
242
241
  def validate_json_response(
243
- self, response_text: str, required_keys: List[str] = None
242
+ self, response_text: str, required_keys: Optional[List[str]] = None
244
243
  ) -> Dict[str, Any]:
245
244
  """
246
245
  Validate and parse JSON response from Claude.
@@ -297,6 +296,12 @@ class ClaudeAPIHandler:
297
296
  self.logger.debug(f"Extracted JSON from response: {extracted_json}")
298
297
  data = json.loads(extracted_json)
299
298
 
299
+ # Ensure data is a dictionary
300
+ if not isinstance(data, dict):
301
+ raise ClaudeValidationError(
302
+ f"Expected JSON object, got {type(data).__name__}"
303
+ )
304
+
300
305
  # Validate required keys if specified
301
306
  if required_keys:
302
307
  missing_keys = [key for key in required_keys if key not in data]
@@ -8,7 +8,10 @@ and manual cleanup methods.
8
8
 
9
9
  import logging
10
10
  import time
11
- from typing import List, Optional
11
+ from typing import Any, List, Optional, TYPE_CHECKING
12
+
13
+ if TYPE_CHECKING:
14
+ from .database.database import DatabaseManager
12
15
 
13
16
  logger = logging.getLogger(__name__)
14
17
 
@@ -21,7 +24,9 @@ class CleanupManager:
21
24
  periodic cleanup to permanently remove old records after the retention period.
22
25
  """
23
26
 
24
- def __init__(self, db_manager, retention_months: int = 6):
27
+ def __init__(
28
+ self, db_manager: "DatabaseManager", retention_months: int = 6
29
+ ) -> None:
25
30
  """
26
31
  Initialize cleanup manager.
27
32
 
@@ -80,7 +85,7 @@ class CleanupManager:
80
85
 
81
86
  cleanup_timestamp = int(time.time())
82
87
 
83
- async def batch_operation(conn):
88
+ async def batch_operation(conn: Any) -> int:
84
89
  data = [(cleanup_timestamp, project_id, path) for path in file_paths]
85
90
  cursor = await conn.executemany(
86
91
  """
@@ -90,7 +95,7 @@ class CleanupManager:
90
95
  """,
91
96
  data,
92
97
  )
93
- return cursor.rowcount
98
+ return int(cursor.rowcount)
94
99
 
95
100
  marked_count = await self.db_manager.execute_transaction_with_retry(
96
101
  batch_operation,
@@ -99,7 +104,7 @@ class CleanupManager:
99
104
  )
100
105
 
101
106
  logger.info(f"Marked {marked_count} files for cleanup in project {project_id}")
102
- return marked_count
107
+ return int(marked_count)
103
108
 
104
109
  async def restore_file_from_cleanup(self, project_id: str, file_path: str) -> bool:
105
110
  """
@@ -177,7 +182,7 @@ class CleanupManager:
177
182
  ) # Approximate months to seconds
178
183
  cutoff_timestamp = int(time.time()) - cutoff_seconds
179
184
 
180
- async def cleanup_operation(conn):
185
+ async def cleanup_operation(conn: Any) -> int:
181
186
  if project_id:
182
187
  cursor = await conn.execute(
183
188
  """
@@ -196,7 +201,7 @@ class CleanupManager:
196
201
  (cutoff_timestamp,),
197
202
  )
198
203
 
199
- return cursor.rowcount
204
+ return int(cursor.rowcount)
200
205
 
201
206
  deleted_count = await self.db_manager.execute_transaction_with_retry(
202
207
  cleanup_operation,
@@ -208,7 +213,7 @@ class CleanupManager:
208
213
  scope = f"project {project_id}" if project_id else "all projects"
209
214
  logger.info(f"Permanently deleted {deleted_count} old records from {scope}")
210
215
 
211
- return deleted_count
216
+ return int(deleted_count)
212
217
 
213
218
  async def get_cleanup_stats(self, project_id: Optional[str] = None) -> dict:
214
219
  """
@@ -226,7 +231,7 @@ class CleanupManager:
226
231
  async with self.db_manager.get_connection() as db:
227
232
  if project_id:
228
233
  base_where = "WHERE project_id = ?"
229
- params = (project_id,)
234
+ params: tuple[Any, ...] = (project_id,)
230
235
  else:
231
236
  base_where = ""
232
237
  params = ()
@@ -239,7 +244,8 @@ class CleanupManager:
239
244
  ),
240
245
  params,
241
246
  )
242
- active_count = (await cursor.fetchone())[0]
247
+ row = await cursor.fetchone()
248
+ active_count = row[0] if row else 0
243
249
 
244
250
  # Files marked for cleanup
245
251
  cursor = await db.execute(
@@ -249,7 +255,8 @@ class CleanupManager:
249
255
  ),
250
256
  params,
251
257
  )
252
- marked_count = (await cursor.fetchone())[0]
258
+ row = await cursor.fetchone()
259
+ marked_count = row[0] if row else 0
253
260
 
254
261
  # Files eligible for permanent deletion
255
262
  if project_id:
@@ -268,7 +275,8 @@ class CleanupManager:
268
275
  ),
269
276
  (cutoff_timestamp,),
270
277
  )
271
- eligible_for_deletion = (await cursor.fetchone())[0]
278
+ row = await cursor.fetchone()
279
+ eligible_for_deletion = row[0] if row else 0
272
280
 
273
281
  return {
274
282
  "active_files": active_count,