Skip to content

fix(gateway): detect stale remote empty-success tool responses#525

Open
syf2211 wants to merge 1 commit into
docker:mainfrom
syf2211:fix/505-stale-remote-empty-success
Open

fix(gateway): detect stale remote empty-success tool responses#525
syf2211 wants to merge 1 commit into
docker:mainfrom
syf2211:fix/505-stale-remote-empty-success

Conversation

@syf2211

@syf2211 syf2211 commented Jun 26, 2026

Copy link
Copy Markdown

Summary

Detect structurally empty tool successes from stale remote streamable-http sessions and stop forwarding them as successful results.

Motivation

Fixes #505. When a remote MCP session goes stale, upstream CallTool can return err == nil with an empty content array. The gateway previously forwarded these as successful tool results, causing silent data loss on writes.

Changes

  • Add isStaleEmptySuccess to detect empty success responses (!isError, no content blocks, no structured content).
  • Add InvalidateKeptClient to evict and close a single cached remote client.
  • Route remote tool calls through callRemoteTool:
    • Return a protocol-level error when empty success is detected and auto-retry is unsafe.
    • For tools with readOnlyHint or idempotentHint, invalidate the stale client and retry once.
  • Unit tests for detection helpers and client invalidation.

Tests

go test ./pkg/gateway/ -run 'TestIsStaleEmptySuccess|TestIsSafeToRetryTool|TestInvalidateKeptClient' -v

All new tests pass.

Notes

  • Scoped to serverConfig.IsRemote() only; Docker/stdio paths are unchanged.
  • Auto-retry is gated on MCP tool annotation hints; absent hints fail safe with an error instead of silent empty success.
  • Reviewed with composer-2.5 subagent: APPROVE.

When a remote streamable-http MCP session goes stale, upstream tool
calls can return structurally empty successes (no content blocks) that
the gateway previously forwarded as successful results.

Detect these responses for remote servers, invalidate the cached
client, and retry once when tool annotations declare the call is
read-only or idempotent. Otherwise surface a protocol-level error
instead of silently returning empty data.

Fixes docker#505
@syf2211 syf2211 requested a review from a team as a code owner June 26, 2026 14:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remote streamable-http session goes stale → gateway returns silent "success" with empty results (writes lost), no error, no reconnect

2 participants