errors.py•2.32 kB
"""Error codes and exceptions for MCP CopyQ."""
from enum import Enum
class ErrorCode(str, Enum):
"""Error codes returned by MCP tools."""
TAB_NOT_FOUND = "TAB_NOT_FOUND"
INDEX_OUT_OF_BOUNDS = "INDEX_OUT_OF_BOUNDS"
INVALID_MODE = "INVALID_MODE"
PERMISSION_DENIED = "PERMISSION_DENIED"
MISSING_PARAM = "MISSING_PARAM"
MATCH_NOT_FOUND = "MATCH_NOT_FOUND"
COPYQ_ERROR = "COPYQ_ERROR"
INVALID_PARAM = "INVALID_PARAM"
class MCPCopyQError(Exception):
"""Base exception for MCP CopyQ errors."""
def __init__(self, code: ErrorCode, message: str):
self.code = code
self.message = message
super().__init__(f"{code.value}: {message}")
def to_response(self) -> str:
"""Format error for MCP response."""
return f"error|{self.code.value}|{self.message}"
class TabNotFoundError(MCPCopyQError):
def __init__(self, tab: str):
super().__init__(ErrorCode.TAB_NOT_FOUND, f"Tab not found: {tab}")
class IndexOutOfBoundsError(MCPCopyQError):
def __init__(self, index: int, count: int):
super().__init__(
ErrorCode.INDEX_OUT_OF_BOUNDS,
f"Index {index} out of bounds (count: {count})"
)
class InvalidModeError(MCPCopyQError):
def __init__(self, mode: str, valid_modes: list[str]):
super().__init__(
ErrorCode.INVALID_MODE,
f"Invalid mode '{mode}'. Valid: {', '.join(valid_modes)}"
)
class PermissionDeniedError(MCPCopyQError):
def __init__(self, operation: str, tab: str):
super().__init__(
ErrorCode.PERMISSION_DENIED,
f"Operation '{operation}' not allowed on '{tab}'"
)
class MissingParamError(MCPCopyQError):
def __init__(self, param: str, mode: str):
super().__init__(
ErrorCode.MISSING_PARAM,
f"Parameter '{param}' required for mode '{mode}'"
)
class MatchNotFoundError(MCPCopyQError):
def __init__(self, match: str):
super().__init__(
ErrorCode.MATCH_NOT_FOUND,
f"Match string not found: '{match[:50]}...'" if len(match) > 50 else f"Match string not found: '{match}'"
)
class CopyQError(MCPCopyQError):
def __init__(self, message: str):
super().__init__(ErrorCode.COPYQ_ERROR, message)