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