Skip to main content

Hot Reloading for MCP Servers

Project description

mcp-hmr

PyPI - Version PyPI - Downloads

Provides Hot Module Reloading for MCP/FastMCP servers.

It acts as a drop-in replacement for mcp run path:app or fastmcp run path:app. Both FastMCP v2 and the official python SDK are supported. Compatible libraries like mcp-use are also supported.

Here's the thing: With this package, you don't need to restart your MCP server on every code change. Just save your files, and the server automatically uses the latest code without dropping client connections.

CLI Usage

If your server instance is named app in ./path/to/main.py, you can run:

mcp-hmr ./path/to/main.py:app

Which will be equivalent to fastmcp run ./path/to/main.py:app but with HMR enabled.

Or using module import format:

mcp-hmr main:app

Now, whenever you save changes to your source code, the server will automatically reload without dropping the connection to the client.

The CLI provides a simple way to get started, but if you need more control, you can also use mcp_hmr programmatically.

Options

The options are aligned with those of fastmcp run, providing a familiar interface if you're already using FastMCP.

mcp-hmr --help

The command supports the following options:

Option Description Default
--transport / -t Transport protocol: stdio, sse, http, streamable-http stdio
--log-level / -l Log level: DEBUG, INFO, WARNING, ERROR, CRITICAL -
--host Host to bind to for HTTP/SSE transports localhost
--port Port to bind to for HTTP/SSE transports 8000
--path Route path for the server /mcp (http) or /sse (sse)
--stateless Sets stateless_http=True and json_response=True False
--no-cors Disable CORS for HTTP transport False

HTTP transport uses a permissive CORS policy by default for development convenience.

Examples

Start with HTTP transport on custom host, port and path:

mcp-hmr main:app -t http --host 0.0.0.0 --port 56789 --path /

Start with debug logging:

mcp-hmr main:app -l DEBUG

Use streamable-http transport:

mcp-hmr main:app -t streamable-http --port 8000

Programmatic API

For more advanced use cases, you can integrate mcp_hmr directly into your existing codebase. Say you have a FastAPI server app:

from mcp_hmr import mcp_server
from uvicorn import Config, Server

app: FastAPI = ...

async with mcp_server("path/to/mcp-server.py:mcp") as mcp:
    # mcp.add_middleware(...)
    app.mount("/", mcp.http_app("/mcp"))  # mount the auto-reloading MCP server to your FastAPI app
    await Server(Config(app)).serve()

This is useful when you want to extend your server with additional features like CORS middleware while maintaining HMR capabilities.

Tips for using the programmatic API

  1. Provide the correct target import path mcp_server("path/to/mcp-server.py:mcp") / mcp_server("module.submodule:mcp"). Test it first with mcp-hmr <target>.
  2. The target module must not be imported yet when calling mcp_server(target), or hot-reloading won't work.
  3. Hot reloading only works within the async with mcp_server(...) as mcp: block. Especially caution for cases that code implicitly exit this block like:
async with anyio.create_task_group() as tg mcp_server("path/to/mcp-server.py:mcp") as mcp:
    tg.start_soon(mcp.run_async)

Here, mcp.run_async() is awaited when the async with anyio.create_task_group() block exits, but the mcp_server context is already closed. Fix this by swapping the context manager order:

async with mcp_server("...") as mcp, create_task_group() as tg:  # note the order
    tg.start_soon(mcp.run_async)

Or await the mcp.run_async() task within the same block:

async with anyio.create_task_group() as tg, mcp_server("...") as mcp:
    event = anyio.Event()

    @tg.start_soon
    async def _():
        await mcp.run_async()
        event.set()

    await event.wait()

Of course the simplest approach is await mcp.run_async() directly. The task group example above assumes you already have some existing lifespan management that requires running the MCP server within a task group.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mcp_hmr-0.0.3.2-py3-none-any.whl (6.1 kB view details)

Uploaded Python 3

File details

Details for the file mcp_hmr-0.0.3.2-py3-none-any.whl.

File metadata

  • Download URL: mcp_hmr-0.0.3.2-py3-none-any.whl
  • Upload date:
  • Size: 6.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.18 {"installer":{"name":"uv","version":"0.9.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for mcp_hmr-0.0.3.2-py3-none-any.whl
Algorithm Hash digest
SHA256 077825df883687416a4dba6839c8a63298753cd77c8ef398b2628cd42be7b3f4
MD5 ac9e32d245c6eebda603ecc5f0cf4b81
BLAKE2b-256 bed3cba432f4ced90f32de11b164bc0cb3e174710ec9a64a2b85a591ea0232ba

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page