fastapi_mcp icon indicating copy to clipboard operation
fastapi_mcp copied to clipboard

[BUG] Uvicorn reload hangs when FastAPI-MCP has active SSE connections

Open jagerzhang opened this issue 6 months ago • 5 comments

Describe the bug When using FastAPI-MCP with SSE connections active, Uvicorn's reload functionality gets stuck during shutdown phase, requiring manual process termination. This severely impacts development workflow.

To Reproduce

  1. Create minimal FastAPI app main.py with MCP mounted:
from fastapi import FastAPI
from fastapi_mcp import FastApiMCP

app = FastAPI()

mcp = FastApiMCP(app)

# Mount the MCP server directly to your FastAPI app
mcp.mount()
  1. Start server with reload:

uvicorn --reload --port 9000 main:app

Open browser to SSE endpoint: http://localhost:9000/mcp and hold on:

Image
  1. Modify any file (e.g. main.py) to trigger reload

Expected Behavior:

Server should:

  1. Detect file changes
  2. Gracefully close existing connections
  3. Restart with new code

Actual Behavior:

Server hangs at shutdown phase:
INFO:     Shutting down
INFO:     Waiting for connections to close. (CTRL+C to force quit)

System Information: fastapi==0.115.12 fastapi-mcp==0.3.6 uvicorn==0.34.2 Python==3.12.10 OS: Linux

Proposed Solutions:

  1. Add proper SSE connection tracking in FastAPI-MCP
  2. Implement graceful shutdown handler for SSE
  3. Provide API to manually close connections before reload

jagerzhang avatar Jul 14 '25 07:07 jagerzhang

Hi, I replicated and didn't face any issue, can you pls elaborate ?

sqrt676 avatar Jul 15 '25 13:07 sqrt676

@sqrt676

Docker Reproduction Environment

1. ​File Structure​

fastapi-mcp-reload-issue/  
├── main.py              # FastAPI + MCP entrypoint  
└── Dockerfile           # Image build  

2. ​File Contents

  • main.py
from fastapi import FastAPI
from fastapi_mcp import FastApiMCP

app = FastAPI()

mcp = FastApiMCP(app)

# Mount the MCP server directly to your FastAPI app
mcp.mount()
  • Dockerfile
FROM python:3.12
WORKDIR /app
RUN pip install --no-cache-dir fastapi fastapi-mcp
EXPOSE 9000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "9000", "--reload"]

3. Build Docker image

cd fastapi-mcp-reload-issue
docker build -t test-fastapi-mcp-reload

4. Start Docker Container

docker run --rm -ti -v "$(pwd):/app" -p 9000:9000 test-fastapi-mcp-reload  

5. Reproduction Steps​

Initiate SSE connection​ (new terminal):

curl -v -N http://localhost:9000/mcp

Modify main.py​ (new terminal; e.g., add a comment):

cd fastapi-mcp-reload-issue
echo "# Trigger reload" >> main.py  

Active SSE connection: Image

Hanging reload process and can not stop with ctrl+c: Image

Reload proceeds normally ONLY AFTER terminating the curl request​ - stopping the SSE client connection allows the shutdown sequence to complete.

jagerzhang avatar Jul 16 '25 02:07 jagerzhang

I'm experiencing the same issue. It does not want to shutdown.

Spenhouet avatar Oct 15 '25 07:10 Spenhouet

Running uvicorn with --timeout-graceful-shutdown seems to do the trick.

uvicorn main:app --port 8000 --reload --timeout-graceful-shutdown=0

tomsquest avatar Nov 04 '25 13:11 tomsquest

I've also had this problem and can confirm @tomsquest solution seems to work.

baebranch avatar Nov 23 '25 04:11 baebranch