openai / openai/codex-plugin-cc
App-server broker retains thread subscriptions after task clients disconnect
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 33.3k
- Forks
- 2.3k
- PR merge metrics
- No merged PRs in 30d
Description
Summary
The app-server broker shares one upstream connection across plugin tasks.
Each task starts or resumes a thread, which subscribes that upstream connection.
The downstream task socket closes after completion.
The broker clears routing state but never sends thread/unsubscribe.
Completed threads and their MCP runtimes remain loaded until unsubscribe or app-server shutdown.
Observed impact
- Fresh tasks accumulate MCP runtimes inside one broker session.
- One app-server retained 11 Basic Memory runtimes.
- Other app-servers retained seven, five, and five runtimes.
- Basic Memory only made the generic broker defect visible.
- The proposed fix contains no Basic Memory dependency.
Reproduction
- Configure any stdio MCP server in Codex.
- Start Claude Code with the Codex plugin.
- Run several fresh Codex tasks in one workspace.
- Let every task finish normally.
- Inspect the app-server process tree.
Observed result
- Each fresh task creates another thread and MCP runtime.
- The downstream task client disconnects.
- The upstream thread subscription remains active.
- Completed tasks therefore accumulate MCP processes.
Expected behavior
The broker should track thread ownership for each downstream socket.
It should send thread/unsubscribe after the final owner disconnects.
Cause
thread/start subscribes the shared upstream connection to thread events.
The broker does not associate that subscription with its downstream owner.
Socket closure therefore removes routing state without removing the subscription.
The final unsubscribe starts Codex's documented 30-minute inactivity period.
Codex unloads the thread and MCP runtime after that period.
Proposed fix
- Track subscribed threads for each downstream socket.
- Preserve subscriptions while another downstream owner remains.
- Cover started, resumed, forked, review, and automatically created child threads.
- Unsubscribe after normal or abrupt final-owner disconnection.
- Log upstream unsubscribe failures.
- Add broker ownership regression tests.
Real-process verification
Tested with Codex CLI 0.150.1 and Basic Memory.
| Case | Probe after client closure | Meaning | MCP process result |
|---|---|---|---|
| Control broker | unsubscribed |
The broker retained the subscription | Exited approximately 30 minutes after the probe unsubscribed |
| Patched broker | notSubscribed |
The broker had already unsubscribed | Exited approximately 30 minutes after client closure |
Both cases started a real Basic Memory wrapper and Python server.
Every isolated test descendant exited during cleanup.
Related work
- #543 tracks retained broker and app-server process trees.
- #660 proposes broader broker supervision and cleanup.
- #680 proposes broker idle shutdown.
Those changes bound session lifetime.
This issue addresses per-task thread retention inside a running broker.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing the app-server broker's handling of thread/start, resumed, forked, review, and automatically created child threads, then follow downstream socket closure through routing cleanup. Add broker ownership regression tests covering shared owners and normal or abrupt final-owner disconnection. Done means final owners trigger thread/unsubscribe, shared subscriptions remain active, failures are logged, and all listed thread paths are covered.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- backend, testing-qa
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100