Symptom
handle_modern_request starts every SSE response with the module-level _SSE_HEADERS list. Middleware that does message["headers"].append(...) mutates that shared list, so later SSE responses carry earlier headers and extra copies.
Evidence what you'll see
- The report's five-call loop prints
1 1,2 2,3 3,4 4,5 5for the count ofx-correlation-idon each SSE response. - JSON responses are not affected, because they build their own header list.
- A comment on 14 Oct 2026 confirms the same line on
maininsrc/mcp/server/_streamable_http_modern.py.
Why it happens
On the 2026-07-28 HTTP entry, handle_modern_request passes _SSE_HEADERS itself into http.response.start. An ASGI wrapper that appends in place therefore grows the SDK's list for the life of the process. Only calls that commit to SSE take this path.
Affected versions
Python 3.13, mcp 2.3.0, also present on main at 754254c. The linked issue does not name an operating system.
Fix steps
0 of 2 done
Your check marks stay in this browser only.
How to check it worked
- The issue's five-request loop prints a count of 1 for
x-correlation-idon every SSE response, not a growing count.
If it still fails
- No published release tag contains pull request 3726. Tag
v2.3.0was compared against merge2af9e3089aand does not contain it. - A JSON response is not this path. The linked issue does not describe a remaining leak after the copy in pull request 3726.
Sources and credit
Summarized in our own words from these public reports. Credit goes to their authors.
Provided as is, without warranty. Try changes in a non-production environment and back up first. Security-related steps: verify against the official docs. Terms · Request removal or attribution change
Hit an error we don't cover? Submit it