editor library

A level editor an agent can drive, over the Model Context Protocol.

The same commands a person uses, offered as tools. Every verb here is an EditorCommand from flutter3d_editor_core — the values the editor application's keyboard and inspector already go through — so an edit made by an agent and an edit made by a hand take one route into the document, get one name in the history, and come back out under the same undo. Nothing about what an edit means is decided twice.

Two tools are not commands, and both were missing from every sketch of this: EditorSession.listing, because a program with no screen cannot point at anything and therefore cannot find out what is in the level it is editing; and EditorSession.validate, because without it the first news of a broken document is a diff somebody reads later.

What it is not

Not a connection to a running editor. The server owns one document for the life of one process, started by dart run. A socket into a live window, so that an agent and a person watch the same level change, is a different and much harder program — two writers on one undo stack — and this is the half that can be tested without a device.

It draws with no GPU and no Flutter. screenshot renders the level through the software rasteriser, and report reads the same frame's object ids to say how much of each brush, light and entity a camera sees and what is in its way — see LevelView. It used to refuse, when every renderer here reached a device whose finished frame was a Flutter widget and the level's scene was built inside a Flutter package; neither is true any more, and dart run resolves everything it needs.

dart run flutter3d_mcp:editor_mcp apps/flutter3d_demo_dungeon/assets/levels/crypt.json

Classes

Answer
What a tool call actually did, and the sentence to say about it.
DepthSpan
How far in front of the eye something reaches, nearest and farthest.
EditorMcpServer
A level editor, offered to an agent as a table of tools.
EditorSession
One level document, open, with the editor's own verbs on it.
LevelCamera
Where a picture of the level is taken from: the eye, and the point it looks at.
LevelView
The level as the software rasteriser draws it, and what an agent can learn from the drawing — screenshot and report.
PieceCover
One piece in front of another, and how much of the other it hides.
PieceReport
What one piece of the level looks like from a camera.
PixelBox
A box of whole pixels on the frame, from the top left, every edge inclusive.
PlaySession
HR5 for an agent: the game the open level belongs to, run, reloaded, stopped and sent the level when it is saved — the editor application's Play, through the same FlutterRun.

Constants

buildTargets → const Set<String>
What flutter build is asked to make, by the word an agent gives it.
editorAnswerSchema → const Map<String, Object?>
The shape of every editor tool's structuredContent, as the outputSchema each tool declares: whether the call did what it was asked (did, false for a refusal), its sentence, the selection after it in the words level.list uses, and whether a picture came with it.
editorMcpSchemaVersion → const String
The version of this server's tools — names and input schemas — as the initialize result announces it beside editorMcpVersion.
editorMcpVersion → const String
The version this server tells a client it is: the pubspec's.
editorToolNames → const Map<String, ToolName>
What each of editorTools is published as, area.verb, and what it does to the document. The name a tool is written under — the editor command's own word, which EditorCommand.fromJson reads — stays answerable as an alias until 2.0.

Properties

editorTools → List<EditorTool>
Everything this server offers: the ten commands, the six verbs that are about the session rather than about the document, and the two that look at it — view.screenshot and view.report.
no setter

Functions

commandInputSchema(PluginCommandInfo command) → Map<String, Object?>
command's arguments as a tool's input schema: an object with one property per argument hint, each required when it has no default.
serveEditorMcp(List<String> arguments, {List<Flutter3dPlugin> plugins = const <Flutter3dPlugin>[]}) → EditorMcpServer
Opens the level arguments names and serves it over stdio, offering the MCP tools plugins bring beside the editor's own.
shareCommands(EditorPieces pieces, McpTools tools, EditorSession session) → Registration
Offers every command the plugins added to pieces as a tool of tools, <namespace>.<name>, that runs it on session's document; keeps the offer in step while plugins are switched on and off, until the registration it returns is cancelled.

Typedefs

EditorTool = OfferedTool<EditorSession, Answer>
One tool: what an agent is offered, and what calling it does to the document — see flutter3d_mcp/kit.dart's OfferedTool for why a pair rather than a table and a switch.
GameAsk = Future<GameExtensionReply> Function(String vmService, String method, {Map<String, String> args})
Asks a running game for one of its ext.flutter3d.* extensions — see callGameExtension, which is what a session asks with unless a test hands in its own.
NewRun = FlutterRun Function(String projectRoot, String? device)
Makes a run of projectRoot on device. A parameter of PlaySession so a test hands it a run over a tool of its own making.
RunFlutterIn = Future<ProcessResult> Function(List<String> arguments, String workingDirectory)
Runs flutter with arguments in workingDirectory to the end — what PlaySession.build builds with. A parameter so a test answers for the tool.