mcpforunityserver 8.5.0__py3-none-any.whl → 9.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. cli/__init__.py +3 -0
  2. cli/commands/__init__.py +3 -0
  3. cli/commands/animation.py +87 -0
  4. cli/commands/asset.py +310 -0
  5. cli/commands/audio.py +133 -0
  6. cli/commands/batch.py +184 -0
  7. cli/commands/code.py +189 -0
  8. cli/commands/component.py +212 -0
  9. cli/commands/editor.py +487 -0
  10. cli/commands/gameobject.py +510 -0
  11. cli/commands/instance.py +101 -0
  12. cli/commands/lighting.py +128 -0
  13. cli/commands/material.py +268 -0
  14. cli/commands/prefab.py +144 -0
  15. cli/commands/scene.py +255 -0
  16. cli/commands/script.py +240 -0
  17. cli/commands/shader.py +238 -0
  18. cli/commands/ui.py +263 -0
  19. cli/commands/vfx.py +439 -0
  20. cli/main.py +248 -0
  21. cli/utils/__init__.py +31 -0
  22. cli/utils/config.py +58 -0
  23. cli/utils/connection.py +191 -0
  24. cli/utils/output.py +195 -0
  25. main.py +207 -62
  26. {mcpforunityserver-8.5.0.dist-info → mcpforunityserver-9.1.0.dist-info}/METADATA +4 -2
  27. mcpforunityserver-9.1.0.dist-info/RECORD +96 -0
  28. {mcpforunityserver-8.5.0.dist-info → mcpforunityserver-9.1.0.dist-info}/WHEEL +1 -1
  29. {mcpforunityserver-8.5.0.dist-info → mcpforunityserver-9.1.0.dist-info}/entry_points.txt +1 -0
  30. {mcpforunityserver-8.5.0.dist-info → mcpforunityserver-9.1.0.dist-info}/top_level.txt +1 -2
  31. services/custom_tool_service.py +179 -19
  32. services/resources/__init__.py +6 -1
  33. services/resources/active_tool.py +1 -1
  34. services/resources/custom_tools.py +2 -2
  35. services/resources/editor_state.py +283 -21
  36. services/resources/gameobject.py +243 -0
  37. services/resources/layers.py +1 -1
  38. services/resources/prefab_stage.py +1 -1
  39. services/resources/project_info.py +1 -1
  40. services/resources/selection.py +1 -1
  41. services/resources/tags.py +1 -1
  42. services/resources/unity_instances.py +1 -1
  43. services/resources/windows.py +1 -1
  44. services/state/external_changes_scanner.py +245 -0
  45. services/tools/__init__.py +6 -1
  46. services/tools/batch_execute.py +24 -9
  47. services/tools/debug_request_context.py +8 -2
  48. services/tools/execute_custom_tool.py +6 -1
  49. services/tools/execute_menu_item.py +6 -3
  50. services/tools/find_gameobjects.py +89 -0
  51. services/tools/find_in_file.py +26 -19
  52. services/tools/manage_asset.py +19 -43
  53. services/tools/manage_components.py +131 -0
  54. services/tools/manage_editor.py +9 -8
  55. services/tools/manage_gameobject.py +120 -79
  56. services/tools/manage_material.py +80 -31
  57. services/tools/manage_prefabs.py +7 -1
  58. services/tools/manage_scene.py +34 -13
  59. services/tools/manage_script.py +62 -19
  60. services/tools/manage_scriptable_object.py +22 -10
  61. services/tools/manage_shader.py +8 -1
  62. services/tools/manage_vfx.py +738 -0
  63. services/tools/preflight.py +110 -0
  64. services/tools/read_console.py +81 -18
  65. services/tools/refresh_unity.py +153 -0
  66. services/tools/run_tests.py +202 -41
  67. services/tools/script_apply_edits.py +15 -7
  68. services/tools/set_active_instance.py +12 -7
  69. services/tools/utils.py +60 -6
  70. transport/legacy/port_discovery.py +2 -2
  71. transport/legacy/unity_connection.py +129 -26
  72. transport/plugin_hub.py +191 -19
  73. transport/unity_instance_middleware.py +93 -2
  74. transport/unity_transport.py +17 -6
  75. utils/focus_nudge.py +321 -0
  76. __init__.py +0 -0
  77. mcpforunityserver-8.5.0.dist-info/RECORD +0 -66
  78. routes/__init__.py +0 -0
  79. {mcpforunityserver-8.5.0.dist-info → mcpforunityserver-9.1.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,128 @@
1
+ """Lighting CLI commands."""
2
+
3
+ import sys
4
+ import click
5
+ from typing import Optional, Tuple
6
+
7
+ from cli.utils.config import get_config
8
+ from cli.utils.output import format_output, print_error, print_success
9
+ from cli.utils.connection import run_command, UnityConnectionError
10
+
11
+
12
+ @click.group()
13
+ def lighting():
14
+ """Lighting operations - create, modify lights and lighting settings."""
15
+ pass
16
+
17
+
18
+ @lighting.command("create")
19
+ @click.argument("name")
20
+ @click.option(
21
+ "--type", "-t",
22
+ "light_type",
23
+ type=click.Choice(["Directional", "Point", "Spot", "Area"]),
24
+ default="Point",
25
+ help="Type of light to create."
26
+ )
27
+ @click.option(
28
+ "--position", "-pos",
29
+ nargs=3,
30
+ type=float,
31
+ default=(0, 3, 0),
32
+ help="Position as X Y Z."
33
+ )
34
+ @click.option(
35
+ "--color", "-c",
36
+ nargs=3,
37
+ type=float,
38
+ default=None,
39
+ help="Color as R G B (0-1)."
40
+ )
41
+ @click.option(
42
+ "--intensity", "-i",
43
+ default=None,
44
+ type=float,
45
+ help="Light intensity."
46
+ )
47
+ def create(name: str, light_type: str, position: Tuple[float, float, float], color: Optional[Tuple[float, float, float]], intensity: Optional[float]):
48
+ """Create a new light.
49
+
50
+ \b
51
+ Examples:
52
+ unity-mcp lighting create "MainLight" --type Directional
53
+ unity-mcp lighting create "PointLight1" --position 0 5 0 --intensity 2
54
+ unity-mcp lighting create "RedLight" --type Spot --color 1 0 0
55
+ """
56
+ config = get_config()
57
+
58
+ try:
59
+ # Step 1: Create empty GameObject with position
60
+ create_result = run_command("manage_gameobject", {
61
+ "action": "create",
62
+ "name": name,
63
+ "position": list(position),
64
+ }, config)
65
+
66
+ if not (create_result.get("success")):
67
+ click.echo(format_output(create_result, config.format))
68
+ return
69
+
70
+ # Step 2: Add Light component using manage_components
71
+ add_result = run_command("manage_components", {
72
+ "action": "add",
73
+ "target": name,
74
+ "componentType": "Light",
75
+ }, config)
76
+
77
+ if not add_result.get("success"):
78
+ click.echo(format_output(add_result, config.format))
79
+ return
80
+
81
+ # Step 3: Set light type using manage_components set_property
82
+ type_result = run_command("manage_components", {
83
+ "action": "set_property",
84
+ "target": name,
85
+ "componentType": "Light",
86
+ "property": "type",
87
+ "value": light_type,
88
+ }, config)
89
+
90
+ if not type_result.get("success"):
91
+ click.echo(format_output(type_result, config.format))
92
+ return
93
+
94
+ # Step 4: Set color if provided
95
+ if color:
96
+ color_result = run_command("manage_components", {
97
+ "action": "set_property",
98
+ "target": name,
99
+ "componentType": "Light",
100
+ "property": "color",
101
+ "value": {"r": color[0], "g": color[1], "b": color[2], "a": 1},
102
+ }, config)
103
+
104
+ if not color_result.get("success"):
105
+ click.echo(format_output(color_result, config.format))
106
+ return
107
+
108
+ # Step 5: Set intensity if provided
109
+ if intensity is not None:
110
+ intensity_result = run_command("manage_components", {
111
+ "action": "set_property",
112
+ "target": name,
113
+ "componentType": "Light",
114
+ "property": "intensity",
115
+ "value": intensity,
116
+ }, config)
117
+
118
+ if not intensity_result.get("success"):
119
+ click.echo(format_output(intensity_result, config.format))
120
+ return
121
+
122
+ # Output the result
123
+ click.echo(format_output(create_result, config.format))
124
+ print_success(f"Created {light_type} light: {name}")
125
+
126
+ except UnityConnectionError as e:
127
+ print_error(str(e))
128
+ sys.exit(1)
@@ -0,0 +1,268 @@
1
+ """Material CLI commands."""
2
+
3
+ import sys
4
+ import json
5
+ import click
6
+ from typing import Optional, Any, Tuple
7
+
8
+ from cli.utils.config import get_config
9
+ from cli.utils.output import format_output, print_error, print_success
10
+ from cli.utils.connection import run_command, UnityConnectionError
11
+
12
+
13
+ @click.group()
14
+ def material():
15
+ """Material operations - create, modify, assign materials."""
16
+ pass
17
+
18
+
19
+ @material.command("info")
20
+ @click.argument("path")
21
+ def info(path: str):
22
+ """Get information about a material.
23
+
24
+ \b
25
+ Examples:
26
+ unity-mcp material info "Assets/Materials/Red.mat"
27
+ """
28
+ config = get_config()
29
+
30
+ try:
31
+ result = run_command("manage_material", {
32
+ "action": "get_material_info",
33
+ "materialPath": path,
34
+ }, config)
35
+ click.echo(format_output(result, config.format))
36
+ except UnityConnectionError as e:
37
+ print_error(str(e))
38
+ sys.exit(1)
39
+
40
+
41
+ @material.command("create")
42
+ @click.argument("path")
43
+ @click.option(
44
+ "--shader", "-s",
45
+ default="Standard",
46
+ help="Shader to use (default: Standard)."
47
+ )
48
+ @click.option(
49
+ "--properties", "-p",
50
+ default=None,
51
+ help='Initial properties as JSON.'
52
+ )
53
+ def create(path: str, shader: str, properties: Optional[str]):
54
+ """Create a new material.
55
+
56
+ \b
57
+ Examples:
58
+ unity-mcp material create "Assets/Materials/NewMat.mat"
59
+ unity-mcp material create "Assets/Materials/Red.mat" --shader "Universal Render Pipeline/Lit"
60
+ unity-mcp material create "Assets/Materials/Blue.mat" --properties '{"_Color": [0,0,1,1]}'
61
+ """
62
+ config = get_config()
63
+
64
+ params: dict[str, Any] = {
65
+ "action": "create",
66
+ "materialPath": path,
67
+ "shader": shader,
68
+ }
69
+
70
+ if properties:
71
+ try:
72
+ params["properties"] = json.loads(properties)
73
+ except json.JSONDecodeError as e:
74
+ print_error(f"Invalid JSON for properties: {e}")
75
+ sys.exit(1)
76
+
77
+ try:
78
+ result = run_command("manage_material", params, config)
79
+ click.echo(format_output(result, config.format))
80
+ if result.get("success"):
81
+ print_success(f"Created material: {path}")
82
+ except UnityConnectionError as e:
83
+ print_error(str(e))
84
+ sys.exit(1)
85
+
86
+
87
+ @material.command("set-color")
88
+ @click.argument("path")
89
+ @click.argument("r", type=float)
90
+ @click.argument("g", type=float)
91
+ @click.argument("b", type=float)
92
+ @click.argument("a", type=float, default=1.0)
93
+ @click.option(
94
+ "--property", "-p",
95
+ default="_Color",
96
+ help="Color property name (default: _Color)."
97
+ )
98
+ def set_color(path: str, r: float, g: float, b: float, a: float, property: str):
99
+ """Set a material's color.
100
+
101
+ \b
102
+ Examples:
103
+ unity-mcp material set-color "Assets/Materials/Red.mat" 1 0 0
104
+ unity-mcp material set-color "Assets/Materials/Blue.mat" 0 0 1 0.5
105
+ unity-mcp material set-color "Assets/Materials/Mat.mat" 1 1 0 --property "_BaseColor"
106
+ """
107
+ config = get_config()
108
+
109
+ params: dict[str, Any] = {
110
+ "action": "set_material_color",
111
+ "materialPath": path,
112
+ "property": property,
113
+ "color": [r, g, b, a],
114
+ }
115
+
116
+ try:
117
+ result = run_command("manage_material", params, config)
118
+ click.echo(format_output(result, config.format))
119
+ if result.get("success"):
120
+ print_success(f"Set color on: {path}")
121
+ except UnityConnectionError as e:
122
+ print_error(str(e))
123
+ sys.exit(1)
124
+
125
+
126
+ @material.command("set-property")
127
+ @click.argument("path")
128
+ @click.argument("property_name")
129
+ @click.argument("value")
130
+ def set_property(path: str, property_name: str, value: str):
131
+ """Set a shader property on a material.
132
+
133
+ \b
134
+ Examples:
135
+ unity-mcp material set-property "Assets/Materials/Mat.mat" _Metallic 0.5
136
+ unity-mcp material set-property "Assets/Materials/Mat.mat" _Smoothness 0.8
137
+ unity-mcp material set-property "Assets/Materials/Mat.mat" _MainTex "Assets/Textures/Tex.png"
138
+ """
139
+ config = get_config()
140
+
141
+ # Try to parse value as JSON for complex types
142
+ try:
143
+ parsed_value = json.loads(value)
144
+ except json.JSONDecodeError:
145
+ # Try to parse as number
146
+ try:
147
+ parsed_value = float(value)
148
+ except ValueError:
149
+ parsed_value = value
150
+
151
+ params: dict[str, Any] = {
152
+ "action": "set_material_shader_property",
153
+ "materialPath": path,
154
+ "property": property_name,
155
+ "value": parsed_value,
156
+ }
157
+
158
+ try:
159
+ result = run_command("manage_material", params, config)
160
+ click.echo(format_output(result, config.format))
161
+ if result.get("success"):
162
+ print_success(f"Set {property_name} on: {path}")
163
+ except UnityConnectionError as e:
164
+ print_error(str(e))
165
+ sys.exit(1)
166
+
167
+
168
+ @material.command("assign")
169
+ @click.argument("material_path")
170
+ @click.argument("target")
171
+ @click.option(
172
+ "--search-method",
173
+ type=click.Choice(["by_name", "by_path", "by_tag",
174
+ "by_layer", "by_component"]),
175
+ default=None,
176
+ help="How to find the target GameObject."
177
+ )
178
+ @click.option(
179
+ "--slot", "-s",
180
+ default=0,
181
+ type=int,
182
+ help="Material slot index (default: 0)."
183
+ )
184
+ @click.option(
185
+ "--mode", "-m",
186
+ type=click.Choice(["shared", "instance", "property_block"]),
187
+ default="shared",
188
+ help="Assignment mode."
189
+ )
190
+ def assign(material_path: str, target: str, search_method: Optional[str], slot: int, mode: str):
191
+ """Assign a material to a GameObject's renderer.
192
+
193
+ \b
194
+ Examples:
195
+ unity-mcp material assign "Assets/Materials/Red.mat" "Cube"
196
+ unity-mcp material assign "Assets/Materials/Blue.mat" "Player" --mode instance
197
+ unity-mcp material assign "Assets/Materials/Mat.mat" "-81840" --search-method by_id --slot 1
198
+ """
199
+ config = get_config()
200
+
201
+ params: dict[str, Any] = {
202
+ "action": "assign_material_to_renderer",
203
+ "materialPath": material_path,
204
+ "target": target,
205
+ "slot": slot,
206
+ "mode": mode,
207
+ }
208
+
209
+ if search_method:
210
+ params["searchMethod"] = search_method
211
+
212
+ try:
213
+ result = run_command("manage_material", params, config)
214
+ click.echo(format_output(result, config.format))
215
+ if result.get("success"):
216
+ print_success(f"Assigned material to: {target}")
217
+ except UnityConnectionError as e:
218
+ print_error(str(e))
219
+ sys.exit(1)
220
+
221
+
222
+ @material.command("set-renderer-color")
223
+ @click.argument("target")
224
+ @click.argument("r", type=float)
225
+ @click.argument("g", type=float)
226
+ @click.argument("b", type=float)
227
+ @click.argument("a", type=float, default=1.0)
228
+ @click.option(
229
+ "--search-method",
230
+ type=click.Choice(["by_name", "by_path", "by_tag",
231
+ "by_layer", "by_component"]),
232
+ default=None,
233
+ help="How to find the target GameObject."
234
+ )
235
+ @click.option(
236
+ "--mode", "-m",
237
+ type=click.Choice(["shared", "instance", "property_block"]),
238
+ default="property_block",
239
+ help="Modification mode."
240
+ )
241
+ def set_renderer_color(target: str, r: float, g: float, b: float, a: float, search_method: Optional[str], mode: str):
242
+ """Set a renderer's material color directly.
243
+
244
+ \b
245
+ Examples:
246
+ unity-mcp material set-renderer-color "Cube" 1 0 0
247
+ unity-mcp material set-renderer-color "Player" 0 1 0 --mode instance
248
+ """
249
+ config = get_config()
250
+
251
+ params: dict[str, Any] = {
252
+ "action": "set_renderer_color",
253
+ "target": target,
254
+ "color": [r, g, b, a],
255
+ "mode": mode,
256
+ }
257
+
258
+ if search_method:
259
+ params["searchMethod"] = search_method
260
+
261
+ try:
262
+ result = run_command("manage_material", params, config)
263
+ click.echo(format_output(result, config.format))
264
+ if result.get("success"):
265
+ print_success(f"Set renderer color on: {target}")
266
+ except UnityConnectionError as e:
267
+ print_error(str(e))
268
+ sys.exit(1)
cli/commands/prefab.py ADDED
@@ -0,0 +1,144 @@
1
+ """Prefab CLI commands."""
2
+
3
+ import sys
4
+ import click
5
+ from typing import Optional, Any
6
+
7
+ from cli.utils.config import get_config
8
+ from cli.utils.output import format_output, print_error, print_success
9
+ from cli.utils.connection import run_command, UnityConnectionError
10
+
11
+
12
+ @click.group()
13
+ def prefab():
14
+ """Prefab operations - open, save, create prefabs."""
15
+ pass
16
+
17
+
18
+ @prefab.command("open")
19
+ @click.argument("path")
20
+ @click.option(
21
+ "--mode", "-m",
22
+ default="InIsolation",
23
+ help="Prefab stage mode (InIsolation)."
24
+ )
25
+ def open_stage(path: str, mode: str):
26
+ """Open a prefab in the prefab stage for editing.
27
+
28
+ \b
29
+ Examples:
30
+ unity-mcp prefab open "Assets/Prefabs/Player.prefab"
31
+ """
32
+ config = get_config()
33
+
34
+ params: dict[str, Any] = {
35
+ "action": "open_stage",
36
+ "prefabPath": path,
37
+ "mode": mode,
38
+ }
39
+
40
+ try:
41
+ result = run_command("manage_prefabs", params, config)
42
+ click.echo(format_output(result, config.format))
43
+ if result.get("success"):
44
+ print_success(f"Opened prefab: {path}")
45
+ except UnityConnectionError as e:
46
+ print_error(str(e))
47
+ sys.exit(1)
48
+
49
+
50
+ @prefab.command("close")
51
+ @click.option(
52
+ "--save", "-s",
53
+ is_flag=True,
54
+ help="Save the prefab before closing."
55
+ )
56
+ def close_stage(save: bool):
57
+ """Close the current prefab stage.
58
+
59
+ \b
60
+ Examples:
61
+ unity-mcp prefab close
62
+ unity-mcp prefab close --save
63
+ """
64
+ config = get_config()
65
+
66
+ params: dict[str, Any] = {
67
+ "action": "close_stage",
68
+ }
69
+ if save:
70
+ params["saveBeforeClose"] = True
71
+
72
+ try:
73
+ result = run_command("manage_prefabs", params, config)
74
+ click.echo(format_output(result, config.format))
75
+ if result.get("success"):
76
+ print_success("Closed prefab stage")
77
+ except UnityConnectionError as e:
78
+ print_error(str(e))
79
+ sys.exit(1)
80
+
81
+
82
+ @prefab.command("save")
83
+ def save_stage():
84
+ """Save the currently open prefab stage.
85
+
86
+ \b
87
+ Examples:
88
+ unity-mcp prefab save
89
+ """
90
+ config = get_config()
91
+
92
+ try:
93
+ result = run_command("manage_prefabs", {
94
+ "action": "save_open_stage"}, config)
95
+ click.echo(format_output(result, config.format))
96
+ if result.get("success"):
97
+ print_success("Saved prefab")
98
+ except UnityConnectionError as e:
99
+ print_error(str(e))
100
+ sys.exit(1)
101
+
102
+
103
+ @prefab.command("create")
104
+ @click.argument("target")
105
+ @click.argument("path")
106
+ @click.option(
107
+ "--overwrite",
108
+ is_flag=True,
109
+ help="Overwrite existing prefab at path."
110
+ )
111
+ @click.option(
112
+ "--include-inactive",
113
+ is_flag=True,
114
+ help="Include inactive objects when finding target."
115
+ )
116
+ def create(target: str, path: str, overwrite: bool, include_inactive: bool):
117
+ """Create a prefab from a scene GameObject.
118
+
119
+ \b
120
+ Examples:
121
+ unity-mcp prefab create "Player" "Assets/Prefabs/Player.prefab"
122
+ unity-mcp prefab create "Enemy" "Assets/Prefabs/Enemy.prefab" --overwrite
123
+ """
124
+ config = get_config()
125
+
126
+ params: dict[str, Any] = {
127
+ "action": "create_from_gameobject",
128
+ "target": target,
129
+ "prefabPath": path,
130
+ }
131
+
132
+ if overwrite:
133
+ params["allowOverwrite"] = True
134
+ if include_inactive:
135
+ params["searchInactive"] = True
136
+
137
+ try:
138
+ result = run_command("manage_prefabs", params, config)
139
+ click.echo(format_output(result, config.format))
140
+ if result.get("success"):
141
+ print_success(f"Created prefab: {path}")
142
+ except UnityConnectionError as e:
143
+ print_error(str(e))
144
+ sys.exit(1)