You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* feat: migrate to FastMCP 2.0 (v2.12.5)
- Update pyproject.toml to use fastmcp>=2.12.5 instead of mcp[cli]
- Replace all imports from mcp.server.fastmcp to fastmcp
- Maintain MCP protocol compliance with mcp>=1.16.0
- All 15 files updated with new import statements
- Server and tools registration working with FastMCP 2.0
* chore: bump MCP for Unity to 6.2.2 and widen numeric tool params (asset search/read_resource/run_tests) for better LLM compatibility
* chore: bump installed server_version.txt to 6.2.2 so Unity installer logs correct version
* fix(parameters): apply parameter hardening to read_console, manage_editor, and manage_gameobject
- read_console: accept int|str for count parameter with coercion
- manage_editor: accept bool|str for wait_for_completion with coercion
- manage_gameobject: accept bool|str for all boolean parameters with coercion
- All tools now handle string parameters gracefully and convert to proper types internally
* chore(deps): drop fastmcp, use mcp>=1.18.0; update imports to mcp.server.fastmcp
* chore(deps): re-add fastmcp>=2.12.5, relax mcp to >=1.16.0
Adds fastmcp as explicit dependency for FastMCP 2.0 migration.
Relaxes mcp version constraint to support broader compatibility.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* test: remove obsolete mcp stubs for FastMCP 2.0 compatibility
Removes stub mcp modules from test files that were conflicting with
the real mcp and fastmcp packages now installed as dependencies.
Adds tests/__init__.py to make tests a proper Python package.
This fixes test collection errors after migrating to FastMCP 2.0.
Test results: 40 passed, 7 xpassed, 5 skipped, 1 failed (pre-existing)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: complete FastMCP 2.0 migration with correct import paths
Updates all remaining files to use `from fastmcp import` instead of
the old `from mcp.server.fastmcp import` path.
Changes:
- server.py: Update FastMCP import
- tools/__init__.py: Update FastMCP import
- resources/__init__.py: Update FastMCP import
- tools/manage_script.py, read_console.py, resource_tools.py: Update imports
- test stubs: Update to stub `fastmcp` instead of `mcp.server.fastmcp`
Addresses PR review feedback about incomplete migration.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: harden parameter type handling and resolve PR feedback
Parameter Type Improvements:
- Broaden count in read_console.py to accept int | str
- Broaden build_index in manage_scene.py to accept int | str
- Harden vector parsing in manage_gameobject.py with NaN/Inf checks
- Add whitespace-delimited vector support (e.g., "1 2 3")
- Narrow exception handling from Exception to (ValueError, TypeError)
Test Improvements:
- Harden _load_module in test files with spec/loader validation
- Fix test_manage_gameobject_boolean_and_tag_mapping by mapping tag→search_term
Bug Fixes:
- Fix syntax error in manage_shader.py (remove stray 'x')
Version: Bump to 6.2.3
All tests pass: 41 passed, 5 skipped, 7 xpassed
---------
Co-authored-by: Claude <noreply@anthropic.com>
description="Controls and queries the Unity editor's state and settings"
10
+
description="Controls and queries the Unity editor's state and settings. Tip: pass booleans as true/false; if your client only sends strings, 'true'/'false' are accepted."
Copy file name to clipboardExpand all lines: MCPForUnity/UnityMcpServer~/src/tools/manage_gameobject.py
+72-20Lines changed: 72 additions & 20 deletions
Original file line number
Diff line number
Diff line change
@@ -1,12 +1,12 @@
1
1
fromtypingimportAnnotated, Any, Literal
2
2
3
-
frommcp.server.fastmcpimportContext
3
+
fromfastmcpimportContext
4
4
fromregistryimportmcp_for_unity_tool
5
5
fromunity_connectionimportsend_command_with_retry
6
6
7
7
8
8
@mcp_for_unity_tool(
9
-
description="Manage GameObjects. Note: for 'get_components', the `data` field contains a dictionary of component names and their serialized properties. For 'get_component', specify 'component_name' to retrieve only that component's serialized data."
9
+
description="Manage GameObjects. For booleans, send true/false; if your client only sends strings, 'true'/'false' are accepted. Vectors may be [x,y,z] or a string like '[x,y,z]'. For 'get_components', the `data` field contains a dictionary of component names and their serialized properties. For 'get_component', specify 'component_name' to retrieve only that component's serialized data."
10
10
)
11
11
defmanage_gameobject(
12
12
ctx: Context,
@@ -21,24 +21,24 @@ def manage_gameobject(
21
21
"Tag name - used for both 'create' (initial tag) and 'modify' (change tag)"] |None=None,
22
22
parent: Annotated[str,
23
23
"Parent GameObject reference - used for both 'create' (initial parent) and 'modify' (change parent)"] |None=None,
24
-
position: Annotated[list[float],
25
-
"Position - used for both 'create' (initial position) and 'modify' (change position)"] |None=None,
26
-
rotation: Annotated[list[float],
27
-
"Rotation - used for both 'create' (initial rotation) and 'modify' (change rotation)"] |None=None,
28
-
scale: Annotated[list[float],
29
-
"Scale - used for both 'create' (initial scale) and 'modify' (change scale)"] |None=None,
24
+
position: Annotated[list[float]|str,
25
+
"Position - [x,y,z] or string '[x,y,z]' for client compatibility"] |None=None,
26
+
rotation: Annotated[list[float]|str,
27
+
"Rotation - [x,y,z] or string '[x,y,z]' for client compatibility"] |None=None,
28
+
scale: Annotated[list[float]|str,
29
+
"Scale - [x,y,z] or string '[x,y,z]' for client compatibility"] |None=None,
30
30
components_to_add: Annotated[list[str],
31
31
"List of component names to add"] |None=None,
32
32
primitive_type: Annotated[str,
33
33
"Primitive type for 'create' action"] |None=None,
34
-
save_as_prefab: Annotated[bool,
35
-
"If True, saves the created GameObject as a prefab"] |None=None,
34
+
save_as_prefab: Annotated[bool|str,
35
+
"If True, saves the created GameObject as a prefab (accepts true/false or 'true'/'false')"] |None=None,
36
36
prefab_path: Annotated[str, "Path for prefab creation"] |None=None,
37
37
prefab_folder: Annotated[str,
38
38
"Folder for prefab creation"] |None=None,
39
39
# --- Parameters for 'modify' ---
40
-
set_active: Annotated[bool,
41
-
"If True, sets the GameObject active"] |None=None,
40
+
set_active: Annotated[bool|str,
41
+
"If True, sets the GameObject active (accepts true/false or 'true'/'false')"] |None=None,
42
42
layer: Annotated[str, "Layer name"] |None=None,
43
43
components_to_remove: Annotated[list[str],
44
44
"List of component names to remove"] |None=None,
@@ -51,21 +51,73 @@ def manage_gameobject(
51
51
# --- Parameters for 'find' ---
52
52
search_term: Annotated[str,
53
53
"Search term for 'find' action ONLY. Use this (not 'name') when searching for GameObjects."] |None=None,
54
-
find_all: Annotated[bool,
55
-
"If True, finds all GameObjects matching the search term"] |None=None,
56
-
search_in_children: Annotated[bool,
57
-
"If True, searches in children of the GameObject"] |None=None,
0 commit comments