Add lifecycle management for beads-mcp processes (bd-148)

- Register atexit handler to close daemon connections
- Add signal handlers for SIGTERM/SIGINT for graceful shutdown
- Implement cleanup() to close all daemon client connections
- Track daemon clients globally for cleanup
- Add close() method to BdDaemonClient (no-op since connections are per-request)
- Register client on first use via _get_client()
- Add comprehensive lifecycle tests

This prevents MCP server processes from accumulating without cleanup.
Each tool invocation will now properly clean up on exit.

Amp-Thread-ID: https://ampcode.com/threads/T-05d76b8e-dac9-472b-bfd0-afe10e3457cd
Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
Steve Yegge
2025-10-18 14:27:37 -07:00
parent 0baac7b22c
commit 5e0030d283
6 changed files with 231 additions and 4 deletions

View File

@@ -424,3 +424,14 @@ class BdDaemonClient(BdClientBase):
return True
except (DaemonNotRunningError, DaemonConnectionError, DaemonError):
return False
def close(self) -> None:
"""Close daemon client connections and cleanup resources.
This is called during MCP server shutdown to ensure clean termination.
Since we use asyncio.open_unix_connection which closes per-request,
there's no persistent connection to close. This method is a no-op
but exists for API consistency.
"""
# No persistent connections to close - each request opens/closes its own
pass