Raxol.MCP.CircuitBreaker (Raxol MCP v2.6.0)

Copy Markdown View Source

Lightweight ETS-backed circuit breaker for MCP tool/resource callbacks.

Tracks failure counts per key and transitions through three states:

  • closed -- normal operation, failures below threshold
  • open -- callback blocked after repeated failures, returns {:error, :circuit_open}
  • half_open -- recovery probe allowed after cooldown; success resets, failure re-opens

No GenServer -- all state lives in a public ETS table with atomic counter updates. The table is created by the owning process (typically MCP.Registry).

Configuration

Defaults can be overridden via application env or per-call opts:

config :raxol_mcp, :circuit_breaker,
  failure_threshold: 5,
  recovery_ms: 30_000

Summary

Functions

Check the circuit state for a key.

Create a new circuit breaker ETS table.

Record a failed callback invocation.

Record a successful callback invocation. Resets the circuit to closed.

Manually reset a circuit to closed.

Reset all circuit breaker state.

Get the current status of a circuit.

Types

key()

@type key() :: {:tool, String.t()} | {:resource, String.t()} | {:prompt, String.t()}

state()

@type state() :: :closed | :open | :half_open

Functions

check(table, key, opts \\ [])

@spec check(:ets.tid(), key(), keyword()) :: state()

Check the circuit state for a key.

Returns :closed (proceed), :open (block), or :half_open (probe). Automatically transitions from open to half_open after the recovery period.

new(name \\ :raxol_mcp_breakers)

@spec new(atom()) :: :ets.tid()

Create a new circuit breaker ETS table.

record_failure(table, key, opts \\ [])

@spec record_failure(:ets.tid(), key(), keyword()) :: :ok

Record a failed callback invocation.

Increments the failure counter. Transitions to open when the threshold is reached. In half_open state, a single failure re-opens the circuit.

record_success(table, key)

@spec record_success(:ets.tid(), key()) :: :ok

Record a successful callback invocation. Resets the circuit to closed.

reset(table, key)

@spec reset(:ets.tid(), key()) :: :ok

Manually reset a circuit to closed.

reset_all(table)

@spec reset_all(:ets.tid()) :: :ok

Reset all circuit breaker state.

status(table, key)

@spec status(:ets.tid(), key()) :: %{state: state(), failures: non_neg_integer()}

Get the current status of a circuit.