Skip to main content

Durable Model Context Protocol (MCP) helpers for building resumable MCP servers on top of Reboot durable workflows.

Project description

Reboot Durable MCP

A framework for building durable MCP servers.

  • Takes advantage of the protocols ability to resume after disconnection, e.g., due to the server getting rebooted.

  • Any existing requests will be retried safely using Reboot workflows.

  • Using Reboot you can run multiple replicas of your server, and session messages will always be routed to the same replica.

Requirements

  • Linux and macOS
  • Python >= 3.12.11
  • Docker

Install

We recommend using uv, as it will manage the version of Python for you. For example, to start a new project in the directory foo:

uv init --python 3.12.11 .
uv add durable-mcp

Activate the venv:

source .venv/bin/activate

Make sure you have Docker running:

docker ps

Building an MCP server

Instead of using FastMCP from the MCP SDK, you use DurableMCP. Here is a simple server to get you started:

import asyncio
from reboot.aio.applications import Application
from reboot.mcp.server import DurableMCP, ToolContext
from reboot.std.collections.v1.sorted_map import SortedMap

# `DurableMCP` server which will handle HTTP requests at path "/mcp".
mcp = DurableMCP(path="/mcp")


@mcp.tool()
async def add(a: int, b: int, context: ToolContext) -> int:
    """Add two numbers and also store result in `SortedMap`."""
    await SortedMap.ref("adds").Insert(
        context,
        entries={f"{a} + {b}": f"{a + b}".encode()},
    )
    return a + b


async def main():
    # Reboot application that runs everything necessary for `DurableMCP`.
    application = Application(servicers=mcp.servicers())

    # Mounts the server at the path specified.
    application.http.mount(mcp.path, factory=mcp.streamable_http_app_factory)

    await application.run()


if __name__ == '__main__':
    asyncio.run(main())

You can run the server via:

rbt dev run --python --application=path/to/your/main.py --working-directory=. --no-generate-watch

While developing you can tell rbt to restart your server when you modify files by adding one or more --watch=path/to/**/*.py to the above command line.

We recommend you move all of your command line args to a .rbtrc:

# This file will aggregate all of the command line args
# into a single command line that will be run when you
# use `rbt`.
#
# For example, to add args for running `rbt dev run`
# you can add lines that start with `dev run`. You can add
# one or more args to each line.

dev run --python
dev run --application=path/to/your/main.py
dev run --watch=path/to/**/*.py --watch=different/path/to/**/*.py

Then you can just run:

rbt dev run

Testing your MCP server

You can use the MCP Inspector to test out the server, or create a simple client.

import asyncio
from reboot.mcp.client import connect, reconnect

URL = "http://localhost:9991"


async def main():
    # Connect is a helper around creating a streamable HTTP client and
    # session from the MCP SDK, you can also use those if you prefer!
    async with connect(URL + "/mcp") as (
        session, session_id, protocol_version
    ):
        print(await session.list_tools())
        print(await session.call_tool("add", arguments={"a": 5, "b": 3}))


if __name__ == '__main__':
    asyncio.run(main())

Supported client --> server requests:

  • initialize
  • tools/call
  • tools/list
  • prompts/get
  • prompts/list
  • resources/list
  • resources/read
  • resources/templates/list
  • resources/subscribe
  • resources/unsubscribe
  • completion/complete
  • logging/setLevel

Supported client --> server notifications:

  • notifications/initialized
  • notifications/progress (for server initiated requests, e.g., elicitation)
  • notifications/roots/list_changed

Supported client <-- server requests:

  • elicitation/create
  • roots/list
  • sampling/createMessage

Supported client <-- server notifications:

  • notifications/progress
  • notifications/message
  • notifications/prompts/list_changed
  • notifications/resources/list_changed
  • notifications/tools/list_changed
  • notifications/resources/updated

Supported client <--> server notifications:

  • notifications/cancelled

TODO:

  • EventStore support for resumability
  • Add examples of how to test via Reboot().start/up/down/stop()
  • Auth
  • Docs
  • yapf
  • Push to durable-mcp in pypi.org
  • Pydantic state for each session

Contributing

First grab all dependencies:

uv sync

Activate the venv:

source .venv/bin/activate

Generate code:

rbt generate

Make sure you have Docker running:

docker ps

Make your changes and run the tests:

pytest tests

Project details


Download files

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

Source Distribution

durable_mcp-0.2.1.tar.gz (87.6 kB view details)

Uploaded Source

Built Distribution

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

durable_mcp-0.2.1-py3-none-any.whl (102.1 kB view details)

Uploaded Python 3

File details

Details for the file durable_mcp-0.2.1.tar.gz.

File metadata

  • Download URL: durable_mcp-0.2.1.tar.gz
  • Upload date:
  • Size: 87.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.11

File hashes

Hashes for durable_mcp-0.2.1.tar.gz
Algorithm Hash digest
SHA256 8a4a9e658aabeb0fe0e925f6749f33246334c4731c0525079ef4494eff6a6b2b
MD5 ed4c6f6e6598da528c7a82a14e17a189
BLAKE2b-256 3f575f19d566849defc5721f0cb3281a81d6fdcb8327d603867655f6b3994ac1

See more details on using hashes here.

File details

Details for the file durable_mcp-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: durable_mcp-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 102.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.11

File hashes

Hashes for durable_mcp-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 cf19dd989631daf56cbc9189ef62a8a5ab53b357498d2b294cedeaa789b2fa92
MD5 6b4b70c2aeeb311a33ccb8e243aa7731
BLAKE2b-256 deb666a4247d4f2531e52fae9058e4a8c635fd55af4e7cadade70222ff02de7c

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