fix: exit orphaned stdio MCP servers on parent death - #66
Conversation
Clients can abandon sessions while a wrapper keeps stdin open, so EOF never arrives and leaked servers thrash swap. Add a parent-liveness watchdog (same approach as mcp-automem).
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d0dccd9900
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Capture os.getppid() before any await and pass it into the watchdog. Soft stdin EOF remains intentional (no hard-exit on EOF alone); hard exit stays on parent reparent / OS signals.
Installed wheels omitted the watchdog module, so entrypoints failed with ModuleNotFoundError. Add it to py-modules alongside the other top-level modules.
CI Python lint failed on I001 for server/profile_server/parent_watchdog imports.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: aba55b0eca
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
CI runs ruff format --check; quote style must match project defaults.
ruff format rewrites fenced Python examples in skill markdown incorrectly (e.g. keyword args become tuples), and those docs were already failing format --check on main. Keep assets out of the CI formatter.
Summary
Stdio MCP servers can leak forever when a client (Claude Desktop / Cursor / Grok / Codex) abandons a session but an intermediate wrapper keeps the stdin write-end open. No EOF arrives, the process stays alive, and repeated leaks cause multi-GB swap thrashing.
This adds a parent-liveness watchdog (same approach as mcp-automem): when
ppid/os.getppid()changes from the startup parent (POSIX reparent), exit promptly.Test plan