Skip to content

fix(mcp): restore live connector preservation and bounded shutdown - #932

Open
breedx wants to merge 1 commit into
mpfaffenberger:mainfrom
breedx:fix/upstream-mcp-shutdown-resubmit
Open

fix(mcp): restore live connector preservation and bounded shutdown#932
breedx wants to merge 1 commit into
mpfaffenberger:mainfrom
breedx:fix/upstream-mcp-shutdown-resubmit

Conversation

@breedx

@breedx breedx commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Refreshing MCP configuration should not replace live connectors, and stopping a healthy connector should not deadlock on its own cleanup lock. This restores the narrow preservation and bounded-shutdown fix from #924 after its revert in #931.

Resubmission

GitHub cannot reopen a merged PR, so this is a new reviewable submission against current main (007c53b2, v0.0.833).

Change

  • Preserve existing connector object identity and status when materializing newly discovered configuration.
  • Cancel registered lifecycle tasks under the registry lock, then drain outside the lock with a five-second deadline.
  • Preserve the cleanup task on timeout, repeated stop, and caller cancellation; retain registration after failed cleanup.
  • Drain registered contexts concurrently through one stable, deduplicated shutdown callback.
  • Keep detailed exception diagnostics at DEBUG with generic cleanup warnings.

Validation

Current upstream lock installed in a dedicated environment: Linux, Python 3.13.13, core plugins 0.0.45, Pydantic AI 2.35.0, MCP 1.27.1, and fastmcp-slim 3.4.7.

  • pytest -q -o addopts= tests/mcp/test_shutdown_preservation.py: 9 passed, including real local stdio transport cleanup.
  • Changed-file Ruff lint and format checks passed; git diff --check passed.
  • Patch identity and public-only diff checks passed.
  • Broad regression selection (tests/mcp tests/agents tests/tools tests/command_line/mcp tests/test_completions_and_small_modules.py tests/test_claude_refresh_review.py): 1,898 passed, 7 skipped, 1 warning.
  • The warning is an unawaited AsyncMockMixin._execute_mock_call in the browser control tests. Running tests/tools/browser/test_browser_control.py independently on both this candidate and unpatched 007c53b2 reproduces the same warning: 26 passed, 1 warning in each lane. It was not suppressed.
  • Public CI: quality and Windows encoding passed; macOS suite 1 failed, 7,854 passed, 14 skipped, 27 warnings. The sole failure is tests/command_line/test_autosave_menu.py::TestSessionBrowser::test_open_project_and_select_session expecting TODAY from entries timestamped one/two hours before datetime.now() just after midnight. The same isolated assertion fails on both unpatched 007c53b2 and this candidate. This patch changes neither the browser nor that test; no clock-dependent rerun or assertion suppression was used.
  • The CI job is labelled Python 3.13, but its paths show Python 3.14.7; local checks above used 3.13.13. CI additionally reports deprecation/resource/coroutine warnings. Those logs were inspected, but only the browser warning above has a new independent local base control here; this is not an all-green or merge-ready claim.

Local tests use disposable HOME/XDG, no inherited credentials, and blocked socket connect/DNS/bind. Prior bug-regression baseline controls and independent review are documented in #924; those historical counts are not being presented as new results.

Boundaries

This does not fix restart/reload/remove ordering, pending startup ownership, late startup registration, manager/CLI completion reporting, or completion-time agent rebinding. Connector-entry containment is separate. The deadline bounds caller waiting, not process termination; operations remain on their owning event loop. No release or deployment qualification is claimed.

Keep materialized connector objects/status during manager refresh. Cancel registered lifecycle tasks under the registry lock, then drain outside it with a five-second deadline. Retain ownership on incomplete cleanup and deduplicate the shutdown callback. Restart ordering and pending startup ownership remain separate concerns.
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