Skip to content

Move reactor-mcp-server to apps/, make toolsets first class, add example toolsets - #26

Open
echarles wants to merge 8 commits into
mainfrom
feat/apps-mcp-server
Open

echarles wants to merge 8 commits into
mainfrom
feat/apps-mcp-server

Conversation

@echarles

@echarles echarles commented Sep 29, 2026 •

Copy link
Copy Markdown
Member

Move

plugins/mcp-server → apps/mcp-server. The MCP server is a host a deployment runs, not a plugin an application installs.

  • CI, the release workflow (PY_PACKAGES), dev/bump_version.py and RELEASE.md follow the new path.
  • apps/README.md says what the folder is for.

Toolsets, first class

The generic parts of what the private Datalayer gateway needed, moved into the foundation:

  • Toolset.title and Toolset.instructions. A toolset's instructions go into the server's instructions only when it is active (host.instructions_for).
  • list_toolsets tool (build_host(..., list_toolsets_tool=True)). It gives the same answer as /toolsets, for a model already in a session or a stdio client. Read-only, and off by default in code.
  • default_selection on create_mcp_app/ToolsetRouter: what a URL naming no toolset gets.
  • ignore_query_keys: query keys the deployment reads itself (e.g. scopes=), which are no longer taken for unknown toolset names. parse_selection and selection_from_scope take ignore=.
  • host.active_for(selection): what a request is about to get, without building. It answers correctly for only=, defaults and without=, where checking the named flags does not.
  • host.describe(selection): the one payload behind /toolsets and list_toolsets. It now includes each toolset's title.
  • CLI: --transport stdio, --toolsets (the default selection, and over stdio the whole selection), --ignore-query-key, and --list-toolsets-tool (on by default).

The gateway's in-session enable/disable was not ported on purpose: toolsets are read once per connection, as the docs explain.

Example

examples/toolsets is one installable distribution with two extensions:

  • math (add, multiply) is on by default and has instructions.
  • geo (get_capital_of_country, get_country_of_capital) is opt-in with an onToolset:geo activation event.

It is tested in process, over HTTP with a real client, and over stdio through the entry points. CI installs it.

Docs

  • toolsets.md: instructions, list_toolsets, what a deployment decides, and active_for.
  • serving.md: the new CLI options and stdio.
  • host.md and index.md are updated.
  • New page: example-toolsets.md.

Tests: 231 passed from the root (80 in the app, 12 in the example).

…ment runs, not a piece an application installs
Copilot AI balanced review requested due to automatic review settings September 29, 2026 08:51

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Plugin activation can leave stale servers and skip lifecycle startup, while CLI shutdown omits extension cleanup.

Review effort: Balanced
Findings: None

What changed in this PR

Moves the MCP server from plugins/ to apps/, reflecting its role as a deployable host while preserving package metadata.

Changes:

  • Relocates MCP server implementation, tests, and documentation.
  • Updates CI, release, and version-bump paths.
  • Documents the new apps/ directory purpose.
File Description
RELEASE.md Updates release package path.
dev/​bump_version.py Updates MCP version-file paths.
apps/​README.md Defines the applications directory.
apps/​mcp-server/​.gitignore Ignores package build metadata.
apps/​mcp-server/​README.md Documents MCP server usage.
apps/​mcp-server/​pyproject.toml Defines package metadata and dependencies.
apps/​mcp-server/​reactor_mcp_server/​__init__.py Exposes the public API.
apps/​mcp-server/​reactor_mcp_server/​__main__.py Provides the server CLI.
apps/​mcp-server/​reactor_mcp_server/​app.py Implements HTTP routing and lifespans.
apps/​mcp-server/​reactor_mcp_server/​extension.py Defines MCP extensions and discovery.
apps/​mcp-server/​reactor_mcp_server/​points.py Defines contribution points and events.
apps/​mcp-server/​reactor_mcp_server/​server.py Builds and caches MCP servers.
apps/​mcp-server/​reactor_mcp_server/​tools.py Defines tool contributions and extensions.
apps/​mcp-server/​reactor_mcp_server/​toolsets.py Parses and resolves toolset selections.
apps/​mcp-server/​tests/​test_activation_by_url.py Tests URL-based activation.
apps/​mcp-server/​tests/​test_review_follow_ups.py Covers prior review regressions.
apps/​mcp-server/​tests/​test_served_over_http.py Tests served HTTP behavior.
apps/​mcp-server/​tests/​test_tools_are_contributions.py Tests contribution composition.
.github/​workflows/​ci.yaml Installs tests from the new path.
.github/​workflows/​release.yaml Builds and releases from the new path.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

…ment's default selection and own query keys, host.active_for, stdio and --toolsets on the CLI; math and geo example toolsets
@echarles echarles changed the title Move reactor-mcp-server to apps/ Move reactor-mcp-server to apps/, make toolsets first class, add example toolsets Sep 29, 2026
…servers when a URL wakes an extension; stop the host on CLI exit; list_server_toolsets, never shadowing an extension's tool
@echarles

Copy link
Copy Markdown
Member Author

Addressed the review overview's three points in a21227c:

  • Lifecycle startup skipped. PluginPlatform.activate_plugin now delivers on_reactor_start to a plugin that activates after start(), whether an event woke it or it was registered or discovered late. It is delivered to that plugin only, and once. A plugin stood down while the platform runs gets on_reactor_stop at that point. The separate late-start path for discovered extensions is folded into this, so nothing is started twice. Tests are in tests/test_start_hooks.py.
  • Stale servers. McpHost.build drops the cached servers (forget_built, which bumps revision) whenever the events it fires wake or stand down a plugin. The router then makes new applications for new connections. Tests are in TestWakingAnExtension.
  • CLI shutdown. reactor-mcp-server now stops the host when either transport exits, so every running extension gets on_stop.

Also renamed the optional tool to list_server_toolsets (host option toolsets_tool, CLI --toolsets-tool) so it cannot collide with a deployment's own list_toolsets. An extension offering a tool of that name is served instead of the host's.

Tests: 239 passed and 1 skipped at the root; with the example installed, its 12 pass, stdio included.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants