Skip to content

Agents (MCP)

While the editor is open it runs a Model Context Protocol server on this computer, so an agent like Claude Code can build games with it: claude mcp add --transport http griff http://127.0.0.1:7650/mcp (or Help → Copy MCP Setup Command; Help → MCP Server turns it off; GRIFF_MCP_PORT picks another port). The server lists no features of its own. Its tools are read from what the editor already has, so everything the editor can do is there, and anything added later shows up by itself:

  • Every command in the menus and toolbar is a tool, named by its id (Entity_CreatePlatformerPlayer, Game_Play, Scene_Save) and described by its documentation. Commands that act on the selection take an entity (or select several first: Delete, Duplicate, Cut and Copy act on all of them); a question a command asks (a scene’s name, saving changes) comes back to the agent, which answers it with answers. So does a question the editor is already showing the user when a call comes in (unsaved changes kept from when it closed without saving, asked as it reopens the last project): the call answers it with its answers, or without them is told what it asks, and the call itself waits for another go, as the editor is in the middle of what asked. A project never opens without a scene: the question about unsaved changes is asked before anything changes, and a start scene that can’t be read gives way to another scene (or a new one). Commands on a right-click menu take what it was opened on: a component’s menu in the Inspector as component (Component_Reset, Component_PasteValues, Component_MoveUp, Component_AddToAll, Component_Remove with {"entity": "Hero", "component": "Health"}), a field a prefab copy changed as field (Component_ApplyToPrefab with {"field": "Pickup.Amount"}), and are told why when they can’t. Edit_Undo and Edit_Redo undo whichever document was changed or worked in last (the scene or prefab, a table, a simulation, a chart, the Sprite Painter’s sheet), as Ctrl+Z does, and say what and where. Commands that pick something take it as choice, and their description lists what there is: the scene to start in (Scene_SetStart), a prefab or image to add to the scene (Asset_AddToScene, as the Assets panel’s right-click menu and dropping on the Scene view do), the Output line of a script error to open (Output_GoToScriptError), a saved layout. Asset_OpenExternally and Asset_ShowInExplorer hand a file in Assets to Windows. Commands that throw something away (Delete, Cut, Clear Save Data, Exit) are marked as destructive. Scene_Open takes a scene (its name, “Game Over”, or a path), and Edit_Undo and Edit_Redo a document (an open scene or prefab, by name or path) to act on when it isn’t the active one. A game_input click by label also finds a Button by the Text on its own entity.
  • Every component, Griff’s and the project’s scripts, can be added and set with entity_create and entity_update (values as scene files have them), described by components_list and component_describe (which lists properties under the Inspector’s subheadings, says which are only used while another is on, which module a genre’s component is part of, its actions: what a Trigger or a wire can make it do, a script’s own [Action] methods included, and its outputs: what a Counter, Bar, Text or wire can read, a script’s own [Output] properties included). scene_tree, entity_get and entity_find look at the scene, the running game included (while it plays, entity_get adds what each component says about itself as it runs and doesn’t save, as live: a beat clock’s beat, a spawner’s spawned; component_describe lists what those mean); scene_tree ends with the fields naming entities that aren’t there, and entity_get shows them as unmatched. Renaming with entity_update renames the entity in the fields that name it, and says which; its remove takes off a component whose script is gone by the name scene_tree shows it with ("remove": ["ShopSign"] for ShopSign (missing)). Each call is one undo step. While a prefab’s tab is showing (Prefab_Open, Entity_EditPrefab), they edit the prefab, Scene_Save saves it (updating its copies) and Prefab_Close goes back to the scene.
  • Many at once: entity_update takes a list of changes (updates) and picks entities by a glob on their path as well as by name, id or path: {"match": "HUD/Toolbar/Tool *", "changes": {"components": {"Tooltip": {"value": "Build"}}}} (* is any characters within a name, ? one; without a / it matches names at any depth), narrowed to those with a component or under an entity, or picked by those alone. entity_create takes a list (entities) too. Either is one undo step and all or nothing: if any change fails, nothing changes and the answer lists each entity as ok or with its error. With "dryRun": true they say what they would do (entity_update each field with its old and new value) and change nothing.
  • Every window, panel, document tab and editor service (the Sprite Painter and the Sound Maker by their tabs’ names, a table open in a tab, the Controls window, the workspace, the Scene view’s clicks, box selection, moving, rotating, scaling and resizing (its Handles mode, ResizeShape), dragging distances (Distances, DragDistance), editing paths (PathPoints, DragPathPoint, InsertPathPoint, RemovePathPoint), painting the selected tilemap (TileTool, whose Select lets clicks select instead, IsPainting, BrushTile, PaintTile, PaintRectangle, FillTiles, PickTile, CellAt) and its layers (PaintLayers, ShowLayer, AddLayer), the links it draws (Links), where it looks (SceneViewport: Pan, Zoom, FrameSelection), its tile palette (TilePalette: Tilesets, Shown, Tiles, VisibleTiles, Scroll, Tool, Layers, Hint, Pick, Step, ShowTileset), whether script tabs show the component beside the code (ScriptEditors’ ShowComponent), where the panels are (PanelLayout: Dock, Tab, Float, CloseFloating, Return, Show, Save, Load, Delete, Reset, its SavedLayouts and its Summary), the Inspector editing several entities at once, a component’s menu (Components[Health]’s ResetToDefaults, CopyValues, PasteValues, MoveUp, MoveDown and AddToAll), picking entities for its fields (PickEntity), a color field’s picker (IsColorOpen, then its ColorPicker’s Hue, Saturation, Value, Alpha, Hex, Pick, SelectedPalette and Recent), the Inspector’s Filter and Transform3D, the Hierarchy’s Filter…) can be read and worked with ui_roots, ui_inspect, ui_set and ui_invoke. Something picked from a list is given by its name, as a value or an argument: ui_invoke the Inspector’s AddComponent with ["Health"]. A method is named at the end of the path, after what has it: ui_invoke on ProjectSession with Project.SetNewRandomEachGame and [true], or Project.SetControlsAsync with [{"PauseTime": ["Space"]}], changes and saves the project’s settings as the menus do; a path ending at a property is refused (ui_inspect reads it, ui_set sets it), and so is an argument a tool doesn’t take, saying what it takes, rather than leaving it out and seeming to have done what was asked. Entities and components are read this way but not changed: ui_set and ui_invoke refuse them and point to entity_update, so every change to a scene is an undo step.
  • Files: asset_write writes scripts (compiled at once, errors reported), pictures, sounds and tables (a .table file reaches the Tables panel and the running game at once, and the answer says how many rows and columns it read, or why it doesn’t read, and what’s wrong with its formulas); asset_read reads them, pictures as images; asset_move renames or moves a prefab, keeping its copies linked. The Tables panel is a root of the ui_ tools like any panel: ui_invoke on Tables with Open, SetCell (["Fireball", "Damage", "14"]), AddRow, AddColumn (a name, a type, choices), ChangeColumn, RenameRow, Sort, Select, FillDown, Copy, Paste (tab-separated text), ImportCsv, ExportCsv, SetFormula (["XP", "=Base * 1.15 ^ (Level - 1)"]), GenerateCurve ({"column": "XP", "kind": "exponential", "first": 100, "last": 50000, "levels": 50, "roundTo": 10}), Values (a column’s values as worked out), Undo and the rest, and ui_inspect on Tables reads Rows[Fireball].Cells[Damage] (a formula’s cell as it works out), FormulaProblems, Summary, Chart (what it charts: each row’s value, dice’s range and spread, and its summary), Curve (the curve editor’s settings, which ui_set changes) and what the last change said (Message); the Data menu’s commands are tools too (Data_NewTable, Data_OpenTable, Data_AddRow, Data_GenerateCurve…). Balance simulations are .sim files (asset_write says what one plays, or what’s missing for it to run) and the Simulations panel: Data_NewSimulation makes one from the open scene, ui_set on Simulations changes its settings (Arena, FirstEntity, FirstTable, FirstRows, SecondTable, Runs, Seed, Sweeps, SweepColumn, SweepTo, Script…), Data_RunSimulation runs it and answers with its summary and what stands out (pass wait for a big one; ui_invoke Simulations RunAsync does the same), and ui_inspect on Simulations reads Pairs (every pair’s measures, a line each), ResultsJson (every pair at every step, as data), MatrixLines, SweepLines, OverARunLines (for the RunPair picked), Findings and Warnings, and ui_invoke Value gives one (["Warrior", "Ogre", "Win %"]). A command that has something to say when it’s done says it after “Done:”. See Tables of game data. Rhythm charts have the Chart panel: Rhythm_EditChart opens one, ui_set on Chart sets its Difficulty, Snap, RecordMode and Playhead, ui_invoke RecordTake records a take of taps given as moments in the song, and AddNote, MoveNote, SetHold and RemoveNote edit it, each an undo step (see Recording a chart).
  • Checking work: editor_screenshot shows the game or the editor, game_input plays the running game with keys, controllers ("Gamepad2 X" for a second player’s; in Play with Players, "player": 2 presses keys in player 2’s own window, as on their machine) and the mouse (pointing, clicking, dragging from one thing to another, which drags a camera with Camera Controls as far as from one to the other, and turning the wheel; put on a button or the HUD, its mouse rests on that spot on the screen as a real one does, so clicking again where it rests clicks a panel that opened there again after the camera moved) and fingers on a touch screen (touch, one point or several at once, held for seconds: rhythm lanes’ chords and holds; it can pause it between moves, or set dialogue flags first to try a branch) and reports on what it’s told to watch (by name, or by id or path to tell apart things with the same name), editor_state and output_read say what’s going on (while the game plays, editor_state lists the dialogue flags set and the systems scripts have added, with their phase and the entity each goes with).
  • Debugging: the Debugger service (ui_invoke) sets breakpoints on any line of a script (SetBreakpoint with ["Scripts/Player.cs", 12], RemoveBreakpoint, RemoveAllBreakpoints). When the game stops at one, editor_state says where and lists the values in scope two levels deep, ui_inspect on the Debugger reads them further (Values[this].Members), Debug_StepOver, Debug_StepInto and Debug_StepOut step (each returns once the step is over, saying where it stopped and what’s in scope, or that it ran to the end of the frame), and Debug_Continue (or Game_Pause) carries on. A command or game_input that runs the game into a breakpoint returns there, saying where it stopped and what’s in scope. A script that throws stops the game too (unless Debug_PauseOnExceptions turns it off): the command, game_input or Game_Play that ran into it returns saying so, with the exception, the line and the values in scope, and editor_state says Game: paused on an exception a script threw (...); Debug_Continue lets the exception end the frame and plays on, a Debug_Step* ends the frame and pauses after it, and Debug_RewindBeforeException goes back to the moment the step that threw began (set a breakpoint there and Debug_Continue or Game_Step to watch it again). Game_Play, Debug_Continue and Game_Pause (resuming) wait for the game’s next frame (up to 2 seconds), so a script that throws or a breakpoint reached straight away is reported by them.

It listens on the loopback address only and refuses requests from web pages.

An agent testing or profiling a game needn’t make the user listen: start the editor with GRIFF_MUTE=1 and it plays no sound (the sound device is never opened) while the game runs exactly as it would with it, for that session only: the user’s own Game → Mute choice is left as it was, and it stays silent even if the agent switches Game_Mute off (which isn’t kept). editor_state says when no sound is heard. Players the editor starts inherit it.

Every command is a tool, every component can be set with the scene tools, and the lists of both are written from the code in the command reference and the component reference: a new command or component reaches agents, and these pages, by itself.

This site’s screenshots are taken this way: site/scripts/screenshots.mjs makes a project from each template over the MCP, plays it and saves what editor_screenshot shows.