"""Typed errors shared by the Firefox MCP server."""
from __future__ import annotations
class FirefoxMcpError(Exception):
"""Base class for errors safe to expose as MCP tool failures."""
code = "internal_error"
retryable = False
def __init__(
self,
message: str,
*,
retryable: bool | None = None,
details: dict[str, object] | None = None,
) -> None:
super().__init__(message)
self.message = message
self.retryable = (
type(self).retryable if retryable is None else retryable
)
self.details = details or {}
class ConfigurationError(FirefoxMcpError):
"""Report an invalid startup configuration."""
code = "configuration_error"
class NotConnectedError(FirefoxMcpError):
"""Report that the configured Firefox RDP endpoint is unavailable."""
code = "not_connected"
retryable = True
class ConnectionLostError(FirefoxMcpError):
"""Report that an established RDP connection was lost."""
code = "connection_lost"
retryable = True
class RdpTimeoutError(FirefoxMcpError):
"""Report an RDP operation that exceeded its deadline."""
code = "rdp_timeout"
retryable = True
class RdpProtocolError(FirefoxMcpError):
"""Report an invalid or unexpected RDP packet."""
code = "rdp_protocol_error"
class NoTabSelectedError(FirefoxMcpError):
"""Report that a page operation has no selected browser tab."""
code = "no_tab_selected"
retryable = True
class TabNotFoundError(FirefoxMcpError):
"""Report that a requested tab no longer exists."""
code = "tab_not_found"
retryable = True
class TargetReplacedError(FirefoxMcpError):
"""Report that navigation replaced the selected target actor."""
code = "target_replaced"
retryable = True
class ElementNotFoundError(FirefoxMcpError):
"""Report that a stored selector no longer resolves."""
code = "element_not_found"
retryable = True
class StaleElementError(FirefoxMcpError):
"""Report that a reference no longer identifies its snapshot element."""
code = "stale_element"
retryable = True
class ElementNotInteractableError(FirefoxMcpError):
"""Report an element that cannot perform the requested interaction."""
code = "element_not_interactable"
class InvalidSelectorError(FirefoxMcpError):
"""Report invalid CSS selector syntax."""
code = "invalid_selector"
class UnsupportedElementError(FirefoxMcpError):
"""Report an element type unsupported by an interaction tool."""
code = "unsupported_element"
class NavigationTimeoutError(FirefoxMcpError):
"""Report a page that did not reach requested readiness in time."""
code = "navigation_timeout"
retryable = True
class WaitTimeoutError(FirefoxMcpError):
"""Report an observable page condition that did not become true."""
code = "wait_timeout"
retryable = True
class UploadFileInvalidError(FirefoxMcpError):
"""Report a local upload path that is not a readable regular file."""
code = "upload_file_invalid"
class UploadTooLargeError(FirefoxMcpError):
"""Report an upload that exceeds configured byte limits."""
code = "upload_too_large"
class UploadTargetInvalidError(FirefoxMcpError):
"""Report a target that is not a usable file input."""
code = "upload_target_invalid"
retryable = True
class UploadTransferError(FirefoxMcpError):
"""Report failure while transferring file chunks to the page."""
code = "upload_transfer_failed"
retryable = True
class UploadAssignmentError(FirefoxMcpError):
"""Report failure while assigning staged files to an input."""
code = "upload_assignment_failed"
retryable = True
class PageScriptError(FirefoxMcpError):
"""Report an unexpected exception in evaluated page JavaScript."""
code = "page_script_failed"
class JavaScriptError(FirefoxMcpError):
"""Report an exception thrown by caller-supplied JavaScript."""
code = "javascript_error"
class CancelledError(FirefoxMcpError):
"""Report cooperative cancellation of a browser operation."""
code = "cancelled"
retryable = True