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.

List Changed Notifications

If your new app has added or removed tools, clients may need a list_changed notification after each remount. The Python MCP SDK does not currently expose a clean hook for this, so you can use patch_session_init():

from mcp_hmr import mcp_server, patch_session_init

unpatch = patch_session_init()
try:
    async with mcp_server("path/to/mcp-server.py:mcp") as mcp:
        await mcp.run_async()
finally:
    unpatch()

patch_session_init() installs the patch and returns a function that removes it. The mcp-hmr CLI already does this for you. If this patch conflicts with your setup, please open an issue and tell us about the scenario.

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.4-py3-none-any.whl (6.6 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: mcp_hmr-0.0.3.4-py3-none-any.whl
  • Upload date:
  • Size: 6.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","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.4-py3-none-any.whl
Algorithm Hash digest
SHA256 395358d3d5c5b2d821ed898dcc86a8f08efa218b7dc017beea729f4e903dc01c
MD5 c6cb7d558621ff7b08fa295644a52cef
BLAKE2b-256 58f40953b1d94d2ade7fafa086c5fc21051ca0931501ec12710921312f7a646c

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