Cursor MCP SSE server times out: TypeError: terminated: Body Timeout Error
When I create an MCP SSE server with the npm package @modelcontextprotocol/sdk using the README's HTTP-with-SSE example, deploy it, and configure it in Cursor on macOS, after about 300 seconds Cursor logs "SSE error: TypeError: terminated: Body Timeout Error". Why is the connection timing out and what can I do?
Originally asked on GitHub: https://github.com/modelcontextprotocol/typescript-sdk/issues/270
5 answers
Status: the SDK issue is closed; a maintainer explained the cause and the workaround that worked in the thread was reported by another user. The timeout is a client-side request timeout. In the TypeScript SDK you can set the timeout as part of RequestOptions, and it defaults to 1 minute, but Cursor does not yet support configuring that request timeout, based on the maintainer's link to a Cursor forum thread.
The workaround that worked: keep the SSE response stream busy. In the Express handler for /sse, after creating the SSEServerTransport from @modelcontextprotocol/sdk/server/sse.js, start an interval that writes an SSE comment every 25 seconds:
res.write(': keepalive\n\n');
The reporter used KEEP_ALIVE_INTERVAL_MS = 25000 and cleaned up by clearing the interval and deleting the transport/session in the response "close" handler. That kept the connection alive.
Another reporter tried the same keep-alive approach with the Streamable HTTP transport, but the response was no longer writable by the time the interval fired, so this workaround is tied to the SSE transport.
The maintainer also suggested testing with the MCP Inspector, setting a longer timeout there, and calling the same tool to see if it completes. If it completes there, the remaining problem is likely Cursor's timeout handling, so the keep-alive workaround may be needed until Cursor implements request timeout management.
Did this work for you?What @Siim tried on GitHub (Worked)
Added a keep-alive interval to the /sse Express handler that writes res.write(': keepalive\n\n'); every 25 seconds and clears the interval on connection close. The reporter said this kept the SSE connection alive.
Did this work for you?What @cliffhall tried on GitHub (Outcome unclear)
A maintainer suggested testing with the MCP Inspector using a longer request timeout. The maintainer noted the SDK supports setting timeout via RequestOptions with a 1-minute default, but Cursor does not yet support configuring that timeout.
Did this work for you?What @Meandmybadself tried on GitHub (Didn't work)
Tried the keep-alive comment technique with the Streamable HTTP transport, but by the time the interval fired the response was no longer writable.
Did this work for you?What a GitHub user tried on GitHub (Didn't work)
Reproduced by building an SSE server with @modelcontextprotocol/sdk from the README's HTTP-with-SSE example, deploying it, and connecting from Cursor on macOS; Cursor logged SSE error: TypeError: terminated: Body Timeout Error after about 300 seconds.
Source: https://github.com/modelcontextprotocol/typescript-sdk/issues/270 (opens external site)
Did this work for you?
Related questions
- MCP TypeScript SDK StreamableHttp without sticky sessions in multi-replica deployments?
- MCP stdio server: SyntaxError Unexpected token in deserializeMessage when using console.log
- MCP typescript-sdk: tool inputSchema/outputSchema reject JSON Schema type 'array'?
- Use Zod union/intersection as MCP tool paramsSchema in typescript-sdk?
- MCP Inspector: "Invalid transport type: undefined" when connecting to an SSE server