Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 19 additions & 19 deletions .secrets.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"files": "package-lock.json|Cargo.lock|^.secrets.baseline$|scripts/sign_image.sh|scripts/zap|sonar-project.properties|^/Users/brian/dev/github.ibm.com/contextforge-org/sps-pipeline-config/.secrets.baseline$|^./.secrets.baseline$",
"lines": null
},
"generated_at": "2026-03-27T22:09:20Z",
"generated_at": "2026-03-28T14:11:28Z",
"plugins_used": [
{
"name": "AWSKeyDetector"
Expand Down Expand Up @@ -10080,87 +10080,87 @@
"hashed_secret": "d63b39580934e062f89aae63426d2f2c77c3e258",
"is_secret": false,
"is_verified": false,
"line_number": 501,
"line_number": 503,
"type": "Base64 High Entropy String",
"verified_result": null
},
{
"hashed_secret": "586a55a9b8b97f0cd88e24ce8279ebc955949688",
"is_secret": false,
"is_verified": false,
"line_number": 502,
"line_number": 504,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "00cafd126182e8a9e7c01bb2f0dfd00496be724f",
"is_secret": false,
"is_verified": false,
"line_number": 518,
"line_number": 520,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "7b1552c7c7ffb8bd70b5666e5997c8e017630aab",
"is_secret": false,
"is_verified": false,
"line_number": 1936,
"line_number": 1934,
"type": "Base64 High Entropy String",
"verified_result": null
},
{
"hashed_secret": "9fb7fe1217aed442b04c0f5e43b5d5a7d3287097",
"is_secret": false,
"is_verified": false,
"line_number": 2704,
"line_number": 2702,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "72cb70dbbafe97e5ea13ad88acd65d08389439b0",
"is_secret": false,
"is_verified": false,
"line_number": 3332,
"line_number": 3330,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "ee977806d7286510da8b9a7492ba58e2484c0ecc",
"is_secret": false,
"is_verified": false,
"line_number": 5366,
"line_number": 5609,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "f2e7745f43b0ef0e2c2faf61d6c6a28be2965750",
"is_secret": false,
"is_verified": false,
"line_number": 5858,
"line_number": 6101,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "4a249743d4d2241bd2ae085b4fe654d089488295",
"is_secret": false,
"is_verified": false,
"line_number": 7025,
"line_number": 7268,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "0c8d051d3c7eada5d31b53d9936fce6bcc232ae2",
"is_secret": false,
"is_verified": false,
"line_number": 7163,
"line_number": 7406,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "f2b14f68eb995facb3a1c35287b778d5bd785511",
"is_secret": false,
"is_verified": false,
"line_number": 7492,
"line_number": 7735,
"type": "Secret Keyword",
"verified_result": null
}
Expand Down Expand Up @@ -10202,55 +10202,55 @@
"hashed_secret": "99834bc4eff3f1e1c1e4692d2476b593b501d045",
"is_secret": false,
"is_verified": false,
"line_number": 5481,
"line_number": 5483,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "f2b14f68eb995facb3a1c35287b778d5bd785511",
"is_secret": false,
"is_verified": false,
"line_number": 5499,
"line_number": 5501,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "b8cec023ad982a1355abb9e7c7700e42d7e6fac3",
"is_secret": false,
"is_verified": false,
"line_number": 5523,
"line_number": 5525,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "0614eb27c6e0d2f4ed9a1cce2a5bcbbbc17aa556",
"is_secret": false,
"is_verified": false,
"line_number": 5587,
"line_number": 5589,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "a38fea79a043f0c9a62f851659d459dc3b716ea9",
"is_secret": false,
"is_verified": false,
"line_number": 5598,
"line_number": 5600,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "a50da1fb101595ac5158f2c9394a65a84061b56c",
"is_secret": false,
"is_verified": false,
"line_number": 5639,
"line_number": 5641,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "ed3e0017cb8e4b06a59af1a441f62cbe58d2ef59",
"is_secret": false,
"is_verified": false,
"line_number": 5645,
"line_number": 5647,
"type": "Secret Keyword",
"verified_result": null
}
Expand Down
6 changes: 5 additions & 1 deletion mcpgateway/plugins/framework/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ async def execute(
combined_metadata: dict[str, Any] = {}
current_payload: PluginPayload | None = None
decision_plugin_name: Optional[str] = None
max_retry_delay_ms: int = 0

for hook_ref in hook_refs:
# Skip disabled plugins
Expand Down Expand Up @@ -224,6 +225,9 @@ async def execute(
combined_metadata,
)

# Propagate retry signal — take the largest delay requested by any plugin
max_retry_delay_ms = max(max_retry_delay_ms, result.retry_delay_ms)

# Apply policy-based controlled merge (per-plugin)
if result.modified_payload is not None:
if policy:
Expand Down Expand Up @@ -292,7 +296,7 @@ async def execute(
if hook_type == HTTP_AUTH_CHECK_PERMISSION_HOOK and decision_plugin_name:
combined_metadata[DECISION_PLUGIN_METADATA_KEY] = decision_plugin_name

return (PluginResult(continue_processing=True, modified_payload=current_payload, violation=None, metadata=combined_metadata), res_local_contexts)
return (PluginResult(continue_processing=True, modified_payload=current_payload, violation=None, metadata=combined_metadata, retry_delay_ms=max_retry_delay_ms), res_local_contexts)

async def execute_plugin(
self,
Expand Down
7 changes: 7 additions & 0 deletions mcpgateway/plugins/framework/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1336,6 +1336,9 @@ class PluginResult(BaseModel, Generic[T]):
violation (Optional[PluginViolation]): violation object.
metadata (Optional[dict[str, Any]]): additional metadata.
http_headers (Optional[dict[str, str]]): HTTP headers to include in successful responses.
retry_delay_ms (int): Milliseconds the gateway should wait before retrying the tool call.
0 (default) means no retry. Set by retry_with_backoff plugin to request
a delayed re-execution of the tool.

Examples:
>>> result = PluginResult()
Expand All @@ -1358,13 +1361,17 @@ class PluginResult(BaseModel, Generic[T]):
>>> r2 = PluginResult(continue_processing=False)
>>> r2.continue_processing
False
>>> r3 = PluginResult(retry_delay_ms=500)
>>> r3.retry_delay_ms
500
"""

continue_processing: bool = True
modified_payload: Optional[T] = None
violation: Optional[PluginViolation] = None
metadata: Optional[dict[str, Any]] = Field(default_factory=dict)
http_headers: Optional[dict[str, str]] = None
retry_delay_ms: int = 0


class GlobalContext(BaseModel):
Expand Down
Loading
Loading