Ryan Malloy 431abcbbe6 feat: complete PyPI platform integration with all 25 tools and MCP endpoints
🎉 COMPLETE IMPLEMENTATION: PyPI Query MCP Server is now a comprehensive PyPI platform management suite!

Features Added:
 25 PyPI Platform Tools across 6 categories:
   - Publishing Tools (6): upload, credentials, history, delete, maintainers, account
   - Metadata Tools (4): update metadata, URLs, visibility, keywords
   - Analytics Tools (4): package analytics, security alerts, rankings, competition
   - Discovery Tools (4): monitor releases, trending, search by maintainer, recommendations
   - Workflow Tools (4): validate names, preview pages, check requirements, build logs
   - Community Tools (3): reviews, discussions, maintainer contacts

 Complete MCP Server Integration:
   - 39 total MCP endpoints (14 existing + 25 new)
   - Comprehensive error handling and logging
   - Consistent API patterns and documentation
   - Full async/await support

 Production-Ready Code:
   - Comprehensive exception handling with custom exception classes
   - Full type hints and docstrings throughout
   - Robust validation and safety checks
   - Async HTTP clients with retry logic and rate limiting
   - Mock-based testing infrastructure ready for expansion

 Advanced Search Capabilities:
   - Semantic search with filtering and sorting
   - Category-based discovery and alternatives finding
   - Trending analysis and recommendation engines

This transforms the basic package query tool into a complete PyPI ecosystem management platform supporting the entire Python package lifecycle from development to publishing to community management.
2025-08-17 21:06:59 -06:00

86 lines
2.6 KiB
Python

"""Custom exceptions for PyPI Query MCP Server."""
class PyPIError(Exception):
"""Base exception for PyPI-related errors."""
def __init__(self, message: str, status_code: int | None = None):
super().__init__(message)
self.message = message
self.status_code = status_code
class PackageNotFoundError(PyPIError):
"""Raised when a package is not found on PyPI."""
def __init__(self, package_name: str):
message = f"Package '{package_name}' not found on PyPI"
super().__init__(message, status_code=404)
self.package_name = package_name
class NetworkError(PyPIError):
"""Raised when network-related errors occur."""
def __init__(self, message: str, original_error: Exception | None = None):
super().__init__(message)
self.original_error = original_error
class RateLimitError(PyPIError):
"""Raised when API rate limit is exceeded."""
def __init__(self, retry_after: int | None = None):
message = "PyPI API rate limit exceeded"
if retry_after:
message += f". Retry after {retry_after} seconds"
super().__init__(message, status_code=429)
self.retry_after = retry_after
class InvalidPackageNameError(PyPIError):
"""Raised when package name is invalid."""
def __init__(self, package_name: str):
message = f"Invalid package name: '{package_name}'"
super().__init__(message, status_code=400)
self.package_name = package_name
class PyPIServerError(PyPIError):
"""Raised when PyPI server returns a server error."""
def __init__(self, status_code: int, message: str | None = None):
if not message:
message = f"PyPI server error (HTTP {status_code})"
super().__init__(message, status_code=status_code)
class SearchError(PyPIError):
"""Raised when search operations fail."""
def __init__(self, message: str, query: str | None = None):
super().__init__(message)
self.query = query
class PyPIAuthenticationError(PyPIError):
"""Raised when PyPI authentication fails."""
def __init__(self, message: str, status_code: int | None = None):
super().__init__(message, status_code)
class PyPIUploadError(PyPIError):
"""Raised when PyPI upload operations fail."""
def __init__(self, message: str, status_code: int | None = None):
super().__init__(message, status_code)
class PyPIPermissionError(PyPIError):
"""Raised when PyPI permission operations fail."""
def __init__(self, message: str, status_code: int | None = None):
super().__init__(message, status_code)