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

Uploaded Python 3

File details

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

File metadata

  • Download URL: mcp_hmr-0.0.3.3-py3-none-any.whl
  • Upload date:
  • Size: 6.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.10.10 {"installer":{"name":"uv","version":"0.10.10","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.3-py3-none-any.whl
Algorithm Hash digest
SHA256 5dfc45f15e9a69469cca6fb3193da3fea745d775f8e75a417bf2a64509b3be49
MD5 2ae625a724218715018025b19618c95b
BLAKE2b-256 6a4e9447707f7b50c6dcbee648381a6d42c07228a540710f166fb1c0bf9b02cd

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