MCP Streamable HTTP: sessions are opened but never terminated (1.8% DELETE ratio), exhausting remote server worker pools
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.4k
- PR merge metrics
- PR metrics pending
Description
Version
codex-mcp-client/0.150.0-alpha.8
What happens
Codex opens MCP Streamable-HTTP SSE sessions against remote MCP servers and almost never tears them down. Concurrent sessions accumulate without bound, and because each open SSE stream pins a request worker on the server for the server's full stream timeout, the server's worker pool is exhausted by idle Codex sessions.
This is not a malformed-request or retry-on-error problem. Every request succeeds: 79,506 of 79,683 GETs returned HTTP 200, and the server opens a correct, spec-compliant stream each time.
Evidence
Measured from web-server access logs across three self-hosted WordPress MCP servers over 30 days (2026-07-31 → 2026-08-30), one Codex client, one source IP.
Session teardown ratio — the core defect:
| method | count | meaning |
|---|---|---|
GET |
79,683 | session / SSE stream opened |
POST |
10,996 | JSON-RPC messages |
DELETE |
1,440 | session terminated |
1.81% of opened sessions are ever explicitly closed — roughly 55 opens per teardown.
Resulting concurrency. I verified the server holds a stream for a fixed 180s (measured directly: http=200 bytes=1175 total=181.44s), so average concurrent streams = opens x 180 / 86400:
| date | server A | server B | server C | total concurrent |
|---|---|---|---|---|
| 2026-08-02 | 6.9 | 8.6 | 4.9 | 20.5 |
| 2026-08-26 | 11.5 | 2.2 | 2.1 | 15.9 |
| 2026-08-27 | 54.0 | 13.2 | 13.0 | 80.3 |
On 2026-08-27 that meant ~80 worker processes pinned by idle Codex sessions on a 2-core host. Observed effects: 64 concurrent PHP workers on a single vhost, run queue 64, %user 89%, ~1.8 GB swapped with sustained swap-in, HTTP 503s, and the sites becoming unreachable. Load average dropped from 67 to 6 within ~8 minutes of disabling the MCP servers in Codex, with no other change.
No active use was required. There were no Codex sessions doing work against these servers during most of the accumulation — the sessions were configured, not driven.
Expected behaviour
- Terminate MCP sessions with
DELETEwhen a session ends, rather than abandoning the stream. - Reuse a single SSE stream per configured server instead of opening a new one alongside the existing ones.
- Cap concurrent sessions per server, and back off when opens outpace teardowns.
Impact
Any remote MCP server that implements Streamable HTTP with a long-lived SSE GET and a bounded worker pool — which is the common shape for PHP, Python WSGI, and Ruby servers — will have its worker pool exhausted by an idle Codex client. Self-hosted and shared-hosting deployments are hit hardest, since worker counts there are small.
Notes
The MCP server here is the AI Engine WordPress plugin. I verified its side is behaving correctly: it gates on Accept: text/event-stream (406 otherwise), opens a compliant stream, and closes cleanly at its configured timeout. Zero 406s were logged, so the client's requests are well-formed throughout.
This may be related to #31499 (duplicate stdio process pools on Windows), but that one concerns local stdio transports; this is remote Streamable HTTP session accumulation.
Contributor guide
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
No source file or test is named. Start by locating the MCP Streamable HTTP session lifecycle and tracing how configured servers open, reuse, and close SSE streams; inspect the handling of session termination and concurrent opens. Done means sessions are explicitly terminated, streams are reused or bounded per server, and tests or measurements demonstrate that idle configured servers no longer accumulate sessions.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- backend-api-design, networking
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100