-
Notifications
You must be signed in to change notification settings - Fork 897
Pr 980 #993
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pr 980 #993
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -905,6 +905,21 @@ private static (bool modified, ErrorResponse error) ApplyModificationsToPrefabOb | |||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| // Delete child GameObjects (supports single string or array of paths/names) | ||||||||||||||||||||||||||||||||||||||||||||||
| JToken deleteChildToken = @params["deleteChild"] ?? @params["delete_child"]; | ||||||||||||||||||||||||||||||||||||||||||||||
| if (deleteChildToken != null) | ||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||
| var deleteResult = RemoveChildren(deleteChildToken, targetGo, prefabRoot); | ||||||||||||||||||||||||||||||||||||||||||||||
| if (deleteResult.error != null) | ||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||
| return (false, deleteResult.error); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| if (deleteResult.removedCount > 0) | ||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||
| modified = true; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| // Set properties on existing components | ||||||||||||||||||||||||||||||||||||||||||||||
| JObject componentProperties = @params["componentProperties"] as JObject ?? @params["component_properties"] as JObject; | ||||||||||||||||||||||||||||||||||||||||||||||
| if (componentProperties != null && componentProperties.Count > 0) | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -1132,6 +1147,47 @@ private static (bool created, ErrorResponse error) CreateSingleChildInPrefab(JTo | |||||||||||||||||||||||||||||||||||||||||||||
| return (true, null); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| /// <summary> | ||||||||||||||||||||||||||||||||||||||||||||||
| /// Removes child GameObjects from a prefab. | ||||||||||||||||||||||||||||||||||||||||||||||
| /// </summary> | ||||||||||||||||||||||||||||||||||||||||||||||
| private static (int removedCount, ErrorResponse error) RemoveChildren(JToken deleteChildToken, GameObject targetGo, GameObject prefabRoot) | ||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||
| int removedCount = 0; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| // Normalize to array | ||||||||||||||||||||||||||||||||||||||||||||||
| JArray childrenToDelete; | ||||||||||||||||||||||||||||||||||||||||||||||
| if (deleteChildToken is JArray arr) | ||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||
| childrenToDelete = arr; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||
| childrenToDelete = new JArray { deleteChildToken }; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| foreach (var childToken in childrenToDelete) | ||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||
| string childPath = childToken.Type == JTokenType.String ? childToken.ToString() : childToken["name"]?.ToString(); | ||||||||||||||||||||||||||||||||||||||||||||||
| if (string.IsNullOrEmpty(childPath)) | ||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||
| return (removedCount, new ErrorResponse("'deleteChild'/'delete_child' entries must be a string or object with 'name' field.")); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| // Find the child to remove | ||||||||||||||||||||||||||||||||||||||||||||||
| Transform childToRemove = targetGo.transform.Find(childPath); | ||||||||||||||||||||||||||||||||||||||||||||||
| if (childToRemove == null) | ||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||
| return (removedCount, new ErrorResponse($"Child '{childPath}' not found under '{targetGo.name}'.")); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1176
to
+1181
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Accept the same root-prefixed paths that The Example normalization- Transform childToRemove = targetGo.transform.Find(childPath);
+ string normalizedPath = childPath;
+ if (normalizedPath.StartsWith(prefabRoot.name + "/", StringComparison.Ordinal))
+ {
+ normalizedPath = normalizedPath.Substring(prefabRoot.name.Length + 1);
+ }
+ if (normalizedPath.StartsWith(targetGo.name + "/", StringComparison.Ordinal))
+ {
+ normalizedPath = normalizedPath.Substring(targetGo.name.Length + 1);
+ }
+
+ Transform childToRemove = targetGo.transform.Find(normalizedPath);
if (childToRemove == null)
{
return (removedCount, new ErrorResponse($"Child '{childPath}' not found under '{targetGo.name}'."));
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| UnityEngine.Object.DestroyImmediate(childToRemove.gameObject); | ||||||||||||||||||||||||||||||||||||||||||||||
| removedCount++; | ||||||||||||||||||||||||||||||||||||||||||||||
| McpLog.Info($"[ManagePrefabs] Removed child '{childPath}' under '{targetGo.name}' in prefab."); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| return (removedCount, null); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| #endregion | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| #region Hierarchy Builder | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -560,6 +560,15 @@ unity-mcp prefab save | |||||||||||||
|
|
||||||||||||||
| # Close prefab stage | ||||||||||||||
| unity-mcp prefab close | ||||||||||||||
|
|
||||||||||||||
| # Modify prefab contents (headless) | ||||||||||||||
| unity-mcp prefab modify "Assets/Prefabs/Player.prefab" --target Weapon --position "0,1,2" | ||||||||||||||
| unity-mcp prefab modify "Assets/Prefabs/Player.prefab" --delete-child Child1 --delete-child "Turret/Barrel" | ||||||||||||||
|
Comment on lines
+565
to
+566
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Clarify the vector syntax exception for Line 565 uses CSV ( ✏️ Suggested doc tweak # Modify prefab contents (headless)
+# Note: `prefab modify --position` expects CSV string format (`"x,y,z"`), unlike gameobject multi-value options.
unity-mcp prefab modify "Assets/Prefabs/Player.prefab" --target Weapon --position "0,1,2"📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||
| unity-mcp prefab modify "Assets/Prefabs/Player.prefab" --set-property "Rigidbody.mass=5" | ||||||||||||||
| unity-mcp prefab modify "Assets/Prefabs/Player.prefab" --add-component BoxCollider --remove-component SphereCollider | ||||||||||||||
| unity-mcp prefab modify "Assets/Prefabs/Player.prefab" --create-child '{"name":"Spawn","primitive_type":"Sphere"}' | ||||||||||||||
| unity-mcp prefab modify "Assets/Prefabs/Player.prefab" --name NewName --tag Player --layer UI | ||||||||||||||
| unity-mcp prefab modify "Assets/Prefabs/Player.prefab" --inactive | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| ### UI Commands | ||||||||||||||
|
|
||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,5 +1,6 @@ | ||||||||||||||||||||||||||||||||||||||||||||||
| """Prefab CLI commands.""" | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| import json | ||||||||||||||||||||||||||||||||||||||||||||||
| import sys | ||||||||||||||||||||||||||||||||||||||||||||||
| import click | ||||||||||||||||||||||||||||||||||||||||||||||
| from typing import Optional, Any | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -246,3 +247,132 @@ def create(target: str, path: str, overwrite: bool, include_inactive: bool, unli | |||||||||||||||||||||||||||||||||||||||||||||
| click.echo(format_output(result, config.format)) | ||||||||||||||||||||||||||||||||||||||||||||||
| if result.get("success"): | ||||||||||||||||||||||||||||||||||||||||||||||
| print_success(f"Created prefab: {path}") | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| def _parse_vector3(value: str) -> list[float]: | ||||||||||||||||||||||||||||||||||||||||||||||
| """Parse 'x,y,z' string to list of floats.""" | ||||||||||||||||||||||||||||||||||||||||||||||
| parts = value.split(",") | ||||||||||||||||||||||||||||||||||||||||||||||
| if len(parts) != 3: | ||||||||||||||||||||||||||||||||||||||||||||||
| raise click.BadParameter("Must be 'x,y,z' format") | ||||||||||||||||||||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||||||||||||||||||||
| return [float(p.strip()) for p in parts] | ||||||||||||||||||||||||||||||||||||||||||||||
| except ValueError as e: | ||||||||||||||||||||||||||||||||||||||||||||||
| raise click.BadParameter(f"All components must be numeric, got: '{value}'") from e | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| def _parse_property(prop_str: str) -> tuple[str, str, Any]: | ||||||||||||||||||||||||||||||||||||||||||||||
| """Parse 'Component.prop=value' into (component, prop, value).""" | ||||||||||||||||||||||||||||||||||||||||||||||
| if "=" not in prop_str: | ||||||||||||||||||||||||||||||||||||||||||||||
| raise click.BadParameter("Must be 'Component.prop=value' format") | ||||||||||||||||||||||||||||||||||||||||||||||
| comp_prop, val_str = prop_str.split("=", 1) | ||||||||||||||||||||||||||||||||||||||||||||||
| if "." not in comp_prop: | ||||||||||||||||||||||||||||||||||||||||||||||
| raise click.BadParameter("Must be 'Component.prop=value' format") | ||||||||||||||||||||||||||||||||||||||||||||||
| component, prop = comp_prop.rsplit(".", 1) | ||||||||||||||||||||||||||||||||||||||||||||||
| if not component.strip() or not prop.strip(): | ||||||||||||||||||||||||||||||||||||||||||||||
| raise click.BadParameter(f"Component and property must be non-empty in '{comp_prop}', expected 'Component.prop=value'") | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| val_str = val_str.strip() | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| # Parse booleans | ||||||||||||||||||||||||||||||||||||||||||||||
| if val_str.lower() == "true": | ||||||||||||||||||||||||||||||||||||||||||||||
| parsed_value: Any = True | ||||||||||||||||||||||||||||||||||||||||||||||
| elif val_str.lower() == "false": | ||||||||||||||||||||||||||||||||||||||||||||||
| parsed_value = False | ||||||||||||||||||||||||||||||||||||||||||||||
| # Parse numbers | ||||||||||||||||||||||||||||||||||||||||||||||
| elif "." in val_str: | ||||||||||||||||||||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||||||||||||||||||||
| parsed_value = float(val_str) | ||||||||||||||||||||||||||||||||||||||||||||||
| except ValueError: | ||||||||||||||||||||||||||||||||||||||||||||||
| parsed_value = val_str | ||||||||||||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||||||||||||||||||||
| parsed_value = int(val_str) | ||||||||||||||||||||||||||||||||||||||||||||||
| except ValueError: | ||||||||||||||||||||||||||||||||||||||||||||||
| parsed_value = val_str | ||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+281
to
+291
|
||||||||||||||||||||||||||||||||||||||||||||||
| # Parse numbers | |
| elif "." in val_str: | |
| try: | |
| parsed_value = float(val_str) | |
| except ValueError: | |
| parsed_value = val_str | |
| else: | |
| try: | |
| parsed_value = int(val_str) | |
| except ValueError: | |
| parsed_value = val_str | |
| else: | |
| # Parse numbers: try int first, then float; fall back to string | |
| parsed_value = val_str | |
| try: | |
| parsed_value = int(val_str) | |
| except ValueError: | |
| try: | |
| parsed_value = float(val_str) | |
| except ValueError: | |
| # Leave as original string if not numeric | |
| parsed_value = val_str |
Copilot
AI
Mar 27, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These lines include trailing whitespace on otherwise blank lines, which commonly fails linters/formatters and creates noisy diffs. Remove the trailing spaces or run the repo formatter so blank lines are truly empty.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -29,6 +29,9 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "(single object or array for batch creation in one save). " | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Example: create_child=[{\"name\": \"Child1\", \"primitive_type\": \"Sphere\", \"position\": [1,0,0]}, " | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "{\"name\": \"Nested\", \"source_prefab_path\": \"Assets/Prefabs/Bullet.prefab\", \"position\": [0,2,0]}]. " | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Use delete_child parameter to remove child GameObjects from the prefab " | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "(single name/path or array of paths for batch deletion. " | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Example: delete_child=[\"Child1\", \"Child2/Grandchild\"]). " | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Use component_properties with modify_contents to set serialized fields on existing components " | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "(e.g. component_properties={\"Rigidbody\": {\"mass\": 5.0}, \"MyScript\": {\"health\": 100}}). " | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "Supports object references via {\"guid\": \"...\"}, {\"path\": \"Assets/...\"}, or {\"instanceID\": 123}. " | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -67,6 +70,7 @@ async def manage_prefabs( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| components_to_add: Annotated[list[str], "Component types to add in modify_contents."] | None = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| components_to_remove: Annotated[list[str], "Component types to remove in modify_contents."] | None = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| create_child: Annotated[dict[str, Any] | list[dict[str, Any]], "Create child GameObject(s) in the prefab. Single object or array of objects, each with: name (required), parent (optional, defaults to target), source_prefab_path (optional: asset path to instantiate as nested prefab, e.g. 'Assets/Prefabs/Bullet.prefab'), primitive_type (optional: Cube, Sphere, Capsule, Cylinder, Plane, Quad), position, rotation, scale, components_to_add, tag, layer, set_active. source_prefab_path and primitive_type are mutually exclusive."] | None = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| delete_child: Annotated[str | list[str], "Child name(s) or path(s) to remove from the prefab. Supports single string or array for batch deletion (e.g. 'Child1' or ['Child1', 'Child1/Grandchild'])."] | None = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| component_properties: Annotated[dict[str, dict[str, Any]], "Set properties on existing components in modify_contents. Keys are component type names, values are dicts of property name to value. Example: {\"Rigidbody\": {\"mass\": 5.0}, \"MyScript\": {\"health\": 100}}. Supports object references via {\"guid\": \"...\"}, {\"path\": \"Assets/...\"}, or {\"instanceID\": 123}. For Sprite sub-assets: {\"guid\": \"...\", \"spriteName\": \"<name>\"}. Single-sprite textures auto-resolve."] | None = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> dict[str, Any]: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Back-compat: map 'name' → 'target' for create_from_gameobject (Unity accepts both) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -185,6 +189,9 @@ def normalize_child_params(child: Any, index: int | None = None) -> tuple[dict | | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return {"success": False, "message": err} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| params["createChild"] = child_params | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if delete_child is not None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| params["deleteChild"] = delete_child | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+192
to
+193
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if delete_child is not None: | |
| params["deleteChild"] = delete_child | |
| def normalize_delete_child_paths(delete_child_val: Any) -> tuple[Any | None, str | None]: | |
| """ | |
| Validate and normalize the delete_child parameter. | |
| - Accepts either a single non-empty string path or a list of non-empty string paths. | |
| - Returns (normalized_value, None) on success, or (None, error_message) on failure. | |
| """ | |
| # Single path as string | |
| if isinstance(delete_child_val, str): | |
| if not delete_child_val.strip(): | |
| return None, "delete_child must be a non-empty string path" | |
| return delete_child_val, None | |
| # List of paths | |
| if isinstance(delete_child_val, list): | |
| for i, item in enumerate(delete_child_val): | |
| if not isinstance(item, str): | |
| return None, f"delete_child[{i}] must be a non-empty string path, got {type(item).__name__}" | |
| if not item.strip(): | |
| return None, f"delete_child[{i}] must be a non-empty string path" | |
| # Preserve original list type to avoid changing behavior for valid inputs | |
| return delete_child_val, None | |
| # Unsupported type | |
| return None, f"delete_child must be a string path or list of string paths, got {type(delete_child_val).__name__}" | |
| if delete_child is not None: | |
| normalized_delete_child, delete_child_err = normalize_delete_child_paths(delete_child) | |
| if delete_child_err: | |
| return {"success": False, "message": delete_child_err} | |
| params["deleteChild"] = normalized_delete_child |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
In Newtonsoft.Json.Linq, does accessingtoken["name"]on aJValueorJArraythrow, and if so which exception type?💡 Result:
Yes, accessing token["name"] on a JValue throws an exception. It throws InvalidOperationException with the message "Cannot access child value on Newtonsoft.Json.Linq.JValue." For JArray, accessing token["name"] (string key) throws InvalidOperationException or ArgumentException with a message like "Accessed array values with invalid key value: 'name'. Int32 array index expected." JArray's indexer expects integer indices for elements, not string property names.
Citations:
🏁 Script executed:
Repository: CoplayDev/unity-mcp
Length of output: 1411
🏁 Script executed:
Repository: CoplayDev/unity-mcp
Length of output: 2759
🏁 Script executed:
Repository: CoplayDev/unity-mcp
Length of output: 521
🏁 Script executed:
Repository: CoplayDev/unity-mcp
Length of output: 136
🏁 Script executed:
Repository: CoplayDev/unity-mcp
Length of output: 1395
🏁 Script executed:
Repository: CoplayDev/unity-mcp
Length of output: 603
🏁 Script executed:
Repository: CoplayDev/unity-mcp
Length of output: 2162
Type-check
deleteChildentries before reading["name"].For non-object entries like
123orfalse, accessingchildToken["name"]throwsInvalidOperationException(onJValue) orArgumentException(onJArray) before the validation check runs. This unhandled exception propagates to the top-level action handler, causing callers to receiveInternal errorinstead of the intended error message. Use anis JObjecttype-check to safely handle the property access:Safer token handling
🤖 Prompt for AI Agents