Skip to content

fix: avoid replaying ambiguous stale stdio MCP calls#924

Open
9s5bz2jvd2-lang wants to merge 2 commits into
Lingtai-AI:mainfrom
9s5bz2jvd2-lang:fix/stdio-mcp-ambiguous-replay
Open

fix: avoid replaying ambiguous stale stdio MCP calls#924
9s5bz2jvd2-lang wants to merge 2 commits into
Lingtai-AI:mainfrom
9s5bz2jvd2-lang:fix/stdio-mcp-ambiguous-replay

Conversation

@9s5bz2jvd2-lang

@9s5bz2jvd2-lang 9s5bz2jvd2-lang commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Stop automatically replaying an MCP tool call after a stale stdio transport failure, because the first remote outcome may already have committed.
  • Restart the transport for a future independent call, but return status="error", outcome="ambiguous", and retryable=false for the in-flight call.
  • Preserve one explicit retry_policy="safe" opt-in for callers that have independently verified replay safety. No production caller opts in in this patch.

Validation

  • git diff --check
  • Focused stale-resource tests on current main: 21 passed
  • MCP-focused tests on current main: 177 passed
  • Direct-caller and structured-result consumer tests on current main: 659 passed
  • Fake-session harness: one caller invocation, one side effect, zero replacement-session calls, one transport restart, FIX_CONFIRMED

Post-review timeout completion

  • Added commit 3b51e21386f3c003a1405f4c0616e1600456fb28 (fix(mcp): mark post-submit timeouts ambiguous).
  • A TimeoutError raised after asyncio.run_coroutine_threadsafe() has returned a Future now returns outcome="ambiguous" and retryable=false; the local Future is cancelled for cleanup only, with no claim that the remote call was cancelled and no blind replay.
  • A same-class error raised before a Future exists remains an ordinary non-ambiguous error.
  • Added regression coverage for both sides of that submission boundary.
  • Additional validation: git diff --check, python -m compileall -q src/lingtai/services/mcp.py, focused test module 23 passed, and relevant MCP suite 156 passed.
  • A second independent, read-only review found APPROVE / no material issue and confirmed the submission boundary plus unchanged stale-resource/safe-retry behavior.

Notes

  • Follow-up to fix: restart stale MCP stdio sessions #222, which introduced stale stdio recovery by restarting the session and retrying once; this change narrows replay behavior when the remote outcome is ambiguous.
  • Scope is limited to the stdio MCPClient and its regression tests; HTTPMCPClient is unchanged.
  • This does not claim exactly-once execution. Shared-client restart synchronization and the existing broad stale-error classifier remain separate follow-ups.
  • Validation used fake sessions only; it did not start a real MCP process, access credentials, contact the network, or perform an external delivery.
  • One post-open broad-suite attempt failed during fixture setup because the test environment and pytest basetemp shared a parent that disappeared; there were no assertion failures. The rerun used independent parents and passed 177 + 659 tests.

@9s5bz2jvd2-lang
9s5bz2jvd2-lang marked this pull request as ready for review July 15, 2026 00:48
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.

1 participant