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 anentity(orselectseveral 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 withanswers. 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 itsanswers, 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 ascomponent(Component_Reset,Component_PasteValues,Component_MoveUp,Component_AddToAll,Component_Removewith{"entity": "Hero", "component": "Health"}), a field a prefab copy changed asfield(Component_ApplyToPrefabwith{"field": "Pickup.Amount"}), and are told why when they can’t.Edit_UndoandEdit_Redoundo 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 aschoice, 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_OpenExternallyandAsset_ShowInExplorerhand a file in Assets to Windows. Commands that throw something away (Delete, Cut, Clear Save Data, Exit) are marked as destructive.Scene_Opentakes ascene(its name, “Game Over”, or a path), andEdit_UndoandEdit_Redoadocument(an open scene or prefab, by name or path) to act on when it isn’t the active one. Agame_inputclick 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_createandentity_update(values as scene files have them), described bycomponents_listandcomponent_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_getandentity_findlook at the scene, the running game included (while it plays,entity_getadds what each component says about itself as it runs and doesn’t save, aslive: a beat clock’sbeat, a spawner’sspawned;component_describelists what those mean);scene_treeends with the fields naming entities that aren’t there, andentity_getshows them asunmatched. Renaming withentity_updaterenames the entity in the fields that name it, and says which; itsremovetakes off a component whose script is gone by the namescene_treeshows it with ("remove": ["ShopSign"]forShopSign (missing)). Each call is one undo step. While a prefab’s tab is showing (Prefab_Open,Entity_EditPrefab), they edit the prefab,Scene_Savesaves it (updating its copies) andPrefab_Closegoes back to the scene. - Many at once:
entity_updatetakes 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 thosewitha component orunderan entity, or picked by those alone.entity_createtakes 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": truethey say what they would do (entity_updateeach 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
Handlesmode,ResizeShape), dragging distances (Distances,DragDistance), editing paths (PathPoints,DragPathPoint,InsertPathPoint,RemovePathPoint), painting the selected tilemap (TileTool, whoseSelectlets 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, itsSavedLayoutsand itsSummary), the Inspector editing several entities at once, a component’s menu (Components[Health]’sResetToDefaults,CopyValues,PasteValues,MoveUp,MoveDownandAddToAll), picking entities for its fields (PickEntity), a color field’s picker (IsColorOpen, then itsColorPicker’sHue,Saturation,Value,Alpha,Hex,Pick,SelectedPaletteandRecent), the Inspector’sFilterandTransform3D, the Hierarchy’sFilter…) can be read and worked withui_roots,ui_inspect,ui_setandui_invoke. Something picked from a list is given by its name, as a value or an argument:ui_invokethe Inspector’sAddComponentwith["Health"]. A method is named at the end of the path, after what has it:ui_invokeonProjectSessionwithProject.SetNewRandomEachGameand[true], orProject.SetControlsAsyncwith[{"PauseTime": ["Space"]}], changes and saves the project’s settings as the menus do; a path ending at a property is refused (ui_inspectreads it,ui_setsets 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_setandui_invokerefuse them and point toentity_update, so every change to a scene is an undo step. - Files:
asset_writewrites scripts (compiled at once, errors reported), pictures, sounds and tables (a.tablefile 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_readreads them, pictures as images;asset_moverenames or moves a prefab, keeping its copies linked. The Tables panel is a root of the ui_ tools like any panel:ui_invokeonTableswithOpen,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),Undoand the rest, andui_inspectonTablesreadsRows[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, whichui_setchanges) 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.simfiles (asset_writesays what one plays, or what’s missing for it to run) and the Simulations panel:Data_NewSimulationmakes one from the open scene,ui_setonSimulationschanges its settings (Arena,FirstEntity,FirstTable,FirstRows,SecondTable,Runs,Seed,Sweeps,SweepColumn,SweepTo,Script…),Data_RunSimulationruns it and answers with its summary and what stands out (passwaitfor a big one;ui_invokeSimulationsRunAsyncdoes the same), andui_inspectonSimulationsreadsPairs(every pair’s measures, a line each),ResultsJson(every pair at every step, as data),MatrixLines,SweepLines,OverARunLines(for theRunPairpicked),FindingsandWarnings, andui_invokeValuegives 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_EditChartopens one,ui_setonChartsets itsDifficulty,Snap,RecordModeandPlayhead,ui_invokeRecordTakerecords a take of taps given as moments in the song, andAddNote,MoveNote,SetHoldandRemoveNoteedit it, each an undo step (see Recording a chart). - Checking work:
editor_screenshotshows the game or the editor,game_inputplays the running game with keys, controllers ("Gamepad2 X"for a second player’s; in Play with Players,"player": 2presses 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 forseconds: 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 towatch(by name, or by id or path to tell apart things with the same name),editor_stateandoutput_readsay what’s going on (while the game plays,editor_statelists the dialogue flags set and the systems scripts have added, with their phase and the entity each goes with). - Debugging: the
Debuggerservice (ui_invoke) sets breakpoints on any line of a script (SetBreakpointwith["Scripts/Player.cs", 12],RemoveBreakpoint,RemoveAllBreakpoints). When the game stops at one,editor_statesays where and lists the values in scope two levels deep,ui_inspecton the Debugger reads them further (Values[this].Members),Debug_StepOver,Debug_StepIntoandDebug_StepOutstep (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), andDebug_Continue(orGame_Pause) carries on. A command orgame_inputthat 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 (unlessDebug_PauseOnExceptionsturns it off): the command,game_inputorGame_Playthat ran into it returns saying so, with the exception, the line and the values in scope, andeditor_statesaysGame: paused on an exception a script threw (...);Debug_Continuelets the exception end the frame and plays on, aDebug_Step*ends the frame and pauses after it, andDebug_RewindBeforeExceptiongoes back to the moment the step that threw began (set a breakpoint there andDebug_ContinueorGame_Stepto watch it again).Game_Play,Debug_ContinueandGame_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.