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.
- cli/__init__.py +3 -0
- cli/commands/__init__.py +3 -0
- cli/commands/animation.py +87 -0
- cli/commands/asset.py +310 -0
- cli/commands/audio.py +133 -0
- cli/commands/batch.py +184 -0
- cli/commands/code.py +189 -0
- cli/commands/component.py +212 -0
- cli/commands/editor.py +487 -0
- cli/commands/gameobject.py +510 -0
- cli/commands/instance.py +101 -0
- cli/commands/lighting.py +128 -0
- cli/commands/material.py +268 -0
- cli/commands/prefab.py +144 -0
- cli/commands/scene.py +255 -0
- cli/commands/script.py +240 -0
- cli/commands/shader.py +238 -0
- cli/commands/ui.py +263 -0
- cli/commands/vfx.py +439 -0
- cli/main.py +248 -0
- cli/utils/__init__.py +31 -0
- cli/utils/config.py +58 -0
- cli/utils/connection.py +191 -0
- cli/utils/output.py +195 -0
- main.py +207 -62
- {mcpforunityserver-8.5.0.dist-info → mcpforunityserver-9.1.0.dist-info}/METADATA +4 -2
- mcpforunityserver-9.1.0.dist-info/RECORD +96 -0
- {mcpforunityserver-8.5.0.dist-info → mcpforunityserver-9.1.0.dist-info}/WHEEL +1 -1
- {mcpforunityserver-8.5.0.dist-info → mcpforunityserver-9.1.0.dist-info}/entry_points.txt +1 -0
- {mcpforunityserver-8.5.0.dist-info → mcpforunityserver-9.1.0.dist-info}/top_level.txt +1 -2
- services/custom_tool_service.py +179 -19
- services/resources/__init__.py +6 -1
- services/resources/active_tool.py +1 -1
- services/resources/custom_tools.py +2 -2
- services/resources/editor_state.py +283 -21
- services/resources/gameobject.py +243 -0
- services/resources/layers.py +1 -1
- services/resources/prefab_stage.py +1 -1
- services/resources/project_info.py +1 -1
- services/resources/selection.py +1 -1
- services/resources/tags.py +1 -1
- services/resources/unity_instances.py +1 -1
- services/resources/windows.py +1 -1
- services/state/external_changes_scanner.py +245 -0
- services/tools/__init__.py +6 -1
- services/tools/batch_execute.py +24 -9
- services/tools/debug_request_context.py +8 -2
- services/tools/execute_custom_tool.py +6 -1
- services/tools/execute_menu_item.py +6 -3
- services/tools/find_gameobjects.py +89 -0
- services/tools/find_in_file.py +26 -19
- services/tools/manage_asset.py +19 -43
- services/tools/manage_components.py +131 -0
- services/tools/manage_editor.py +9 -8
- services/tools/manage_gameobject.py +120 -79
- services/tools/manage_material.py +80 -31
- services/tools/manage_prefabs.py +7 -1
- services/tools/manage_scene.py +34 -13
- services/tools/manage_script.py +62 -19
- services/tools/manage_scriptable_object.py +22 -10
- services/tools/manage_shader.py +8 -1
- services/tools/manage_vfx.py +738 -0
- services/tools/preflight.py +110 -0
- services/tools/read_console.py +81 -18
- services/tools/refresh_unity.py +153 -0
- services/tools/run_tests.py +202 -41
- services/tools/script_apply_edits.py +15 -7
- services/tools/set_active_instance.py +12 -7
- services/tools/utils.py +60 -6
- transport/legacy/port_discovery.py +2 -2
- transport/legacy/unity_connection.py +129 -26
- transport/plugin_hub.py +191 -19
- transport/unity_instance_middleware.py +93 -2
- transport/unity_transport.py +17 -6
- utils/focus_nudge.py +321 -0
- __init__.py +0 -0
- mcpforunityserver-8.5.0.dist-info/RECORD +0 -66
- routes/__init__.py +0 -0
- {mcpforunityserver-8.5.0.dist-info → mcpforunityserver-9.1.0.dist-info}/licenses/LICENSE +0 -0
cli/commands/editor.py
ADDED
|
@@ -0,0 +1,487 @@
|
|
|
1
|
+
"""Editor 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, print_info
|
|
9
|
+
from cli.utils.connection import run_command, UnityConnectionError
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@click.group()
|
|
13
|
+
def editor():
|
|
14
|
+
"""Editor operations - play mode, console, tags, layers."""
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@editor.command("play")
|
|
19
|
+
def play():
|
|
20
|
+
"""Enter play mode."""
|
|
21
|
+
config = get_config()
|
|
22
|
+
|
|
23
|
+
try:
|
|
24
|
+
result = run_command("manage_editor", {"action": "play"}, config)
|
|
25
|
+
click.echo(format_output(result, config.format))
|
|
26
|
+
if result.get("success"):
|
|
27
|
+
print_success("Entered play mode")
|
|
28
|
+
except UnityConnectionError as e:
|
|
29
|
+
print_error(str(e))
|
|
30
|
+
sys.exit(1)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@editor.command("pause")
|
|
34
|
+
def pause():
|
|
35
|
+
"""Pause play mode."""
|
|
36
|
+
config = get_config()
|
|
37
|
+
|
|
38
|
+
try:
|
|
39
|
+
result = run_command("manage_editor", {"action": "pause"}, config)
|
|
40
|
+
click.echo(format_output(result, config.format))
|
|
41
|
+
if result.get("success"):
|
|
42
|
+
print_success("Paused play mode")
|
|
43
|
+
except UnityConnectionError as e:
|
|
44
|
+
print_error(str(e))
|
|
45
|
+
sys.exit(1)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@editor.command("stop")
|
|
49
|
+
def stop():
|
|
50
|
+
"""Stop play mode."""
|
|
51
|
+
config = get_config()
|
|
52
|
+
|
|
53
|
+
try:
|
|
54
|
+
result = run_command("manage_editor", {"action": "stop"}, config)
|
|
55
|
+
click.echo(format_output(result, config.format))
|
|
56
|
+
if result.get("success"):
|
|
57
|
+
print_success("Stopped play mode")
|
|
58
|
+
except UnityConnectionError as e:
|
|
59
|
+
print_error(str(e))
|
|
60
|
+
sys.exit(1)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@editor.command("console")
|
|
64
|
+
@click.option(
|
|
65
|
+
"--type", "-t",
|
|
66
|
+
"log_types",
|
|
67
|
+
multiple=True,
|
|
68
|
+
type=click.Choice(["error", "warning", "log", "all"]),
|
|
69
|
+
default=["error", "warning", "log"],
|
|
70
|
+
help="Message types to retrieve."
|
|
71
|
+
)
|
|
72
|
+
@click.option(
|
|
73
|
+
"--count", "-n",
|
|
74
|
+
default=10,
|
|
75
|
+
type=int,
|
|
76
|
+
help="Number of messages to retrieve."
|
|
77
|
+
)
|
|
78
|
+
@click.option(
|
|
79
|
+
"--filter", "-f",
|
|
80
|
+
"filter_text",
|
|
81
|
+
default=None,
|
|
82
|
+
help="Filter messages containing this text."
|
|
83
|
+
)
|
|
84
|
+
@click.option(
|
|
85
|
+
"--stacktrace", "-s",
|
|
86
|
+
is_flag=True,
|
|
87
|
+
help="Include stack traces."
|
|
88
|
+
)
|
|
89
|
+
@click.option(
|
|
90
|
+
"--clear",
|
|
91
|
+
is_flag=True,
|
|
92
|
+
help="Clear the console instead of reading."
|
|
93
|
+
)
|
|
94
|
+
def console(log_types: tuple, count: int, filter_text: Optional[str], stacktrace: bool, clear: bool):
|
|
95
|
+
"""Read or clear the Unity console.
|
|
96
|
+
|
|
97
|
+
\b
|
|
98
|
+
Examples:
|
|
99
|
+
unity-mcp editor console
|
|
100
|
+
unity-mcp editor console --type error --count 20
|
|
101
|
+
unity-mcp editor console --filter "NullReference" --stacktrace
|
|
102
|
+
unity-mcp editor console --clear
|
|
103
|
+
"""
|
|
104
|
+
config = get_config()
|
|
105
|
+
|
|
106
|
+
if clear:
|
|
107
|
+
try:
|
|
108
|
+
result = run_command("read_console", {"action": "clear"}, config)
|
|
109
|
+
click.echo(format_output(result, config.format))
|
|
110
|
+
if result.get("success"):
|
|
111
|
+
print_success("Console cleared")
|
|
112
|
+
except UnityConnectionError as e:
|
|
113
|
+
print_error(str(e))
|
|
114
|
+
sys.exit(1)
|
|
115
|
+
return
|
|
116
|
+
|
|
117
|
+
params: dict[str, Any] = {
|
|
118
|
+
"action": "get",
|
|
119
|
+
"types": list(log_types),
|
|
120
|
+
"count": count,
|
|
121
|
+
"include_stacktrace": stacktrace,
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if filter_text:
|
|
125
|
+
params["filter_text"] = filter_text
|
|
126
|
+
|
|
127
|
+
try:
|
|
128
|
+
result = run_command("read_console", params, config)
|
|
129
|
+
click.echo(format_output(result, config.format))
|
|
130
|
+
except UnityConnectionError as e:
|
|
131
|
+
print_error(str(e))
|
|
132
|
+
sys.exit(1)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
@editor.command("add-tag")
|
|
136
|
+
@click.argument("tag_name")
|
|
137
|
+
def add_tag(tag_name: str):
|
|
138
|
+
"""Add a new tag.
|
|
139
|
+
|
|
140
|
+
\b
|
|
141
|
+
Examples:
|
|
142
|
+
unity-mcp editor add-tag "Enemy"
|
|
143
|
+
unity-mcp editor add-tag "Collectible"
|
|
144
|
+
"""
|
|
145
|
+
config = get_config()
|
|
146
|
+
|
|
147
|
+
try:
|
|
148
|
+
result = run_command(
|
|
149
|
+
"manage_editor", {"action": "add_tag", "tagName": tag_name}, config)
|
|
150
|
+
click.echo(format_output(result, config.format))
|
|
151
|
+
if result.get("success"):
|
|
152
|
+
print_success(f"Added tag: {tag_name}")
|
|
153
|
+
except UnityConnectionError as e:
|
|
154
|
+
print_error(str(e))
|
|
155
|
+
sys.exit(1)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
@editor.command("remove-tag")
|
|
159
|
+
@click.argument("tag_name")
|
|
160
|
+
def remove_tag(tag_name: str):
|
|
161
|
+
"""Remove a tag.
|
|
162
|
+
|
|
163
|
+
\b
|
|
164
|
+
Examples:
|
|
165
|
+
unity-mcp editor remove-tag "OldTag"
|
|
166
|
+
"""
|
|
167
|
+
config = get_config()
|
|
168
|
+
|
|
169
|
+
try:
|
|
170
|
+
result = run_command(
|
|
171
|
+
"manage_editor", {"action": "remove_tag", "tagName": tag_name}, config)
|
|
172
|
+
click.echo(format_output(result, config.format))
|
|
173
|
+
if result.get("success"):
|
|
174
|
+
print_success(f"Removed tag: {tag_name}")
|
|
175
|
+
except UnityConnectionError as e:
|
|
176
|
+
print_error(str(e))
|
|
177
|
+
sys.exit(1)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
@editor.command("add-layer")
|
|
181
|
+
@click.argument("layer_name")
|
|
182
|
+
def add_layer(layer_name: str):
|
|
183
|
+
"""Add a new layer.
|
|
184
|
+
|
|
185
|
+
\b
|
|
186
|
+
Examples:
|
|
187
|
+
unity-mcp editor add-layer "Interactable"
|
|
188
|
+
"""
|
|
189
|
+
config = get_config()
|
|
190
|
+
|
|
191
|
+
try:
|
|
192
|
+
result = run_command(
|
|
193
|
+
"manage_editor", {"action": "add_layer", "layerName": layer_name}, config)
|
|
194
|
+
click.echo(format_output(result, config.format))
|
|
195
|
+
if result.get("success"):
|
|
196
|
+
print_success(f"Added layer: {layer_name}")
|
|
197
|
+
except UnityConnectionError as e:
|
|
198
|
+
print_error(str(e))
|
|
199
|
+
sys.exit(1)
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
@editor.command("remove-layer")
|
|
203
|
+
@click.argument("layer_name")
|
|
204
|
+
def remove_layer(layer_name: str):
|
|
205
|
+
"""Remove a layer.
|
|
206
|
+
|
|
207
|
+
\b
|
|
208
|
+
Examples:
|
|
209
|
+
unity-mcp editor remove-layer "OldLayer"
|
|
210
|
+
"""
|
|
211
|
+
config = get_config()
|
|
212
|
+
|
|
213
|
+
try:
|
|
214
|
+
result = run_command(
|
|
215
|
+
"manage_editor", {"action": "remove_layer", "layerName": layer_name}, config)
|
|
216
|
+
click.echo(format_output(result, config.format))
|
|
217
|
+
if result.get("success"):
|
|
218
|
+
print_success(f"Removed layer: {layer_name}")
|
|
219
|
+
except UnityConnectionError as e:
|
|
220
|
+
print_error(str(e))
|
|
221
|
+
sys.exit(1)
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
@editor.command("tool")
|
|
225
|
+
@click.argument("tool_name")
|
|
226
|
+
def set_tool(tool_name: str):
|
|
227
|
+
"""Set the active editor tool.
|
|
228
|
+
|
|
229
|
+
\b
|
|
230
|
+
Examples:
|
|
231
|
+
unity-mcp editor tool "Move"
|
|
232
|
+
unity-mcp editor tool "Rotate"
|
|
233
|
+
unity-mcp editor tool "Scale"
|
|
234
|
+
"""
|
|
235
|
+
config = get_config()
|
|
236
|
+
|
|
237
|
+
try:
|
|
238
|
+
result = run_command(
|
|
239
|
+
"manage_editor", {"action": "set_active_tool", "toolName": tool_name}, config)
|
|
240
|
+
click.echo(format_output(result, config.format))
|
|
241
|
+
if result.get("success"):
|
|
242
|
+
print_success(f"Set active tool: {tool_name}")
|
|
243
|
+
except UnityConnectionError as e:
|
|
244
|
+
print_error(str(e))
|
|
245
|
+
sys.exit(1)
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
@editor.command("menu")
|
|
249
|
+
@click.argument("menu_path")
|
|
250
|
+
def execute_menu(menu_path: str):
|
|
251
|
+
"""Execute a menu item.
|
|
252
|
+
|
|
253
|
+
\b
|
|
254
|
+
Examples:
|
|
255
|
+
unity-mcp editor menu "File/Save"
|
|
256
|
+
unity-mcp editor menu "Edit/Undo"
|
|
257
|
+
unity-mcp editor menu "GameObject/Create Empty"
|
|
258
|
+
"""
|
|
259
|
+
config = get_config()
|
|
260
|
+
|
|
261
|
+
try:
|
|
262
|
+
result = run_command("execute_menu_item", {
|
|
263
|
+
"menu_path": menu_path}, config)
|
|
264
|
+
click.echo(format_output(result, config.format))
|
|
265
|
+
if result.get("success"):
|
|
266
|
+
print_success(f"Executed: {menu_path}")
|
|
267
|
+
except UnityConnectionError as e:
|
|
268
|
+
print_error(str(e))
|
|
269
|
+
sys.exit(1)
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
@editor.command("tests")
|
|
273
|
+
@click.option(
|
|
274
|
+
"--mode", "-m",
|
|
275
|
+
type=click.Choice(["EditMode", "PlayMode"]),
|
|
276
|
+
default="EditMode",
|
|
277
|
+
help="Test mode to run."
|
|
278
|
+
)
|
|
279
|
+
@click.option(
|
|
280
|
+
"--async", "async_mode",
|
|
281
|
+
is_flag=True,
|
|
282
|
+
help="Run asynchronously and return job ID for polling."
|
|
283
|
+
)
|
|
284
|
+
@click.option(
|
|
285
|
+
"--wait", "-w",
|
|
286
|
+
type=int,
|
|
287
|
+
default=None,
|
|
288
|
+
help="Wait up to N seconds for completion (default: no wait)."
|
|
289
|
+
)
|
|
290
|
+
@click.option(
|
|
291
|
+
"--details",
|
|
292
|
+
is_flag=True,
|
|
293
|
+
help="Include detailed results for all tests."
|
|
294
|
+
)
|
|
295
|
+
@click.option(
|
|
296
|
+
"--failed-only",
|
|
297
|
+
is_flag=True,
|
|
298
|
+
help="Include details for failed/skipped tests only."
|
|
299
|
+
)
|
|
300
|
+
def run_tests(mode: str, async_mode: bool, wait: Optional[int], details: bool, failed_only: bool):
|
|
301
|
+
"""Run Unity tests.
|
|
302
|
+
|
|
303
|
+
\b
|
|
304
|
+
Examples:
|
|
305
|
+
unity-mcp editor tests
|
|
306
|
+
unity-mcp editor tests --mode PlayMode
|
|
307
|
+
unity-mcp editor tests --async
|
|
308
|
+
unity-mcp editor tests --wait 60 --failed-only
|
|
309
|
+
"""
|
|
310
|
+
config = get_config()
|
|
311
|
+
|
|
312
|
+
params: dict[str, Any] = {"mode": mode}
|
|
313
|
+
if wait is not None:
|
|
314
|
+
params["wait_timeout"] = wait
|
|
315
|
+
if details:
|
|
316
|
+
params["include_details"] = True
|
|
317
|
+
if failed_only:
|
|
318
|
+
params["include_failed_tests"] = True
|
|
319
|
+
|
|
320
|
+
try:
|
|
321
|
+
result = run_command("run_tests", params, config)
|
|
322
|
+
|
|
323
|
+
# For async mode, just show job ID
|
|
324
|
+
if async_mode and result.get("success"):
|
|
325
|
+
job_id = result.get("data", {}).get("job_id")
|
|
326
|
+
if job_id:
|
|
327
|
+
click.echo(f"Test job started: {job_id}")
|
|
328
|
+
print_info("Poll with: unity-mcp editor poll-test " + job_id)
|
|
329
|
+
return
|
|
330
|
+
|
|
331
|
+
click.echo(format_output(result, config.format))
|
|
332
|
+
except UnityConnectionError as e:
|
|
333
|
+
print_error(str(e))
|
|
334
|
+
sys.exit(1)
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
@editor.command("poll-test")
|
|
338
|
+
@click.argument("job_id")
|
|
339
|
+
@click.option(
|
|
340
|
+
"--wait", "-w",
|
|
341
|
+
type=int,
|
|
342
|
+
default=30,
|
|
343
|
+
help="Wait up to N seconds for completion (default: 30)."
|
|
344
|
+
)
|
|
345
|
+
@click.option(
|
|
346
|
+
"--details",
|
|
347
|
+
is_flag=True,
|
|
348
|
+
help="Include detailed results for all tests."
|
|
349
|
+
)
|
|
350
|
+
@click.option(
|
|
351
|
+
"--failed-only",
|
|
352
|
+
is_flag=True,
|
|
353
|
+
help="Include details for failed/skipped tests only."
|
|
354
|
+
)
|
|
355
|
+
def poll_test(job_id: str, wait: int, details: bool, failed_only: bool):
|
|
356
|
+
"""Poll an async test job for status/results.
|
|
357
|
+
|
|
358
|
+
\b
|
|
359
|
+
Examples:
|
|
360
|
+
unity-mcp editor poll-test abc123
|
|
361
|
+
unity-mcp editor poll-test abc123 --wait 60
|
|
362
|
+
unity-mcp editor poll-test abc123 --failed-only
|
|
363
|
+
"""
|
|
364
|
+
config = get_config()
|
|
365
|
+
|
|
366
|
+
params: dict[str, Any] = {"job_id": job_id}
|
|
367
|
+
if wait:
|
|
368
|
+
params["wait_timeout"] = wait
|
|
369
|
+
if details:
|
|
370
|
+
params["include_details"] = True
|
|
371
|
+
if failed_only:
|
|
372
|
+
params["include_failed_tests"] = True
|
|
373
|
+
|
|
374
|
+
try:
|
|
375
|
+
result = run_command("get_test_job", params, config)
|
|
376
|
+
click.echo(format_output(result, config.format))
|
|
377
|
+
|
|
378
|
+
if isinstance(result, dict) and result.get("success"):
|
|
379
|
+
data = result.get("data", {})
|
|
380
|
+
status = data.get("status", "unknown")
|
|
381
|
+
if status == "succeeded":
|
|
382
|
+
print_success("Tests completed successfully")
|
|
383
|
+
elif status == "failed":
|
|
384
|
+
summary = data.get("result", {}).get("summary", {})
|
|
385
|
+
failed = summary.get("failed", 0)
|
|
386
|
+
print_error(f"Tests failed: {failed} failures")
|
|
387
|
+
elif status == "running":
|
|
388
|
+
progress = data.get("progress", {})
|
|
389
|
+
completed = progress.get("completed", 0)
|
|
390
|
+
total = progress.get("total", 0)
|
|
391
|
+
print_info(f"Tests running: {completed}/{total}")
|
|
392
|
+
except UnityConnectionError as e:
|
|
393
|
+
print_error(str(e))
|
|
394
|
+
sys.exit(1)
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
@editor.command("refresh")
|
|
398
|
+
@click.option(
|
|
399
|
+
"--mode",
|
|
400
|
+
type=click.Choice(["if_dirty", "force"]),
|
|
401
|
+
default="if_dirty",
|
|
402
|
+
help="Refresh mode."
|
|
403
|
+
)
|
|
404
|
+
@click.option(
|
|
405
|
+
"--scope",
|
|
406
|
+
type=click.Choice(["assets", "scripts", "all"]),
|
|
407
|
+
default="all",
|
|
408
|
+
help="What to refresh."
|
|
409
|
+
)
|
|
410
|
+
@click.option(
|
|
411
|
+
"--compile",
|
|
412
|
+
is_flag=True,
|
|
413
|
+
help="Request script compilation."
|
|
414
|
+
)
|
|
415
|
+
@click.option(
|
|
416
|
+
"--no-wait",
|
|
417
|
+
is_flag=True,
|
|
418
|
+
help="Don't wait for refresh to complete."
|
|
419
|
+
)
|
|
420
|
+
def refresh(mode: str, scope: str, compile: bool, no_wait: bool):
|
|
421
|
+
"""Force Unity to refresh assets/scripts.
|
|
422
|
+
|
|
423
|
+
\b
|
|
424
|
+
Examples:
|
|
425
|
+
unity-mcp editor refresh
|
|
426
|
+
unity-mcp editor refresh --mode force
|
|
427
|
+
unity-mcp editor refresh --compile
|
|
428
|
+
unity-mcp editor refresh --scope scripts --compile
|
|
429
|
+
"""
|
|
430
|
+
config = get_config()
|
|
431
|
+
|
|
432
|
+
params: dict[str, Any] = {
|
|
433
|
+
"mode": mode,
|
|
434
|
+
"scope": scope,
|
|
435
|
+
"wait_for_ready": not no_wait,
|
|
436
|
+
}
|
|
437
|
+
if compile:
|
|
438
|
+
params["compile"] = "request"
|
|
439
|
+
|
|
440
|
+
try:
|
|
441
|
+
click.echo("Refreshing Unity...")
|
|
442
|
+
result = run_command("refresh_unity", params, config)
|
|
443
|
+
click.echo(format_output(result, config.format))
|
|
444
|
+
if result.get("success"):
|
|
445
|
+
print_success("Unity refreshed")
|
|
446
|
+
except UnityConnectionError as e:
|
|
447
|
+
print_error(str(e))
|
|
448
|
+
sys.exit(1)
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
@editor.command("custom-tool")
|
|
452
|
+
@click.argument("tool_name")
|
|
453
|
+
@click.option(
|
|
454
|
+
"--params", "-p",
|
|
455
|
+
default="{}",
|
|
456
|
+
help="Tool parameters as JSON."
|
|
457
|
+
)
|
|
458
|
+
def custom_tool(tool_name: str, params: str):
|
|
459
|
+
"""Execute a custom Unity tool.
|
|
460
|
+
|
|
461
|
+
Custom tools are registered by Unity projects via the MCP plugin.
|
|
462
|
+
|
|
463
|
+
\b
|
|
464
|
+
Examples:
|
|
465
|
+
unity-mcp editor custom-tool "MyCustomTool"
|
|
466
|
+
unity-mcp editor custom-tool "BuildPipeline" --params '{"target": "Android"}'
|
|
467
|
+
"""
|
|
468
|
+
import json
|
|
469
|
+
config = get_config()
|
|
470
|
+
|
|
471
|
+
try:
|
|
472
|
+
params_dict = json.loads(params)
|
|
473
|
+
except json.JSONDecodeError as e:
|
|
474
|
+
print_error(f"Invalid JSON for params: {e}")
|
|
475
|
+
sys.exit(1)
|
|
476
|
+
|
|
477
|
+
try:
|
|
478
|
+
result = run_command("execute_custom_tool", {
|
|
479
|
+
"tool_name": tool_name,
|
|
480
|
+
"parameters": params_dict,
|
|
481
|
+
}, config)
|
|
482
|
+
click.echo(format_output(result, config.format))
|
|
483
|
+
if result.get("success"):
|
|
484
|
+
print_success(f"Executed custom tool: {tool_name}")
|
|
485
|
+
except UnityConnectionError as e:
|
|
486
|
+
print_error(str(e))
|
|
487
|
+
sys.exit(1)
|