feat: add comprehensive security, license, health, and requirements analysis tools
- Add security vulnerability scanning with OSV and GitHub advisories integration - Add license compatibility analysis with SPDX normalization and risk assessment - Add package health scoring across 7 categories with GitHub metrics integration - Add requirements file analysis supporting multiple formats (requirements.txt, pyproject.toml, etc.) - Fix search functionality MCP wrapper and error handling - Fix Python compatibility checking parameter order issue - Fix package recommendations NoneType handling - Add 8 new MCP tool endpoints for enhanced analysis capabilities This brings the total to 37 comprehensive MCP tools across 8 categories for complete PyPI package analysis and management.
This commit is contained in:
parent
48f1027c3e
commit
43f36b60fb
12 changed files with 4688 additions and 53 deletions
143
pypi_query_mcp/tools/requirements_tools.py
Normal file
143
pypi_query_mcp/tools/requirements_tools.py
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
"""Requirements file analysis tools for Python projects."""
|
||||
|
||||
import logging
|
||||
from typing import Any, Dict, List
|
||||
|
||||
from ..core.exceptions import InvalidPackageNameError, NetworkError, SearchError
|
||||
from ..tools.requirements_analyzer import analyze_project_requirements, compare_requirements_files
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def analyze_requirements_file_tool(
|
||||
file_path: str,
|
||||
check_updates: bool = True,
|
||||
security_scan: bool = True,
|
||||
compatibility_check: bool = True
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Analyze project requirements file for dependencies, security, and compatibility.
|
||||
|
||||
This tool provides comprehensive analysis of Python project requirements files
|
||||
including dependency parsing, version checking, security vulnerability scanning,
|
||||
Python compatibility assessment, and actionable recommendations for improvements.
|
||||
|
||||
Args:
|
||||
file_path: Path to the requirements file (requirements.txt, pyproject.toml, setup.py, etc.)
|
||||
check_updates: Whether to check for available package updates
|
||||
security_scan: Whether to perform security vulnerability scanning on dependencies
|
||||
compatibility_check: Whether to check Python version compatibility for all dependencies
|
||||
|
||||
Returns:
|
||||
Dictionary containing comprehensive requirements analysis including:
|
||||
- File information and detected format (requirements.txt, pyproject.toml, etc.)
|
||||
- Parsed dependencies with version specifiers and extras
|
||||
- Dependency health analysis with specification issues and recommendations
|
||||
- Package update analysis showing outdated packages and latest versions
|
||||
- Security vulnerability scan results for all dependencies
|
||||
- Python version compatibility assessment
|
||||
- Overall risk level and actionable improvement recommendations
|
||||
|
||||
Raises:
|
||||
FileNotFoundError: If the requirements file is not found
|
||||
NetworkError: For network-related errors during analysis
|
||||
SearchError: If requirements analysis fails
|
||||
"""
|
||||
logger.info(f"MCP tool: Analyzing requirements file {file_path}")
|
||||
|
||||
try:
|
||||
result = await analyze_project_requirements(
|
||||
file_path=file_path,
|
||||
check_updates=check_updates,
|
||||
security_scan=security_scan,
|
||||
compatibility_check=compatibility_check
|
||||
)
|
||||
|
||||
summary = result.get("analysis_summary", {})
|
||||
total_deps = summary.get("total_dependencies", 0)
|
||||
risk_level = summary.get("overall_risk_level", "unknown")
|
||||
logger.info(f"MCP tool: Requirements analysis completed for {file_path} - {total_deps} dependencies, risk level: {risk_level}")
|
||||
return result
|
||||
|
||||
except (FileNotFoundError, NetworkError, SearchError) as e:
|
||||
logger.error(f"Error analyzing requirements file {file_path}: {e}")
|
||||
return {
|
||||
"error": f"Requirements analysis failed: {e}",
|
||||
"error_type": type(e).__name__,
|
||||
"file_path": file_path,
|
||||
"analysis_timestamp": "",
|
||||
"file_info": {"name": file_path, "format": "unknown"},
|
||||
"dependencies": [],
|
||||
"dependency_analysis": {},
|
||||
"analysis_summary": {
|
||||
"total_dependencies": 0,
|
||||
"health_score": 0,
|
||||
"packages_with_issues": 0,
|
||||
"outdated_packages": 0,
|
||||
"security_vulnerabilities": 0,
|
||||
"compatibility_issues": 0,
|
||||
"overall_risk_level": "critical",
|
||||
},
|
||||
"recommendations": [f"❌ Requirements analysis failed: {e}"],
|
||||
"python_requirements": None,
|
||||
}
|
||||
|
||||
|
||||
async def compare_multiple_requirements_files(
|
||||
file_paths: List[str]
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Compare multiple requirements files to identify differences and conflicts.
|
||||
|
||||
This tool analyzes multiple requirements files simultaneously to identify
|
||||
version conflicts, unique dependencies, and inconsistencies across different
|
||||
project configurations or environments.
|
||||
|
||||
Args:
|
||||
file_paths: List of paths to requirements files to compare and analyze
|
||||
|
||||
Returns:
|
||||
Dictionary containing comparative requirements analysis including:
|
||||
- Detailed analysis results for each individual file
|
||||
- Common packages shared across all files
|
||||
- Conflicting package versions between files with specific version details
|
||||
- Packages unique to specific files
|
||||
- Recommendations for resolving conflicts and standardizing requirements
|
||||
- Statistics on package overlap and conflict rates
|
||||
|
||||
Raises:
|
||||
ValueError: If file_paths list is empty
|
||||
NetworkError: For network-related errors during analysis
|
||||
SearchError: If requirements comparison fails
|
||||
"""
|
||||
if not file_paths:
|
||||
raise ValueError("File paths list cannot be empty")
|
||||
|
||||
logger.info(f"MCP tool: Comparing {len(file_paths)} requirements files")
|
||||
|
||||
try:
|
||||
result = await compare_requirements_files(file_paths=file_paths)
|
||||
|
||||
comparison_results = result.get("comparison_results", {})
|
||||
conflicts = len(comparison_results.get("conflicting_packages", []))
|
||||
total_packages = comparison_results.get("total_unique_packages", 0)
|
||||
|
||||
logger.info(f"MCP tool: Requirements comparison completed - {total_packages} unique packages, {conflicts} conflicts found")
|
||||
return result
|
||||
|
||||
except (ValueError, NetworkError, SearchError) as e:
|
||||
logger.error(f"Error comparing requirements files: {e}")
|
||||
return {
|
||||
"error": f"Requirements comparison failed: {e}",
|
||||
"error_type": type(e).__name__,
|
||||
"comparison_timestamp": "",
|
||||
"files_compared": len(file_paths),
|
||||
"file_analyses": {},
|
||||
"comparison_results": {
|
||||
"total_unique_packages": 0,
|
||||
"common_packages": [],
|
||||
"conflicting_packages": [],
|
||||
"unique_to_files": {},
|
||||
},
|
||||
"recommendations": [f"❌ Requirements comparison failed: {e}"]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue