Skip to content

Conversation

@dsarno
Copy link
Owner

@dsarno dsarno commented Dec 26, 2025

Summary

This PR makes ScriptableObject creation/patching reliable and repeatable when driven via MCP by:

  • Implementing a single unified ScriptableObject tool (manage_scriptable_object) backed by Unity SerializedObject/SerializedProperty paths (instead of reflection).
  • Fixing the “wrong placement” class of issues by validating/normalizing folder paths (preventing silent creation into unintended locations).
  • Adding targeted EditMode coverage for private/inherited fields, nested structs, arrays/lists, and object references.

Motivation / problems addressed

Matches the failure modes called out in FixscriptableobjecPlan.md:

  • Wrong placement / folder path weirdness (relative paths, backslashes, “Packages/…”).
  • Partial setup failures when patching:
    • private [SerializeField] fields
    • inherited serialized fields
    • arrays/lists (.Array.size + .Array.data[i])
    • nested struct paths
    • UnityEngine.Object references by GUID or asset path
  • Better behavior during transient Unity states (compiling/reloading returns a retryable error code).

Key changes

  • Unity Editor tool

    • Added MCPForUnity/Editor/Tools/ManageScriptableObject.cs
    • Supports:
      • action=create (create asset + optional patches)
      • action=modify (patch existing asset by {guid|path})
    • Patching uses SerializedObject.FindProperty(propertyPath) and applies typed writes, including object reference assignment by GUID/path.
    • Folder handling:
      • normalizes slashes + removes double slashes
      • supports relative paths by rooting under Assets/
      • rejects non-project roots like Packages/, absolute paths, and file://… with invalid_folder_path.
  • Python server wrapper

    • Added Server/src/services/tools/manage_scriptable_object.py to expose the unified tool as a first-class MCP tool.
  • Tests

    • Added fixtures + tests under TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/… covering:
      • nested folder creation and correct placement
      • private [SerializeField] patching
      • inherited serialized field patching
      • nested struct field patching
      • list resize + ref assignment by GUID and by path
      • rejecting invalid folder roots (Packages/absolute/file URI)
      • path normalization (relative + backslashes; no // in result)
    • Added server integration test: Server/tests/integration/test_manage_scriptable_object_tool.py
  • Repo hygiene

    • .gitignore: ignore TestProjects/UnityMCPTests/Assets/Temp/ so temporary test assets never get committed again.
    • Removed vestigial SO tool implementations from the packaged server build output (Server/build/lib/...) so they don’t appear in the tool list anymore.

How to test

  • Unity EditMode: 156/156 passed
  • Unity PlayMode: no PlayMode tests in this project (0)
  • Pytest (repo root): 78 passed, 2 skipped, 7 xpassed

Notes

  • Tool surface is now simpler: ScriptableObject workflows should go through manage_scriptable_object (create/modify + patches) using Unity property paths, matching the design direction in FixscriptableobjecPlan.md.

Summary by CodeRabbit

  • New Features

    • Added MCP capability to create and modify Unity ScriptableObject assets with nested folder creation, overwrite handling, property patching (set, array resize), and object-reference assignment.
  • Documentation

    • Added a design/plan detailing creation/patch behavior, error codes, request/response contracts, and acceptance tests.
  • Chores

    • Ignored Unity Temp artifacts.
  • Tests

    • Added integration and Unity Editor tests and fixtures; improved test teardown to avoid global state leakage.
  • Behavior Change

    • Legacy asset-creation path no longer handles ScriptableObject creation — use the new tool.

✏️ Tip: You can customize this high-level summary in your review settings.

CodexConfigHelperTests was calling MCPServiceLocator.Reset() in TearDown, which disposes the active bridge/transport during MCP-driven test runs. Replace with restoring only the mutated service (IPlatformService).
Capture the original IPlatformService before this fixture runs and restore it in TearDown. This preserves the MCP connection safety fix (no MCPServiceLocator.Reset()) while avoiding global state leakage to subsequent tests.
@coderabbitai
Copy link

coderabbitai bot commented Dec 26, 2025

Walkthrough

Adds a new MCP-managed ScriptableObject workflow: design doc, Unity Editor tool to create/modify ScriptableObject assets, a Python server tool to forward requests, Unity editor tests and fixtures, integration tests, Unity project metadata, and a .gitignore entry for Temp artifacts.

Changes

Cohort / File(s) Summary
Design & Plan
FixscriptableobjecPlan.md
New design/spec describing goals, failure modes, JSON request/response schemas, two Unity-side tools (create_scriptable_object_asset, set_serialized_properties), error codes, implementation notes, and acceptance tests.
Unity Editor Tool
MCPForUnity/Editor/Tools/ManageScriptableObject.cs, MCPForUnity/Editor/Tools/ManageScriptableObject.cs.meta
New static editor tool ManageScriptableObject.HandleCommand(JObject) supporting create/modify, compile/reload detection, path normalization/folder creation, type resolution, asset creation/overwrite semantics, and SerializedObject/SerializedProperty-based patch application (ops: set, array_resize, object refs) with per-patch results/warnings.
Server tool wrapper
Server/src/services/tools/manage_scriptable_object.py
New MCP tool manage_scriptable_object(...) validating/coercing inputs (accepts JSON strings for target/patches), normalizing params, forwarding to Unity via send_with_unity_instance / async_send_command_with_retry, and returning Unity responses or structured errors.
Server tests
Server/tests/integration/test_manage_scriptable_object_tool.py
Integration tests mocking async_send_command_with_retry to assert create/modify payloads forwarded correctly and inputs (overwrite, target, patches) are parsed/coerced as expected.
Unity test fixtures & types
TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/Fixtures/*
.../ManageScriptableObjectTestDefinitionBase.cs, .../ManageScriptableObjectTestDefinition.cs, corresponding .meta files
New ScriptableObject base and derived test types, nested struct, serialized fields, and Unity .meta files for folders/assets used by tests.
Unity editor tests
TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageScriptableObjectTests.cs, ...ManageScriptableObjectTests.cs.meta
New editor test suite covering nested folder creation, patch application, array resizing, object reference assignment by GUID/path, error cases, path normalization, and helpers for folder management/cleanup.
Test harness tweak
TestProjects/UnityMCPTests/Assets/Tests/EditMode/Helpers/CodexConfigHelperTests.cs
TearDown now restores original IPlatformService captured in OneTimeSetUp instead of calling global Reset to avoid terminating active MCP sessions.
Unity project metadata & config
.gitignore, TestProjects/UnityMCPTests/Assets/Packages.meta, TestProjects/UnityMCPTests/Assets/Temp.meta, .../Fixtures.meta, TestProjects/UnityMCPTests/ProjectSettings/SceneTemplateSettings.json
.gitignore entry added to ignore TestProjects/UnityMCPTests/Assets/Temp/; added Unity folder/asset .meta files and scene template settings JSON.
ManageAsset update
MCPForUnity/Editor/Tools/ManageAsset.cs, Server/src/services/tools/manage_asset.py
Removed ScriptableObject creation branch from ManageAsset and updated comments/docstring to recommend manage_scriptable_object for ScriptableObjects; ModifyAsset retains deprecated ScriptableObject handling as fallback.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Server as "Python Server"
    participant Unity as "Unity Editor"
    participant AssetDB as "Unity AssetDB"

    rect `#EAF5FA`
    Note over Client,Server: Create action (new feature)
    Client->>Server: manage_scriptable_object(action="create", type_name, folder_path, asset_name, patches)
    Server->>Server: validate & normalize params\n(parse JSON strings, coerce overwrite)
    Server->>Unity: send_with_unity_instance / async_send_command_with_retry(params)
    Unity->>Unity: check compiling/reloading state\nresolve typeName
    Unity->>AssetDB: ensure folders exist\ncreate or overwrite asset
    Unity->>Unity: apply patches via SerializedObject/SerializedProperty
    Unity-->>Server: {guid, path, typeNameResolved, patchResults, warnings}
    Server-->>Client: forward response
    end

    rect `#F9F0E6`
    Note over Client,Server: Modify action
    Client->>Server: manage_scriptable_object(action="modify", target, patches)
    Server->>Server: validate target & patches
    Server->>Unity: send_with_unity_instance / async_send_command_with_retry(params)
    Unity->>Unity: resolve target (guid or path)
    Unity->>Unity: apply patches (set, array_resize, object refs)
    Unity-->>Server: {targetGuid/Path/Type, results}
    Server-->>Client: forward response
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Suggested labels

codex

Poem

🐇 I hop through Assets, GUIDs in paw,
I build neat folders at the server's law,
I stretch arrays and link refs with cheer,
ScriptableObjects appear, tidy and clear,
Hooray — the rabbit hums, patching near!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.22% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'Fix/scriptableobject tools' is vague and generic, using a pattern that doesn't clearly convey the main change to someone scanning history. Use a more descriptive title such as 'Add ManageScriptableObject tool for reliable ScriptableObject creation and patching' to clearly summarize the primary change.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/scriptableobject-tools

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cc9b9a3 and 553ef26.

📒 Files selected for processing (2)
  • MCPForUnity/Editor/Tools/ManageAsset.cs
  • MCPForUnity/Editor/Tools/ManageScriptableObject.cs
🚧 Files skipped from review as they are similar to previous changes (2)
  • MCPForUnity/Editor/Tools/ManageScriptableObject.cs
  • MCPForUnity/Editor/Tools/ManageAsset.cs

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.

@greptile-apps
Copy link

greptile-apps bot commented Dec 27, 2025

Greptile Summary

This PR introduces a robust, unified ScriptableObject management tool that replaces previous implementations with a SerializedObject/SerializedProperty-based approach, fixing placement issues and enabling reliable patching of private fields, inherited fields, arrays, and object references.

Key improvements:

  • Unified tool interface: Single manage_scriptable_object tool handles both create and modify operations with consistent patching behavior
  • Reliable path handling: Comprehensive validation rejects invalid roots (Packages/, absolute paths, file:// URIs), normalizes backslashes and relative paths, and creates nested folders recursively
  • SerializedProperty-based patching: Replaces reflection with Unity's native serialization system, supporting private [SerializeField] fields, inherited fields, nested structs, and arrays/lists
  • Transient state handling: Returns retryable error code during compilation/domain reload instead of failing
  • Object reference assignment: Supports both GUID and path-based assignment with proper resolution
  • Array handling: Immediate apply after resize operations ensures subsequent element assignments work correctly
  • Comprehensive test coverage: 156 EditMode tests pass, covering all major scenarios from the design doc (nested folders, private fields, inheritance, object refs by GUID/path, array resize, path normalization, and invalid path rejection)
  • Repository hygiene: Fixed test teardown to avoid dropping MCP bridge during test execution, added .gitignore entry for test artifacts

Confidence Score: 5/5

  • This PR is safe to merge with high confidence
  • The implementation is production-ready with excellent engineering practices: comprehensive test coverage (156/156 tests passing), well-structured error handling with typed error codes, defensive path validation that rejects invalid inputs, proper use of Unity's SerializedObject API, and immediate application of array resizes to prevent downstream failures. The code follows the design document specifications precisely, includes both unit and integration tests, and fixes an unrelated test teardown issue that could have caused flakiness.
  • No files require special attention

Important Files Changed

Filename Overview
MCPForUnity/Editor/Tools/ManageScriptableObject.cs New unified ScriptableObject tool using SerializedObject/SerializedProperty with comprehensive path validation and error handling
Server/src/services/tools/manage_scriptable_object.py Python wrapper exposing unified SO tool to MCP with JSON payload coercion
TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageScriptableObjectTests.cs Comprehensive test coverage for nested folders, private fields, inheritance, arrays, object refs, and path validation
TestProjects/UnityMCPTests/Assets/Tests/EditMode/Helpers/CodexConfigHelperTests.cs Fixed test teardown to avoid killing MCP bridge during test execution
.gitignore Added Assets/Temp/ to prevent test artifacts from being committed

Sequence Diagram

sequenceDiagram
    participant MCP as MCP Client
    participant Server as Python Server
    participant Unity as Unity Editor
    participant SO as SerializedObject
    participant AssetDB as AssetDatabase

    Note over MCP,AssetDB: Create ScriptableObject Flow

    MCP->>Server: manage_scriptable_object(action="create", type_name, folder_path, asset_name, patches)
    Server->>Server: parse_json_payload(target, patches)
    Server->>Server: coerce_bool(overwrite)
    Server->>Unity: send_command("manage_scriptable_object", params)
    
    Unity->>Unity: Check EditorApplication.isCompiling/isUpdating
    alt Unity is compiling/reloading
        Unity-->>Server: ErrorResponse("compiling_or_reloading")
        Server-->>MCP: {success: false, hint: "retry"}
    end

    Unity->>Unity: TryNormalizeFolderPath(folderPath)
    Note over Unity: Validate/reject Packages/, absolute, file:// paths<br/>Normalize backslashes, root under Assets/
    Unity->>Unity: EnsureFolderExists(normalizedFolder)
    Unity->>AssetDB: CreateFolder (recursively if needed)
    
    Unity->>Unity: ResolveType(typeName)
    Unity->>Unity: ScriptableObject.CreateInstance(resolvedType)
    Unity->>AssetDB: CreateAsset(instance, finalPath)
    Unity->>AssetDB: ImportAsset(finalPath)
    
    alt patches provided
        Unity->>SO: new SerializedObject(instance)
        loop for each patch
            Unity->>SO: FindProperty(propertyPath)
            alt array_resize op
                Unity->>SO: set arraySize or intValue
                Unity->>SO: ApplyModifiedProperties()
                Note over Unity,SO: Immediate apply for array resize
            else set op
                alt ObjectReference type
                    Unity->>AssetDB: GUIDToAssetPath or SanitizeAssetPath
                    Unity->>AssetDB: LoadAssetAtPath
                    Unity->>SO: set objectReferenceValue
                else primitive/enum
                    Unity->>SO: set intValue/stringValue/boolValue/enumValueIndex
                end
            end
        end
        Unity->>SO: ApplyModifiedProperties()
    end

    Unity->>AssetDB: SetDirty(instance)
    Unity->>AssetDB: SaveAssets()
    Unity->>AssetDB: AssetPathToGUID(finalPath)
    
    Unity-->>Server: SuccessResponse(guid, path, patchResults)
    Server-->>MCP: {success: true, data: {guid, path, ...}}

    Note over MCP,AssetDB: Modify ScriptableObject Flow

    MCP->>Server: manage_scriptable_object(action="modify", target={guid|path}, patches)
    Server->>Unity: send_command("manage_scriptable_object", params)
    
    Unity->>Unity: TryResolveTarget(target)
    alt by GUID
        Unity->>AssetDB: GUIDToAssetPath(guid)
    else by path
        Unity->>Unity: SanitizeAssetPath(path)
    end
    Unity->>AssetDB: LoadAssetAtPath(resolvedPath)
    
    Unity->>SO: new SerializedObject(target)
    Unity->>SO: Update()
    loop for each patch
        Unity->>SO: FindProperty(propertyPath)
        Unity->>Unity: ApplyPatch (same as create flow)
    end
    Unity->>SO: ApplyModifiedProperties()
    Unity->>AssetDB: SetDirty(target)
    Unity->>AssetDB: SaveAssets()
    
    Unity-->>Server: SuccessResponse(targetGuid, targetPath, results)
    Server-->>MCP: {success: true, data: {...}}
Loading

@greptile-apps
Copy link

greptile-apps bot commented Dec 27, 2025

Greptile's behavior is changing!

From now on, if a review finishes with no comments, we will not post an additional "statistics" comment to confirm that our review found nothing to comment on. However, you can confirm that we reviewed your changes in the status check section.

This feature can be toggled off in your Code Review Settings by deselecting "Create a status check for each PR".

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
MCPForUnity/Editor/Tools/ManageScriptableObject.cs (1)

289-363: Consider clarifying array resize fallback logic (optional).

The implementation correctly handles Unity's dual representation of array size (.Array.size synthetic property vs. arraySize on the array property itself). The fallback logic at lines 305-315 works but is complex.

The current implementation passes all tests and handles the edge cases Unity's serialization system presents. If you want to improve clarity, consider adding more inline comments explaining each fallback branch.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8e3bd1d and a117c64.

📒 Files selected for processing (17)
  • .gitignore
  • FixscriptableobjecPlan.md
  • MCPForUnity/Editor/Tools/ManageScriptableObject.cs
  • MCPForUnity/Editor/Tools/ManageScriptableObject.cs.meta
  • Server/src/services/tools/manage_scriptable_object.py
  • Server/tests/integration/test_manage_scriptable_object_tool.py
  • TestProjects/UnityMCPTests/Assets/Packages.meta
  • TestProjects/UnityMCPTests/Assets/Temp.meta
  • TestProjects/UnityMCPTests/Assets/Tests/EditMode/Helpers/CodexConfigHelperTests.cs
  • TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/Fixtures.meta
  • TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/Fixtures/ManageScriptableObjectTestDefinition.cs
  • TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/Fixtures/ManageScriptableObjectTestDefinition.cs.meta
  • TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/Fixtures/ManageScriptableObjectTestDefinitionBase.cs
  • TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/Fixtures/ManageScriptableObjectTestDefinitionBase.cs.meta
  • TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageScriptableObjectTests.cs
  • TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageScriptableObjectTests.cs.meta
  • TestProjects/UnityMCPTests/ProjectSettings/SceneTemplateSettings.json
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-09-04T00:02:45.818Z
Learnt from: dsarno
Repo: dsarno/unity-mcp PR: 60
File: TestProjects/UnityMCPTests/Assets/Scripts/TestAsmdef/TestAsmdef.asmdef.meta:1-7
Timestamp: 2025-09-04T00:02:45.818Z
Learning: Unity assembly definition (.asmdef) files use name-based references by default, not GUID references. When an .asmdef file references another assembly, it uses the target assembly's name (from the "name" field) in the "references" array, and Unity automatically resolves this to the appropriate GUID at build time. Direct GUID references are not required for standard Unity assembly references.

Applied to files:

  • TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/Fixtures/ManageScriptableObjectTestDefinitionBase.cs.meta
📚 Learning: 2025-09-04T00:02:45.818Z
Learnt from: dsarno
Repo: dsarno/unity-mcp PR: 60
File: TestProjects/UnityMCPTests/Assets/Scripts/TestAsmdef/TestAsmdef.asmdef.meta:1-7
Timestamp: 2025-09-04T00:02:45.818Z
Learning: Unity assembly definition (.asmdef) files use name-based references by default, not GUID references. When an .asmdef file references another assembly, it uses the target assembly's name (from the "name" field) in the "references" array, and Unity automatically resolves this to the appropriate GUID at build time. Direct GUID references are not required for standard Unity assembly references. Name-based references are the standard and recommended approach.

Applied to files:

  • TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/Fixtures/ManageScriptableObjectTestDefinitionBase.cs.meta
🧬 Code graph analysis (4)
Server/tests/integration/test_manage_scriptable_object_tool.py (2)
Server/tests/integration/test_helpers.py (2)
  • DummyContext (16-55)
  • set_state (49-51)
Server/src/services/tools/manage_scriptable_object.py (1)
  • manage_scriptable_object (27-72)
TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/Fixtures/ManageScriptableObjectTestDefinition.cs (2)
TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/Fixtures/ManageScriptableObjectTestDefinitionBase.cs (1)
  • ManageScriptableObjectTestDefinitionBase (6-10)
MCPForUnity/Editor/Tools/ManageScriptableObject.cs (1)
  • List (213-265)
MCPForUnity/Editor/Tools/ManageScriptableObject.cs (2)
MCPForUnity/Editor/Tools/JsonUtil.cs (2)
  • JsonUtil (6-29)
  • CoerceJsonStringParameter (12-28)
MCPForUnity/Editor/Helpers/AssetPathUtility.cs (2)
  • AssetPathUtility (15-201)
  • SanitizeAssetPath (20-34)
TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageScriptableObjectTests.cs (2)
MCPForUnity/Editor/Tools/ManageAsset.cs (2)
  • CreateAsset (163-302)
  • CreateFolder (304-357)
MCPForUnity/Editor/Helpers/AssetPathUtility.cs (2)
  • AssetPathUtility (15-201)
  • SanitizeAssetPath (20-34)
🪛 Ruff (0.14.10)
Server/tests/integration/test_manage_scriptable_object_tool.py

10-10: Unused function argument: kwargs

(ARG001)


46-46: Unused function argument: kwargs

(ARG001)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Greptile Review
🔇 Additional comments (30)
TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/Fixtures.meta (1)

1-8: LGTM! Standard Unity folder metadata.

This is a properly formatted Unity .meta file for the Fixtures folder. Unity automatically generates these files to track folder assets in the project, and the format follows Unity's standard conventions with appropriate default values.

TestProjects/UnityMCPTests/Assets/Tests/EditMode/Helpers/CodexConfigHelperTests.cs (2)

35-35: LGTM! Clean capture of original state.

Capturing the original platform service in OneTimeSetUp ensures that the pre-fixture state is preserved and can be restored after each test, preventing state leakage to other test fixtures.

Also applies to: 44-44


59-68: LGTM! Proper test isolation without disrupting active MCP sessions.

The new approach correctly addresses the issue where MCPServiceLocator.Reset() would terminate active MCP connections during test execution. By restoring only the mutated platform service, the tests remain properly isolated while preserving any active MCP bridge.

The null check is appropriately defensive, and the detailed comment clearly explains the rationale.

.gitignore (1)

37-38: LGTM. Clear comment explaining why temporary artifacts should be ignored, and the rule is appropriately scoped to the test project.

TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageScriptableObjectTests.cs.meta (1)

1-11: LGTM. Standard Unity MonoImporter metadata for the test script.

TestProjects/UnityMCPTests/Assets/Packages.meta (1)

1-8: LGTM. Standard Unity folder metadata.

TestProjects/UnityMCPTests/Assets/Temp.meta (1)

1-8: LGTM. Standard folder metadata; aligns with the .gitignore rule for this artifact location.

TestProjects/UnityMCPTests/ProjectSettings/SceneTemplateSettings.json (1)

1-121: LGTM. Valid JSON configuration with expected structure for Unity scene template settings. The 23 dependency types provide comprehensive coverage for common asset types.

TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/Fixtures/ManageScriptableObjectTestDefinition.cs.meta (1)

1-11: LGTM. Standard Unity MonoImporter metadata for the test fixture.

TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/Fixtures/ManageScriptableObjectTestDefinitionBase.cs.meta (1)

1-11: LGTM. Standard Unity MonoImporter metadata for the test base class.

MCPForUnity/Editor/Tools/ManageScriptableObject.cs.meta (1)

1-14: LGTM. Standard Unity MonoImporter metadata for the editor tool.

TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/Fixtures/ManageScriptableObjectTestDefinitionBase.cs (1)

1-14: LGTM! Clean test fixture design.

The base fixture follows Unity best practices with a private [SerializeField] field exposed via a read-only property. The comment about file naming is helpful for maintainability.

Server/tests/integration/test_manage_scriptable_object_tool.py (3)

7-41: LGTM! Comprehensive create parameter forwarding test.

The test thoroughly validates that create parameters are correctly parsed and forwarded, including boolean coercion for overwrite and JSON string parsing for patches.


43-70: LGTM! Good coverage of modify parameter forwarding.

The test validates that modify parameters (target as JSON string, patches as list) are correctly parsed and forwarded. The target JSON string parsing is particularly important for LLM-generated payloads.


10-10: Static analysis false positive on unused kwargs.

The kwargs parameter is required to match the signature of the mocked async_send_command_with_retry function. This is a false positive from Ruff.

Also applies to: 46-46

TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/Fixtures/ManageScriptableObjectTestDefinition.cs (1)

1-27: LGTM! Well-structured test fixture.

The fixture design effectively tests the tool's capabilities:

  • Nested struct (ManageScriptableObjectNestedData) for testing nested property paths
  • List for testing array resize and object reference assignment
  • Private serialized fields exposed via read-only properties

The use of modern C# collection initialization (new()) is appropriate.

MCPForUnity/Editor/Tools/ManageScriptableObject.cs (6)

42-77: LGTM! Robust entry point with good error handling.

The implementation handles several important cases:

  • Returns retryable error during compilation/reload (lines 49-53)
  • Tolerates JSON-string parameters for LLM compatibility (lines 56-57)
  • Validates action with clear error messages and lists valid actions

The structured error responses with error codes facilitate client-side retry logic.


79-178: LGTM! Comprehensive create workflow.

The create handler is thorough:

  • Validates all required parameters with clear error messages
  • Normalizes and validates folder paths (lines 101-109)
  • Ensures folders exist with recursive creation (line 106)
  • Resolves type and validates ScriptableObject inheritance (lines 111-115)
  • Handles overwrite semantics correctly (lines 123-126)
  • Applies patches after creation (lines 157-162)
  • Properly persists changes (lines 164-165)

Exception handling during CreateInstance and CreateAsset provides clear diagnostics.


180-265: LGTM! Well-designed patch application.

Key strengths:

  • Target resolution supports both GUID and path (line 182)
  • Validates patches parameter type (lines 188-196)
  • Processes patches in order with per-patch error handling (lines 222-248)
  • Critically important: array_resize changes are applied immediately (lines 250-254) so subsequent patches can resolve newly created array elements
  • Batches remaining changes for efficiency (lines 257-262)

The per-patch result tracking ensures clients can identify which specific patches succeeded or failed.


365-478: LGTM! Robust type-safe property setting.

The implementation handles Unity's SerializedProperty system correctly:

  • Object references support GUID, path, and explicit null (lines 374-404)
  • Type-safe setters for each SerializedPropertyType (lines 417-446)
  • Enum handling accepts both integer index and case-insensitive string name (lines 455-478)
  • Helper methods (TryGetInt/Float/Bool) handle type coercion and parsing

The error messages are descriptive and aid debugging.


606-653: LGTM! Excellent path validation and normalization.

The path normalization includes important security and correctness checks:

  • Rejects absolute paths and file:// URIs (lines 624-628)
  • Rejects non-Assets roots like Packages/, ProjectSettings/, Library/ (lines 630-636)
  • Normalizes backslashes and removes double slashes (lines 617-621)
  • Automatically roots relative paths under Assets/ (line 651)

This prevents directory traversal and ensures all created assets are in safe, expected locations.


707-746: LGTM! Comprehensive type resolution with robust fallbacks.

The type resolution strategy is thorough:

  • Tries Type.GetType first (fast path, line 711)
  • Scans assemblies with asm.GetType (line 714-725)
  • Falls back to scanning all types by FullName (lines 728-743)
  • Handles ReflectionTypeLoadException gracefully (line 732)

This ensures types can be found even in edge cases where standard lookup fails, which is important for Unity's dynamic assembly landscape.

FixscriptableobjecPlan.md (1)

1-206: Documentation provides excellent design context.

This design document clearly outlines the tool's requirements, error codes, patch language, and acceptance criteria. It serves as useful reference material for understanding the implementation decisions in ManageScriptableObject.cs.

Server/src/services/tools/manage_scriptable_object.py (1)

1-75: LGTM! Clean server-side wrapper with good validation.

The wrapper implementation is solid:

  • Tolerates JSON-string payloads for complex objects (lines 42-44) - important for LLM compatibility
  • Validates payload shapes with clear error messages (lines 46-50)
  • Coerces overwrite to boolean (line 57)
  • Removes None values to simplify Unity-side handling (line 63)
  • Provides detailed type annotations with Annotated for tool documentation

The error handling ensures malformed requests are caught before reaching Unity.

TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageScriptableObjectTests.cs (6)

22-84: LGTM! Well-designed test lifecycle.

The SetUp and TearDown ensure test isolation:

  • Starts from clean slate (deletes TempRoot if it exists, lines 27-30)
  • Creates test material assets with unique names (lines 37-47)
  • TearDown performs best-effort cleanup (lines 50-84)
  • Cleans up empty parent Temp folder (lines 73-81)

The use of unique GUIDs in material names prevents test interference.


86-124: LGTM! Comprehensive create + patch test.

This test validates the core create workflow:

  • Creates nested folders that don't exist (line 114)
  • Places asset correctly under the target folder (line 115)
  • Applies patches to private serialized field displayName (line 121)
  • Applies patches to inherited field baseNumber (line 122)
  • Applies patches to nested struct field nested.note (line 123)

The test covers the acceptance criteria from the design document.


126-189: LGTM! Thorough test of array and reference handling.

This test validates complex patching scenarios:

  • Resizes array using .Array.size path (line 152)
  • Assigns object reference by GUID (lines 154-159)
  • Assigns object reference by path (lines 161-166)
  • Verifies per-patch results (lines 174-179)
  • Verifies final persisted state (lines 181-188)

The combination of resize + reference assignment exercises the immediate-apply logic for array resizing.


191-219: LGTM! Good error case coverage.

The test validates error handling for:

  • Invalid action → invalid_params error code
  • Type not found → type_not_found error code
  • Target not found → target_not_found error code

The structured error codes enable client-side retry and error handling logic.


221-256: LGTM! Critical security validation tests.

These tests ensure path validation prevents unauthorized file system access:

  • Rejects Packages/ root (lines 224-233)
  • Rejects absolute paths like /tmp/ (lines 235-244)
  • Rejects file:// URIs (lines 246-255)

All cases correctly return invalid_folder_path error code.


258-278: LGTM! Path normalization verification.

This test validates that:

  • Backslashes are converted to forward slashes
  • Relative paths are rooted under Assets/
  • Double slashes are removed (line 277)
  • Final path is correct (lines 275-276)

The test input deliberately includes multiple path issues to verify robust normalization.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (4)
MCPForUnity/Editor/Tools/ManageScriptableObject.cs (4)

30-40: Consider simplifying ValidActions set.

Since NormalizeAction (line 704) removes underscores/hyphens and the set uses OrdinalIgnoreCase, many entries are redundant. The set could be reduced to just the normalized forms: ["create", "createso", "modify", "modifyso"].

🔎 Proposed simplification
 private static readonly HashSet<string> ValidActions = new(StringComparer.OrdinalIgnoreCase)
 {
     "create",
-    "createso",
-    "create_so",
-    "createSO",
+    "createso",
     "modify",
-    "modifyso",
-    "modify_so",
-    "modifySO",
+    "modifyso"
 };

157-165: Consider conditional SaveAssets call.

AssetDatabase.SaveAssets() is called unconditionally, even when no patches are applied. While this ensures the new asset is persisted, it might be unnecessary since CreateAsset + ImportAsset typically handle persistence. Consider making the save conditional on patchesToken != null.

🔎 Proposed optimization
 if (patchesToken is JArray patches && patches.Count > 0)
 {
     var patchApply = ApplyPatches(instance, patches);
     patchResults = patchApply.results;
     warnings.AddRange(patchApply.warnings);
+    // ApplyPatches already calls SaveAssets if changes were made
+}
+else
+{
+    // Ensure new asset is saved even without patches
+    EditorUtility.SetDirty(instance);
+    AssetDatabase.SaveAssets();
 }
-
-EditorUtility.SetDirty(instance);
-AssetDatabase.SaveAssets();

426-462: Consider supporting additional SerializedPropertyType values.

TrySetValue currently supports Integer, Boolean, Float, String, and Enum, but common Unity types like Vector2/3/4, Color, Rect, Bounds, etc. are unsupported. This limits patching capabilities for many ScriptableObject fields.

Example: Adding Vector3 support
 case SerializedPropertyType.String:
     prop.stringValue = valueToken.Type == JTokenType.Null ? null : valueToken.ToString();
     message = "Set string."; return true;

+case SerializedPropertyType.Vector3:
+    if (valueToken is not JObject vec || 
+        !TryGetFloat(vec["x"], out float x) ||
+        !TryGetFloat(vec["y"], out float y) ||
+        !TryGetFloat(vec["z"], out float z))
+    {
+        message = "Expected object with x, y, z float fields."; return false;
+    }
+    prop.vector3Value = new Vector3(x, y, z);
+    message = "Set Vector3."; return true;
+
 case SerializedPropertyType.Enum:
     return TrySetEnum(prop, valueToken, out message);

Similar patterns can be added for Vector2, Vector4, Color, etc.


554-662: Consider extracting common path sanitization logic.

Both EnsureFolderExists (lines 564-568) and TryNormalizeFolderPath (lines 626-630) duplicate the slash normalization logic. Extracting to a helper method would improve maintainability.

🔎 Proposed helper method
+private static string SanitizeSlashes(string path)
+{
+    if (string.IsNullOrWhiteSpace(path)) return path;
+    var s = path.Replace('\\', '/');
+    while (s.IndexOf("//", StringComparison.Ordinal) >= 0)
+    {
+        s = s.Replace("//", "/", StringComparison.Ordinal);
+    }
+    return s;
+}
+
 private static bool EnsureFolderExists(string folderPath, out string error)
 {
     error = null;
     // ...
-    string sanitized = folderPath.Replace('\\', '/');
-    while (sanitized.IndexOf("//", StringComparison.Ordinal) >= 0)
-    {
-        sanitized = sanitized.Replace("//", "/", StringComparison.Ordinal);
-    }
+    string sanitized = SanitizeSlashes(folderPath);
     // ...
 }
 
 private static bool TryNormalizeFolderPath(string folderPath, out string normalized, out string error)
 {
     // ...
-    var s = folderPath.Trim().Replace('\\', '/');
-    while (s.IndexOf("//", StringComparison.Ordinal) >= 0)
-    {
-        s = s.Replace("//", "/", StringComparison.Ordinal);
-    }
+    var s = SanitizeSlashes(folderPath.Trim());
     // ...
 }
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a117c64 and c8907ac.

📒 Files selected for processing (1)
  • MCPForUnity/Editor/Tools/ManageScriptableObject.cs
🔇 Additional comments (10)
MCPForUnity/Editor/Tools/ManageScriptableObject.cs (10)

20-21: LGTM: Manual registration is appropriate for MCP server integration.

The AutoRegister = false attribute correctly indicates that this tool is registered manually via the Python server wrapper rather than through automatic discovery.


42-77: LGTM: Robust entry point with proper validation.

The compilation state check, JSON coercion, action validation, and dispatch logic are all well-implemented. The retryable error code for transient Unity states is particularly good for MCP client resilience.


123-126: Verify overwrite behavior is acceptable for your use case.

The asset deletion when overwrite=true is destructive and irreversible. Ensure that:

  1. Callers understand this behavior
  2. There are no references to the old asset that would be broken
  3. Version control or other backup mechanisms are in place if needed

180-211: LGTM: Clean modify implementation.

The target resolution, patch validation, and application logic are well-structured with appropriate error handling.


213-265: LGTM: Well-designed patching with proper array resize handling.

The immediate ApplyModifiedProperties after array resize (lines 249-254) is critical for ensuring subsequent patches can reference the resized array elements. The change tracking and conditional save logic are also excellent.


289-372: LGTM: Robust array resize with necessary fallback logic.

The multiple fallback strategies (lines 307-372) correctly handle Unity's serialization quirks across versions. The detailed comments explain the rationale, and the implementation covers all edge cases including synthetic ".Array.size" properties and direct array properties.


464-487: LGTM: Flexible enum handling.

Supporting both integer indices and string names with case-insensitive matching makes the API user-friendly and robust.


489-532: LGTM: Comprehensive target resolution.

The dual GUID/path resolution with proper validation and error messages is well-implemented.


716-755: LGTM: Comprehensive type resolution with appropriate fallbacks.

The multi-stage approach (Type.GetType → Assembly.GetType → FullName scan) is necessary for Unity's assembly structure. While the fallback scan (lines 737-752) is expensive, it's acceptable since type resolution happens infrequently and ensures comprehensive coverage.


534-552: LGTM: Robust helper methods.

The JSON coercion with fallback warnings (lines 534-552) and the flexible Try* methods supporting multiple token types (lines 664-702) make the API resilient to various input formats.

Also applies to: 664-714

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
MCPForUnity/Editor/Tools/ManageScriptableObject.cs (2)

287-370: Consider documenting tested Unity versions for array resize logic.

The array resize implementation includes sophisticated fallback logic to handle Unity version differences in how array properties are represented (direct arraySize vs synthetic .Array.size property). While well-commented, this complexity could be fragile across Unity versions.

Consider adding a comment documenting which Unity versions have been tested with this implementation, to help future maintainers understand the support matrix.


721-760: Type resolution is comprehensive but potentially slow.

The type resolution includes three fallback strategies, with the final fallback (lines 742-757) iterating through all types in all assemblies. For large projects with many assemblies, this could be slow.

Consider caching resolved types if repeated lookups are expected, or log a performance warning when falling back to the full type scan. However, for single create operations, the current approach is acceptable.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c8907ac and 14ff22a.

📒 Files selected for processing (1)
  • MCPForUnity/Editor/Tools/ManageScriptableObject.cs
🔇 Additional comments (5)
MCPForUnity/Editor/Tools/ManageScriptableObject.cs (5)

40-75: LGTM! Well-structured entry point with proper validation.

The entry point correctly handles Unity's transient compilation state with a retry hint, validates parameters, and dispatches to the appropriate handler. The dual JSON coercion approach (object vs array) is appropriate for the different parameter types.


178-209: LGTM! Clean modification workflow with good error handling.

The method properly resolves the target asset, validates the patches parameter, and returns detailed results including per-patch outcomes and warnings.


248-252: Good design: immediate application for array resizing.

Applying array resize changes immediately via ApplyModifiedProperties() ensures that subsequent patches referencing array elements (e.g., items.Array.data[0]) will resolve correctly. This is essential for reliable patch ordering.


624-667: Excellent path validation and security boundaries.

The folder path normalization properly rejects non-Assets paths (Packages/, absolute paths, file:// URLs, etc.) and consistently roots relative paths under Assets/. This prevents accidental or malicious writes outside the project's asset directory.


381-411: ObjectReference resolution is well-designed.

The implementation supports both GUID and path resolution for object references, with proper null handling. The use of AssetPathUtility.SanitizeAssetPath for path-based resolution is consistent with the target resolution logic (line 511), ensuring uniform path handling throughout the tool.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
MCPForUnity/Editor/Tools/ManageScriptableObject.cs (2)

234-286: Consider disposing SerializedObject explicitly.

While Unity's garbage collector typically handles SerializedObject cleanup, explicit disposal via using statement is a best practice to ensure timely resource release.

🔎 Proposed refactor to dispose SerializedObject
-var so = new SerializedObject(target);
-so.Update();
+using (var so = new SerializedObject(target))
+{
+    so.Update();

-for (int i = 0; i < patches.Count; i++)
-{
+    for (int i = 0; i < patches.Count; i++)
+    {
     // ... existing patch logic ...
-}
+    }

-if (anyChanged)
-{
-    so.ApplyModifiedProperties();
-    EditorUtility.SetDirty(target);
-    AssetDatabase.SaveAssets();
-}
+    if (anyChanged)
+    {
+        so.ApplyModifiedProperties();
+        EditorUtility.SetDirty(target);
+        AssetDatabase.SaveAssets();
+    }

-return (results, warnings);
+    return (results, warnings);
+}

447-500: Document ObjectReference support in the comment.

The comment on line 452 lists supported types but omits ObjectReference, which is actually supported (handled separately in ApplySet lines 404-434). Including it would improve clarity.

🔎 Proposed documentation update
-// Supported Types: Integer, Boolean, Float, String, Enum, Vector2, Vector3, Vector4, Color
+// Supported Types: Integer, Boolean, Float, String, Enum, ObjectReference, Vector2, Vector3, Vector4, Color
+// Note: ObjectReference is handled separately in ApplySet before calling TrySetValue
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 14ff22a and 6b76817.

📒 Files selected for processing (1)
  • MCPForUnity/Editor/Tools/ManageScriptableObject.cs
🧰 Additional context used
🧬 Code graph analysis (1)
MCPForUnity/Editor/Tools/ManageScriptableObject.cs (2)
MCPForUnity/Editor/Tools/JsonUtil.cs (2)
  • JsonUtil (6-29)
  • CoerceJsonStringParameter (12-28)
MCPForUnity/Editor/Helpers/AssetPathUtility.cs (2)
  • AssetPathUtility (15-201)
  • SanitizeAssetPath (20-34)
🔇 Additional comments (5)
MCPForUnity/Editor/Tools/ManageScriptableObject.cs (5)

135-171: Past issues successfully resolved.

The GUID-preserving overwrite logic has been properly implemented using EditorUtility.CopySerialized when the existing asset type matches, addressing the previous concern about breaking references. The fallback to delete-and-recreate for type mismatches is appropriate.


40-75: LGTM: Well-structured entry point.

The parameter validation, JSON string coercion, and retryable error handling for transient Unity states (compiling_or_reloading) are well-designed for reliable MCP integration.


77-199: LGTM: Robust asset creation with proper validation.

The parameter validation, folder normalization, type resolution, GUID-preserving overwrite, and optional patch application are well-coordinated. Error handling covers all failure paths.


664-707: LGTM: Secure path validation.

The folder path normalization properly rejects non-project paths (absolute paths, file: URIs, Packages/, etc.) and roots relative paths under Assets/ as documented in the PR objectives. This prevents path traversal and ensures assets are created in valid locations.


879-918: LGTM: Comprehensive type resolution.

The multi-stage type resolution (direct Type.GetType, assembly scan, and fallback to FullName matching with ReflectionTypeLoadException handling) is thorough and appropriate for editor tools where performance is less critical than reliability.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
MCPForUnity/Editor/Tools/ManageScriptableObject.cs (1)

760-874: Inconsistent validation: object parsing accepts partial values, array parsing doesn't.

The Vector2/3/4 and Color parsing helpers treat array and object inputs inconsistently:

  • Array syntax (e.g., [1, 2]) requires all components to be present and valid.
  • Object syntax (e.g., {"x": 1}) accepts partial objects, filling missing components with zero (or 1 for alpha).

This inconsistency could lead to silent errors when users provide incomplete objects expecting validation to fail.

Specific examples:

  • Line 780: TryGetVector2 accepts {"x": 1}Vector2(1, 0)
  • Lines 806-811: TryGetVector3 accepts {}Vector3(0, 0, 0) (always returns true)
  • Lines 834-840: TryGetVector4 accepts {}Vector4(0, 0, 0, 0) (always returns true)
  • Lines 866-871: TryGetColor accepts {}Color(0, 0, 0, 1) (always returns true)

Consider requiring all required components when parsing objects for clarity and consistency with array parsing.

🔎 Proposed fix to require all components
 // TryGetVector2 object parsing
 if (token is JObject obj)
 {
     float x = 0, y = 0;
     bool hasX = TryGetFloat(obj["x"], out x);
     bool hasY = TryGetFloat(obj["y"], out y);
-    if (hasX || hasY) // partial okay? usually stricter is better, but allow flexible
+    if (hasX && hasY) // require both x and y
     {
         value = new Vector2(x, y);
         return true;
     }
 }

Apply similar strictness to TryGetVector3 (require x, y, z), TryGetVector4 (require x, y, z, w), and TryGetColor (require r, g, b; allow optional a with default 1).

For Vector3:

 if (token is JObject obj)
 {
     float x = 0, y = 0, z = 0;
-    TryGetFloat(obj["x"], out x);
-    TryGetFloat(obj["y"], out y);
-    TryGetFloat(obj["z"], out z);
-    value = new Vector3(x, y, z);
-    return true;
+    bool hasX = TryGetFloat(obj["x"], out x);
+    bool hasY = TryGetFloat(obj["y"], out y);
+    bool hasZ = TryGetFloat(obj["z"], out z);
+    if (hasX && hasY && hasZ)
+    {
+        value = new Vector3(x, y, z);
+        return true;
+    }
 }
+return false;

Apply analogous changes to TryGetVector4 and TryGetColor.

🧹 Nitpick comments (1)
MCPForUnity/Editor/Tools/ManageScriptableObject.cs (1)

175-175: Clarify why AssetDatabase.ImportAsset is commented out.

The commented AssetDatabase.ImportAsset(finalPath) call may be intentional (since SaveAssets() is called later at line 195), but this should be documented to prevent confusion.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 39c73cb and 64a3bc6.

📒 Files selected for processing (1)
  • MCPForUnity/Editor/Tools/ManageScriptableObject.cs

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
MCPForUnity/Editor/Tools/ManageScriptableObject.cs (1)

676-719: Consider Windows absolute path detection.

The folder path normalization rejects Unix-style absolute paths (/...) and URI schemes (file:...), but doesn't explicitly check for Windows drive letters (e.g., C:/..., D:\...). While Unity paths should always be project-relative, adding a check like Regex.IsMatch(s, @"^[A-Za-z]:[/\\]") would be more defensive.

🔎 Proposed enhancement
 var s = SanitizeSlashes(folderPath.Trim());
 
 // Reject obvious non-project/invalid roots. We only support Assets/ (and relative paths that will be rooted under Assets/).
-if (s.StartsWith("/", StringComparison.Ordinal) || s.StartsWith("file:", StringComparison.OrdinalIgnoreCase))
+if (s.StartsWith("/", StringComparison.Ordinal) 
+    || s.StartsWith("file:", StringComparison.OrdinalIgnoreCase)
+    || System.Text.RegularExpressions.Regex.IsMatch(s, @"^[A-Za-z]:[/\\]"))
 {
     error = "Folder path must be a project-relative path under Assets/.";
     return false;
 }
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 64a3bc6 and cc9b9a3.

📒 Files selected for processing (3)
  • MCPForUnity/Editor/Tools/ManageAsset.cs
  • MCPForUnity/Editor/Tools/ManageScriptableObject.cs
  • Server/src/services/tools/manage_asset.py
🧰 Additional context used
🧬 Code graph analysis (1)
MCPForUnity/Editor/Tools/ManageScriptableObject.cs (1)
MCPForUnity/Editor/Helpers/AssetPathUtility.cs (2)
  • AssetPathUtility (15-201)
  • SanitizeAssetPath (20-34)
🔇 Additional comments (7)
Server/src/services/tools/manage_asset.py (1)

25-25: LGTM! Clear documentation update.

The docstring update appropriately directs users to the new dedicated manage_scriptable_object tool for ScriptableObject workflows, aligning with the broader refactoring described in the PR objectives.

MCPForUnity/Editor/Tools/ManageScriptableObject.cs (4)

100-103: Good validation for path separators.

The assetName validation correctly rejects path separators, addressing the concern from past reviews. This prevents unexpected nested paths or failures during asset creation.


141-178: Excellent GUID-preserving overwrite implementation.

The code correctly uses EditorUtility.CopySerialized to preserve the asset GUID during overwrite, preventing broken references. The explicit name restoration at line 156 fixes the "Main Object Name does not match filename" warning. Well done addressing the past review concern.


464-505: Comprehensive SerializedPropertyType coverage.

The implementation now supports Integer, Boolean, Float, String, Enum, Vector2, Vector3, Vector4, and Color types, with clear comments documenting supported types. This addresses the past review concern about limited type support and provides a solid foundation for common use cases.


763-787: Strict Vector2 parsing implemented.

The object parsing now requires both x and y components (line 780 uses &&), providing consistent validation with the array parsing. This addresses the past review concern about overly permissive partial object parsing.

MCPForUnity/Editor/Tools/ManageAsset.cs (2)

423-429: Clear deprecation guidance for ScriptableObject modification.

The deprecation comments appropriately direct users to the new manage_scriptable_object tool while maintaining backward compatibility for simple property setting. This provides a smooth migration path.


356-412: Well-structured GameObject component modification flow.

The new component modification logic properly uses ComponentResolver for type resolution, iterates through component properties, applies nested properties via ApplyObjectProperties, and logs helpful warnings for unresolved or missing components. The modified flag tracking ensures assets are only saved when changes occur.

@dsarno dsarno merged commit f70c703 into main Dec 27, 2025
2 checks passed
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.

2 participants