McpTools class final

The McpToolRegistry a project fills: the MCP tools its plugins bring, each under the plugin's namespace.

Decision 19 of the plugin plan: a plugin brings everything, its tools for an agent included. A plugin's install asks the host for this type, host.registry<McpTools>(), and gets a view scoped to the plugin: a tool added through it is published as <namespace>.<name> — wind.gust — so two plugins can each have a reset and neither shadows the other or a server's own. The namespace is PluginManifest.namespace, the plugin's id up to its first dot, as every other name a plugin registers is in: the editor half of a package (wind.editor) publishes under wind. too. No plugin from outside the engine may take one of the servers' areas (light, level, …) as its namespace, which PluginManifest.idProblem refuses at install (PluginManifest.reservedAreas), so a tool a server adds to its area in a minor never shadows a plugin's. Switching the plugin off withdraws its tools; a running server hears it and tells its client the list changed.

void install(PluginHost host) {
  final tools = host.registry<McpTools>()..declareSchemaVersion('1.0.0');
  tools.addTool(
    ToolSpec(
      name: 'gust',
      description: 'Blow once, as hard as asked.',
      inputSchema: {
        'type': 'object',
        'properties': {'strength': {'type': 'number'}},
      },
    ),
    (ToolCall call) => ToolResult.text('blew ${call.arguments['strength']}'),
  );
}

A plugin asks for the tools permission to add one. Its manifest lists PluginPermission.tools, so a person installing it reads that it talks to agents; a plugin that did not ask is refused at addTool with a PluginException naming it.

Each namespace versions its own tools. declareSchemaVersion gives the namespace's schema version, by the same rule a server's follows; it travels in each of its tools' _meta and in every server's flutter3d.schema answer, and schema_snapshot --plugin writes the plugin's tools to its own api/<package>.mcp.

One per project, handed to the plugin host and to every server. The engine gets it among its registries — EngineLoop(registries: [tools]) — and each server takes it as projectTools, so the editor's, the simulation's and the modeller's servers all offer the same plugin tools beside their own. ProjectMcpServer (flutter3d_mcp) offers them alone, for a project with no other server running. The application's own tools go through the root with a namespace it names after itself: tools.addTool(tool, run, namespace: 'acme_racer'). An area of the engine's (PluginManifest.reservedAreas, game among them) is refused there as it is to a plugin.

Ordered as every registry is: the application's first, then each plugin's in install order, and within one owner as they were added.

Snapshotted by the package that brings them. A server built without this offers exactly what api/<package>.mcp lists; the tools added here are a plugin's surface, versioned with the plugin.

Inheritance

Constructors

McpTools()
An empty registry: the root, which the application owns.

Properties

companions → Iterable<PluginRegistry>
The registries that come with this one, found by PluginHost.registry as if each had been handed to the host itself.
no setterinherited
hashCode → int
The hash code for this object.
no setterinherited
runtimeType → Type
A representation of the runtime type of the object.
no setterinherited
schemaVersions → Map<String, String>
The schema version each namespace declared, by namespace.
no setter
tools → List<ProjectTool>
Every tool added, in order: the application's, then each plugin's by install order, and within one owner as added.
no setter

Methods

addTool(ToolSpec tool, ProjectToolRun run, {String? namespace}) → Registration
Adds tool, to be run by run, published as <namespace>.<name>.
declareSchemaVersion(String version, {String? namespace}) → Registration
Gives the schema version of the tools under this view's namespace — the plugin's, or namespace through the root — by the rule a server's schema version follows: a new tool or optional argument is a minor, a removed tool or a new required argument a major.
forPlugin(PluginScope scope) → McpTools
This registry as scope's plugin sees it: everything registered through the result is tracked by scope, ranked by it, and checked against its manifest. Must return the same type the registry is looked up by.
override
listen(void onChange()) → Registration
Calls onChange whenever a tool is added or withdrawn, until the registration it returns is cancelled. What a running server listens with, to keep its tools/list in step.
named(String name) → ProjectTool?
The tool published as name, or null.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
toString() → String
A string representation of this object.
inherited

Operators

operator ==(Object other) → bool
The equality operator.
inherited

Static Methods

published(String namespace, String name) → String
The published name of a tool called name under namespace.

Constants

maxNameLength → const int
The longest published name; MCP hosts are told to expect no more.