Hot Reloading for MCP Servers
Project description
mcp-hmr
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
- Provide the correct target import path
mcp_server("path/to/mcp-server.py:mcp")/mcp_server("module.submodule:mcp"). Test it first withmcp-hmr <target>.- The target module must not be imported yet when calling
mcp_server(target), or hot-reloading won't work.- 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 theasync with anyio.create_task_group()block exits, but themcp_servercontext 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
077825df883687416a4dba6839c8a63298753cd77c8ef398b2628cd42be7b3f4
|
|
| MD5 |
ac9e32d245c6eebda603ecc5f0cf4b81
|
|
| BLAKE2b-256 |
bed3cba432f4ced90f32de11b164bc0cb3e174710ec9a64a2b85a591ea0232ba
|