Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
michaelpoluektov opened this issue Apr 22, 2025 · 4 comments · May be fixed by #564
Open

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

michaelpoluektov opened this issue Apr 22, 2025 · 4 comments · May be fixed by #564

Comments

@michaelpoluektov
Copy link

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.

@TheCulliganMan
Copy link

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/"

@theobjectivedad
Copy link

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.

@theobjectivedad
Copy link

#412

@theobjectivedad
Copy link

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants