Repository navigation
Python: Make MCP connection-loss recovery ownership-aware #9426
Description
Problem
Agent Framework has three MCP connection ownership modes:
- framework-created high-level
mcp.Client; - caller-supplied high-level
mcp.Client; - caller-supplied low-level
ClientSession.
The public contract is ownership-preserving. A supplied Client must already be entered, remains caller-owned, and is not entered, closed, replaced, or recreated by Agent Framework. A supplied ClientSession is likewise caller-owned and is not replaced or reconnected by the wrapper. Closing or resetting the wrapper preserves either supplied object.
Connection-loss handling does not consistently honor that contract. Discovery, liveness, tool, and prompt paths call connect(reset=True) or _reconnect_without_loading() and log that they are reconnecting. For a caller-owned connection, reset correctly preserves the supplied object. The operation can therefore retry against the same ended connection while reporting a reconnection that did not occur.
This mismatch predates caller-supplied high-level Client support. The original reconnect implementation did not distinguish ownership and could silently discard a supplied session and open the tool's configured transport. #8126 intentionally corrected that ownership violation, but the older recovery call sites were not made ownership-aware.
Public API Boundary
The existing API and documentation establish this division of responsibility:
- Agent Framework may construct, enter, close, and recreate connections that it owns.
- The caller constructs, configures, enters, closes, and replaces connections that it supplies.
- The MCP SDK owns protocol negotiation, standard operations, MRTR, caching, and event delivery.
- Agent Framework owns wrapper coordination, catalog publication, tracing, parsing, policy, and recovery only where the framework owns the connection lifecycle.
A caller-provided replacement factory is not part of this contract. Adding one would create a new lifecycle/ownership mode and is not required to fix the current behavior.
Desired Behavior
Centralize connection-loss handling around ownership:
- Framework-owned connections may be recreated when the failed operation is safe to retry.
- Caller-owned
ClientandClientSessionconnections must not claim to reconnect or retry the same object after a definitive connection-loss condition. - Instead, fail immediately with an actionable error explaining that the caller must create and supply a replacement connection or reconstruct the MCP tool wrapper.
- Preserve the supplied connection object so Agent Framework does not close or replace caller resources.
- Keep diagnostics truthful about whether a connection was actually recreated.
The shared helper should decide whether Agent Framework can recover the connection, while individual operations retain their own retry-safety policy.
Separate Correctness Concern
Ordinary tools/call currently retries once after an ambiguous lost response. The server may already have executed a side-effecting tool, so replay can duplicate the operation. The repository already avoids this for task-backed calls before a task ID is known.
That replay-safety problem affects framework-owned connections as well as caller-owned connections and should be tracked separately. This issue must not assume that recreating a connection automatically makes tools/call safe to repeat.
Acceptance Criteria
- Connection-loss recovery uses one ownership-aware internal decision point across discovery, liveness, tool, and prompt paths.
- Framework-owned connection recovery continues to recreate the Client where the operation's policy permits retry.
- Caller-owned connection loss produces an actionable ownership error before a second RPC is attempted against the same ended object.
- Logs and exceptions do not claim that a caller-owned connection was reconnected or replaced.
- Reset and close continue to preserve caller-owned Clients and ClientSessions.
- Tests cover caller-owned modern and legacy Clients plus caller-owned
ClientSessionbehavior for discovery, liveness, tools, and prompts. - ADR/API documentation remains explicit that replacement of supplied connections is the caller's responsibility.
Non-Goals
- Adding a Client/session factory or replacement-provider API.
- Transferring lifecycle ownership of supplied connections to Agent Framework.
- Defining replay safety for ordinary side-effecting
tools/calloperations. - MCP 2026 protocol compliance work.
- Subscription-stream recovery while the underlying Client remains usable; that behavior was implemented by Python: [BREAKING] Add MCP 2.x compatibility foundation #9236 and Python: Decide recovery policy for ended MCP subscription streams #9109 is closed.
Related
- Python: Clean up MCP HTTP resources after failed connections #8126 — established ownership-preserving reset and cleanup for caller-supplied sessions
- Python: [Feature]: Support the stateless MCP 2026-07-28 revision alongside 2025-era peers #8245 — MCP 2026-07-28 migration umbrella
- Python: [BREAKING] Add MCP 2.x compatibility foundation #9236 — MCP 2.x compatibility foundation
- Python: Document MCP v2 client lifecycle and update samples #9237 — MCP v2 client lifecycle ADR and caller-supplied Client support
- Python: [Feature]: Python: Define lifecycle ownership for agents with MCP tools inside workflows and orchestrations #9369 — lifecycle ownership for agents with MCP tools inside workflows
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsDone
Activity
KNIHAL commentedon Oct 18, 2026
Hi, I'd like to contribute to this issue.
I'm interested in implementing the ownership-aware MCP connection recovery behavior, including focused regression tests for caller-owned
ClientandClientSessionconnections.Before starting, could a maintainer confirm the intended recovery policy and whether this issue is available for a community contribution? If the direction aligns, could you please assign it to me?
I'll wait for confirmation before implementation. Thanks!
[-]Python: Define recovery semantics for caller-owned MCP connections[/-][+]Python: Make MCP connection-loss recovery ownership-aware[/+]jpalvarezl commentedon Oct 21, 2026
The scope has been clarified after reviewing the implementation history, ADR, API docs, and public Microsoft Learn guidance. This is now tracked as an ownership-aware recovery bug: framework-owned connections may be recreated where retry is safe, while definitive loss of a caller-owned connection must fail clearly instead of retrying the same ended object. A replacement factory/provider is explicitly out of scope, and ambiguous replay of ordinary side-effecting tools/call will be handled as a separate correctness concern.
jpalvarezl commentedon Oct 21, 2026
Maintainer direction confirmed: proceed with the ownership-aware fail-fast behavior and shared recovery decision described above. Keep caller-owned connection replacement and ordinary tools/call replay safety outside this issue's implementation scope.