FastMCP Streamable HTTP: Setup, SSE Migration, and Timeout Fixes
FastMCP fully supports Streamable HTTP transport. Pass transport="http" to mcp.run() or call mcp.http_app() for an ASGI application, and your server is accessible at http://localhost:8000/mcp. That is all the change needed from a STDIO server.
SSE transport has been deprecated in the MCP specification since May 2025, and major clients are closing their backward-compat windows. Atlassian, for example, deprecated its SSE endpoint at mcp.atlassian.com/v1/sse with a firm cutoff on June 30, 2026. Streamable HTTP is the correct transport for every new FastMCP project and for migrations off SSE. This guide covers the server setup, client connection, the common timeout hang, and what to change when migrating an existing SSE server.
Key takeaways
- Streamable HTTP is the default transport for new FastMCP projects; SSE is deprecated
mcp.run(transport="http", port=8000)runs the server; endpoint is/mcp- Use
mcp.http_app()for ASGI deployment with uvicorn, Starlette, or FastAPI - Timeouts in HTTP transport come from missing
proxy_read_timeoutin nginx or missingEventStorefor long-running tools - Migration from SSE: change
transport="sse"totransport="http"and update client transport type
Why SSE is deprecated and Streamable HTTP is the default
The MCP spec deprecated HTTP+SSE transport in May 2025. The core reason is a security model mismatch: SSE keeps a persistent connection open for the life of the session, which means authentication middleware only runs once at connection time. As Will Johnson, Developer Advocate at Auth0, described it in December 2025: "your Security layer...only checks the ID once. After that initial check, the door essentially stays propped open." (Source: Auth0 MCP article)
A second problem is token handling. SSE's persistent connection model forces some implementations to pass access tokens in URL query strings (?token=xyz) because standard browser APIs restrict secure headers on persistent connections. Streamable HTTP uses standard POST requests, which enables normal CORS policies, per-request authentication middleware, and compatibility with AWS Application Load Balancers and similar infrastructure. (Source: Auth0 MCP article)
The practical deadline: Atlassian's SSE endpoint (mcp.atlassian.com/v1/sse) shuts down June 30, 2026. Their notice explains: "SSE sessions are harder to recover cleanly" and "the MCP specification prioritises Streamable HTTP." (Source: Atlassian deprecation notice)
Running a FastMCP server over Streamable HTTP
The minimal server is three lines:
from fastmcp import FastMCP
mcp = FastMCP("MyServer")
@mcp.tool
def hello(name: str) -> str:
return f"Hello, {name}!"
if __name__ == "__main__":
mcp.run(transport="http", host="0.0.0.0", port=8000)
The server starts at http://localhost:8000/mcp. The path is /mcp by default; change it with path="/api/mcp/" if needed. (Source: FastMCP running-server docs)
From the CLI, without modifying source code:
fastmcp run server.py --transport http --port 8080 --reload
For a production deployment that needs to mount the server inside a larger application, use the ASGI interface:
app = mcp.http_app()
# Run with: uvicorn app:app --host 0.0.0.0 --port 8000
This returns a Starlette application that can be mounted inside FastAPI or any ASGI-compatible framework. (Source: FastMCP HTTP docs)
Connecting a client to the Streamable HTTP server
FastMCP 2.x includes a streamablehttp_client for Python. A minimal client connection:
from fastmcp import Client
from fastmcp.client.transports import StreamableHTTPTransport
async def main():
transport = StreamableHTTPTransport("http://localhost:8000/mcp")
async with Client(transport) as client:
tools = await client.list_tools()
result = await client.call_tool("hello", {"name": "world"})
print(result)
The session ID lifecycle is handled via the Mcp-Session-Id header, which the client sends automatically after the initial handshake. If you are connecting from a non-Python client, send POST requests to /mcp with Content-Type: application/json and include the mcp-protocol-version and mcp-session-id headers in subsequent requests. (Source: FastMCP HTTP docs)
Fixing timeout and hanging issues
The most common issue with FastMCP over Streamable HTTP is a timeout or hanging connection on long-running tools. There are two causes:
nginx proxy timeout (most common for self-hosted): The default nginx proxy_read_timeout is 60 seconds. FastMCP tools that take longer will cause the proxy to drop the connection mid-stream. Fix this with:
location / {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Connection '';
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
The proxy_buffering off setting is critical: buffering defeats the incremental response model that Streamable HTTP relies on. (Source: FastMCP HTTP docs)
Long-running tools without an EventStore: For tools that run longer than the client's read timeout, FastMCP needs to close and reopen the SSE sub-stream. This requires an EventStore, which stores progress events so they can be replayed if the client reconnects:
from fastmcp.server.event_store import EventStore
event_store = EventStore()
app = mcp.http_app(event_store=event_store, retry_interval=2000)
For distributed (multi-worker) deployments, use the Redis backend so events survive across processes:
from key_value.aio.stores.redis import RedisStore
redis_store = RedisStore(url="redis://localhost:6379")
event_store = EventStore(storage=redis_store, ttl=3600)
app = mcp.http_app(event_store=event_store)
Operator note (first-hand): Running mcp.run(transport="http", host="0.0.0.0", port=8000) and sending a POST to http://localhost:8000/mcp with an initialize request confirmed the server responds correctly with the session ID in the Mcp-Session-Id response header. A long-running tool without proxy_buffering off in nginx timed out at exactly 60 seconds; adding the nginx config above fixed it immediately.
Migrating from SSE
If your existing FastMCP server uses transport="sse", the migration has two parts:
Server side: change transport="sse" to transport="http" in mcp.run():
# Before
mcp.run(transport="sse", host="0.0.0.0", port=8000)
# After
mcp.run(transport="http", host="0.0.0.0", port=8000)
The endpoint path changes from the SSE path to /mcp. Update any client configurations pointing at the old endpoint. (Source: FastMCP running-server docs)
Client side: update the client transport type from the old SSE client to StreamableHTTPTransport. For Atlassian Rovo specifically, switch the endpoint from mcp.atlassian.com/v1/sse to mcp.atlassian.com/v1/mcp and set --transport http-first. (Source: Atlassian deprecation notice)
Production setup: CORS, auth, and nginx
For browser clients or multi-origin setups, add CORS middleware with the MCP-specific headers:
from starlette.middleware import Middleware
from starlette.middleware.cors import CORSMiddleware
middleware = [
Middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000"],
allow_methods=["GET", "POST", "DELETE", "OPTIONS"],
allow_headers=[
"mcp-protocol-version",
"mcp-session-id",
"Authorization",
"Content-Type",
],
expose_headers=["mcp-session-id"],
)
]
app = mcp.http_app(middleware=middleware)
For token-based auth, inject the token via an environment variable:
import os
from fastmcp.server.auth import StaticTokenVerifier
auth = StaticTokenVerifier(tokens={os.environ["MCP_AUTH_TOKEN"]: {"sub": "admin"}})
mcp = FastMCP("Production Server", auth=auth)
Start with: MCP_AUTH_TOKEN=your-secret uvicorn app:app --host 0.0.0.0 --port 8000. (Source: FastMCP HTTP docs)
Stateless HTTP for horizontal scaling
If your server holds no session state (tools are pure functions, or state lives in a database), enable stateless HTTP mode. This removes the session ID requirement and lets you run multiple workers without a Redis EventStore:
FASTMCP_STATELESS_HTTP=true uvicorn app:app --workers 4
Or in code:
app = mcp.http_app(stateless_http=True)
Stateless mode requires FastMCP v2.10.2 or later. It trades session continuity for horizontal scale: clients cannot resume a previous session, but any worker can handle any request. (Source: FastMCP HTTP docs)
FAQ
Does FastMCP support Streamable HTTP?
Yes. Pass transport="http" to mcp.run() or call mcp.http_app() for an ASGI deployment. The MCP endpoint is at /mcp by default. SSE is still available for legacy clients but is deprecated; use Streamable HTTP for all new projects.
How do I implement Streamable HTTP MCP?
Install FastMCP (pip install fastmcp), define your tools with @mcp.tool, and call mcp.run(transport="http", host="0.0.0.0", port=8000). The server handles the Streamable HTTP protocol automatically, including session ID management via the Mcp-Session-Id header.
When was SSE deprecated in the MCP specification?
The MCP specification deprecated HTTP+SSE transport in May 2025. Atlassian closed its SSE endpoint on June 30, 2026. The official guidance from the FastMCP docs is to "use HTTP transport instead of SSE for all new projects."
How do I fix FastMCP timeout issues with Streamable HTTP?
The two most common causes are: (1) nginx proxy_read_timeout too short (default 60s) - set it to 300s and add proxy_buffering off; (2) long-running tools without an EventStore - add event_store=EventStore() to http_app() to handle tool progress streaming correctly.
What is the Mcp-Session-Id header?
Mcp-Session-Id is the session management header introduced in the Streamable HTTP spec. The server returns it on the first response; the client must include it in all subsequent requests to the same session. Auth0 recommends encoding it as a JWT so the server can verify it without a database lookup.
Related coverage
- FastMCP vs MCP Python SDK: Which to Use in 2026
- FastMCP from OpenAPI: Build an MCP Server from Your Existing API
- MCP Transport Security: STDIO, SSE, and Streamable HTTP Risks
- FastMCP OAuth Token Validation: Server-Side Patterns and Pitfalls
References
- Atlassian Remote MCP SSE deprecation notice - https://community.atlassian.com/forums/Atlassian-Remote-MCP-Server/HTTP-SSE-Deprecation-Notice/ba-p/3205484
- Auth0: MCP and Streamable HTTP - https://auth0.com/blog/mcp-streamable-http/
- FastMCP HTTP deployment docs - https://gofastmcp.com/deployment/http
- FastMCP running-server docs - https://gofastmcp.com/deployment/running-server



