Skip to main content

Two toolsets, start to served

examples/mcp-toolsets is one distribution carrying two extensions, each declaring one toolset. How to run it, and what each file holds, is on its examples page.

ToolsetToolsServed
mathadd, multiplyTo everybody — on by default, with instructions
geoget_capital_of_country, get_country_of_capitalTo a client that asks — ?geo — and not woken until one does

A toolset on by default​

from mcp.types import ToolAnnotations
from reactor import PluginManifest
from reactor_mcp_server import McpExtension, Toolset, tool

PURE = ToolAnnotations(
read_only_hint=True, destructive_hint=False, idempotent_hint=True, open_world_hint=False
)


class MathExtension(McpExtension):
def manifest(self) -> PluginManifest:
return PluginManifest(name="math", version="0.1.0")

def toolsets(self):
return (
Toolset(
name="math",
title="Math",
description="Add and multiply numbers.",
instructions="Use the math tools for arithmetic instead of computing in your head.",
),
)

@tool(title="Add", annotations=PURE)
async def add(self, a: float, b: float) -> float:
"""Add two numbers and return the sum."""
return a + b

@tool(title="Multiply", annotations=PURE)
async def multiply(self, a: float, b: float) -> float:
"""Multiply two numbers and return the product."""
return a * b

Nothing about activation: the extension is registered when the host starts, and a client leaves the toolset out with ?without=math. Its instructions reach every session that has it.

A toolset nobody gets unless they ask​

from reactor_mcp_server import on_toolset


class GeoExtension(McpExtension):
def manifest(self) -> PluginManifest:
return PluginManifest(
name="geo",
version="0.1.0",
activation_events=[on_toolset("geo")],
)

def toolsets(self):
return (
Toolset(
name="geo",
title="Geography",
description="Look up the capital of a country, or the country of a capital.",
default=False,
),
)

@tool(title="Get Capital of Country", annotations=LOOKUP)
async def get_capital_of_country(self, country: str) -> str:
"""Return the capital city of a country, by the country's English name."""
...

Two things make it opt-in, and they do different jobs. default=False keeps its tools off a bare /mcp. The activation event keeps the extension itself asleep until a URL names geo: before that it has contributed nothing and costs nothing, though /toolsets still lists it, read from the extension's declaration, so a client can find the name to ask for.

Published by installing​

[project.entry-points."reactor.mcp.extensions"]
math = "reactor_mcp_toolsets_example.math:extension"
geo = "reactor_mcp_toolsets_example.geo:extension"
pip install -e "examples/mcp-toolsets[server]"
reactor-mcp-server --port 4040
URLTools
/mcpadd, multiply, list_server_toolsets
/mcp?geothe above, and the two geo tools
/mcp?only=geothe geo tools, and list_server_toolsets

Over stdio the command line selects instead of a URL:

reactor-mcp-server --transport stdio --toolsets geo

A real one​

The same shape serves NASA Earthdata: the earthdata extension declares an opt-in toolset, and installing earthdata-mcp-server beside any host serves it at /mcp?earthdata.