TellWorldAI World Archive
Ask中文

Home›Practice›Practice

Practice

Deploying an MCP server over HTTP with FastMCP

Run a FastMCP server over HTTP: direct and ASGI deployment, custom paths, authentication, multiple workers with stateless mode, and checks before going live.

Who this is for and what you will learn

This article is for readers who can already run a FastMCP server locally and want remote clients to reach it. By the end you should be able to tell the direct HTTP approach from the ASGI approach, know where the /mcp endpoint lives, understand how multiple workers relate to stateless mode, and know what to check before going live.

Run it locally first

The running guide focuses on local development and testing. For deploying to a URL, the HTTP deployment guide is the one to read[1][2].

Calling run() on a FastMCP instance starts the server, and the call blocks until the server is stopped[1]. The guide recommends placing run() inside an if __name__ == "__main__": block. That way the server starts only when the script is executed directly, not when it is imported[1]. The example below runs a hello tool:

from fastmcp import FastMCP

mcp = FastMCP(name="MyServer")

@mcp.tool
def hello(name: str) -> str:
    return f"Hello, {name}!"

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

Called without arguments, run() uses the STDIO transport, which is the default. With STDIO, the client starts a new server process for each session and manages its lifecycle. The server reads MCP messages from stdin and writes responses to stdout[1]. STDIO servers are therefore started on demand by the client rather than kept running[1].

Switch to HTTP

The HTTP transport turns the MCP server into a web service that is reachable by URL. It uses the Streamable HTTP protocol and can serve several clients at the same time[1]. The running guide recommends Streamable HTTP for network-based deployments[1].

Pass the transport and network options to run():

from fastmcp import FastMCP

mcp = FastMCP("MyServer")

@mcp.tool
def hello(name: str) -> str:
    return f"Hello, {name}!"

if __name__ == "__main__":
    # Start an HTTP server on port 8000
    mcp.run(transport="http", host="127.0.0.1", port=8000)

With this configuration the server is reachable at http://localhost:8000/mcp. That path is the MCP endpoint that clients connect to[1]. SSE is described as legacy, and the guide recommends HTTP transport instead of SSE for all new projects[1].

Two ways to deploy over HTTP

Direct HTTP is the quickest way online. Start the server with mcp.run(transport="http", host="0.0.0.0", port=8000), and FastMCP handles the web server configuration. It suits internal tools, development environments and simple deployments that do not need advanced server features[2].

The ASGI application suits production more closely. FastMCP can create a standard ASGI application that runs under Uvicorn, Gunicorn or Hypercorn. This approach is better when you need multiple workers, custom middleware, or integration with an existing web application[2]. The example below creates the application with mcp.http_app()[2]:

from fastmcp import FastMCP

mcp = FastMCP("My Server")

@mcp.tool
def process_data(input: str) -> str:
    """Process data on the server"""
    return f"Processed: {input}"

# Create ASGI application
app = mcp.http_app()

Run it with Uvicorn using uvicorn app:app --host 0.0.0.0 --port 8000. The server is still reachable at http://localhost:8000/mcp[2].

Change the endpoint path

By default the endpoint is /mcp. To fit your URL structure, change it with mcp.run(transport="http", host="0.0.0.0", port=8000, path="/api/mcp"), or with mcp.http_app(path="/api/mcp")[2].

Authentication

Authentication is highly recommended for remote MCP servers. Some LLM clients require authentication for remote servers and refuse to connect without it[2].

Multiple workers and stateless mode

By default, the Streamable HTTP transport keeps sessions in memory on each server instance. When several instances sit behind a load balancer, a request can reach an instance that does not hold its session, and then it fails[2]. Sticky sessions do not reliably fix this with MCP clients, because many of them do not forward Set-Cookie headers[2].

Running several workers requires stateless mode. The example command is[2]:

FASTMCP_STATELESS_HTTP=true uvicorn app:app --host 0.0.0.0 --port 8000 --workers 4

Stateless mode can also be enabled with mcp.http_app(stateless_http=True) or with mcp.run(transport="http", stateless_http=True). Each request then creates a fresh transport context, so session affinity is no longer needed[2].

Useful CLI options

  • fastmcp run server.py finds a FastMCP instance named mcp, server or app in the file and runs it[1].
  • With --python, --with, --project or --with-requirements, the server runs through a uv run subprocess instead of the local environment[1].
  • Arguments for the server go after --, for example fastmcp run config_server.py -- --config config.json[1].
  • --reload restarts the server when source files change. This flag appeared in version 3.0.0[1]. SSE does not support auto-reload, so use HTTP if you need both network access and auto-reload[1].

Async code and custom routes

In code that already runs in an async context, use run_async(). Calling run() from inside an async function raises an error about the event loop already running[1].

For a health check or a similar endpoint, add a custom route with @mcp.custom_route("/health", methods=["GET"]). It is served by the same web server as the MCP endpoint[1].

What to check before going live

  • Platforms include cloud VMs, container platforms, platform-as-a-service providers, edge platforms and Kubernetes clusters. The key requirements are Python 3.11 or newer and the ability to expose an HTTP port[2].
  • After deployment, connect to the server URL with the FastMCP client to confirm it is reachable and lists the tools you expect[2].
  • Confirm that authentication is configured before you expose a remote server[2].

Limits

  • Multiple workers need stateless mode. Otherwise sessions exist only in the memory of one instance[2].
  • Sticky sessions do not reliably solve the session problem across instances[2].
  • SSE is a legacy transport and does not support auto-reload[1].

Next steps

For the full set of deployment options, including authentication, CORS, reverse proxies and hosting, read the FastMCP HTTP deployment guide[2].

Adapted from the Running Your Server and HTTP Deployment pages of the FastMCP official documentation[1][2], released under the Apache-2.0 License.

Sources

  1. 1
    FastMCP Running Your ServerFastMCP docs (Apache-2.0)
  2. 2
    FastMCP HTTP DeploymentFastMCP docs (Apache-2.0)

Cite this page: Deploying an MCP server over HTTP with FastMCP. TellWorld, https://www.tellworld.net/practice/practice-fastmcp-http-deploy. Updated 2026-11-14

Related news

View all