Cursor successfully connects to a custom SSE-based MCP server (indicated by the yellow dot and correct Server Link URL in the MCP Servers UI), but it consistently displays “No tools available”.
Server-side logs confirm the initial SSE connection (GET /sse), but Cursor never seems to send the subsequent POST /sse request required to fetch the tool list (tools/list).
However, manually sending this POST request to the server using curl works correctly and returns the expected tool list.
Steps to Reproduce:
Set up an SSE MCP Server: Create an MCP server (in my case, using Wasp framework on Node.js) that listens on a specific URL (e.g., http://localhost:3001/sse or a specific IP).
Implement Server Logic:
Handle GET /sse: Establish the SSE connection, store the client connection, and send a valid mcp/hello message, including "capabilities": { "tools": { "listChanged": true } }.
Handle POST /sse: Listen for JSON-RPC requests on the same/sse path. Implement the tools/list method to return a correctly formatted JSON-RPC response containing the available tools directly in the HTTP response body.
Configure in Cursor: Add the server to Cursor via the UI or using .cursor/mcp.json:
{
"mcpServers": {
"my-custom-sse-server": {
"name": "My Custom SSE Server",
"url": "http://localhost:3001/sse" // Or the correct IP/port
}
}
}
Observe Cursor: Restart Cursor or refresh the MCP server list.
Result: Cursor shows the server with a yellow dot and the correct URL, but displays “No tools available”.
Expected Behavior:
After receiving the mcp/hello, Cursor should send a POST /sse request with the tools/list method. Upon receiving a valid response to this POST request, Cursor should display the available tools in the UI.
Actual Behavior:
Cursor connects via GET /sse and receives mcp/hello (confirmed by server logs), but it never sends the POST /sse request for tools/list (confirmed by absence of corresponding server logs). Consequently, it displays “No tools available”.
Evidence:
Server Logs: Show successful GET /sse connection and mcp/hello sent, but no subsequent logs indicating a received POST /sse request from Cursor.
curl Test: Manually sending a POST request works perfectly:
# Using cmd.exe on Windows, adjust quotes for other terminals
curl -X POST -H "Content-Type: application/json" -d "{\"jsonrpc\": \"2.0\", \"method\": \"tools/list\", \"id\": \"curl-test\"}" http://<your-server-ip>:3001/sse
This command successfully returns the JSON-RPC response with the tool list from the server.
Following up on this issue, I’ve conducted further investigation with extensive troubleshooting, including network analysis using Wireshark.
Summary of Findings:
While my initial report suggested Cursor wasn’t sending a POST request for tools/list, further testing revealed complexities in how the SSE connection and initial messages are handled. We experimented with different server-side approaches, ultimately configuring the server to behave as follows, which seems most compliant based on standard SSE/JSON-RPC practices:
On GET /sse Connection:
Server establishes the SSE connection.
Server immediately sends the mcp/hello message (with "capabilities": { "tools": { "listChanged": true } }).
Server immediately follows up by pushing a tools/list notification (JSON-RPC message with method: "tools/list", no id, and the tool list in params) over the same established SSE connection.
Chunked Encoding Issue Fixed: Wireshark analysis initially revealed that the server’s SSE response was being sent with Transfer-Encoding: chunked. This is generally incorrect for text/event-stream. We have fixed this issue on the server-side, and the response is no longer chunked.
Current Situation & Evidence (Wireshark Confirmed):
Despite the server now operating correctly, Cursor still shows “No tools available”.
Server → Cursor:HTTP/1.1 200 OK (Correct SSE headers: Content-Type: text/event-stream, Connection: keep-alive, Cache-Control: no-cache, NOTransfer-Encoding: chunked).
Server → Cursor (Same TCP Stream): A single data packet containing both SSE messages sequentially:
data: {"jsonrpc":"2.0","method":"mcp/hello",...}
data: {"jsonrpc":"2.0","method":"tools/list","params":{...}} (Schema simplified during testing, even tested with input_schema: {})
Crucially, the Transfer-Encoding: chunked header and the associated chunk size indicators (like the 96 hex value seen previously) are no longer present in the server’s response stream captured by Wireshark.
A simple curl -N http://localhost:3001/sse also correctly receives both the mcp/hello and the subsequent tools/list messages streamed from the server.
Conclusion:
Given that:
The server correctly establishes the SSE connection.
The server sends valid, non-chunked mcp/hello and tools/list messages immediately upon connection.
curl can receive these messages correctly.
Cursor still fails to display the tools.
The evidence strongly suggests the issue lies within Cursor’s MCP client implementation and its handling of the incoming SSE stream or the parsing/processing of the mcp/hello and subsequent tools/list messages, even when they are correctly formatted and delivered according to standard SSE practices (and confirmed via Wireshark).