Skip to content

Pro builder#870

Merged
Scriptwonder merged 9 commits intoCoplayDev:betafrom
Scriptwonder:ProBuilder
Mar 6, 2026
Merged

Pro builder#870
Scriptwonder merged 9 commits intoCoplayDev:betafrom
Scriptwonder:ProBuilder

Conversation

@Scriptwonder
Copy link
Collaborator

@Scriptwonder Scriptwonder commented Mar 6, 2026

Description

Experimental ProBuilder support that offers full support to the current Native API latest to ProBuilder V6.

Type of Change

Save your change type

  • New feature (non-breaking change that adds functionality)
  • Documentation update
  • Test update

Changes Made

Add a new manage_probuilder feature that could directly manipulate probuilder modeling.
Shape Creation

  • create_shape — 13 primitives: Cube, Cylinder, Sphere, Plane, Cone, Torus, Pipe, Arch, Stair, CurvedStair, Door, Prism
  • create_poly_shape — extrude a custom 2D polygon footprint

Face Editing

  • extrude_faces — push faces out/in
  • extrude_edges — extrude open edges
  • bevel_edges — chamfer edges
  • subdivide — split faces into smaller quads
  • delete_faces — remove faces
  • bridge_edges — connect two open edges with a face
  • connect_elements — insert edge loops across edges/faces
  • detach_faces — separate faces into new object
  • flip_normals — reverse face winding
  • merge_faces — collapse multiple faces into one
  • duplicate_and_flip — create double-sided geometry
  • create_polygon — form a new face from existing vertices

Vertex Operations

  • merge_vertices — collapse to single point
  • weld_vertices — merge within a radius
  • split_vertices — unshare shared vertices
  • move_vertices — translate by offset
  • insert_vertex — add point on edge or face
  • append_vertices_to_edge — insert evenly-spaced points on edges

Selection

  • select_faces — by direction, grow, flood, loop, ring

UV & Materials

  • set_face_material — assign material per face
  • set_face_color — vertex color per face
  • set_face_uvs — auto-unwrap scale/offset/rotation per face

Smoothing

  • set_smoothing — assign smoothing group (0=hard)
  • auto_smooth — assign groups by angle threshold

Utilities

  • get_mesh_info — query
    faces/edges/vertices/bounds/materials
  • center_pivot — move pivot to bounds center
  • set_pivot — move pivot to world position
  • freeze_transform — bake transform into vertices
  • validate_mesh — health check (degenerate tris,
    unused verts)
  • repair_mesh — auto-fix mesh issues
  • combine_meshes — merge multiple PB objects
  • merge_objects — merge into one PB mesh
  • convert_to_probuilder — convert standard mesh

Testing/Screenshots/Recordings

截屏2026-03-06 上午1 23 24 截屏2026-03-06 上午1 29 23

Documentation Updates

  • I have added/removed/modified tools or resources
  • If yes, I have updated all documentation files using:
    • The LLM prompt at tools/UPDATE_DOCS_PROMPT.md (recommended)
    • Manual updates following the guide at tools/UPDATE_DOCS.md

Related Issues

#862

Additional Notes

Summary by Sourcery

Add experimental ProBuilder mesh editing support across Unity MCP tools, CLI, and documentation, along with related screenshot improvements and minor API tweaks.

New Features:

  • Introduce a new manage_probuilder tool in the Unity editor for comprehensive ProBuilder mesh creation, editing, selection, smoothing, and utilities.
  • Expose ProBuilder operations through a new CLI probuilder command group, including shape creation, mesh editing, info queries, and a raw escape hatch.
  • Add a dedicated ProBuilder Workflow Guide and reference sections describing available actions, patterns, and best practices for AI-driven 3D modeling with ProBuilder.

Enhancements:

  • Improve multi-view screenshot batching by adjusting camera radius heuristics and forcing material refresh before capture, and persist positioned screenshots to disk while returning base64 data.
  • Extend manage_material to support by_id search, and manage_gameobject rename operations to accept new_name/newName aliases.
  • Surface ProBuilder as an experimental tool group in the editor UI with a safety warning, and document it in SKILL, README, and tool group registry metadata.

Documentation:

  • Update tools-reference and workflows docs (and their mirrored .claude copies) with a new ProBuilder Tools section and usage examples.
  • Extend CLI usage documentation with ProBuilder examples and update Chinese README release notes to mention ProBuilder mesh editing support.

Tests:

  • Add extensive editor tests for manage_probuilder behavior in Unity and Python tests for the manage_probuilder service wrapper, covering actions, parameters, and error handling.

Summary by CodeRabbit

  • New Features

    • ProBuilder mesh-editing support: manage_probuilder tool (shape/mesh/vertex/face ops, smoothing, utilities), CLI commands, and new probuilder tool group; expanded search methods for tagged searches.
  • Enhancements

    • Scene screenshots now saved to Assets with returned file paths; increased capture radius and pre-capture refresh for reliable results.
  • Bug Fixes

    • GameObject rename now respects additional name parameters.
  • Documentation

    • New ProBuilder guides, API reference, README and CLI docs; experimental UI warning added (some docs duplicated).
  • Tests

    • Comprehensive unit and Unity editor tests for ProBuilder workflows.

Copilot AI review requested due to automatic review settings March 6, 2026 06:40
@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Mar 6, 2026

Reviewer's Guide

Adds experimental manage_probuilder ProBuilder support across the Unity MCP stack (editor tool, server tool, CLI, docs, tests) plus some screenshot and GameObject/Material quality-of-life tweaks.

Sequence diagram for a manage_probuilder mesh edit call

sequenceDiagram
    actor User
    participant LLM
    participant Server as manage_probuilder_py
    participant Transport as UnityTransport
    participant Editor as ManageProBuilder_cs
    participant ProBuilder as ProBuilder_Package

    User->>LLM: Request to extrude top face of cube
    LLM->>Server: manage_probuilder(action="extrude_faces",\n target="MyCube", properties={faceIndices:[2],distance:1.5})
    Server->>Transport: send_with_unity_instance("manage_probuilder", params)
    Transport->>Editor: HandleCommand(params)
    Editor->>Editor: EnsureProBuilder()\n(reflect types, patch material)
    Editor->>Editor: RequireProBuilderMesh(target)
    Editor->>ProBuilder: ExtrudeElements.Extrude(mesh, faces, method, distance)
    ProBuilder-->>Editor: Mesh modified in memory
    Editor->>ProBuilder: ToMesh() and Refresh()
    Editor-->>Transport: SuccessResponse(data)
    Transport-->>Server: result
    Server-->>LLM: JSON tool result
    LLM-->>User: Describes change and next steps
Loading

File-Level Changes

Change Details Files
Introduce a fully featured ProBuilder management tool in the Unity editor, with reflection-based integration to the ProBuilder package and rich mesh operations.
  • Add ManageProBuilder editor tool that reflects ProBuilder types at runtime and exposes actions for shape creation, mesh editing, vertex operations, selection, UV/material changes, smoothing, mesh utilities, and mesh info queries.
  • Implement extensive helpers for resolving targets, faces, edges, vertices, computing normals/centers, and refreshing ProBuilder meshes after mutation.
  • Patch the ProBuilder default material at startup to disable unintended emission in URP, preventing glowing newly created ProBuilder meshes.
  • Add ProBuilderMeshUtils and ProBuilderSmoothing helpers to encapsulate pivot, transform, validation/repair, and smoothing-group logic used by ManageProBuilder.
  • Add extensive edit-mode unit tests covering ProBuilder actions, mesh info, smoothing, and utilities to guard against API/behavior regressions when ProBuilder is installed or absent.
MCPForUnity/Editor/Tools/ProBuilder/ManageProBuilder.cs
MCPForUnity/Editor/Tools/ProBuilder/ProBuilderMeshUtils.cs
MCPForUnity/Editor/Tools/ProBuilder/ProBuilderSmoothing.cs
TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageProBuilderTests.cs
Expose the ProBuilder tool as a first-class MCP tool group and CLI command, including server-side plumbing and configuration.
  • Register manage_probuilder as a new MCP tool in the server (manage_probuilder.py) with typed action lists and pass-through of target/search_method/properties to Unity.
  • Add CLI probuilder command group with subcommands for shape creation, mesh editing, vertex operations, smoothing, mesh utilities, mesh info, and a generic raw escape hatch.
  • Register the new CLI command module in the main CLI entrypoint so the probuilder group is available when installed.
  • Extend the tool registry to add a probuilder tool group description and keep default enabled groups unchanged.
Server/src/services/tools/manage_probuilder.py
Server/src/cli/commands/probuilder.py
Server/src/cli/main.py
Server/src/services/registry/tool_registry.py
Server/tests/test_manage_probuilder.py
Document the new ProBuilder capabilities and workflows throughout the skill references, workflows, skill metadata, and CLI docs (including Chinese README).
  • Extend tools reference docs in both .claude and runtime skill trees with a comprehensive manage_probuilder section (parameters, actions by category, and usage examples).
  • Add a dedicated ProBuilder workflow guide covering decision matrix vs primitives, basic build examples, edit-verify loop, and known limitations.
  • Link the ProBuilder tool and guide into SKILL docs, workflows index, and tool summary tables so LLM agents discover and prefer it for editable geometry.
  • Update CLI usage guide with ProBuilder CLI examples and a new command summary row.
  • Update top-level English and Chinese READMEs to mention ProBuilder support in the v9.4.8 changelog and recent updates section.
.claude/skills/unity-mcp-skill/references/tools-reference.md
unity-mcp-skill/references/tools-reference.md
.claude/skills/unity-mcp-skill/references/workflows.md
unity-mcp-skill/references/workflows.md
unity-mcp-skill/references/probuilder-guide.md
unity-mcp-skill/SKILL.md
.claude/skills/unity-mcp-skill/SKILL.md
docs/guides/CLI_USAGE.md
docs/i18n/README-zh.md
README.md
Improve screenshot tooling and editor UI/UX around scene capture and tool discovery, especially for experimental ProBuilder workflows.
  • Adjust manage_scene surround/orbit screenshot radius calculations to capture a larger area and increase minimum radius for more reliable framing.
  • Force material refresh and SceneView repaint before batch screenshot capture to avoid stale materials in contact sheets.
  • Change positioned screenshot capture to also save PNGs under Assets/Screenshots/ with unique filenames and return the asset-relative path in the response payload/message.
  • Update SKILL docs to simplify screenshot parameter exposition and clarify best-practice usage patterns.
  • Add a new ProBuilder category entry to the editor MCP tools UI with an experimental warning helpbox describing potential mesh-editing risks.
MCPForUnity/Editor/Tools/ManageScene.cs
unity-mcp-skill/SKILL.md
.claude/skills/unity-mcp-skill/SKILL.md
MCPForUnity/Editor/Windows/Components/Tools/McpToolsSection.cs
Introduce small QoL and correctness fixes around GameObject renaming and material management.
  • Make manage_gameobject modify handler accept new_name/newName aliases in addition to name for renaming, improving API ergonomics.
  • Extend manage_material tool signature to accept by_id as a valid search_method, aligning it with other tools’ target resolution modes.
  • Compact renderer sharedMaterials in SetFaceMaterial to remove unused entries and avoid 'more materials than submeshes' warnings after per-face material changes.
MCPForUnity/Editor/Tools/GameObjects/GameObjectModify.cs
Server/src/services/tools/manage_material.py
MCPForUnity/Editor/Tools/ProBuilder/ManageProBuilder.cs

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
Contributor

coderabbitai bot commented Mar 6, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6ad6d66d-bd66-49c0-aa2e-e34b946f9bf4

📥 Commits

Reviewing files that changed from the base of the PR and between 5bd3a22 and 2c59260.

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

📝 Walkthrough

Walkthrough

Adds ProBuilder mesh-editing support across the stack: Unity Editor C# utilities and tests, server-side manage_probuilder tool and CLI commands, docs and skill updates, tool registry/UI integration, and scene screenshot capture enhancements.

Changes

Cohort / File(s) Summary
ProBuilder Editor code & metadata
MCPForUnity/Editor/Tools/ProBuilder/ManageProBuilder.cs, MCPForUnity/Editor/Tools/ProBuilder/ProBuilderMeshUtils.cs, MCPForUnity/Editor/Tools/ProBuilder/ProBuilderSmoothing.cs, MCPForUnity/Editor/Tools/ProBuilder/*.cs.meta, MCPForUnity/Editor/Tools/ProBuilder.meta
New ProBuilder integration: reflection-based mesh utilities (center pivot, freeze transform, validate/repair), smoothing helpers, undo handling, refresh calls, and Unity .meta files.
Editor UI & Scene tooling
MCPForUnity/Editor/Windows/Components/Tools/McpToolsSection.cs, MCPForUnity/Editor/Tools/ManageScene.cs, MCPForUnity/Editor/Tools/GameObjects/GameObjectModify.cs
Added experimental ProBuilder group UI/warning; increased surround/orbit capture radius; queueing of editor refresh before captures; positioned screenshots saved to Assets/Screenshots/ with asset import and assets-relative path returned; extended GameObject rename fallback.
Server tool & registry
Server/src/services/tools/manage_probuilder.py, Server/src/services/registry/tool_registry.py
New async manage_probuilder tool exposing categorized ProBuilder actions, validation, request assembly, and dispatch to Unity; added probuilder tool group.
CLI integration
Server/src/cli/commands/probuilder.py, Server/src/cli/main.py, Server/src/cli/utils/constants.py
New Click CLI group probuilder with many subcommands (shape create, mesh edits, smoothing, utilities, raw), registration added to main CLI, and SEARCH_METHODS_TAGGED extended (added by_layer).
Server tests
Server/tests/test_manage_probuilder.py
Extensive async unit tests for manage_probuilder covering action list integrity, parameter forwarding/normalization, error cases, and passthrough behaviors.
Unity Editor tests
TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageProBuilderTests.cs, .../ManageProBuilderTests.cs.meta
Comprehensive EditMode tests covering shape creation, mesh edits, smoothing, utilities, mesh info, and ProBuilder-absent error handling.
Skill, docs & references
.claude/skills/unity-mcp-skill/SKILL.md, unity-mcp-skill/references/*, unity-mcp-skill/references/probuilder-guide.md, unity-mcp-skill/references/tools-reference.md, unity-mcp-skill/references/workflows.md, README.md, docs/guides/CLI_USAGE.md, docs/i18n/README-zh.md
Added manage_probuilder skill entry and README note; new ProBuilder guide, tools reference, workflows and CLI docs. Note: several documentation insertions appear duplicated in the diffs.
Material tool tweak
Server/src/services/tools/manage_material.py
Extended search_method Literal to include "by_id".

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant User as CLI/User
  participant Server as MCP Server
  participant Unity as Unity Editor
  participant PB as ProBuilder

  User->>Server: probuilder <action, target, params>
  Server->>Unity: send_with_unity_instance("manage_probuilder", params)
  Unity->>PB: ManageProBuilder invokes action (reflection / ProBuilder API)
  PB-->>Unity: return result (JSON payload)
  Unity-->>Server: forward result
  Server-->>User: print formatted result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

codex

Suggested reviewers

  • msanatan
  • dsarno
  • justinpbarnett

Poem

🐰 I hop through vertices, nibble at a face,

I center pivots, smooth with gentle pace.
Extrude a tunnel, bevel round a seam,
I stitch the mesh together — a rabbit's dream.
Hoppity-hop, the model gleams.

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 31.25% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Pro builder' is vague and uses generic capitalization without clearly describing the scope or nature of the changes (e.g., adding, implementing, or supporting ProBuilder). Revise the title to be more descriptive and specific, such as 'Add experimental ProBuilder mesh editing support' or 'Implement manage_probuilder tool for mesh manipulation'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed The PR description includes all major template sections with comprehensive details about features, testing, and documentation updates, though documentation updates were only partially completed via automation.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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
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 5 issues, and left some high level feedback:

  • The ManageProBuilder class has grown into a very large, reflection-heavy monolith (~2.5k lines); consider splitting per concern (e.g. shape creation, mesh editing, vertex ops, query/smoothing) or using partial classes to keep the code easier to navigate and reason about.
  • Given that set_pivot and convert_to_probuilder are documented as not yet working, you might want to explicitly gate or short‑circuit those actions (e.g. return a clear error before attempting the operation) so callers get consistent failure modes instead of potentially fragile partial behavior.
  • The ProBuilder material patch in PatchProBuilderDefaultMaterial relies on a hard‑coded package asset path; it may be worth guarding it with a version/exists check or centralizing the path as a constant so that Unity/ProBuilder package layout changes are easier to handle.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The `ManageProBuilder` class has grown into a very large, reflection-heavy monolith (~2.5k lines); consider splitting per concern (e.g. shape creation, mesh editing, vertex ops, query/smoothing) or using partial classes to keep the code easier to navigate and reason about.
- Given that `set_pivot` and `convert_to_probuilder` are documented as not yet working, you might want to explicitly gate or short‑circuit those actions (e.g. return a clear error before attempting the operation) so callers get consistent failure modes instead of potentially fragile partial behavior.
- The ProBuilder material patch in `PatchProBuilderDefaultMaterial` relies on a hard‑coded package asset path; it may be worth guarding it with a version/exists check or centralizing the path as a constant so that Unity/ProBuilder package layout changes are easier to handle.

## Individual Comments

### Comment 1
<location path="MCPForUnity/Editor/Tools/ProBuilder/ManageProBuilder.cs" line_range="2106-2115" />
<code_context>
+            var meshRenderer = pbMesh.gameObject.GetComponent<MeshRenderer>();
</code_context>
<issue_to_address>
**issue (bug_risk):** MeshRenderer changes in SetFaceMaterial are not recorded for Undo, and the material compaction logic mutates both faces and renderer without separate undo tracking.

Because only `pbMesh` is registered with Undo, the changes to `Face.submeshIndex` and `meshRenderer.sharedMaterials` won’t roll back together. Please also register the `MeshRenderer` (and, if applicable, the underlying `Mesh`) in the same undo group before modifying `sharedMaterials` and submesh indices so the operation is fully reversible.
</issue_to_address>

### Comment 2
<location path="MCPForUnity/Editor/Tools/ProBuilder/ProBuilderMeshUtils.cs" line_range="209-212" />
<code_context>
+            });
+        }
+
+        private static void SetVertexPositions(Component pbMesh, Vector3[] positions)
+        {
+            var positionsProp = ManageProBuilder._proBuilderMeshType.GetProperty("positions");
+            if (positionsProp != null && positionsProp.CanWrite)
+                positionsProp.SetValue(pbMesh, new List<Vector3>(positions));
+        }
</code_context>
<issue_to_address>
**issue:** SetVertexPositions only handles the writable positions property and lacks the fallbacks used elsewhere, which may break on some ProBuilder versions.

This assumes `ProBuilderMesh.positions` is writable and accepts a `List<Vector3>`. In `ManageProBuilder.MoveVertices`, you already handle the non-writable case via `SetPositions` / `RebuildWithPositionsAndFaces`. To keep behavior consistent across ProBuilder versions, please reuse that fallback logic here (e.g., via a shared helper) instead of this reduced implementation.
</issue_to_address>

### Comment 3
<location path="Server/src/services/tools/manage_probuilder.py" line_range="117-118" />
<code_context>
+    ctx: Context,
+    action: Annotated[str, "Action to perform."],
+    target: Annotated[str | None, "Target GameObject (name/path/id)."] = None,
+    search_method: Annotated[
+        Literal["by_id", "by_name", "by_path", "by_tag", "by_layer"] | None,
+        "How to find the target GameObject.",
+    ] = None,
</code_context>
<issue_to_address>
**issue (bug_risk):** The search_method Literal excludes 'by_component', which other tools and the CLI helper allow.

The type for `manage_probuilder`’s `search_method` doesn’t include `by_component`, even though other tools (and the CLI via `SEARCH_METHOD_CHOICE_TAGGED`) support it. If `ObjectResolver` accepts `by_component` here, please add it to the `Literal` so the annotation matches the actual valid values and doesn’t mislead type‑aware tooling or clients.
</issue_to_address>

### Comment 4
<location path="Server/src/cli/commands/probuilder.py" line_range="16-24" />
<code_context>
+_PB_TOP_LEVEL_KEYS = {"action", "target", "searchMethod", "properties"}
+
+
+def _parse_edges_param(edges: str) -> dict[str, Any]:
+    """Parse edge JSON into either 'edges' (vertex pairs) or 'edgeIndices' (flat indices)."""
+    import json
+    try:
+        parsed = json.loads(edges)
+    except json.JSONDecodeError:
+        print_error("Invalid JSON for edges parameter")
+        raise SystemExit(1)
+    if parsed and isinstance(parsed[0], dict):
+        return {"edges": parsed}
+    return {"edgeIndices": parsed}
</code_context>
<issue_to_address>
**issue:** _parse_edges_param assumes the parsed JSON is indexable, which will break for non-list JSON inputs.

In `_parse_edges_param`, `parsed[0]` is accessed without confirming `parsed` is a list. If the JSON decodes to a scalar or dict, this will raise a `TypeError` instead of producing a clear, user-facing error. Consider checking `isinstance(parsed, list)` (and perhaps that it’s non-empty) before indexing and return a friendly message when the structure is invalid.
</issue_to_address>

### Comment 5
<location path="unity-mcp-skill/references/probuilder-guide.md" line_range="202" />
<code_context>
+### Auto-Smooth (Recommended Default)
+
+```python
+# Apply auto-smoothing with default 30 degree threshold
+manage_probuilder(action="auto_smooth", target="MyMesh",
+    properties={"angleThreshold": 30})
</code_context>
<issue_to_address>
**nitpick (typo):** Hyphenate "30-degree" when used as a compound modifier.

As a unit modifying “threshold,” it should be written as “30-degree threshold.”

```suggestion
# Apply auto-smoothing with default 30-degree threshold
```
</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.

Comment on lines +2106 to +2115
var meshRenderer = pbMesh.gameObject.GetComponent<MeshRenderer>();
if (meshRenderer != null)
{
var allFacesList = (System.Collections.IList)GetFacesArray(pbMesh);
var submeshIndexProp = _faceType.GetProperty("submeshIndex");
var currentMats = meshRenderer.sharedMaterials;

var usedIndices = new SortedSet<int>();
foreach (var f in allFacesList)
usedIndices.Add((int)submeshIndexProp.GetValue(f));
Copy link
Contributor

Choose a reason for hiding this comment

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

issue (bug_risk): MeshRenderer changes in SetFaceMaterial are not recorded for Undo, and the material compaction logic mutates both faces and renderer without separate undo tracking.

Because only pbMesh is registered with Undo, the changes to Face.submeshIndex and meshRenderer.sharedMaterials won’t roll back together. Please also register the MeshRenderer (and, if applicable, the underlying Mesh) in the same undo group before modifying sharedMaterials and submesh indices so the operation is fully reversible.

Comment on lines +209 to +212
private static void SetVertexPositions(Component pbMesh, Vector3[] positions)
{
var positionsProp = ManageProBuilder._proBuilderMeshType.GetProperty("positions");
if (positionsProp != null && positionsProp.CanWrite)
Copy link
Contributor

Choose a reason for hiding this comment

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

issue: SetVertexPositions only handles the writable positions property and lacks the fallbacks used elsewhere, which may break on some ProBuilder versions.

This assumes ProBuilderMesh.positions is writable and accepts a List<Vector3>. In ManageProBuilder.MoveVertices, you already handle the non-writable case via SetPositions / RebuildWithPositionsAndFaces. To keep behavior consistent across ProBuilder versions, please reuse that fallback logic here (e.g., via a shared helper) instead of this reduced implementation.

Comment on lines +117 to +118
search_method: Annotated[
Literal["by_id", "by_name", "by_path", "by_tag", "by_layer"] | None,
Copy link
Contributor

Choose a reason for hiding this comment

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

issue (bug_risk): The search_method Literal excludes 'by_component', which other tools and the CLI helper allow.

The type for manage_probuilder’s search_method doesn’t include by_component, even though other tools (and the CLI via SEARCH_METHOD_CHOICE_TAGGED) support it. If ObjectResolver accepts by_component here, please add it to the Literal so the annotation matches the actual valid values and doesn’t mislead type‑aware tooling or clients.

Comment on lines +16 to +24
def _parse_edges_param(edges: str) -> dict[str, Any]:
"""Parse edge JSON into either 'edges' (vertex pairs) or 'edgeIndices' (flat indices)."""
import json
try:
parsed = json.loads(edges)
except json.JSONDecodeError:
print_error("Invalid JSON for edges parameter")
raise SystemExit(1)
if parsed and isinstance(parsed[0], dict):
Copy link
Contributor

Choose a reason for hiding this comment

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

issue: _parse_edges_param assumes the parsed JSON is indexable, which will break for non-list JSON inputs.

In _parse_edges_param, parsed[0] is accessed without confirming parsed is a list. If the JSON decodes to a scalar or dict, this will raise a TypeError instead of producing a clear, user-facing error. Consider checking isinstance(parsed, list) (and perhaps that it’s non-empty) before indexing and return a friendly message when the structure is invalid.

### Auto-Smooth (Recommended Default)

```python
# Apply auto-smoothing with default 30 degree threshold
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick (typo): Hyphenate "30-degree" when used as a compound modifier.

As a unit modifying “threshold,” it should be written as “30-degree threshold.”

Suggested change
# Apply auto-smoothing with default 30 degree threshold
# Apply auto-smoothing with default 30-degree threshold

Copy link
Contributor

@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: 11

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/i18n/README-zh.md (1)

94-95: ⚠️ Potential issue | 🟡 Minor

manage_probuilder is missing from the available tools list.

The new release notes above mention ProBuilder support, but this tool inventory still omits manage_probuilder. Readers scanning the tool list won't discover the new feature.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/i18n/README-zh.md` around lines 94 - 95, The tools list is missing the
new manage_probuilder entry; update the tools inventory line that enumerates
available tools (the backticked list containing manage_animation, manage_asset,
manage_components, etc.) to include `manage_probuilder` among the other manage_*
items so the README reflects the ProBuilder support mentioned in the release
notes.
🧹 Nitpick comments (7)
MCPForUnity/Editor/Tools/ManageScene.cs (3)

940-941: Minor inefficiency: redundant base64 encode/decode round-trip.

The image is rendered, encoded to base64 by RenderCameraToBase64, then decoded back to bytes here for disk write. For large images, this adds unnecessary CPU overhead.

Consider having ScreenshotUtility expose a method that returns raw bytes (or both bytes and base64), allowing direct disk write without the decode step:

♻️ Suggested approach
// In ScreenshotUtility, add or modify to return raw bytes:
// public static (byte[] pngBytes, string base64, int w, int h) RenderCameraToBytes(...)

// Then in CapturePositionedScreenshot:
var (pngBytes, b64, w, h) = ScreenshotUtility.RenderCameraToBytes(tempCam, maxRes);
File.WriteAllBytes(fullPath, pngBytes);

This is a minor optimization and can be deferred if the utility refactor isn't trivial.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@MCPForUnity/Editor/Tools/ManageScene.cs` around lines 940 - 941, The code
does an unnecessary base64 round-trip: RenderCameraToBase64 in ScreenshotUtility
returns a base64 string which CapturePositionedScreenshot immediately decodes
into bytes before File.WriteAllBytes; modify ScreenshotUtility to expose a
bytes-returning API (e.g., add RenderCameraToBytes or change
RenderCameraToBase64 to also return byte[]/tuple) and update
CapturePositionedScreenshot to call that new method and pass the returned
pngBytes directly to File.WriteAllBytes(fullPath, pngBytes) instead of decoding
a base64 string; keep the original base64 overload if needed for backward
compatibility.

929-939: Optional: Add upper bound to filename collision loop.

The while loop has no upper bound. While practically impossible to exhaust (would require thousands of screenshots in the same second), a defensive upper limit improves robustness:

♻️ Defensive improvement
 int counter = 1;
-while (File.Exists(fullPath))
+const int maxAttempts = 1000;
+while (File.Exists(fullPath) && counter < maxAttempts)
 {
     fullPath = Path.Combine(screenshotsFolder, $"{baseName}_{counter}{ext}");
     counter++;
 }
+if (counter >= maxAttempts)
+    return new ErrorResponse($"Could not generate unique filename after {maxAttempts} attempts.");

This is a minor defensive coding suggestion and can be safely deferred.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@MCPForUnity/Editor/Tools/ManageScene.cs` around lines 929 - 939, The
filename-collision while loop that increments counter on fullPath (using
baseName, ext and screenshotsFolder) has no upper bound; add a defensive maximum
attempts constant (e.g., maxAttempts) and stop the loop after that many
iterations, then handle the failure (log/error or throw/return a fallback
filename) so you don't loop indefinitely — change the loop that uses counter and
File.Exists(fullPath) to also check counter < maxAttempts and handle the
exceeded-attempts case.

668-671: Minor performance consideration with per-frame refresh calls.

These refresh calls are executed inside the capture loop (6 iterations here, but up to 108+ in CaptureOrbitBatch). While necessary to ensure materials render correctly, this adds overhead per shot.

If performance becomes a concern for large orbit batches, consider batching the refresh: call once before the loop, then delay briefly (e.g., using EditorApplication.Step() or a small frame wait) rather than refreshing before every individual capture. That said, if this resolves material rendering issues reliably, the current approach is acceptable.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@MCPForUnity/Editor/Tools/ManageScene.cs` around lines 668 - 671, The
per-iteration material refresh calls (EditorApplication.QueuePlayerLoopUpdate
and SceneView.RepaintAll) inside the capture loop in ManageScene (see methods
CaptureOrbit and/or CaptureOrbitBatch) cause extra overhead; move these calls
out of the inner loop and invoke them once before starting the loop to batch
refresh materials, and if needed add a short frame advance/wait (e.g., using
EditorApplication.Step or a small frame delay) after that single refresh to
ensure materials have updated before the first capture; update
CaptureOrbitBatch/CaptureOrbit to remove the per-iteration
QueuePlayerLoopUpdate/RepaintAll and perform a single pre-loop refresh instead.
MCPForUnity/Editor/Windows/Components/Tools/McpToolsSection.cs (1)

207-208: Key this off the actual group name, not the prefs key.

prefsSuffix is a persistence/detail string, so tying experimental behavior to "group-probuilder" makes this warning depend on the current EditorPrefs naming scheme. Passing the semantic group key into BuildCategory would keep the behavior aligned with the registered probuilder group.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@MCPForUnity/Editor/Windows/Components/Tools/McpToolsSection.cs` around lines
207 - 208, The code gates experimental behavior by comparing prefsSuffix to the
persistence string "group-probuilder"; instead compare the actual semantic group
key instead — update BuildCategory's call sites to accept and pass the
registered group key (e.g., "probuilder") into the method, and change the
isExperimental check to compare that group key (not prefsSuffix) using
StringComparison.OrdinalIgnoreCase so experimental flags are driven by the
registered group name rather than the EditorPrefs suffix; adjust the
BuildCategory signature and all callers accordingly to propagate the semantic
group identifier.
Server/src/cli/commands/probuilder.py (1)

19-26: Use explicit exception chaining for cleaner tracebacks.

Per static analysis (B904), within an except clause, use raise ... from None to suppress the exception chain, providing cleaner error output.

Suggested fix
     try:
         parsed = json.loads(edges)
     except json.JSONDecodeError:
         print_error("Invalid JSON for edges parameter")
-        raise SystemExit(1)
+        raise SystemExit(1) from None
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Server/src/cli/commands/probuilder.py` around lines 19 - 26, The except block
catching json.JSONDecodeError should suppress exception chaining by re-raising
the SystemExit with explicit exception chaining; update the except that
currently calls print_error("Invalid JSON for edges parameter") and raise
SystemExit(1) so it uses "raise SystemExit(1) from None" after the print_error
call to avoid exposing the original JSONDecodeError traceback; locate the
json.loads(edges) try/except and the print_error / raise SystemExit(1) lines to
make this change.
MCPForUnity/Editor/Tools/ProBuilder/ProBuilderMeshUtils.cs (1)

233-261: Consider logging swallowed exceptions for debugging.

The bare catch blocks silently swallow all exceptions when falling back between overloads. While this is intentional for API compatibility, unexpected exceptions could make debugging difficult.

Optional: Add debug logging
                     catch
                     {
+                        // First overload failed, try alternate signature
                         // Some overloads differ; try without faces param
                         try
                         {
                             // ... existing fallback code ...
                         }
-                        catch
+                        catch (Exception fallbackEx)
                         {
-                            // Ignore fallback failure
+                            // Both overloads failed - log for debugging
+                            UnityEngine.Debug.LogWarning($"RepairMesh fallback failed: {fallbackEx.Message}");
                         }
                     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@MCPForUnity/Editor/Tools/ProBuilder/ProBuilderMeshUtils.cs` around lines 233
- 261, The catch blocks around removeMethod.Invoke and the fallback
altMethod.Invoke silently swallow all exceptions; update them to log the caught
exceptions (at debug/verbose level) so unexpected errors are visible while
preserving the fallback behavior: in the first catch capture the exception from
removeMethod.Invoke and log it via the existing logger (or
UnityEngine.Debug.LogException) including context (method name
RemoveDegenerateTriangles, pbMesh, allFaces) before attempting the overload
fallback, and in the inner catch similarly log the exception from
altMethod.Invoke (referencing ManageProBuilder._meshValidationType,
ManageProBuilder._proBuilderMeshType and the repaired variable) instead of
leaving it empty.
Server/src/services/registry/tool_registry.py (1)

25-25: Consider using a standard hyphen for consistency.

The description contains an EN DASH () which may cause inconsistency with other entries that use the standard hyphen-minus (-). This could also affect searchability.

Suggested fix
-    "probuilder": "ProBuilder 3D modeling – requires com.unity.probuilder package",
+    "probuilder": "ProBuilder 3D modeling - requires com.unity.probuilder package",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Server/src/services/registry/tool_registry.py` at line 25, The "probuilder"
registry entry value contains an EN DASH (–); locate the "probuilder" mapping in
tool_registry (the string value "ProBuilder 3D modeling – requires
com.unity.probuilder package") and replace the EN DASH with a standard
hyphen-minus (-) so the description reads "ProBuilder 3D modeling - requires
com.unity.probuilder package" to ensure consistency and searchability.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.claude/skills/unity-mcp-skill/references/tools-reference.md:
- Around line 849-869: The catalog lists experimental actions
(convert_to_probuilder, set_pivot) as exposed but omits them from the Query and
Mesh Utilities sections, creating a contradiction; update the reference so the
action lists and the "choose an action" guidance match by either (A) adding
convert_to_probuilder to the Query or Mesh Utilities lists and set_pivot to Mesh
Utilities with a clear "(experimental / known-bug: see Not Yet Working)" tag, or
(B) remove these actions from the exposed action surface and only keep them in
the "Not Yet Working" section—also update the line that instructs readers to
choose an action from the categories to mention that experimental/buggy actions
are listed with that tag if you choose option A.
- Around line 813-815: The "create_shape" tool description incorrectly states
"13 types" while listing 12 shapes; update the documentation by either adding
the missing shape name to the list of ProBuilder primitives or changing the
count to "12 types" so they match; locate the create_shape entry (the heading
"Shape Creation:" and the list that follows) and either append the missing
primitive name to the existing list of Cube, Cylinder, Sphere, Plane, Cone,
Torus, Pipe, Arch, Stair, CurvedStair, Door, Prism or replace "13 types:" with
"12 types" to keep the description consistent.

In `@docs/guides/CLI_USAGE.md`:
- Around line 285-288: Update the hard-coded header "Raw ProBuilder actions
(access all 21 actions)" so it no longer understates available actions: either
remove the parenthetical count entirely or replace "21" with a dynamic/sourced
value from the authoritative ProBuilder action list; adjust the related examples
(the three sample commands including "unity-mcp probuilder raw extrude_faces",
"bevel_edges", and "set_face_material") as needed to avoid implying a fixed
action count and ensure the header accurately reflects that all raw ProBuilder
actions are accessible.

In `@MCPForUnity/Editor/Tools/ProBuilder/ProBuilderSmoothing.cs`:
- Around line 90-94: The response is reporting facesList.Count (all faces)
instead of the actual number smoothed; change the SuccessResponse payload to
report the count of faces actually processed (e.g., facesToSmooth.Count or the
variable used after filtering) so when faceIndices is provided the returned
faceCount reflects the smoothed subset; update the call that constructs the
SuccessResponse (the return statement creating new SuccessResponse(...) near the
end of ProBuilderSmoothing) to use the filtered collection's Count and keep
angleThreshold as-is.

In `@Server/src/cli/commands/probuilder.py`:
- Line 155: SEARCH_METHODS_TAGGED currently omits "by_layer" which causes the
CLI option SEARCH_METHOD_CHOICE_TAGGED to be out of sync with the backend
(manage_probuilder.py accepts "by_layer"); update the constants by adding
"by_layer" to SEARCH_METHODS_TAGGED (and any derived SEARCH_METHOD_CHOICE_TAGGED
or related choice lists) so the click.option("--search-method",
type=SEARCH_METHOD_CHOICE_TAGGED) accepts the same Literal values as
manage_probuilder.py; ensure any tests or usages referencing
SEARCH_METHODS_TAGGED/SEARCH_METHOD_CHOICE_TAGGED are updated accordingly.

In
`@TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageProBuilderTests.cs`:
- Around line 248-254: The test currently asserts that data["faces"] is not null
even though GetMeshInfo default include is "summary" and does not return faces;
update the test to either remove the faces assertion or call GetMeshInfo with
include="faces" so the response contains faces; specifically modify the code
path that produces result["data"] (the GetMeshInfo invocation used by this test)
or the assertion block that checks data["faces"] to align with
GetMeshInfo_DefaultInclude_ReturnsSummaryOnly behavior.

In `@unity-mcp-skill/references/probuilder-guide.md`:
- Around line 139-146: The Python examples use JSON boolean literals
`false`/`true` which will raise NameError in Python; update the
`manage_probuilder` example calls (the properties dicts used with action
"detach_faces" and target "MyCube") to use Python booleans `False` and `True`
(e.g., replace `deleteSourceFaces: false` with `deleteSourceFaces: False` and
`deleteSourceFaces: true` with `deleteSourceFaces: True`) so the snippets are
valid Python.
- Around line 41-82: Update the section heading text from "All 13 Shape Types"
to "All 12 Shape Types" to accurately reflect the primitives created by
manage_probuilder(action="create_shape"); leave create_poly_shape
(manage_probuilder(action="create_poly_shape")) as a separate action and do not
include it in the count, and ensure any nearby explanatory text references only
the 12 create_shape primitives (Cube, Cylinder, Sphere, Plane, Cone, Prism,
Torus, Pipe, Arch, Stair, CurvedStair, Door).

In `@unity-mcp-skill/references/tools-reference.md`:
- Around line 867-869: The documentation lists actions `set_pivot` and
`convert_to_probuilder` only in the "Not Yet Working" caveats but omits them
from the main action catalog, causing inconsistency; either add entries for
`set_pivot` and `convert_to_probuilder` to the action catalog above (include
their parameter shape and mark them as "experimental" or "broken" with a short
note and link to the caveat), or remove these two action names from the public
reference entirely; update the catalog section that says "see categories below"
to reflect whichever choice so the reference is consistent.
- Around line 813-815: The documentation for create_shape lists 13 types but
enumerates 12 names; update the tools-reference entry for create_shape to
reconcile them by either adding the missing primitive name to the enumerated
list (so it contains 13 actual types) or changing the count from 13 to 12;
ensure the enum text near the create_shape signature and the listed types (Cube,
Cylinder, Sphere, Plane, Cone, Torus, Pipe, Arch, Stair, CurvedStair, Door,
Prism) are consistent.

In `@unity-mcp-skill/SKILL.md`:
- Around line 61-62: Update the example in SKILL.md that shows
manage_scene(action="screenshot") so it states the screenshot is saved to the
Screenshots subfolder under Assets (Assets/Screenshots/) instead of just Assets;
edit the example text to reference this correct output directory and ensure any
returned file path example matches the Assets/Screenshots/ location.

---

Outside diff comments:
In `@docs/i18n/README-zh.md`:
- Around line 94-95: The tools list is missing the new manage_probuilder entry;
update the tools inventory line that enumerates available tools (the backticked
list containing manage_animation, manage_asset, manage_components, etc.) to
include `manage_probuilder` among the other manage_* items so the README
reflects the ProBuilder support mentioned in the release notes.

---

Nitpick comments:
In `@MCPForUnity/Editor/Tools/ManageScene.cs`:
- Around line 940-941: The code does an unnecessary base64 round-trip:
RenderCameraToBase64 in ScreenshotUtility returns a base64 string which
CapturePositionedScreenshot immediately decodes into bytes before
File.WriteAllBytes; modify ScreenshotUtility to expose a bytes-returning API
(e.g., add RenderCameraToBytes or change RenderCameraToBase64 to also return
byte[]/tuple) and update CapturePositionedScreenshot to call that new method and
pass the returned pngBytes directly to File.WriteAllBytes(fullPath, pngBytes)
instead of decoding a base64 string; keep the original base64 overload if needed
for backward compatibility.
- Around line 929-939: The filename-collision while loop that increments counter
on fullPath (using baseName, ext and screenshotsFolder) has no upper bound; add
a defensive maximum attempts constant (e.g., maxAttempts) and stop the loop
after that many iterations, then handle the failure (log/error or throw/return a
fallback filename) so you don't loop indefinitely — change the loop that uses
counter and File.Exists(fullPath) to also check counter < maxAttempts and handle
the exceeded-attempts case.
- Around line 668-671: The per-iteration material refresh calls
(EditorApplication.QueuePlayerLoopUpdate and SceneView.RepaintAll) inside the
capture loop in ManageScene (see methods CaptureOrbit and/or CaptureOrbitBatch)
cause extra overhead; move these calls out of the inner loop and invoke them
once before starting the loop to batch refresh materials, and if needed add a
short frame advance/wait (e.g., using EditorApplication.Step or a small frame
delay) after that single refresh to ensure materials have updated before the
first capture; update CaptureOrbitBatch/CaptureOrbit to remove the per-iteration
QueuePlayerLoopUpdate/RepaintAll and perform a single pre-loop refresh instead.

In `@MCPForUnity/Editor/Tools/ProBuilder/ProBuilderMeshUtils.cs`:
- Around line 233-261: The catch blocks around removeMethod.Invoke and the
fallback altMethod.Invoke silently swallow all exceptions; update them to log
the caught exceptions (at debug/verbose level) so unexpected errors are visible
while preserving the fallback behavior: in the first catch capture the exception
from removeMethod.Invoke and log it via the existing logger (or
UnityEngine.Debug.LogException) including context (method name
RemoveDegenerateTriangles, pbMesh, allFaces) before attempting the overload
fallback, and in the inner catch similarly log the exception from
altMethod.Invoke (referencing ManageProBuilder._meshValidationType,
ManageProBuilder._proBuilderMeshType and the repaired variable) instead of
leaving it empty.

In `@MCPForUnity/Editor/Windows/Components/Tools/McpToolsSection.cs`:
- Around line 207-208: The code gates experimental behavior by comparing
prefsSuffix to the persistence string "group-probuilder"; instead compare the
actual semantic group key instead — update BuildCategory's call sites to accept
and pass the registered group key (e.g., "probuilder") into the method, and
change the isExperimental check to compare that group key (not prefsSuffix)
using StringComparison.OrdinalIgnoreCase so experimental flags are driven by the
registered group name rather than the EditorPrefs suffix; adjust the
BuildCategory signature and all callers accordingly to propagate the semantic
group identifier.

In `@Server/src/cli/commands/probuilder.py`:
- Around line 19-26: The except block catching json.JSONDecodeError should
suppress exception chaining by re-raising the SystemExit with explicit exception
chaining; update the except that currently calls print_error("Invalid JSON for
edges parameter") and raise SystemExit(1) so it uses "raise SystemExit(1) from
None" after the print_error call to avoid exposing the original JSONDecodeError
traceback; locate the json.loads(edges) try/except and the print_error / raise
SystemExit(1) lines to make this change.

In `@Server/src/services/registry/tool_registry.py`:
- Line 25: The "probuilder" registry entry value contains an EN DASH (–); locate
the "probuilder" mapping in tool_registry (the string value "ProBuilder 3D
modeling – requires com.unity.probuilder package") and replace the EN DASH with
a standard hyphen-minus (-) so the description reads "ProBuilder 3D modeling -
requires com.unity.probuilder package" to ensure consistency and searchability.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 32fe01d4-fdb8-488f-b66d-0576b7b01142

📥 Commits

Reviewing files that changed from the base of the PR and between 1fde301 and fa6b52f.

⛔ Files ignored due to path filters (1)
  • Server/uv.lock is excluded by !**/*.lock
📒 Files selected for processing (28)
  • .claude/skills/unity-mcp-skill/SKILL.md
  • .claude/skills/unity-mcp-skill/references/tools-reference.md
  • .claude/skills/unity-mcp-skill/references/workflows.md
  • MCPForUnity/Editor/Tools/GameObjects/GameObjectModify.cs
  • MCPForUnity/Editor/Tools/ManageScene.cs
  • MCPForUnity/Editor/Tools/ProBuilder.meta
  • MCPForUnity/Editor/Tools/ProBuilder/ManageProBuilder.cs
  • MCPForUnity/Editor/Tools/ProBuilder/ManageProBuilder.cs.meta
  • MCPForUnity/Editor/Tools/ProBuilder/ProBuilderMeshUtils.cs
  • MCPForUnity/Editor/Tools/ProBuilder/ProBuilderMeshUtils.cs.meta
  • MCPForUnity/Editor/Tools/ProBuilder/ProBuilderSmoothing.cs
  • MCPForUnity/Editor/Tools/ProBuilder/ProBuilderSmoothing.cs.meta
  • MCPForUnity/Editor/Windows/Components/Tools/McpToolsSection.cs
  • README.md
  • Server/src/cli/commands/probuilder.py
  • Server/src/cli/main.py
  • Server/src/services/registry/tool_registry.py
  • Server/src/services/tools/manage_material.py
  • Server/src/services/tools/manage_probuilder.py
  • Server/tests/test_manage_probuilder.py
  • TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageProBuilderTests.cs
  • TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageProBuilderTests.cs.meta
  • docs/guides/CLI_USAGE.md
  • docs/i18n/README-zh.md
  • unity-mcp-skill/SKILL.md
  • unity-mcp-skill/references/probuilder-guide.md
  • unity-mcp-skill/references/tools-reference.md
  • unity-mcp-skill/references/workflows.md

Comment on lines +849 to +869
**Query:**
- `get_mesh_info` — Get mesh details with `include` parameter:
- `"summary"` (default): counts, bounds, materials
- `"faces"`: + face normals, centers, and direction labels (capped at 100)
- `"edges"`: + edge vertex pairs with world positions (capped at 200, deduplicated)
- `"all"`: everything
- `ping` — Check if ProBuilder is available

**Smoothing:**
- `set_smoothing` — Set smoothing group on faces (faceIndices, smoothingGroup: 0=hard, 1+=smooth)
- `auto_smooth` — Auto-assign smoothing groups by angle (angleThreshold: default 30)

**Mesh Utilities:**
- `center_pivot` — Move pivot to mesh bounds center
- `freeze_transform` — Bake transform into vertices, reset transform
- `validate_mesh` — Check mesh health (read-only diagnostics)
- `repair_mesh` — Auto-fix degenerate triangles

**Not Yet Working (known bugs):**
- `set_pivot` — Vertex positions don't persist through mesh rebuild. Use `center_pivot` or Transform positioning instead.
- `convert_to_probuilder` — MeshImporter throws internally. Create shapes natively instead.
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

The action catalog is incomplete for experimental actions.

convert_to_probuilder and set_pivot are still exposed actions, but they are omitted from the Query/Mesh Utilities lists and only mentioned later as known-bug cases. Since Line 806 tells readers to choose an action from the categories below, this makes the reference self-contradictory.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/skills/unity-mcp-skill/references/tools-reference.md around lines
849 - 869, The catalog lists experimental actions (convert_to_probuilder,
set_pivot) as exposed but omits them from the Query and Mesh Utilities sections,
creating a contradiction; update the reference so the action lists and the
"choose an action" guidance match by either (A) adding convert_to_probuilder to
the Query or Mesh Utilities lists and set_pivot to Mesh Utilities with a clear
"(experimental / known-bug: see Not Yet Working)" tag, or (B) remove these
actions from the exposed action surface and only keep them in the "Not Yet
Working" section—also update the line that instructs readers to choose an action
from the categories to mention that experimental/buggy actions are listed with
that tag if you choose option A.

Comment on lines +90 to +94
return new SuccessResponse($"Auto-smoothed with angle threshold {angleThreshold}°", new
{
angleThreshold,
faceCount = facesList.Count,
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

faceCount may not reflect actual smoothed faces when filtering.

When faceIndices is provided, facesToSmooth contains only the specified subset, but the response reports facesList.Count (all faces). Consider reporting the actual count of smoothed faces for accuracy.

Suggested fix
+            int smoothedCount = facesToSmooth is Array arr ? arr.Length : facesList.Count;
+
             return new SuccessResponse($"Auto-smoothed with angle threshold {angleThreshold}°", new
             {
                 angleThreshold,
-                faceCount = facesList.Count,
+                faceCount = smoothedCount,
             });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@MCPForUnity/Editor/Tools/ProBuilder/ProBuilderSmoothing.cs` around lines 90 -
94, The response is reporting facesList.Count (all faces) instead of the actual
number smoothed; change the SuccessResponse payload to report the count of faces
actually processed (e.g., facesToSmooth.Count or the variable used after
filtering) so when faceIndices is provided the returned faceCount reflects the
smoothed subset; update the call that constructs the SuccessResponse (the return
statement creating new SuccessResponse(...) near the end of ProBuilderSmoothing)
to use the filtered collection's Count and keep angleThreshold as-is.

Comment on lines +41 to +82
### All 13 Shape Types

```python
# Basic shapes
manage_probuilder(action="create_shape", properties={"shape_type": "Cube", "name": "MyCube"})
manage_probuilder(action="create_shape", properties={"shape_type": "Sphere", "name": "MySphere"})
manage_probuilder(action="create_shape", properties={"shape_type": "Cylinder", "name": "MyCyl"})
manage_probuilder(action="create_shape", properties={"shape_type": "Plane", "name": "MyPlane"})
manage_probuilder(action="create_shape", properties={"shape_type": "Cone", "name": "MyCone"})
manage_probuilder(action="create_shape", properties={"shape_type": "Prism", "name": "MyPrism"})

# Parametric shapes
manage_probuilder(action="create_shape", properties={
"shape_type": "Torus", "name": "MyTorus",
"rows": 16, "columns": 24, "innerRadius": 0.5, "outerRadius": 1.0
})
manage_probuilder(action="create_shape", properties={
"shape_type": "Pipe", "name": "MyPipe",
"radius": 1.0, "height": 2.0, "thickness": 0.2
})
manage_probuilder(action="create_shape", properties={
"shape_type": "Arch", "name": "MyArch",
"radius": 2.0, "angle": 180, "segments": 12
})

# Architectural shapes
manage_probuilder(action="create_shape", properties={
"shape_type": "Stair", "name": "MyStairs", "steps": 10
})
manage_probuilder(action="create_shape", properties={
"shape_type": "CurvedStair", "name": "Spiral", "steps": 12
})
manage_probuilder(action="create_shape", properties={
"shape_type": "Door", "name": "MyDoor"
})

# Custom polygon
manage_probuilder(action="create_poly_shape", properties={
"points": [[0,0,0], [5,0,0], [5,0,5], [2.5,0,7], [0,0,5]],
"extrudeHeight": 3.0, "name": "Pentagon"
})
```
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Find files related to ProBuilder implementation
find . -type f -name "*probuilder*" -o -name "*shape*" | head -20

Repository: CoplayDev/unity-mcp

Length of output: 241


🏁 Script executed:

# Search for shape type definitions or lists
rg "shape_type.*=|shape.*type.*:|Create.*Shape|SHAPE" --type md --type py --type json | head -40

Repository: CoplayDev/unity-mcp

Length of output: 4801


🏁 Script executed:

# Look at the probuilder-guide.md file directly to see full content
wc -l unity-mcp-skill/references/probuilder-guide.md 2>/dev/null || find . -name "probuilder-guide.md" -exec wc -l {} \;

Repository: CoplayDev/unity-mcp

Length of output: 113


🏁 Script executed:

# Read manage_probuilder.py to find shape type definitions
cat ./Server/src/services/tools/manage_probuilder.py | head -100

Repository: CoplayDev/unity-mcp

Length of output: 5522


🏁 Script executed:

# Search for shape type lists or constants in the implementation
rg "Cube|Cylinder|Sphere|Plane|Cone|Torus|Pipe|Arch|Stair|Door|Prism" ./Server/src/services/tools/manage_probuilder.py -A 2 -B 2

Repository: CoplayDev/unity-mcp

Length of output: 592


🏁 Script executed:

# Look for shape type handling/validation in the implementation
rg "create_shape|shape_type.*:" ./Server/src/services/tools/manage_probuilder.py -A 5 | head -80

Repository: CoplayDev/unity-mcp

Length of output: 730


🏁 Script executed:

# Check the CLI command definition
cat ./Server/src/cli/commands/probuilder.py | grep -A 20 "def create_shape"

Repository: CoplayDev/unity-mcp

Length of output: 1096


Change heading from "All 13 Shape Types" to "All 12 Shape Types".

The section heading claims 13 shape types, but create_shape supports only 12 primitives: Cube, Cylinder, Sphere, Plane, Cone, Torus, Pipe, Arch, Stair, CurvedStair, Door, and Prism. The create_poly_shape is a separate action and should not be counted toward this count.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@unity-mcp-skill/references/probuilder-guide.md` around lines 41 - 82, Update
the section heading text from "All 13 Shape Types" to "All 12 Shape Types" to
accurately reflect the primitives created by
manage_probuilder(action="create_shape"); leave create_poly_shape
(manage_probuilder(action="create_poly_shape")) as a separate action and do not
include it in the count, and ensure any nearby explanatory text references only
the 12 create_shape primitives (Cube, Cylinder, Sphere, Plane, Cone, Prism,
Torus, Pipe, Arch, Stair, CurvedStair, Door).

Comment on lines +867 to +869
**Not Yet Working (known bugs):**
- `set_pivot` — Vertex positions don't persist through mesh rebuild. Use `center_pivot` or Transform positioning instead.
- `convert_to_probuilder` — MeshImporter throws internally. Create shapes natively instead.
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Document these actions consistently, or hide them consistently.

set_pivot and convert_to_probuilder are called out as known-bug actions here, but they are omitted from the action catalog above. Right now the reference says “see categories below” for valid actions, yet these two real action names only appear in the caveats section with no parameter shape. Either list them in the main catalog with a broken/experimental note, or remove them from the public reference until they are supported.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@unity-mcp-skill/references/tools-reference.md` around lines 867 - 869, The
documentation lists actions `set_pivot` and `convert_to_probuilder` only in the
"Not Yet Working" caveats but omits them from the main action catalog, causing
inconsistency; either add entries for `set_pivot` and `convert_to_probuilder` to
the action catalog above (include their parameter shape and mark them as
"experimental" or "broken" with a short note and link to the caveat), or remove
these two action names from the public reference entirely; update the catalog
section that says "see categories below" to reflect whichever choice so the
reference is consistent.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds experimental end-to-end ProBuilder support to MCP for Unity (Unity editor tool + server tool + CLI + docs/tests), enabling in-editor parametric shape creation and mesh editing operations via a single manage_probuilder entrypoint.

Changes:

  • Introduces manage_probuilder across Unity (C#), Server (Python), and CLI (Click) with action routing and tool-grouping.
  • Adds documentation/workflows + a dedicated ProBuilder guide, plus updates tool references and recent updates.
  • Extends/adjusts screenshot capture behavior and adds test coverage (Unity edit-mode + Python unit tests) for the new tool.

Reviewed changes

Copilot reviewed 27 out of 29 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
unity-mcp-skill/references/workflows.md Adds ProBuilder workflows section and patterns.
unity-mcp-skill/references/tools-reference.md Documents manage_probuilder parameters/actions.
unity-mcp-skill/references/probuilder-guide.md New detailed ProBuilder guide and best practices.
unity-mcp-skill/SKILL.md Updates skill quickstart/docs; adds ProBuilder row; edits screenshot guidance.
docs/i18n/README-zh.md Adds “recent updates” mentioning ProBuilder support.
docs/guides/CLI_USAGE.md Adds CLI examples and command reference entry for ProBuilder.
TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageProBuilderTests.cs New Unity edit-mode tests for ProBuilder tool behavior.
TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageProBuilderTests.cs.meta Unity meta for new test file.
Server/uv.lock Lockfile updates (incl. fastmcp constraint bump).
Server/tests/test_manage_probuilder.py New Python unit tests for server-side manage_probuilder wrapper.
Server/src/services/tools/manage_probuilder.py New server tool wrapper + action validation and routing to Unity.
Server/src/services/tools/manage_material.py Expands search_method to include by_id.
Server/src/services/registry/tool_registry.py Registers new probuilder tool group label.
Server/src/cli/main.py Registers optional probuilder CLI command group.
Server/src/cli/commands/probuilder.py Adds ProBuilder CLI subcommands + raw escape hatch.
README.md Mentions ProBuilder in recent updates and tools list.
MCPForUnity/Editor/Windows/Components/Tools/McpToolsSection.cs Adds ProBuilder tool group UI + experimental warning.
MCPForUnity/Editor/Tools/ProBuilder/ProBuilderSmoothing.cs New smoothing operations for ProBuilder meshes.
MCPForUnity/Editor/Tools/ProBuilder/ProBuilderSmoothing.cs.meta Unity meta for smoothing helper.
MCPForUnity/Editor/Tools/ProBuilder/ProBuilderMeshUtils.cs New pivot/transform/validate/repair utilities for ProBuilder meshes.
MCPForUnity/Editor/Tools/ProBuilder/ProBuilderMeshUtils.cs.meta Unity meta for mesh utils helper.
MCPForUnity/Editor/Tools/ProBuilder/ManageProBuilder.cs New Unity tool implementing ProBuilder operations via reflection.
MCPForUnity/Editor/Tools/ProBuilder/ManageProBuilder.cs.meta Unity meta for new tool.
MCPForUnity/Editor/Tools/ProBuilder.meta Folder meta for new ProBuilder tools directory.
MCPForUnity/Editor/Tools/ManageScene.cs Adjusts batch screenshot radius + refresh + positioned screenshot saving behavior.
MCPForUnity/Editor/Tools/GameObjects/GameObjectModify.cs Adds new_name / newName rename alias support.
.claude/skills/unity-mcp-skill/references/workflows.md Mirrors ProBuilder workflow docs for Claude skill bundle.
.claude/skills/unity-mcp-skill/references/tools-reference.md Mirrors ProBuilder tools reference for Claude skill bundle.
.claude/skills/unity-mcp-skill/SKILL.md Mirrors ProBuilder row addition for Claude skill bundle.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +16 to +26
def _parse_edges_param(edges: str) -> dict[str, Any]:
"""Parse edge JSON into either 'edges' (vertex pairs) or 'edgeIndices' (flat indices)."""
import json
try:
parsed = json.loads(edges)
except json.JSONDecodeError:
print_error("Invalid JSON for edges parameter")
raise SystemExit(1)
if parsed and isinstance(parsed[0], dict):
return {"edges": parsed}
return {"edgeIndices": parsed}
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

_parse_edges_param assumes json.loads(edges) returns a list and then indexes parsed[0]. If the user passes a JSON object (e.g. '{"a":0,"b":1}') this will raise at runtime (KeyError/TypeError). Validate that the parsed value is a non-empty list before indexing, and emit a clear CLI error if it's not a list of ints or list of {a,b} objects.

Copilot uses AI. Check for mistakes.
# Get mesh info
unity-mcp probuilder info "MyCube"

# Raw ProBuilder actions (access all 21 actions)
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

This documentation hard-codes "access all 21 actions", but manage_probuilder currently exposes more actions than that. To avoid docs drifting out of date, either update the count to match the actual action list or remove the specific number (e.g., "access all actions").

Suggested change
# Raw ProBuilder actions (access all 21 actions)
# Raw ProBuilder actions (access all actions)

Copilot uses AI. Check for mistakes.
Comment on lines 412 to +413
| `vfx` | `raw` (access all 60+ actions) |
| `probuilder` | `create-shape`, `create-poly`, `info`, `raw` (access all 21 actions) |
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

The command reference table also says ProBuilder raw can "access all 21 actions", which will become inaccurate as actions are added/removed. Prefer removing the numeric count or ensuring it is generated/kept in sync with the actual action list.

Suggested change
| `vfx` | `raw` (access all 60+ actions) |
| `probuilder` | `create-shape`, `create-poly`, `info`, `raw` (access all 21 actions) |
| `vfx` | `raw` (access all VFX actions) |
| `probuilder` | `create-shape`, `create-poly`, `info`, `raw` (access all ProBuilder actions) |

Copilot uses AI. Check for mistakes.

```python
# Basic screenshot (saves to Assets/Screenshots/, returns file path)
# Basic screenshot (saves to Assets/, returns file path only)
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

This says screenshots save to "Assets/", but the implementation (ScreenshotUtility / manage_scene) saves under Assets/Screenshots/. Please update the text so users look in the correct folder and the docs match the tool’s response paths.

Suggested change
# Basic screenshot (saves to Assets/, returns file path only)
# Basic screenshot (saves to Assets/Screenshots/, returns file path only)

Copilot uses AI. Check for mistakes.
Comment on lines +668 to +671
// Force material refresh before capture
EditorApplication.QueuePlayerLoopUpdate();
SceneView.RepaintAll();

Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

Calling EditorApplication.QueuePlayerLoopUpdate() and SceneView.RepaintAll() inside the per-angle loop will scale linearly with the number of tiles and can significantly slow down batch screenshots. Consider moving these refresh calls outside the loop (once before the capture series) or gating them behind a flag when a refresh is actually needed.

Copilot uses AI. Check for mistakes.
Comment on lines +811 to +814
// Force material refresh before capture
EditorApplication.QueuePlayerLoopUpdate();
SceneView.RepaintAll();

Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

Calling EditorApplication.QueuePlayerLoopUpdate() and SceneView.RepaintAll() for every orbit tile can become a major performance bottleneck for larger azimuth/elevation grids. Consider doing a single refresh before the orbit capture (or only when scene content/materials changed) rather than per-frame per-tile.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

@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: 4

♻️ Duplicate comments (4)
unity-mcp-skill/SKILL.md (1)

61-62: ⚠️ Potential issue | 🟡 Minor

Fix the screenshot save location in this example.

manage_scene(action="screenshot") saves into Assets/Screenshots/, not directly into Assets/. Leaving this path wrong will send follow-up asset/file operations to the wrong location.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@unity-mcp-skill/SKILL.md` around lines 61 - 62, The example shows
manage_scene(action="screenshot") saving to Assets/, but the function actually
writes screenshots to Assets/Screenshots/; update the example text to reflect
the correct save location (Assets/Screenshots/) so follow-up asset/file
operations use the right path and continue to mention that the function returns
the file path only; refer to manage_scene(action="screenshot") in the doc
update.
unity-mcp-skill/references/tools-reference.md (1)

806-809: ⚠️ Potential issue | 🟡 Minor

The action catalog is still incomplete for exposed-but-buggy actions.

convert_to_probuilder and set_pivot are valid actions in both Server/src/services/tools/manage_probuilder.py:12-47 and MCPForUnity/Editor/Tools/ProBuilder/ManageProBuilder.cs:179-240, but this reference only mentions them in the “Not Yet Working” caveat block. Since Line 806 tells readers to choose from the categories below, the catalog should either list both actions with an experimental/known-bug note or remove them from the exposed surface entirely.

Also applies to: 849-869

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@unity-mcp-skill/references/tools-reference.md` around lines 806 - 809, The
actions catalog omits two exposed but buggy actions—convert_to_probuilder and
set_pivot—which are implemented and exposed in manage_probuilder.py (functions
handling those actions) and ManageProBuilder.cs (methods around the ProBuilder
management class), so update the reference table to include both actions with an
“experimental / known issues” note (or alternatively remove them from the public
catalog if you want them hidden); specifically add rows for
`convert_to_probuilder` and `set_pivot` in the action table and add a short
parenthetical or footnote linking them to the ManageProBuilder/manage_probuilder
implementations and their known-bug status so readers aren’t misled by the
“choose from the categories below” instruction.
.claude/skills/unity-mcp-skill/references/tools-reference.md (1)

806-809: ⚠️ Potential issue | 🟡 Minor

This catalog still hides two valid actions behind the caveat section.

convert_to_probuilder and set_pivot are accepted actions in both the Python validator and the Unity handler, but this reference omits them from the categorized action list and only mentions them later as broken. That leaves the “choose an action from the categories below” guidance incomplete.

Also applies to: 849-869

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/skills/unity-mcp-skill/references/tools-reference.md around lines
806 - 809, The action catalog table omits two valid
actions—convert_to_probuilder and set_pivot—that are accepted by the Python
validator and Unity handler; update the categorized action list (the sections
referenced by “choose an action from the categories below”) to include these two
action names under the appropriate category, and remove the caveat-only mention
later so the main list is complete; ensure the table row/description for
`action` and any category subsections reference `convert_to_probuilder` and
`set_pivot` with brief descriptions consistent with how other actions are
listed.
docs/guides/CLI_USAGE.md (1)

413-413: ⚠️ Potential issue | 🟡 Minor

Update or remove the hard-coded ProBuilder action count.

unity-mcp probuilder raw exposes far more than 21 actions in Server/src/cli/commands/probuilder.py:670-703, so this reference is already stale. Dropping the parenthetical count entirely would avoid future drift.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/guides/CLI_USAGE.md` at line 413, Remove the hard-coded "(access all 21
actions)" text from the `probuilder` CLI entry in CLI_USAGE.md (or replace it
with a non-count phrase like "access all actions" or a dynamic reference), since
the actual actions are defined in the probuilder command implementation (the
action list used by the `raw` subcommand in probuilder.py) and the number can
change; update the line that contains the `probuilder` entry to drop the
parenthetical count or make it descriptive/dynamic instead.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.claude/skills/unity-mcp-skill/references/tools-reference.md:
- Around line 804-809: Update the tool reference entry for the `properties`
parameter to reflect that it can be either a dict or a JSON string (e.g., "dict
or JSON string") and expand the Description column to note that the server will
accept and parse JSON strings into dicts (see manage_probuilder.py handling
around the `properties` parameter); this ensures the docs match the actual API
behavior and the server-side parsing logic.

In `@MCPForUnity/Editor/Tools/ManageScene.cs`:
- Around line 923-943: The code unconditionally sets fileName to a timestamped
string, ignoring a caller-supplied cmd.fileName; update the save logic to use
cmd.fileName when present (fall back to the timestamped name only if
cmd.fileName is null/empty), ensure the filename has a .png extension, compute
fullPath from that chosen name, keep the existing unique-filename loop that
references baseName/ext, write the bytes to fullPath, and set assetsRelativePath
using Path.GetFileName(fullPath) so callers receive the honored filename (refer
to the variables fileName, cmd.fileName, fullPath, baseName, ext,
assetsRelativePath).
- Line 862: CapturePositionedScreenshot writes the PNG file directly to disk but
doesn't call AssetDatabase.ImportAsset, so the newly created file isn't
registered by Unity until an automatic refresh; update
CapturePositionedScreenshot to call UnityEditor.AssetDatabase.ImportAsset(path)
after successfully writing the PNG (same as the other branches), and ensure the
method returns the imported asset path or the same path after import so the file
is immediately available to editor operations.

In `@unity-mcp-skill/references/tools-reference.md`:
- Around line 804-809: The docs currently list the `properties` parameter as
only `dict`, but the `manage_probuilder` service accepts either a structured
object or a JSON string; update the tools-reference table row for `properties`
to read `dict | JSON string` (or similar concise type union) and add a short
note/example showing both forms; verify against the `manage_probuilder` function
signature/handling to ensure wording matches expected payload parsing and adjust
any examples or schema comments to reflect both accepted shapes.

---

Duplicate comments:
In @.claude/skills/unity-mcp-skill/references/tools-reference.md:
- Around line 806-809: The action catalog table omits two valid
actions—convert_to_probuilder and set_pivot—that are accepted by the Python
validator and Unity handler; update the categorized action list (the sections
referenced by “choose an action from the categories below”) to include these two
action names under the appropriate category, and remove the caveat-only mention
later so the main list is complete; ensure the table row/description for
`action` and any category subsections reference `convert_to_probuilder` and
`set_pivot` with brief descriptions consistent with how other actions are
listed.

In `@docs/guides/CLI_USAGE.md`:
- Line 413: Remove the hard-coded "(access all 21 actions)" text from the
`probuilder` CLI entry in CLI_USAGE.md (or replace it with a non-count phrase
like "access all actions" or a dynamic reference), since the actual actions are
defined in the probuilder command implementation (the action list used by the
`raw` subcommand in probuilder.py) and the number can change; update the line
that contains the `probuilder` entry to drop the parenthetical count or make it
descriptive/dynamic instead.

In `@unity-mcp-skill/references/tools-reference.md`:
- Around line 806-809: The actions catalog omits two exposed but buggy
actions—convert_to_probuilder and set_pivot—which are implemented and exposed in
manage_probuilder.py (functions handling those actions) and ManageProBuilder.cs
(methods around the ProBuilder management class), so update the reference table
to include both actions with an “experimental / known issues” note (or
alternatively remove them from the public catalog if you want them hidden);
specifically add rows for `convert_to_probuilder` and `set_pivot` in the action
table and add a short parenthetical or footnote linking them to the
ManageProBuilder/manage_probuilder implementations and their known-bug status so
readers aren’t misled by the “choose from the categories below” instruction.

In `@unity-mcp-skill/SKILL.md`:
- Around line 61-62: The example shows manage_scene(action="screenshot") saving
to Assets/, but the function actually writes screenshots to Assets/Screenshots/;
update the example text to reflect the correct save location
(Assets/Screenshots/) so follow-up asset/file operations use the right path and
continue to mention that the function returns the file path only; refer to
manage_scene(action="screenshot") in the doc update.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: eaac8b65-4b6e-48ef-8135-a65297b240c8

📥 Commits

Reviewing files that changed from the base of the PR and between fa6b52f and 1acfbe4.

📒 Files selected for processing (7)
  • .claude/skills/unity-mcp-skill/references/tools-reference.md
  • MCPForUnity/Editor/Tools/ManageScene.cs
  • Server/src/cli/utils/constants.py
  • docs/guides/CLI_USAGE.md
  • unity-mcp-skill/SKILL.md
  • unity-mcp-skill/references/probuilder-guide.md
  • unity-mcp-skill/references/tools-reference.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • unity-mcp-skill/references/probuilder-guide.md

Copy link
Contributor

@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.

♻️ Duplicate comments (2)
unity-mcp-skill/references/tools-reference.md (1)

867-869: ⚠️ Potential issue | 🟡 Minor

Document these actions consistently, or hide them consistently.

set_pivot and convert_to_probuilder are valid action names (present in UTILITY_ACTIONS and QUERY_ACTIONS respectively per Server/src/services/tools/manage_probuilder.py:12-47) that pass server validation, but they are omitted from the main action catalog above. The current documentation only mentions them in this caveats section with no parameter shape.

Either:

  1. Add entries for set_pivot (under Mesh Utilities) and convert_to_probuilder (under Query) to the main catalog with their parameter signatures and mark them as "⚠️ experimental/broken" with a link to this caveat, OR
  2. Remove these action names from the public reference entirely until they are fully supported

The current approach—mentioning them only in caveats—misleads readers about which actions are available, even if buggy.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@unity-mcp-skill/references/tools-reference.md` around lines 867 - 869, The
doc currently omits two valid action names—set_pivot and
convert_to_probuilder—that exist in UTILITY_ACTIONS and QUERY_ACTIONS (see
manage_probuilder module) and pass server validation; either add canonical
entries for set_pivot (under Mesh Utilities) and convert_to_probuilder (under
Query) to the main action catalog including their parameter signatures and a
clear "⚠️ experimental/broken" label linking to the caveats section, or remove
those names from the public reference entirely so the catalog matches what is
supported; update the catalog entries or the caveat text accordingly so the main
action list and UTILITY_ACTIONS/QUERY_ACTIONS remain consistent.
MCPForUnity/Editor/Tools/ManageScene.cs (1)

923-943: ⚠️ Potential issue | 🟡 Minor

Honor cmd.fileName here too.

This branch still hardcodes a timestamped name, so positioned captures ignore caller-selected output names while the other screenshot flows respect them.

Suggested fix
-                    string fileName = $"screenshot-{DateTime.Now:yyyyMMdd-HHmmss}.png";
+                    string baseFileName = string.IsNullOrWhiteSpace(cmd.fileName)
+                        ? $"screenshot-{DateTime.Now:yyyyMMdd-HHmmss}"
+                        : Path.GetFileNameWithoutExtension(cmd.fileName);
+                    string fileName = $"{baseFileName}.png";
                     string fullPath = Path.Combine(screenshotsFolder, fileName);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@MCPForUnity/Editor/Tools/ManageScene.cs` around lines 923 - 943, The
save-to-disk branch currently hardcodes a timestamped fileName (using DateTime)
instead of honoring the caller-provided cmd.fileName; update the creation of
fileName/fullPath so that if cmd.fileName is non-empty you use that (ensure it
has a .png extension), otherwise fall back to the timestamped name, then
continue the uniqueness loop that updates fullPath and finally write pngBytes as
before; look for symbols screenshotsFolder, fileName, fullPath, cmd.fileName,
b64 and preserve the existing File.Exists uniqueness logic and
assetsRelativePath = "Assets/Screenshots/" + Path.GetFileName(fullPath).
🧹 Nitpick comments (3)
unity-mcp-skill/references/tools-reference.md (2)

800-800: Clarify when ProBuilder preference applies.

The guidance to "prefer ProBuilder over primitive GameObjects" is broad. This advice is most valuable for editable geometry, multi-material surfaces, or complex shapes, but adds unnecessary overhead for simple static primitives. Consider qualifying the preference with criteria such as "when geometry editing, face-level materials, or complex shapes are needed" to help agents make context-appropriate choices.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@unity-mcp-skill/references/tools-reference.md` at line 800, The guidance line
"prefer ProBuilder over primitive GameObjects" is too broad; update the sentence
in the tools-reference text so it qualifies when ProBuilder should be preferred
by adding criteria like "when geometry editing, face-level/multi-material
surfaces, or complex shapes are needed" and note that simple static primitives
can remain as GameObjects; reference the existing phrase "prefer ProBuilder over
primitive GameObjects" and the package mention "com.unity.probuilder" when
making this clarification.

809-809: Specify "JSON string" for clarity.

The properties parameter is documented as dict | string, but the server accepts structured objects or JSON strings. Using "JSON string" instead of "string" would clarify the expected serialized format and align with the implementation in Server/src/services/tools/manage_probuilder.py:113-127.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@unity-mcp-skill/references/tools-reference.md` at line 809, Update the tools
reference entry for the properties parameter to use "JSON string" instead of
"string" so it clearly documents the serialized format accepted by the server;
specifically change the table cell for `properties` to "dict | JSON string" and
ensure the description still mentions action-specific parameters (dict or JSON
string) to align with the implementation in manage_probuilder.py where the
server accepts structured objects or JSON-serialized strings.
MCPForUnity/Editor/Tools/ManageScene.cs (1)

946-959: Keep the asset-path key consistent with the other screenshot responses.

The camera/default screenshot branches return path, but this branch only emits filePath. Server/src/services/tools/manage_scene.py:16-64 forwards that payload to clients as-is, so positioned captures become the only single-image screenshot response with a different asset-path key. Consider keeping path as the canonical field and adding filePath only as an alias if you want the new name.

Suggested fix
                     var data = new Dictionary<string, object>
                     {
+                        { "path", assetsRelativePath },
                         { "imageBase64", b64 },
                         { "imageWidth", w },
                         { "imageHeight", h },
                         { "viewPosition", new[] { camPos.x, camPos.y, camPos.z } },
                         { "screenshotsFolder", screenshotsFolder },
                         { "filePath", assetsRelativePath },
                     };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@MCPForUnity/Editor/Tools/ManageScene.cs` around lines 946 - 959, The response
payload for positioned screenshots uses the key "filePath" which is inconsistent
with other branches that use "path"; update the dictionary construction in
ManageScene (the block building 'data' around
imageBase64/imageWidth/imageHeight/viewPosition/screenshotsFolder) to include
"path" with the same assetsRelativePath value (and optionally also set
"filePath" = assetsRelativePath if you want an alias), so clients receive the
canonical "path" field like the camera/default screenshot responses before
returning the SuccessResponse.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@MCPForUnity/Editor/Tools/ManageScene.cs`:
- Around line 923-943: The save-to-disk branch currently hardcodes a timestamped
fileName (using DateTime) instead of honoring the caller-provided cmd.fileName;
update the creation of fileName/fullPath so that if cmd.fileName is non-empty
you use that (ensure it has a .png extension), otherwise fall back to the
timestamped name, then continue the uniqueness loop that updates fullPath and
finally write pngBytes as before; look for symbols screenshotsFolder, fileName,
fullPath, cmd.fileName, b64 and preserve the existing File.Exists uniqueness
logic and assetsRelativePath = "Assets/Screenshots/" +
Path.GetFileName(fullPath).

In `@unity-mcp-skill/references/tools-reference.md`:
- Around line 867-869: The doc currently omits two valid action names—set_pivot
and convert_to_probuilder—that exist in UTILITY_ACTIONS and QUERY_ACTIONS (see
manage_probuilder module) and pass server validation; either add canonical
entries for set_pivot (under Mesh Utilities) and convert_to_probuilder (under
Query) to the main action catalog including their parameter signatures and a
clear "⚠️ experimental/broken" label linking to the caveats section, or remove
those names from the public reference entirely so the catalog matches what is
supported; update the catalog entries or the caveat text accordingly so the main
action list and UTILITY_ACTIONS/QUERY_ACTIONS remain consistent.

---

Nitpick comments:
In `@MCPForUnity/Editor/Tools/ManageScene.cs`:
- Around line 946-959: The response payload for positioned screenshots uses the
key "filePath" which is inconsistent with other branches that use "path"; update
the dictionary construction in ManageScene (the block building 'data' around
imageBase64/imageWidth/imageHeight/viewPosition/screenshotsFolder) to include
"path" with the same assetsRelativePath value (and optionally also set
"filePath" = assetsRelativePath if you want an alias), so clients receive the
canonical "path" field like the camera/default screenshot responses before
returning the SuccessResponse.

In `@unity-mcp-skill/references/tools-reference.md`:
- Line 800: The guidance line "prefer ProBuilder over primitive GameObjects" is
too broad; update the sentence in the tools-reference text so it qualifies when
ProBuilder should be preferred by adding criteria like "when geometry editing,
face-level/multi-material surfaces, or complex shapes are needed" and note that
simple static primitives can remain as GameObjects; reference the existing
phrase "prefer ProBuilder over primitive GameObjects" and the package mention
"com.unity.probuilder" when making this clarification.
- Line 809: Update the tools reference entry for the properties parameter to use
"JSON string" instead of "string" so it clearly documents the serialized format
accepted by the server; specifically change the table cell for `properties` to
"dict | JSON string" and ensure the description still mentions action-specific
parameters (dict or JSON string) to align with the implementation in
manage_probuilder.py where the server accepts structured objects or
JSON-serialized strings.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e6548e05-56d8-4d57-b579-2ec1ebb097e7

📥 Commits

Reviewing files that changed from the base of the PR and between 1acfbe4 and 5bd3a22.

📒 Files selected for processing (2)
  • MCPForUnity/Editor/Tools/ManageScene.cs
  • unity-mcp-skill/references/tools-reference.md

@Scriptwonder Scriptwonder merged commit 1cd1807 into CoplayDev:beta Mar 6, 2026
1 check 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