Repository navigation
Mounting a Streamable HTTP MCP endpoint on existing FastAPI app does not work #1367
Description
Activity
- addedbugSomething isn't workingSomething isn't workingneeds confirmationNeeds confirmation that the PR is actually required or needed.Needs confirmation that the PR is actually required or needed.
on Sep 19, 2025 This looks potentially related to some recent PRs:
I am observing this too, regardless of whether I mount the mcp app on
/or on a subpath like/mcp.According to #1007 the exported app will continue to be a complete app with MCP endpoint on
/mcp(instead of letting devs decide where to mount it), from my understanding the reason is not wanting to impose breaking changes and maintainers don't have time to work on thisFor information, I managed to make it work by dropping FastAPI and directly using the Starlette app generated by the MCP SDK, adding the routes I need manually, e.g.
from mcp.server.fastmcp import FastMCP mcp = FastMCP( name="My MCP", debug=True, dependencies=["mcp"], instructions="Provide tools that helps users do things.", stateless_http=True, json_response=True, ) app = mcp.streamable_http_app() app.router.add_route("/", ui_handler, methods=["GET"])
Reacted by Felix WeinbergerReacted by Willy Martin Aguirre Rodriguez and AbdealiLoKoAccording to #1007 the exported app will continue to be a complete app with MCP endpoint on
/mcp(instead of letting devs decide where to mount it), from my understanding the reason is not wanting to impose breaking changes and maintainers don't have time to work on thisFor information, I managed to make it work by dropping FastAPI and directly using the Starlette app generated by the MCP SDK, adding the routes I need manually, e.g.
from mcp.server.fastmcp import FastMCP
mcp = FastMCP(
name="My MCP",
debug=True,
dependencies=["mcp"],
instructions="Provide tools that helps users do things.",
stateless_http=True,
json_response=True,
)app = mcp.streamable_http_app()
app.router.add_route("/", ui_handler, methods=["GET"])
Closing this issue as instructions here show the appropriate way for implementing this usecase.
- added a commit that references this issue
on Apr 11, 2026 - added a commit that references this issue
on Jul 5, 2026
Initial Checks
Description
Hi,
We are trying to create a web server with 2 endpoints:
/mcp: the MCP server endpoint/hello: whatever custom endpoint getting JSON returning JSONThis is important because it allows to build more advanced app than just a MCP server, and avoid having 35 micro services to manage.
We use a really popular solution for doing so: FastAPI, which claims full support for mounting ASGI apps, such as the
Starletteobject returned bymcp.streamable_http_app()Run with:
Going directly to http://localhost:8000/mcp gives plain text
Not FoundGoing to any actually not defined path gives the usual FastAPI
{"detail":"Not Found"}So this shows something has been mounted on
/mcp, but yourStarletteobject returns an incorrect error (it can't be not found, maximum it could be method not allowed, or something else, but not found does not seems correct here)Try to access it with the official MCP client using the official documentation:
We get a redirect and a 404 in the server logs:
So now if we change the mcp_url to http://localhost:8000/mcp/mcp we get:
Many problems here
Starlettealready preconfigured to mount the endpoint on/mcpdoes not seems like a good pattern. From our (devs using your lib) pov, mounting on/is problematic, we should be able to easily mount the MCP endpoint on any path no? Or is there somewhere in the protocol specified that the Streamable HTTP endpoints absolutely needs to be mounted on/mcp? Not sure exactly of your lib internals, but I should be able to deploy multiple MCP endpoints on different path on the same serverStrangely we had less issues implementing the same thing in rust with axum and the official rmcp crate. And it seems like the rmcp crate let us mount the MCP endpoint on any path, so we should be able to do the same with python
Note that deploying the exact same MCP app directly with
mcp.run(transport="streamable-http")works fine (the client scripts above works and print the tools)Would it be possible to clarify a bit how can this be done properly? A basic working example is the usual way of documenting such feature (it's just 10 lines)
Thanks a lot
Example Code
Python & MCP Python SDK