Circuit Breaking

The proxy wraps each upstream in a circuit breaker. When an upstream starts failing consistently, the breaker opens and subsequent calls fail fast — protecting the upstream from being hammered and the MCP client from waiting on timeouts.

How it works

The circuit breaker has three states:

  • Closed — requests flow normally. Failures are counted in a rolling window.
  • Open — requests fail immediately without reaching the upstream. After the timeout the breaker moves to half-open.
  • Half-open — a probe request is sent. Success closes the breaker; failure reopens it.

Configuration

upstreams:
  - name: myapi
    type: http
    tool_prefix: api
    base_url: https://api.example.com
    openapi:
      source: spec.yaml
    circuit_breaker:
      threshold: 5          # failures before opening (within the window)
      window: 30s           # rolling window size
      timeout: 10s          # how long to stay open before probing
      success_threshold: 2  # consecutive successes needed to close from half-open

Configuration fields

FieldDefaultDescription
threshold5Number of failures in window that trip the breaker
window60sRolling time window for counting failures
timeout30sHow long the breaker stays open before allowing a probe
success_threshold1Consecutive successes in half-open state before closing

What counts as a failure

By default, any HTTP 5xx response or a connection error increments the failure counter. HTTP 4xx responses are not counted — they indicate a client error, not an upstream outage.

MCP error when open

When the breaker is open, tool calls return an MCP error with code -32030 (upstream unavailable). The error message includes the upstream name and an estimate of when the next probe will fire.

Metrics

State transitions are emitted as OpenTelemetry events on the active trace span and as counters under mcp.circuit_breaker.*. The mcp.circuit_breaker.state gauge tracks the current state (0 = closed, 1 = half-open, 2 = open) per upstream. See OpenTelemetry.

See also