Title: MCP Server Session Lost in Multi-Worker Environment · Issue #520 · modelcontextprotocol/python-sdk · GitHub
Open Graph Title: MCP Server Session Lost in Multi-Worker Environment · Issue #520 · modelcontextprotocol/python-sdk
X Title: MCP Server Session Lost in Multi-Worker Environment · Issue #520 · modelcontextprotocol/python-sdk
Description: Describe the bug When deploying the MCP server in a Kubernetes environment with gunicorn's multi-process configuration, SSE connections disconnect after a period of time, resulting in subsequent messages receiving a 404 error "Could not ...
Open Graph Description: Describe the bug When deploying the MCP server in a Kubernetes environment with gunicorn's multi-process configuration, SSE connections disconnect after a period of time, resulting in subsequent me...
X Description: Describe the bug When deploying the MCP server in a Kubernetes environment with gunicorn's multi-process configuration, SSE connections disconnect after a period of time, resulting in subsequen...
Opengraph URL: https://github.com/modelcontextprotocol/python-sdk/issues/520
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"MCP Server Session Lost in Multi-Worker Environment","articleBody":"## Describe the bug\nWhen deploying the MCP server in a Kubernetes environment with gunicorn's multi-process configuration, SSE connections disconnect after a period of time, resulting in subsequent messages receiving a 404 error \"Could not find session for ID\". This occurs because SSE sessions are created in one worker process, but subsequent requests may be routed to different worker processes where the session state is not shared.\n\n## Steps to reproduce\n1. Deploy an MCP server in a Kubernetes environment using gunicorn\n2. Configure gunicorn with multiple workers (`workers \u003e 1`)\n3. Connect a client to the MCP server and establish an SSE connection (initial connection succeeds)\n4. Send the first message (successfully processed, returns 202)\n5. Wait a few seconds or try to send a second message\n6. Receive error: `WARNING mcp.server.sse Could not find session for ID: xxx-xxx-xxx`\n\n## Logs\n```\n[2025-04-15 19:26:26 +0800] [32] [INFO] connection open\n127.0.0.1:48270 - \"GET /mcps/sse HTTP/1.1\" 200\n127.0.0.1:48280 - \"POST /mcps/messages/?session_id=cb7ed84c8f2f4109b5712f9fb025a5c2 HTTP/1.1\" 202\n127.0.0.1:48280 - \"POST /mcps/messages/?session_id=cb7ed84c8f2f4109b5712f9fb025a5c2 HTTP/1.1\" 202\n127.0.0.1:48280 - \"POST /mcps/messages/?session_id=cb7ed84c8f2f4109b5712f9fb025a5c2 HTTP/1.1\" 202\n127.0.0.1:48280 - \"POST /mcps/messages/?session_id=cb7ed84c8f2f4109b5712f9fb025a5c2 HTTP/1.1\" 202\n127.0.0.1:48280 - \"POST /mcps/messages/?session_id=cb7ed84c8f2f4109b5712f9fb025a5c2 HTTP/1.1\" 202\n127.0.0.1:39380 - \"POST /mcps/messages/?session_id=cb7ed84c8f2f4109b5712f9fb025a5c2 HTTP/1.1\" 202\n[2025-04-15 19:26:47 +0800] [32] [WARNING] mcp.server.sse Could not find session for ID: cb7ed84c-8f2f-4109-b571-2f9fb025a5c2\n127.0.0.1:53124 - \"POST /mcps/messages/?session_id=cb7ed84c8f2f4109b5712f9fb025a5c2 HTTP/1.1\" 404\n[2025-04-15 19:26:47 +0800] [32] [ERROR] mcp.client.sse Error in post_writer: Client error '404 Not Found' for url 'http://localhost:8000/mcps/messages/?session_id=cb7ed84c8f2f4109b5712f9fb025a5c2'\n```\n\n## Expected behavior\nAll messages, whether initial or subsequent, should be processed normally without any session not found errors. Even when using multiple workers, SSE sessions should maintain continuous connections.\n\n## Environment information\n- Deployment environment: Kubernetes\n- Web server: gunicorn + uvicorn.workers.UvicornWorker\n- Session ID handling: Server converts UUIDs without hyphens to the hyphenated format\n- Local environment (running directly with uvicorn, single process) does not exhibit this issue\n\n## Reproduction conditions\n- Using gunicorn with multiple workers (`workers \u003e 1`)\n- Proxying multiple services (using ASGI routing)\n- Each worker maintains its own session state, with no session sharing between processes\n\n## Solution\nI resolved this issue by setting the worker count to 1:\n```bash\n# Before\nworkers=$(nproc --all) # Use all available CPU cores\n\n# After\nworkers=1 # Use single worker to maintain session consistency\n```\n\nHowever, this is not an ideal solution as it limits the service's scalability.\n\n## Suggested improvements\n1. Implement distributed session storage (e.g., Redis) in the MCP server to allow multiple workers to share session state\n2. Document the MCP server's session management limitations in multi-process environments\n3. Provide session recovery/reconnection mechanisms to handle session disconnections\n\n## Additional context\n- Server code (`session.py`) shows that session state is stored in process memory\n- In our implementation, we solved the problem by separating the MCP service from the main application, deploying it independently with a single worker\n- Regular ping operations can mitigate the issue but cannot completely solve the session state sharing problem in multi-process environments\n\n## Potential solution approach\nCould the MCP server be modified to add a session storage abstraction layer that allows users to configure different session storage backends (memory, Redis, file, etc.) to support distributed deployments?","author":{"url":"https://github.com/Mile-Away","@type":"Person","name":"Mile-Away"},"datePublished":"2025-04-15T12:38:17.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":11},"url":"https://github.com/520/python-sdk/issues/520"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:1153543a-7284-d595-ef51-0fcc8b195836 |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | BE9A:1AEEB2:3E3EAD:55041E:6A5A6346 |
| html-safe-nonce | bc62199998bf8dee5fff82d1e668349278a7ce96d9eb5e95f7f6cdeb0d663b60 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJCRTlBOjFBRUVCMjozRTNFQUQ6NTUwNDFFOjZBNUE2MzQ2IiwidmlzaXRvcl9pZCI6IjM4NTcxMjg1NDMzOTk2MDA5NjYiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ== |
| visitor-hmac | 270fc688bf3a2c6c561ae61cc81234bf19a378ec10637e623ef2083b92d841b4 |
| hovercard-subject-tag | issue:2996289145 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/modelcontextprotocol/python-sdk/520/issue_layout |
| twitter:image | https://opengraph.githubassets.com/a96de4e858f5b9b7616d65f703cf2be266e65ec99400c3a75ebee4084e7199ad/modelcontextprotocol/python-sdk/issues/520 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/a96de4e858f5b9b7616d65f703cf2be266e65ec99400c3a75ebee4084e7199ad/modelcontextprotocol/python-sdk/issues/520 |
| og:image:alt | Describe the bug When deploying the MCP server in a Kubernetes environment with gunicorn's multi-process configuration, SSE connections disconnect after a period of time, resulting in subsequent me... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | Mile-Away |
| hostname | github.com |
| expected-hostname | github.com |
| None | 05b9ddf6a47d2dbe13944873a99f5fb4b83ba4871f9cb8a8e256793a63ca9687 |
| turbo-cache-control | no-preview |
| go-import | github.com/modelcontextprotocol/python-sdk git https://github.com/modelcontextprotocol/python-sdk.git |
| octolytics-dimension-user_id | 182288589 |
| octolytics-dimension-user_login | modelcontextprotocol |
| octolytics-dimension-repository_id | 862584018 |
| octolytics-dimension-repository_nwo | modelcontextprotocol/python-sdk |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 862584018 |
| octolytics-dimension-repository_network_root_nwo | modelcontextprotocol/python-sdk |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | f8d29d1bd03dda2dd14b3f80b8bc27e1111f43bd |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width