Skip to content

feat(manage_editor): add open_prefab_stage and save_prefab_stage actions#988

Closed
zaferdace wants to merge 2 commits intoCoplayDev:mainfrom
zaferdace:feat/open-prefab-stage
Closed

feat(manage_editor): add open_prefab_stage and save_prefab_stage actions#988
zaferdace wants to merge 2 commits intoCoplayDev:mainfrom
zaferdace:feat/open-prefab-stage

Conversation

@zaferdace
Copy link
Copy Markdown
Contributor

@zaferdace zaferdace commented Mar 25, 2026

Summary

Closes #976

Adds open_prefab_stage and save_prefab_stage actions to manage_editor, completing the prefab stage workflow alongside the existing close_prefab_stage.

Problem

There was no way to programmatically open a prefab in Prefab Mode via MCP. Users had to manually double-click prefabs in the Editor before AI agents could modify objects inside them. The existing manage_gameobject and manage_components tools already support prefab stage (via GameObjectLookup.GetAllSceneObjects() which checks PrefabStageUtility.GetCurrentPrefabStage()), but there was no MCP action to enter the stage.

Changes

New actions in manage_editor:

Action Parameter Description
open_prefab_stage path (required) Opens a prefab in Prefab Mode using PrefabStageUtility.OpenPrefab(). Validates the asset exists and is a prefab.
save_prefab_stage Saves changes in the currently open prefab stage back to the prefab asset.

Updated: Supported actions list in the error message now includes the new actions.

Workflow

manage_editor(action="open_prefab_stage", path="Assets/Prefabs/MyPrefab.prefab")
  → manage_gameobject / manage_components (modify objects inside)
  → manage_editor(action="save_prefab_stage")
  → manage_editor(action="close_prefab_stage")

Alternative headless approach (already works, no stage needed):

manage_prefabs(action="modify_contents", path="...", componentProperties={...})

Implementation Details

  • Uses PrefabStageUtility.OpenPrefab(path) (not AssetDatabase.OpenAsset) as it is purpose-built for Prefab Mode
  • Validates asset exists and is actually a prefab before opening
  • Returns root object name on success for easy subsequent tool calls
  • Save uses EditorSceneManager.MarkSceneDirty + SaveScene on the prefab stage scene
  • Follows the same error handling pattern as existing close_prefab_stage

Test Plan

  • Open a prefab via open_prefab_stage, verify stage is active
  • Modify objects inside via manage_components set_property
  • Save via save_prefab_stage, verify changes persist in the .prefab asset
  • Close via close_prefab_stage, verify return to main scene
  • Error case: invalid path, non-prefab asset, no stage open when saving
  • Verify existing close_prefab_stage still works unchanged

Summary by Sourcery

Add support in the editor management tool for opening and saving Unity prefab stages to complete the prefab editing workflow.

New Features:

  • Introduce an open_prefab_stage action to open a prefab in Prefab Mode by asset path and return basic metadata.
  • Introduce a save_prefab_stage action to persist changes made in the currently open prefab stage.

Enhancements:

  • Expand the unknown-action error message to list the new prefab stage actions alongside existing manage_editor actions.

Adds two new actions to manage_editor to complete the prefab stage workflow:

- `open_prefab_stage`: Opens a prefab in Prefab Mode using
  PrefabStageUtility.OpenPrefab(). After opening, existing tools
  (manage_gameobject, manage_components) can modify objects inside
  the prefab stage.

- `save_prefab_stage`: Saves changes made in the currently open
  prefab stage back to the prefab asset.

Combined with the existing `close_prefab_stage`, this enables a
full programmatic workflow:
  open_prefab_stage → manage_components/manage_gameobject → save_prefab_stage → close_prefab_stage

Also updates the supported actions list in the error message.

Closes CoplayDev#976
@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai bot commented Mar 25, 2026

Reviewer's Guide

Adds prefab stage workflow support to the manage_editor MCP tool by introducing open and save actions around the existing close_prefab_stage, plus wiring them into the command dispatcher and error messaging.

Sequence diagram for prefab stage MCP workflow

sequenceDiagram
    actor User
    participant MCPClient
    participant ManageEditor
    participant ManageGameObject
    participant ManageComponents
    participant AssetDatabase
    participant PrefabUtility
    participant PrefabStageUtility
    participant EditorSceneManager

    User->>MCPClient: manage_editor(action=open_prefab_stage, path=Assets/Prefabs/MyPrefab.prefab)
    MCPClient->>ManageEditor: HandleCommand(action=open_prefab_stage, path)
    ManageEditor->>ManageEditor: OpenPrefabStage(prefabPath)
    ManageEditor->>AssetDatabase: LoadMainAssetAtPath(prefabPath)
    AssetDatabase-->>ManageEditor: asset
    ManageEditor->>PrefabUtility: GetPrefabAssetType(asset)
    PrefabUtility-->>ManageEditor: prefabAssetType
    alt asset missing or not a prefab
        ManageEditor-->>MCPClient: ErrorResponse
    else valid prefab
        ManageEditor->>PrefabStageUtility: OpenPrefab(prefabPath)
        PrefabStageUtility-->>ManageEditor: prefabStage
        alt open failed
            ManageEditor-->>MCPClient: ErrorResponse
        else opened
            ManageEditor-->>MCPClient: SuccessResponse(prefabPath, rootName)
        end
    end

    User->>MCPClient: manage_gameobject / manage_components
    MCPClient->>ManageGameObject: modify objects inside prefab stage
    MCPClient->>ManageComponents: set_property, etc.

    User->>MCPClient: manage_editor(action=save_prefab_stage)
    MCPClient->>ManageEditor: HandleCommand(action=save_prefab_stage)
    ManageEditor->>ManageEditor: SavePrefabStage()
    ManageEditor->>PrefabStageUtility: GetCurrentPrefabStage()
    PrefabStageUtility-->>ManageEditor: prefabStage
    alt no current prefab stage
        ManageEditor-->>MCPClient: SuccessResponse("Nothing to save")
    else stage open
        ManageEditor->>EditorSceneManager: MarkSceneDirty(prefabStage.scene)
        ManageEditor->>EditorSceneManager: SaveScene(prefabStage.scene)
        EditorSceneManager-->>ManageEditor: saveResult
        ManageEditor-->>MCPClient: SuccessResponse(prefabPath)
    end

    User->>MCPClient: manage_editor(action=close_prefab_stage)
    MCPClient->>ManageEditor: HandleCommand(action=close_prefab_stage)
    ManageEditor->>PrefabStageUtility: GetCurrentPrefabStage() / close logic
    ManageEditor-->>MCPClient: SuccessResponse or ErrorResponse
Loading

File-Level Changes

Change Details Files
Wire new prefab stage actions into manage_editor command handling and error messaging.
  • Add action cases open_prefab_stage and save_prefab_stage in HandleCommand, including required path parameter validation for open_prefab_stage
  • Update the unknown-action error message to list open_prefab_stage and save_prefab_stage among supported actions
MCPForUnity/Editor/Tools/ManageEditor.cs
Implement OpenPrefabStage helper to validate and open a prefab in Prefab Mode and return metadata.
  • Load main asset at provided path and return an error response if it is missing
  • Check that the asset is a prefab using PrefabUtility.GetPrefabAssetType and reject non-prefab assets
  • Open the prefab using PrefabStageUtility.OpenPrefab and return a structured SuccessResponse with path and root object name, handling exceptions via ErrorResponse
MCPForUnity/Editor/Tools/ManageEditor.cs
Implement SavePrefabStage helper to persist changes in the current prefab stage.
  • Fetch current prefab stage via PrefabStageUtility.GetCurrentPrefabStage and no-op with SuccessResponse if not in prefab mode
  • Mark the prefab stage scene dirty and save it via EditorSceneManager.SaveScene, returning a SuccessResponse with the prefab path
  • Wrap logic in try/catch and surface failures as ErrorResponse with exception message
MCPForUnity/Editor/Tools/ManageEditor.cs

Possibly linked issues

  • #unknown: PR adds prefab stage open/save so existing tools can edit prefab component fields, directly addressing prefab-serialization workflow gap.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 25, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: df6ea81a-a8e8-4346-a4ce-67370ca87863

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • In SavePrefabStage, returning a SuccessResponse when no prefab stage is open may make it harder for callers to distinguish a no-op from a real save; consider using an error response or including an explicit saved: false flag in the payload to make this state machine clearer for tools.
  • When opening the prefab stage, you validate that the asset is a prefab but don’t distinguish between regular, variant, or model prefabs; if these types should be handled differently by agents, consider returning the specific PrefabAssetType in the success payload so callers can adapt behavior.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `SavePrefabStage`, returning a `SuccessResponse` when no prefab stage is open may make it harder for callers to distinguish a no-op from a real save; consider using an error response or including an explicit `saved: false` flag in the payload to make this state machine clearer for tools.
- When opening the prefab stage, you validate that the asset is a prefab but don’t distinguish between regular, variant, or model prefabs; if these types should be handled differently by agents, consider returning the specific `PrefabAssetType` in the success payload so callers can adapt behavior.

## Individual Comments

### Comment 1
<location path="MCPForUnity/Editor/Tools/ManageEditor.cs" line_range="455" />
<code_context>
+
+                // Mark the prefab stage scene as dirty then save
+                EditorSceneManager.MarkSceneDirty(prefabStage.scene);
+                EditorSceneManager.SaveScene(prefabStage.scene);
+
+                return new SuccessResponse($"Saved prefab stage changes for '{prefabPath}'.", new { prefabPath });
</code_context>
<issue_to_address>
**issue (bug_risk):** Handle the `SaveScene` return value to detect save failures.

`EditorSceneManager.SaveScene` returns a `bool` indicating whether the save succeeded. The current code always returns success if no exception is thrown, so cases like write-permission errors or disk-full conditions could be misreported. Please check the return value and surface an appropriate error or message when the save fails.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

- SavePrefabStage: return ErrorResponse when no stage is open
- SavePrefabStage: check SaveScene return value for save failures
- OpenPrefabStage: include PrefabAssetType in success payload
@zaferdace
Copy link
Copy Markdown
Contributor Author

Closing — open_prefab_stage was already merged in #968. Rebased onto beta with only save_prefab_stage in a new PR.

@zaferdace zaferdace closed this Mar 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant