An extensible MCP server
reactor_mcp_server is a foundation for building Model Context
Protocol servers out of plugins. A
deployment adds tools by installing a distribution; nothing in the server is
edited, and nothing in the server names what is installed.
It is a reactor plugin package, and an MCP extension is a reactor plugin: the tools, toolsets, resources and prompts it offers are ordinary contributions at four contribution points, so what a server is made of can be listed, grouped and drawn before anything is built.
pip install reactor_mcp_server
Three ideas
A tool is a contribution. An extension does not reach into a server object
and register a function on it. It offers a ToolSpec, and the host builds a
server from what has been offered. See Tools.
A contribution can be extended. An extension may narrow, wrap or re-describe a tool that another extension offered, by name and in a declared order. See Extending a tool.
The URL decides what is served. Tools belong to named toolsets, and a
client says which ones it wants in the URL it connects to. A toolset carries
its own title, description and instructions, can be opt-in and not woken until
asked for, and is listed at /toolsets and by the list_server_toolsets tool. See
Toolsets.
The smallest server that works
from reactor import PluginManifest
from reactor_mcp_server import McpExtension, build_host, create_mcp_app, tool
class Notebooks(McpExtension):
def manifest(self) -> PluginManifest:
return PluginManifest(name="notebooks", version="1.0.0")
@tool(title="List Notebooks")
async def list_notebooks(self) -> list[str]:
"""Every notebook the caller can reach."""
return ["Titanic", "Pyramid"]
app = create_mcp_app(build_host([Notebooks()], name="my-server"), path="/mcp")
app is a Starlette application: serve it with uvicorn, or mount it in one
you already have. A deployment that wants the installed extensions and no
code at all runs the module instead — see Serving.
What the pieces are called
| Construct | What it is |
|---|---|
McpExtension | A reactor plugin that offers tools. One subclass per extension. |
ToolSpec | One tool, as an extension offers it: a name, a handler, what a model reads. |
ToolExtension | What one extension does to another extension's tool. |
Toolset | A named group of tools, the thing a URL switches on. |
McpHost | The platform, the extensions on it, and the servers built from them. |
BuiltServer | A server and what it was built from — so a host can say why these tools. |
ToolsetRouter | The ASGI application that reads the URL and routes to the right built server. |
Where to go next
- Tools — offering one, and what a client sees.
- Extending a tool — narrowing somebody else's.
- Toolsets — the URL grammar, and activation.
- The host — building a server, and what a deployment decides.
- Serving — over HTTP, with one endpoint and many servers.
- Writing an extension — start to published.
- Example toolsets —
mathandgeo, in one installable example.