fastmcp icon indicating copy to clipboard operation
fastmcp copied to clipboard

Received request before initialization was complete

Open Minseok0917 opened this issue 7 months ago • 5 comments

Description

I’m encountering the same issue as described here: https://github.com/modelcontextprotocol/python-sdk/issues/423

Example Code


Version Information

2.3.0

Additional Context

No response

Minseok0917 avatar May 12 '25 02:05 Minseok0917

Is this different than the bug reported in the low-level SDK, or does the traceback relate to FastMCP?

jlowin avatar May 12 '25 14:05 jlowin

I was working with the MCP Python SDK and migrated to FastMCP. During the process, I confirmed that the same error also occurs in FastMCP.

Minseok0917 avatar May 12 '25 18:05 Minseok0917

I understand that you encountered the error using FastMCP, but FastMCP's low-level server instance is the same as the one in the MCP SDK, so unless there is something FastMCP-related in a traceback, this issue should only be opened on the low-level repo (e.g. # 423) because it probably can not be solved here.

jlowin avatar May 12 '25 19:05 jlowin

@jlowin I’ve documented the issues I encountered while using the FastMCP SSE version. After reviewing the comments and logs above, I believe this issue does indeed originate from the mcp.server path in the MCP Python SDK.

Python sse_app example code

uv run uvicorn main:app --host 127.0.0.1 --port 9000 --reload

# main.py 
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

from fastmcp import FastMCP



app = FastAPI()
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],         
    allow_credentials=True,
    allow_methods=["*"],            
    allow_headers=["*"],        
)
mcp = FastMCP('agent-server')

@mcp.tool(
    name="add",       
    description="add function", 
)
def add(a:int, b:int):
    return a+b 

app.mount("/", mcp.sse_app())

Experiment code

<!--  index.html -->
<!DOCTYPE html>
<html>
  <head>
    <title>MCP SSE Client</title>
  </head>
  <body>
    <h1>SSE MCP Experiment</h1>
    <pre id="log"></pre>

    <script src="./common.js"></script>
  </body>
</html>
// common.js
let isInitialized = false;

const host = "http://localhost:9000";
const log = (msg) => {
  document.getElementById("log").textContent += msg + "\n";
};

const $fetch = (path, body) => {
  return fetch(path, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify(body),
  });
};

const eventSource = new EventSource(
  `${host}/sse?transportType=sse&url=${host}/sse`
);

eventSource.onopen = () => {
  log("✅ SSE Connected");
};

eventSource.onerror = (err) => {
  log("❌ Error: " + (err.message || JSON.stringify(err)));
};
eventSource.onmessage = (event) => {
  log("📨 Server  Message: " + event.data);
};

eventSource.addEventListener("endpoint", async function handler(event) {
  if (isInitialized) return;
  isInitialized = true;

  const endpoint = event.data;
  log("🛠️ server send endpoint: " + endpoint);

  await fetch(host + endpoint, {
    method: "POST",
    body: JSON.stringify({
      jsonrpc: "2.0",
      id: 0,
      method: "initialize",
      params: {
        protocolVersion: "2024-11-05",
        capabilities: {
          roots: {
            listChanged: true,
          },
          tools: {
            listChanged: true,
          },
          sampling: {},
        },
        clientInfo: {
          name: "ExampleClient",
          version: "1.0.0",
        },
      },
    }),
  }).then(async (response) => {
    const text = await response.text();
    log("✅ initialize:" + text);
  });

  await fetch(host + endpoint, {
    method: "POST",
    body: JSON.stringify({
      method: "notifications/initializedialize",
      jsonrpc: "2.0",
      params: {},
    }),
  }).then(async (response) => {
    const text = await response.text();
    log("✅ notifications/initializedialize:" + text);
  });

  await fetch(host + endpoint, {
    method: "POST",
    body: JSON.stringify({
      jsonrpc: "2.0",
      id: 1,
      method: "tools/list",
      params: {},
    }),
  }).then(async (response) => {
    const text = await response.text();
    log("✅ tools/list:" + text);
  });

});

Error log

ERROR:    Exception in ASGI application
  + Exception Group Traceback (most recent call last):
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\uvicorn\protocols\http\h11_impl.py", line 403, in run_asgi
  |     result = await app(  # type: ignore[func-returns-value]
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 60, in __call__
  |     return await self.app(scope, receive, send)
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\fastapi\applications.py", line 1054, in __call__
  |     await super().__call__(scope, receive, send)
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\starlette\applications.py", line 112, in __call__
  |     await self.middleware_stack(scope, receive, send)
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\starlette\middleware\errors.py", line 187, in __call__
  |     raise exc
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\starlette\middleware\errors.py", line 165, in __call__
  |     await self.app(scope, receive, _send)
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\starlette\middleware\cors.py", line 93, in __call__
  |     await self.simple_response(scope, receive, send, request_headers=headers)
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\starlette\middleware\cors.py", line 144, in simple_response
  |     await self.app(scope, receive, send)
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\starlette\middleware\exceptions.py", line 62, in __call__
  |     await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\starlette\_exception_handler.py", line 53, in wrapped_app
  |     raise exc
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\starlette\_exception_handler.py", line 42, in wrapped_app
  |     await app(scope, receive, sender)
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\starlette\routing.py", line 714, in __call__
  |     await self.middleware_stack(scope, receive, send)
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\starlette\routing.py", line 734, in app
  |     await route.handle(scope, receive, send)
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\starlette\routing.py", line 460, in handle
  |     await self.app(scope, receive, send)
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\starlette\applications.py", line 112, in __call__
  |     await self.middleware_stack(scope, receive, send)
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\starlette\middleware\errors.py", line 187, in __call__
  |     raise exc
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\starlette\middleware\errors.py", line 165, in __call__
  |     await self.app(scope, receive, _send)
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\fastmcp\server\http.py", line 59, in __call__
  |     await self.app(scope, receive, send)
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\starlette\middleware\exceptions.py", line 62, in __call__
  |     await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\starlette\_exception_handler.py", line 53, in wrapped_app
  |     raise exc
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\starlette\_exception_handler.py", line 42, in wrapped_app
  |     await app(scope, receive, sender)
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\starlette\routing.py", line 714, in __call__
  |     await self.middleware_stack(scope, receive, send)
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\starlette\routing.py", line 734, in app
  |     await route.handle(scope, receive, send)
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\starlette\routing.py", line 288, in handle
  |     await self.app(scope, receive, send)
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\starlette\routing.py", line 76, in app
  |     await wrap_app_handling_exceptions(app, request)(scope, receive, send)
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\starlette\_exception_handler.py", line 53, in wrapped_app
  |     raise exc
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\starlette\_exception_handler.py", line 42, in wrapped_app
  |     await app(scope, receive, sender)
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\starlette\routing.py", line 73, in app
  |     response = await f(request)
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\fastmcp\server\http.py", line 206, in sse_endpoint
  |     return await handle_sse(request.scope, request.receive, request._send)  # type: ignore[reportPrivateUsage]
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\fastmcp\server\http.py", line 171, in handle_sse
  |     async with sse.connect_sse(scope, receive, send) as streams:
  |   File "C:\Users\nmins\AppData\Local\Programs\Python\Python310\lib\contextlib.py", line 217, in __aexit__
  |     await self.gen.athrow(typ, value, traceback)
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\mcp\server\sse.py", line 128, in connect_sse
  |     async with anyio.create_task_group() as tg:
  |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\anyio\_backends\_asyncio.py", line 772, in __aexit__
  |     raise BaseExceptionGroup(
  | exceptiongroup.ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
  +-+---------------- 1 ----------------
    | Exception Group Traceback (most recent call last):
    |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\mcp\server\sse.py", line 147, in connect_sse
    |     yield (read_stream, write_stream)
    |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\fastmcp\server\http.py", line 172, in handle_sse
    |     await server._mcp_server.run(
    |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\mcp\server\lowlevel\server.py", line 489, in run
    |     async with AsyncExitStack() as stack:
    |   File "C:\Users\nmins\AppData\Local\Programs\Python\Python310\lib\contextlib.py", line 714, in __aexit__
    |     raise exc_details[1]
    |   File "C:\Users\nmins\AppData\Local\Programs\Python\Python310\lib\contextlib.py", line 217, in __aexit__
    |     await self.gen.athrow(typ, value, traceback)
    |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\fastmcp\server\server.py", line 87, in wrap
    |     yield context
    |   File "C:\Users\nmins\AppData\Local\Programs\Python\Python310\lib\contextlib.py", line 697, in __aexit__
    |     cb_suppress = await cb(*exc_details)
    |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\mcp\shared\session.py", line 209, in __aexit__
    |     return await self._task_group.__aexit__(exc_type, exc_val, exc_tb)
    |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\anyio\_backends\_asyncio.py", line 772, in __aexit__
    |     raise BaseExceptionGroup(
    | exceptiongroup.ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
    +-+---------------- 1 ----------------
      | Traceback (most recent call last):
      |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\mcp\server\session.py", line 146, in _receive_loop
      |     await super()._receive_loop()
      |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\mcp\shared\session.py", line 349, in _receive_loop
      |     await self._received_request(responder)
      |   File "C:\workspaces\experiment_sse\.venv\lib\site-packages\mcp\server\session.py", line 171, in _received_request
      |     raise RuntimeError(
      | RuntimeError: Received request before initialization was complete
      +------------------------------------

Minseok0917 avatar May 13 '25 07:05 Minseok0917

Same here, but for stdio

n-sviridenko avatar May 24 '25 10:05 n-sviridenko

same error

wenlinguo avatar Jun 10 '25 00:06 wenlinguo

I think this is addressed by https://github.com/modelcontextprotocol/python-sdk/pull/1478

jlowin avatar Oct 15 '25 15:10 jlowin