Skip to content

sse_client fails if URL is not on the root path #563

Closed

Description

@michaelpoluektov

Describe the bug
This line is the problem:

endpoint_url = urljoin(url, sse.data)

urljoin discards the whole path, meaning that if url is http://localhost:8000/mcp/sse and sse.data is /messages/?session_id=123 we get endpoint_url == "http://localhost:8000/messages/?session_id=123" instead of http://localhost:8000/mcp/messages/?session_id=123

To Reproduce

  • Launch an MCP server with SSE on a path different from the root of the application.
app = FastAPI()
mcp = FastMCP("my-mcp-server")
app.mount("/mcp", mcp.sse_app())
  • Try to connect to it using sse_client as per the tutorial

Expected behavior

endpoint_url should contain the suffix of url with /sse stripped instead of the whole path being stripped.

Activity

  1. TheCulliganMan commented on Apr 22, 2025

    @TheCulliganMan

    The setup is a bit strange here, but setting the sse_path and message_path in your FastMCP instantiation does allow for this behavior.

    mcp = FastMCP(
        sse_path=f"/mcp/sse",
        message_path=f"/mcp/messages/",
    )

    sse_path: str = "/sse"
    message_path: str = "/messages/"

  2. theobjectivedad commented on Apr 23, 2025

    @theobjectivedad

    As far as I understand, the main use case is to have multiple MCP servers managed within a single Starlette/FastAPI server. Here, setting sse_path and message_path will only work when a single FastMCP is bound to "/". However, since we can't bind multiple FastMCP apps to the same path the core issue remains. For example:

    app1 = FastMCP(
        sse_path="/app1/sse",
        message_path="/app1/message/",
    )
    
    app2 = FastMCP(
        sse_path="/app2/sse",
        message_path="/app2/message/",
    )
    
    # Only exposes app1
    container_app = Starlette(
        routes=[
            Mount(path="/", app=app1.sse_app()),
            Mount(path="/", app=app2.sse_app()),
        ]
    )

    When connecting to app1, the proper path is returned in data. Unfortunately app1's path is absolute w.r.t. the server root and will only work when binding to /:

    event: endpoint
    data: /app1/message/?session_id=f80b327ec4ef4ad7b9a8d0c6848f2596
    

    IMO the right solution is not in the client but within FastMCP. I remember seeing a thread on the proper implementation somewhere, I'l link back when I find it.

  3. theobjectivedad commented on Apr 23, 2025

    @theobjectivedad
  4. theobjectivedad commented on Apr 23, 2025

    @theobjectivedad

    One more - looks like there is already a PR open for the proper fix: #540

  5. felixweinberger commented on Oct 3, 2025

    @felixweinberger
    Contributor

    Closing as I believe this is resolved by #540

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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