Skip to main content

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

After each HMR remount, mcp-hmr automatically sends list_changed notifications for tools, resources, and prompts to connected clients.

This matters because many MCP clients cache the initial lists they receive. Without these notifications, newly added or removed tools/resources/prompts may stay invisible until you fully restart the server.

No extra setup is required when you use the mcp-hmr CLI, mcp_server(), or run_with_hmr().

Internally, mcp-hmr temporarily patches ServerSession.__init__ during FastMCP session initialization and restores it as soon as the managed session is captured. The Python MCP SDK does not expose a cleaner hook for tracking active sessions yet. If this causes conflicts in your setup, please open an issue and share the details.

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.

Metadata

Release files for mcp-hmr 0.0.3.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distribution (wheel)

Table of built distributions (wheels) for mcp-hmr 0.0.3.5
File Interpreter ABI Platform
mcp_hmr-0.0.3.5-py3-none-any.whl Python 3 none any Details

Release files / mcp_hmr-0.0.3.5-py3-none-any.whl

Download URL mcp_hmr-0.0.3.5-py3-none-any.whl
Size 6.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
edb99e213d5863483243d4930bb00079d1f57ec0952ec2b67a73c45ee21aa593
BLAKE2b-256 checksum
How to use checksums
fca296d85c0876173690bfc2bc0d94094620b3648d31bfecfa4a9b3cb9cc100f
Upload date
Uploaded using Trusted Publishing?
What is 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}

Release history Release notifications | RSS feed

This release

0.0.3.5 This release

1 release file

0.0.3.4

1 release file

0.0.3.3

1 release file

0.0.3.2

1 release file

0.0.3.1

1 release file

0.0.3

1 release file

0.0.2.3

1 release file

0.0.2.2

1 release file

0.0.2.1

1 release file

0.0.2

1 release file

0.0.1

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page