Skip to main content

High-performance retry and backoff policy engine for MCP Gateway

Project description

Retry With Backoff (Rust)

High-performance retry and backoff policy engine for ContextForge and MCP Gateway.

Features

  • Rust-backed retry state tracking for tool invocations
  • Exponential backoff with optional jitter
  • Per-tool policy overrides without duplicating whole plugin configs
  • Retry decisions based on isError, structured status_code, or optional parsed text payloads
  • Automatic state eviction for stale request entries
  • Gateway ceiling enforcement for max_retries
  • Retry policy metadata returned on tool and resource hooks

Build

make install

Runtime Requirements

This plugin depends on cpex>=0.1.0,<0.2 and imports hook models from cpex.framework. The compiled Rust extension is mandatory; there is no Python fallback implementation.

Usage

The plugin runs on tool_post_invoke and resource_post_fetch.

Typical uses:

  • Retry transient upstream failures such as 429, 500, 502, 503, and 504
  • Clamp aggressive plugin settings to the gateway-wide retry ceiling
  • Apply stricter retry budgets to fragile or expensive tools

Configuration

Core settings

  • max_retries: maximum retry attempts before giving up
  • backoff_base_ms: base delay for exponential backoff
  • max_backoff_ms: upper bound for computed retry delays
  • retry_on_status: HTTP or structured status codes treated as retriable
  • jitter: randomize delay within the current exponential ceiling
  • check_text_content: inspect text content for JSON-encoded error payloads when structured content is absent

Per-tool overrides

Use tool_overrides to change retry behavior for a specific tool:

  • max_retries
  • backoff_base_ms
  • max_backoff_ms
  • retry_on_status
  • jitter

Behavior Notes

  • Successful responses clear retry state for the (tool, request_id) pair.
  • Retry state expires after a short TTL so abandoned request state does not accumulate indefinitely.
  • If check_text_content is disabled, the hot path uses the Rust state manager directly.
  • If check_text_content is enabled, Python-side payload inspection supplements the Rust state manager before applying retry policy.

Returned Metadata

tool_post_invoke — OpenTelemetry metrics

tool_post_invoke accepts an optional extensions parameter carrying OpenTelemetry trace context. When a trace context is present (via extensions.request.trace_id), the plugin emits operational metrics on result.metadata["retry_with_backoff"] with the following schema:

result.metadata["retry_with_backoff"] = {
    "retry_count": 1,      # int — consecutive_failures after this call's outcome is recorded; 0 on success
    "retry_delay_ms": 100, # int — the per-attempt delay computed for this call; 0 on success or once exhausted
}

Every call (success, within-budget retry, or exhausted) has a meaningful outcome to report, including the all-zero success case — there is deliberately no total_backoff_ms cumulative counter, only these two per-call fields.

Gating: Metrics are only emitted when a valid trace_id is present in the trace context (extensions.request.trace_id). No trace context means no result.metadata write at all, regardless of any config flag.

resource_post_fetch — unchanged config echo

resource_post_fetch is out of scope for the OTel metrics contract above — it never receives extensions and continues to unconditionally emit the plugin's active retry policy configuration (not per-call outcome data) on result.metadata:

  • max_retries
  • backoff_base_ms
  • max_backoff_ms
  • retry_on_status

Migration Note

Version 0.3.6 is a breaking change for tool_post_invoke consumers only (resource_post_fetch is unaffected):

  • tool_post_invoke no longer emits the flat, unconditional retry_policy config echo (max_retries, backoff_base_ms, max_backoff_ms, retry_on_status). That echo is replaced by the namespaced, trace-gated result.metadata["retry_with_backoff"] schema above (retry_count, retry_delay_ms).
  • tool_post_invoke now accepts a new optional extensions parameter carrying OpenTelemetry trace context. Emission is gated solely on extensions.request.trace_id being present and valid — if no trace context is supplied, no metrics are written at all.
  • Consumers that previously read the config echo from tool_post_invoke unconditionally must migrate to reading result.metadata["retry_with_backoff"] and must pass a trace_id via extensions to receive metrics.
  • resource_post_fetch keeps its pre-existing, un-namespaced config echo byte-for-byte unchanged — it is a different contract, not covered by this migration.

Testing

# Full plugin CI
make ci

Performance

The retry state manager is implemented in Rust so the common retry decision path avoids Python bookkeeping overhead for normal structured tool results.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cpex_retry_with_backoff-0.3.6.tar.gz (40.0 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

cpex_retry_with_backoff-0.3.6-cp311-abi3-win_amd64.whl (205.6 kB view details)

Uploaded CPython 3.11+Windows x86-64

cpex_retry_with_backoff-0.3.6-cp311-abi3-manylinux_2_34_x86_64.whl (288.1 kB view details)

Uploaded CPython 3.11+manylinux: glibc 2.34+ x86-64

cpex_retry_with_backoff-0.3.6-cp311-abi3-manylinux_2_34_s390x.whl (315.8 kB view details)

Uploaded CPython 3.11+manylinux: glibc 2.34+ s390x

cpex_retry_with_backoff-0.3.6-cp311-abi3-manylinux_2_34_ppc64le.whl (314.4 kB view details)

Uploaded CPython 3.11+manylinux: glibc 2.34+ ppc64le

cpex_retry_with_backoff-0.3.6-cp311-abi3-manylinux_2_34_aarch64.whl (272.7 kB view details)

Uploaded CPython 3.11+manylinux: glibc 2.34+ ARM64

cpex_retry_with_backoff-0.3.6-cp311-abi3-macosx_11_0_arm64.whl (260.7 kB view details)

Uploaded CPython 3.11+macOS 11.0+ ARM64

File details

Details for the file cpex_retry_with_backoff-0.3.6.tar.gz.

File metadata

  • Download URL: cpex_retry_with_backoff-0.3.6.tar.gz
  • Upload date:
  • Size: 40.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for cpex_retry_with_backoff-0.3.6.tar.gz
Algorithm Hash digest
SHA256 89f0716a176f096b1a7a996f5dfc06b91145014d372955969fd5b378f9bd1dcc
MD5 23beb866c5aeb30088685249738de047
BLAKE2b-256 94460ef6e5bfa66c6e5d5b261dc9ca8c98179d155e83ebd2ea1c111f1b710fd0

See more details on using hashes here.

Provenance

The following attestation bundles were made for cpex_retry_with_backoff-0.3.6.tar.gz:

Publisher: release-rust-python-package.yaml on IBM/cpex-plugins

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cpex_retry_with_backoff-0.3.6-cp311-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for cpex_retry_with_backoff-0.3.6-cp311-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 2e093a1dba401d2c0695a542b037c58a99d0f98daf5e40f77325afbebe0dceaa
MD5 f429bc578abef44fa7beb89c2f0e6134
BLAKE2b-256 40eca5d512633610762b56cca78220af3fb8a8919dc098cd7a5edab17cf3dbd2

See more details on using hashes here.

Provenance

The following attestation bundles were made for cpex_retry_with_backoff-0.3.6-cp311-abi3-win_amd64.whl:

Publisher: release-rust-python-package.yaml on IBM/cpex-plugins

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cpex_retry_with_backoff-0.3.6-cp311-abi3-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for cpex_retry_with_backoff-0.3.6-cp311-abi3-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 8ba14b4f0d6520de272d304ba2535d5d0cd3939d9147640ddf106d57b6f1831a
MD5 90b8d129d1864b1511e22921fe591e3b
BLAKE2b-256 e2e513f77ecd5412d46f167a72b78f27f32b5affebd35538b995e454eb5d8ba8

See more details on using hashes here.

Provenance

The following attestation bundles were made for cpex_retry_with_backoff-0.3.6-cp311-abi3-manylinux_2_34_x86_64.whl:

Publisher: release-rust-python-package.yaml on IBM/cpex-plugins

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cpex_retry_with_backoff-0.3.6-cp311-abi3-manylinux_2_34_s390x.whl.

File metadata

File hashes

Hashes for cpex_retry_with_backoff-0.3.6-cp311-abi3-manylinux_2_34_s390x.whl
Algorithm Hash digest
SHA256 b49c5c2840611c5127af27d7d35eb855ebcd802bc7f988a4a540e1a5b7644c8f
MD5 d08a58be7c93683c92892fe344b86a13
BLAKE2b-256 3d054186f836eee5f30927d1e2a1f2a331e19504820978a284c78db8ad0a7449

See more details on using hashes here.

Provenance

The following attestation bundles were made for cpex_retry_with_backoff-0.3.6-cp311-abi3-manylinux_2_34_s390x.whl:

Publisher: release-rust-python-package.yaml on IBM/cpex-plugins

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cpex_retry_with_backoff-0.3.6-cp311-abi3-manylinux_2_34_ppc64le.whl.

File metadata

File hashes

Hashes for cpex_retry_with_backoff-0.3.6-cp311-abi3-manylinux_2_34_ppc64le.whl
Algorithm Hash digest
SHA256 0036413ce7a5dca13810a0766f1013c53ed2b6bcbc0864255a9528c589de85df
MD5 8d6690911d9853d8f433e7254e7b5ba5
BLAKE2b-256 de12122bcf86748d7431f251fb9deb37dfa5577d17d9ee3be7049268537b0f90

See more details on using hashes here.

Provenance

The following attestation bundles were made for cpex_retry_with_backoff-0.3.6-cp311-abi3-manylinux_2_34_ppc64le.whl:

Publisher: release-rust-python-package.yaml on IBM/cpex-plugins

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cpex_retry_with_backoff-0.3.6-cp311-abi3-manylinux_2_34_aarch64.whl.

File metadata

File hashes

Hashes for cpex_retry_with_backoff-0.3.6-cp311-abi3-manylinux_2_34_aarch64.whl
Algorithm Hash digest
SHA256 c38fa0e3f0823787ce95e14869dc7ea015e9080f8ae6c7fc57e44cfa4d916aca
MD5 138e6be03b3e4043ba42be3a9a137c33
BLAKE2b-256 8cfd70e7f1f83eeca21b0f00e690a9246e9e3b44db4bfa71328596e9830cad1e

See more details on using hashes here.

Provenance

The following attestation bundles were made for cpex_retry_with_backoff-0.3.6-cp311-abi3-manylinux_2_34_aarch64.whl:

Publisher: release-rust-python-package.yaml on IBM/cpex-plugins

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cpex_retry_with_backoff-0.3.6-cp311-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for cpex_retry_with_backoff-0.3.6-cp311-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 0765e2d0c7e87e2208624437f7f277e038bc1d1ec264b4c328b40cb80cb69070
MD5 d4cdbaee169b06f0b3cc04e2abcf5032
BLAKE2b-256 8d8ec84c0f3bf5ecc889a56828fd3691c254a1f4deec90dd149275f5b34520c7

See more details on using hashes here.

Provenance

The following attestation bundles were made for cpex_retry_with_backoff-0.3.6-cp311-abi3-macosx_11_0_arm64.whl:

Publisher: release-rust-python-package.yaml on IBM/cpex-plugins

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page