The scene toolset can read any open scene, but nothing can change which one is active, or open a .scene that isn't open at all. The scene parameter is read-only scoping: set_component, set_game_object, save_scene and undo all implicitly hit the active session.
That combination silently loses edits. FindByGuid walks every open session and returns the first match, so set_component aimed at a component in a background tab does mutate that object - but the dirty flag lands on the active tab, save_scene saves the active scene, and the background scene reloads from disk on focus. With duplicated scenes (same component guids in two files) the agent can't even tell which one it hit. Today the only fix is asking a human to click the right tab, which defeats the point of driving the editor over MCP.
Both behaviours already exist as public API:
/// <summary>
/// Make a scene the active editor tab. Opens it from its asset path if it isn't open.
/// Scene edits always target the active scene, so switch before editing a background scene.
/// </summary>
/// <param name="scene">Scene name or resource path from list_scenes, or a .scene/.prefab path from asset_search.</param>
[McpTool( "open_scene" )]
public static OpenScene OpenScene( string scene )
backed by SceneEditorSession.MakeActive() (the same call SceneTabWidget makes on click) and SceneEditorSession.CreateFromPath( path ), which already returns the existing session if the scene is open. It's a ResolveSession helper mirroring ResolveScene (Scene.cs ~1002), a short tool method and a small result DTO.
Notes:
- Refuse
GameEditorSession - it has no tab, so MakeActive half-switches the editor invisibly. Error points at play_stop, guarded like the play toolset guards.
- No undo step: tab focus is editor UI state, not scene state. Worth saying out loud since the server instructions promise undo on scene edits, and switching changes what a later
undo targets.
- Plain
[McpTool], not [McpTool.ReadOnly].
- Not-found error points at
list_scenes / asset_search, matching the existing idiom.
- Name is bikesheddable -
open_scene covers both open-and-activate, but tool names are permanent public API, so I'll take whatever you prefer.
Happy to PR it if the shape looks right - it'd be about the size of #11557.
The
scenetoolset can read any open scene, but nothing can change which one is active, or open a.scenethat isn't open at all. Thesceneparameter is read-only scoping:set_component,set_game_object,save_sceneandundoall implicitly hit the active session.That combination silently loses edits.
FindByGuidwalks every open session and returns the first match, soset_componentaimed at a component in a background tab does mutate that object - but the dirty flag lands on the active tab,save_scenesaves the active scene, and the background scene reloads from disk on focus. With duplicated scenes (same component guids in two files) the agent can't even tell which one it hit. Today the only fix is asking a human to click the right tab, which defeats the point of driving the editor over MCP.Both behaviours already exist as public API:
backed by
SceneEditorSession.MakeActive()(the same callSceneTabWidgetmakes on click) andSceneEditorSession.CreateFromPath( path ), which already returns the existing session if the scene is open. It's aResolveSessionhelper mirroringResolveScene(Scene.cs ~1002), a short tool method and a small result DTO.Notes:
GameEditorSession- it has no tab, soMakeActivehalf-switches the editor invisibly. Error points atplay_stop, guarded like theplaytoolset guards.undotargets.[McpTool], not[McpTool.ReadOnly].list_scenes/asset_search, matching the existing idiom.open_scenecovers both open-and-activate, but tool names are permanent public API, so I'll take whatever you prefer.Happy to PR it if the shape looks right - it'd be about the size of #11557.