Skip to content

sse_client blocks indefinitely when server has incorrect base URL #447

Open
@Kudryavkaz

Description

@Kudryavkaz

Describe the bug
When using the sse_client function to connect to a remote MCP server, if the MCP server sets an incorrect base URL (like http://localhost:8080), the sse_client will raise an exception in the following code:

raise ValueError(error_msg)

The read_stream_writer then sends this exception to the read_stream:

await read_stream_writer.send(exc)

However, since the read_stream has not been yielded yet, the exception will never be received.
As a result, the sse_client will be blocked indefinitely.

To Reproduce

  1. Set up an MCP server with an incorrect base URL on a remote server, for example:
import express, { Request, Response } from 'express';
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
import { z } from 'zod';

const server = new McpServer({
    name: 'example-server',
    version: '1.0.0',
});

server.tool(
  "calculate-bmi",
  {
    weightKg: z.number(),
    heightM: z.number()
  },
  async ({ weightKg, heightM }) => ({
    content: [{
      type: "text",
      text: String(weightKg / (heightM * heightM))
    }]
  })
);

const app = express();

const transports: { [sessionId: string]: SSEServerTransport } = {};

app.get('/sse', async (_: Request, res: Response) => {
    // set baseUrl for the transport
    const baseUrl = 'http://localhost:8080';
    const transport = new SSEServerTransport(`${baseUrl}/messages`, res);
    transports[transport.sessionId] = transport;
    res.on('close', () => {
        delete transports[transport.sessionId];
    });
    await server.connect(transport);
});

app.post('/messages', async (req: Request, res: Response) => {
    const sessionId = req.query.sessionId as string;
    const transport = transports[sessionId];
    if (transport) {
        await transport.handlePostMessage(req, res);
    } else {
        res.status(400).send('No transport found for sessionId');
    }
});

app.listen(8080);
  1. Try to connect to the remote MCP server, for example:
import asyncio

from mcp.client.sse import sse_client


async def run():
    try:
        async with sse_client("http://{your_remote_server}:8080/sse"):
            print("Connected to SSE endpoint successfully.")
    except Exception as e:
        print(f"Error: {e}")


if __name__ == "__main__":
    asyncio.run(run())

Expected behavior
The sse_client should raise an exception and exit gracefully.

Logs
None

Additional context
None

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions