coplay-mcp-server 1.4.1__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.
@@ -0,0 +1,1643 @@
1
+ """Generated MCP tools from unity_functions_schema.json"""
2
+
3
+ import logging
4
+ from typing import Annotated, Optional, Any, Dict, Literal
5
+ from pydantic import Field
6
+ from fastmcp import FastMCP
7
+ from ..unity_client import UnityRpcClient
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+ # Global references to be set by register_tools
12
+ _mcp: Optional[FastMCP] = None
13
+ _unity_client: Optional[UnityRpcClient] = None
14
+
15
+
16
+ async def create_game_object(
17
+ name: Annotated[
18
+ str,
19
+ Field(
20
+ description="""The name of the new GameObject."""
21
+ ),
22
+ ],
23
+ position: Annotated[
24
+ str,
25
+ Field(
26
+ description="""Comma-separated position coordinates (e.g., 'x,y,z')."""
27
+ ),
28
+ ],
29
+ primitive_type: Annotated[
30
+ Literal['Cube', 'Sphere', 'Capsule', 'Cylinder', 'Plane'] | None,
31
+ Field(
32
+ description="""Optional. Type of primitive to create. If not specified, creates an empty GameObject. Keep it empty in 2D mode."""
33
+ ),
34
+ ] = None,
35
+ size: Annotated[
36
+ str | None,
37
+ Field(
38
+ description="""Optional. Comma-separated scale factors (e.g., 'x,y,z')."""
39
+ ),
40
+ ] = None,
41
+ prefab_path: Annotated[
42
+ str | None,
43
+ Field(
44
+ description="""Optional. Filesystem path to a prefab asset i.e. files that end in .prefab. Example: Assets/MyPrefab.prefab. Only used when reading/modifying a prefab."""
45
+ ),
46
+ ] = None,
47
+ use_world_coordinates: Annotated[
48
+ bool | None,
49
+ Field(
50
+ description="""Optional. Whether to use world coordinates (true) or local coordinates (false, default). Defaults to false."""
51
+ ),
52
+ ] = None,
53
+ ) -> Any:
54
+ """Creates a new GameObject in the Unity scene. If primitive_type is not specified, creates an empty GameObject."""
55
+ try:
56
+ logger.debug(f"Executing create_game_object with parameters: {locals()}")
57
+
58
+ # Prepare parameters for Unity RPC call
59
+ params = {}
60
+ if name is not None:
61
+ params['name'] = str(name)
62
+ if primitive_type is not None:
63
+ params['primitive_type'] = str(primitive_type)
64
+ if position is not None:
65
+ params['position'] = str(position)
66
+ if size is not None:
67
+ params['size'] = str(size)
68
+ if prefab_path is not None:
69
+ params['prefab_path'] = str(prefab_path)
70
+ if use_world_coordinates is not None:
71
+ params['use_world_coordinates'] = str(use_world_coordinates)
72
+
73
+ # Execute Unity RPC call
74
+ result = await _unity_client.execute_request('create_game_object', params)
75
+ logger.debug(f"create_game_object completed successfully")
76
+ return result
77
+
78
+ except Exception as e:
79
+ logger.error(f"Failed to execute create_game_object: {e}")
80
+ raise RuntimeError(f"Tool execution failed for create_game_object: {e}")
81
+
82
+
83
+ async def delete_game_object(
84
+ gameobject_path: Annotated[
85
+ str,
86
+ Field(
87
+ description="""Path to the GameObject in the scene or in a prefab asset. e.g Body/Head/Eyes"""
88
+ ),
89
+ ],
90
+ prefab_path: Annotated[
91
+ str | None,
92
+ Field(
93
+ description="""Optional. Filesystem path to a prefab asset i.e. files that end in .prefab. Example: Assets/MyPrefab.prefab. Only used when reading/modifying a prefab."""
94
+ ),
95
+ ] = None,
96
+ ) -> Any:
97
+ """Deletes a GameObject from the Unity scene."""
98
+ try:
99
+ logger.debug(f"Executing delete_game_object with parameters: {locals()}")
100
+
101
+ # Prepare parameters for Unity RPC call
102
+ params = {}
103
+ if gameobject_path is not None:
104
+ params['gameobject_path'] = str(gameobject_path)
105
+ if prefab_path is not None:
106
+ params['prefab_path'] = str(prefab_path)
107
+
108
+ # Execute Unity RPC call
109
+ result = await _unity_client.execute_request('delete_game_object', params)
110
+ logger.debug(f"delete_game_object completed successfully")
111
+ return result
112
+
113
+ except Exception as e:
114
+ logger.error(f"Failed to execute delete_game_object: {e}")
115
+ raise RuntimeError(f"Tool execution failed for delete_game_object: {e}")
116
+
117
+
118
+ async def remove_component(
119
+ gameobject_path: Annotated[
120
+ str,
121
+ Field(
122
+ description="""Path to the GameObject in the scene or path in a prefab asset. e.g Body/Head/Eyes"""
123
+ ),
124
+ ],
125
+ component_type: Annotated[
126
+ str,
127
+ Field(
128
+ description="""Type of component to remove."""
129
+ ),
130
+ ],
131
+ prefab_path: Annotated[
132
+ str | None,
133
+ Field(
134
+ description="""Optional. Filesystem path to a prefab asset i.e. files that end in .prefab. Example: Assets/MyPrefab.prefab. Only used when reading/modifying a prefab."""
135
+ ),
136
+ ] = None,
137
+ ) -> Any:
138
+ """Removes a component from a GameObject in the scene or from a prefab."""
139
+ try:
140
+ logger.debug(f"Executing remove_component with parameters: {locals()}")
141
+
142
+ # Prepare parameters for Unity RPC call
143
+ params = {}
144
+ if gameobject_path is not None:
145
+ params['gameobject_path'] = str(gameobject_path)
146
+ if component_type is not None:
147
+ params['component_type'] = str(component_type)
148
+ if prefab_path is not None:
149
+ params['prefab_path'] = str(prefab_path)
150
+
151
+ # Execute Unity RPC call
152
+ result = await _unity_client.execute_request('remove_component', params)
153
+ logger.debug(f"remove_component completed successfully")
154
+ return result
155
+
156
+ except Exception as e:
157
+ logger.error(f"Failed to execute remove_component: {e}")
158
+ raise RuntimeError(f"Tool execution failed for remove_component: {e}")
159
+
160
+
161
+ async def set_transform(
162
+ gameobject_path: Annotated[
163
+ str,
164
+ Field(
165
+ description="""Path to the GameObject in the scene or in a prefab asset. e.g Body/Head/Eyes"""
166
+ ),
167
+ ],
168
+ position: Annotated[
169
+ str | None,
170
+ Field(
171
+ description="""Optional. Comma-separated position coordinates (e.g., 'x,y,z')."""
172
+ ),
173
+ ] = None,
174
+ rotation: Annotated[
175
+ str | None,
176
+ Field(
177
+ description="""Optional. Comma-separated rotation angles (e.g., 'x,y,z')."""
178
+ ),
179
+ ] = None,
180
+ scale: Annotated[
181
+ str | None,
182
+ Field(
183
+ description="""Optional. Comma-separated scale factors (e.g., 'x,y,z')."""
184
+ ),
185
+ ] = None,
186
+ prefab_path: Annotated[
187
+ str | None,
188
+ Field(
189
+ description="""Optional. Filesystem path to a prefab asset i.e. files that end in .prefab. Example: Assets/MyPrefab.prefab. Only used when reading/modifying a prefab."""
190
+ ),
191
+ ] = None,
192
+ use_world_coordinates: Annotated[
193
+ bool | None,
194
+ Field(
195
+ description="""Optional. Whether to use world coordinates (true) or local coordinates (false, default). Defaults to false."""
196
+ ),
197
+ ] = None,
198
+ ) -> Any:
199
+ """Sets the position, rotation, or scale of a GameObject."""
200
+ try:
201
+ logger.debug(f"Executing set_transform with parameters: {locals()}")
202
+
203
+ # Prepare parameters for Unity RPC call
204
+ params = {}
205
+ if gameobject_path is not None:
206
+ params['gameobject_path'] = str(gameobject_path)
207
+ if position is not None:
208
+ params['position'] = str(position)
209
+ if rotation is not None:
210
+ params['rotation'] = str(rotation)
211
+ if scale is not None:
212
+ params['scale'] = str(scale)
213
+ if prefab_path is not None:
214
+ params['prefab_path'] = str(prefab_path)
215
+ if use_world_coordinates is not None:
216
+ params['use_world_coordinates'] = str(use_world_coordinates)
217
+
218
+ # Execute Unity RPC call
219
+ result = await _unity_client.execute_request('set_transform', params)
220
+ logger.debug(f"set_transform completed successfully")
221
+ return result
222
+
223
+ except Exception as e:
224
+ logger.error(f"Failed to execute set_transform: {e}")
225
+ raise RuntimeError(f"Tool execution failed for set_transform: {e}")
226
+
227
+
228
+ async def set_property(
229
+ gameobject_path: Annotated[
230
+ str,
231
+ Field(
232
+ description="""Path to the GameObject in the scene or in a prefab asset. e.g Body/Head/Eyes"""
233
+ ),
234
+ ],
235
+ component_type: Annotated[
236
+ str,
237
+ Field(
238
+ description="""Type of the component (e.g., 'Rigidbody')."""
239
+ ),
240
+ ],
241
+ property_name: Annotated[
242
+ str,
243
+ Field(
244
+ description="""Name of the property to set."""
245
+ ),
246
+ ],
247
+ value: Annotated[
248
+ str,
249
+ Field(
250
+ description="""New value for the property. If it's an asset, use the path to the asset from its top level directory e.g. Assets/, Packages/, etc. If it's a gameobject in the hierarchy, use the path to the gameobject from the root of the scene."""
251
+ ),
252
+ ],
253
+ prefab_path: Annotated[
254
+ str | None,
255
+ Field(
256
+ description="""Optional. Filesystem path to a prefab asset i.e. files that end in .prefab. Example: Assets/MyPrefab.prefab. Only used when reading/modifying a prefab."""
257
+ ),
258
+ ] = None,
259
+ asset_path: Annotated[
260
+ str | None,
261
+ Field(
262
+ description="""Optional. Filesystem path to an asset i.e. files that end in .asset. Example: Assets/MyAsset.asset. Only used when reading/modifying an asset that's not a prefab."""
263
+ ),
264
+ ] = None,
265
+ ) -> Any:
266
+ """Sets a property of a component on a GameObject."""
267
+ try:
268
+ logger.debug(f"Executing set_property with parameters: {locals()}")
269
+
270
+ # Prepare parameters for Unity RPC call
271
+ params = {}
272
+ if gameobject_path is not None:
273
+ params['gameobject_path'] = str(gameobject_path)
274
+ if component_type is not None:
275
+ params['component_type'] = str(component_type)
276
+ if property_name is not None:
277
+ params['property_name'] = str(property_name)
278
+ if value is not None:
279
+ params['value'] = str(value)
280
+ if prefab_path is not None:
281
+ params['prefab_path'] = str(prefab_path)
282
+ if asset_path is not None:
283
+ params['asset_path'] = str(asset_path)
284
+
285
+ # Execute Unity RPC call
286
+ result = await _unity_client.execute_request('set_property', params)
287
+ logger.debug(f"set_property completed successfully")
288
+ return result
289
+
290
+ except Exception as e:
291
+ logger.error(f"Failed to execute set_property: {e}")
292
+ raise RuntimeError(f"Tool execution failed for set_property: {e}")
293
+
294
+
295
+ async def save_scene(
296
+ scene_name: Annotated[
297
+ str,
298
+ Field(
299
+ description="""Name for the saved scene."""
300
+ ),
301
+ ],
302
+ ) -> Any:
303
+ """Saves the current scene."""
304
+ try:
305
+ logger.debug(f"Executing save_scene with parameters: {locals()}")
306
+
307
+ # Prepare parameters for Unity RPC call
308
+ params = {}
309
+ if scene_name is not None:
310
+ params['scene_name'] = str(scene_name)
311
+
312
+ # Execute Unity RPC call
313
+ result = await _unity_client.execute_request('save_scene', params)
314
+ logger.debug(f"save_scene completed successfully")
315
+ return result
316
+
317
+ except Exception as e:
318
+ logger.error(f"Failed to execute save_scene: {e}")
319
+ raise RuntimeError(f"Tool execution failed for save_scene: {e}")
320
+
321
+
322
+ async def create_material(
323
+ material_name: Annotated[
324
+ str,
325
+ Field(
326
+ description="""Name of the new material."""
327
+ ),
328
+ ],
329
+ color: Annotated[
330
+ str,
331
+ Field(
332
+ description="""Comma-separated color components (e.g., 'r,g,b,a'). Minimum 0, maximum 1."""
333
+ ),
334
+ ],
335
+ material_path: Annotated[
336
+ str,
337
+ Field(
338
+ description="""The folder path where the material should be created. If the folder doesn't exist, it will be created automatically."""
339
+ ),
340
+ ],
341
+ texture_path: Annotated[
342
+ str | None,
343
+ Field(
344
+ description="""The path to a texture file to be applied to the material."""
345
+ ),
346
+ ] = None,
347
+ ) -> Any:
348
+ """Creates a new material asset."""
349
+ try:
350
+ logger.debug(f"Executing create_material with parameters: {locals()}")
351
+
352
+ # Prepare parameters for Unity RPC call
353
+ params = {}
354
+ if material_name is not None:
355
+ params['material_name'] = str(material_name)
356
+ if color is not None:
357
+ params['color'] = str(color)
358
+ if material_path is not None:
359
+ params['material_path'] = str(material_path)
360
+ if texture_path is not None:
361
+ params['texture_path'] = str(texture_path)
362
+
363
+ # Execute Unity RPC call
364
+ result = await _unity_client.execute_request('create_material', params)
365
+ logger.debug(f"create_material completed successfully")
366
+ return result
367
+
368
+ except Exception as e:
369
+ logger.error(f"Failed to execute create_material: {e}")
370
+ raise RuntimeError(f"Tool execution failed for create_material: {e}")
371
+
372
+
373
+ async def assign_material(
374
+ gameobject_path: Annotated[
375
+ str,
376
+ Field(
377
+ description="""Path to the GameObject in the scene or in a prefab asset. e.g Body/Head/Eyes"""
378
+ ),
379
+ ],
380
+ material_name: Annotated[
381
+ str,
382
+ Field(
383
+ description="""Name of the material to assign."""
384
+ ),
385
+ ],
386
+ material_path: Annotated[
387
+ str | None,
388
+ Field(
389
+ description="""The folder path where the material is located."""
390
+ ),
391
+ ] = None,
392
+ prefab_path: Annotated[
393
+ str | None,
394
+ Field(
395
+ description="""Optional. Filesystem path to a prefab asset i.e. files that end in .prefab. Example: Assets/MyPrefab.prefab. Only used when reading/modifying a prefab."""
396
+ ),
397
+ ] = None,
398
+ ) -> Any:
399
+ """Assigns a material to a GameObject or a nested object within a Prefab."""
400
+ try:
401
+ logger.debug(f"Executing assign_material with parameters: {locals()}")
402
+
403
+ # Prepare parameters for Unity RPC call
404
+ params = {}
405
+ if gameobject_path is not None:
406
+ params['gameobject_path'] = str(gameobject_path)
407
+ if material_name is not None:
408
+ params['material_name'] = str(material_name)
409
+ if material_path is not None:
410
+ params['material_path'] = str(material_path)
411
+ if prefab_path is not None:
412
+ params['prefab_path'] = str(prefab_path)
413
+
414
+ # Execute Unity RPC call
415
+ result = await _unity_client.execute_request('assign_material', params)
416
+ logger.debug(f"assign_material completed successfully")
417
+ return result
418
+
419
+ except Exception as e:
420
+ logger.error(f"Failed to execute assign_material: {e}")
421
+ raise RuntimeError(f"Tool execution failed for assign_material: {e}")
422
+
423
+
424
+ async def assign_material_to_fbx(
425
+ fbx_path: Annotated[
426
+ str,
427
+ Field(
428
+ description="""Path to the FBX file within the Assets folder (e.g., 'Assets/Models/MyModel.fbx')."""
429
+ ),
430
+ ],
431
+ material_path: Annotated[
432
+ str,
433
+ Field(
434
+ description="""Path to the material within the Assets folder (e.g., 'Assets/Materials/MyMaterial.mat')."""
435
+ ),
436
+ ],
437
+ submesh_index: Annotated[
438
+ str | int | None,
439
+ Field(
440
+ description="""Optional. Index of the submesh to apply the material to. Defaults to 0."""
441
+ ),
442
+ ] = None,
443
+ ) -> Any:
444
+ """Assigns a material to an FBX model in the project (without requiring it to be in the scene)."""
445
+ try:
446
+ logger.debug(f"Executing assign_material_to_fbx with parameters: {locals()}")
447
+
448
+ # Prepare parameters for Unity RPC call
449
+ params = {}
450
+ if fbx_path is not None:
451
+ params['fbx_path'] = str(fbx_path)
452
+ if material_path is not None:
453
+ params['material_path'] = str(material_path)
454
+ if submesh_index is not None:
455
+ params['submesh_index'] = str(submesh_index)
456
+
457
+ # Execute Unity RPC call
458
+ result = await _unity_client.execute_request('assign_material_to_fbx', params)
459
+ logger.debug(f"assign_material_to_fbx completed successfully")
460
+ return result
461
+
462
+ except Exception as e:
463
+ logger.error(f"Failed to execute assign_material_to_fbx: {e}")
464
+ raise RuntimeError(f"Tool execution failed for assign_material_to_fbx: {e}")
465
+
466
+
467
+ async def add_component(
468
+ gameobject_path: Annotated[
469
+ str,
470
+ Field(
471
+ description="""Path to the GameObject in the scene or path in a prefab asset. e.g Body/Head/Eyes"""
472
+ ),
473
+ ],
474
+ component_type: Annotated[
475
+ str,
476
+ Field(
477
+ description="""Type of component to add (e.g., 'Rigidbody', 'BoxCollider')."""
478
+ ),
479
+ ],
480
+ prefab_path: Annotated[
481
+ str | None,
482
+ Field(
483
+ description="""Optional. Filesystem path to a prefab asset i.e. files that end in .prefab. Example: Assets/MyPrefab.prefab. Only used when reading/modifying a prefab."""
484
+ ),
485
+ ] = None,
486
+ ) -> Any:
487
+ """Adds a component to a GameObject, Prefab, or nested object within a Prefab."""
488
+ try:
489
+ logger.debug(f"Executing add_component with parameters: {locals()}")
490
+
491
+ # Prepare parameters for Unity RPC call
492
+ params = {}
493
+ if gameobject_path is not None:
494
+ params['gameobject_path'] = str(gameobject_path)
495
+ if component_type is not None:
496
+ params['component_type'] = str(component_type)
497
+ if prefab_path is not None:
498
+ params['prefab_path'] = str(prefab_path)
499
+
500
+ # Execute Unity RPC call
501
+ result = await _unity_client.execute_request('add_component', params)
502
+ logger.debug(f"add_component completed successfully")
503
+ return result
504
+
505
+ except Exception as e:
506
+ logger.error(f"Failed to execute add_component: {e}")
507
+ raise RuntimeError(f"Tool execution failed for add_component: {e}")
508
+
509
+
510
+ async def duplicate_game_object(
511
+ gameobject_path: Annotated[
512
+ str,
513
+ Field(
514
+ description="""Path to the GameObject in the scene or in a prefab asset. e.g Body/Head/Eyes"""
515
+ ),
516
+ ],
517
+ prefab_path: Annotated[
518
+ str | None,
519
+ Field(
520
+ description="""Optional. Filesystem path to a prefab asset i.e. files that end in .prefab. Example: Assets/MyPrefab.prefab. Only used when reading/modifying a prefab."""
521
+ ),
522
+ ] = None,
523
+ new_name: Annotated[
524
+ str | None,
525
+ Field(
526
+ description="""Optional. Name for the duplicated GameObject."""
527
+ ),
528
+ ] = None,
529
+ ) -> Any:
530
+ """Duplicates a GameObject."""
531
+ try:
532
+ logger.debug(f"Executing duplicate_game_object with parameters: {locals()}")
533
+
534
+ # Prepare parameters for Unity RPC call
535
+ params = {}
536
+ if gameobject_path is not None:
537
+ params['gameobject_path'] = str(gameobject_path)
538
+ if prefab_path is not None:
539
+ params['prefab_path'] = str(prefab_path)
540
+ if new_name is not None:
541
+ params['new_name'] = str(new_name)
542
+
543
+ # Execute Unity RPC call
544
+ result = await _unity_client.execute_request('duplicate_game_object', params)
545
+ logger.debug(f"duplicate_game_object completed successfully")
546
+ return result
547
+
548
+ except Exception as e:
549
+ logger.error(f"Failed to execute duplicate_game_object: {e}")
550
+ raise RuntimeError(f"Tool execution failed for duplicate_game_object: {e}")
551
+
552
+
553
+ async def parent_game_object(
554
+ child_path: Annotated[
555
+ str,
556
+ Field(
557
+ description="""Path to the child GameObject in the scene or in a prefab asset. e.g Body/Head/Eyes"""
558
+ ),
559
+ ],
560
+ parent_path: Annotated[
561
+ str,
562
+ Field(
563
+ description="""Path to the parent GameObject in the scene or in a prefab asset. e.g Body/Head/Eyes"""
564
+ ),
565
+ ],
566
+ prefab_path: Annotated[
567
+ str | None,
568
+ Field(
569
+ description="""Optional. Filesystem path to a prefab asset i.e. files that end in .prefab. Example: Assets/MyPrefab.prefab. Only used when reading/modifying a prefab."""
570
+ ),
571
+ ] = None,
572
+ ) -> Any:
573
+ """Sets the parent of a GameObject."""
574
+ try:
575
+ logger.debug(f"Executing parent_game_object with parameters: {locals()}")
576
+
577
+ # Prepare parameters for Unity RPC call
578
+ params = {}
579
+ if child_path is not None:
580
+ params['child_path'] = str(child_path)
581
+ if parent_path is not None:
582
+ params['parent_path'] = str(parent_path)
583
+ if prefab_path is not None:
584
+ params['prefab_path'] = str(prefab_path)
585
+
586
+ # Execute Unity RPC call
587
+ result = await _unity_client.execute_request('parent_game_object', params)
588
+ logger.debug(f"parent_game_object completed successfully")
589
+ return result
590
+
591
+ except Exception as e:
592
+ logger.error(f"Failed to execute parent_game_object: {e}")
593
+ raise RuntimeError(f"Tool execution failed for parent_game_object: {e}")
594
+
595
+
596
+ async def rename_game_object(
597
+ current_path: Annotated[
598
+ str,
599
+ Field(
600
+ description="""Current path of the GameObject."""
601
+ ),
602
+ ],
603
+ new_name: Annotated[
604
+ str,
605
+ Field(
606
+ description="""New name for the GameObject."""
607
+ ),
608
+ ],
609
+ prefab_path: Annotated[
610
+ str | None,
611
+ Field(
612
+ description="""Optional. Filesystem path to a prefab asset i.e. files that end in .prefab. Example: Assets/MyPrefab.prefab. Only used when reading/modifying a prefab."""
613
+ ),
614
+ ] = None,
615
+ ) -> Any:
616
+ """Renames an existing GameObject."""
617
+ try:
618
+ logger.debug(f"Executing rename_game_object with parameters: {locals()}")
619
+
620
+ # Prepare parameters for Unity RPC call
621
+ params = {}
622
+ if current_path is not None:
623
+ params['current_path'] = str(current_path)
624
+ if new_name is not None:
625
+ params['new_name'] = str(new_name)
626
+ if prefab_path is not None:
627
+ params['prefab_path'] = str(prefab_path)
628
+
629
+ # Execute Unity RPC call
630
+ result = await _unity_client.execute_request('rename_game_object', params)
631
+ logger.debug(f"rename_game_object completed successfully")
632
+ return result
633
+
634
+ except Exception as e:
635
+ logger.error(f"Failed to execute rename_game_object: {e}")
636
+ raise RuntimeError(f"Tool execution failed for rename_game_object: {e}")
637
+
638
+
639
+ async def set_tag(
640
+ gameobject_path: Annotated[
641
+ str,
642
+ Field(
643
+ description="""Path to the GameObject in the scene or in a prefab asset. e.g Body/Head/Eyes"""
644
+ ),
645
+ ],
646
+ tag_name: Annotated[
647
+ str,
648
+ Field(
649
+ description="""The tag to assign to the GameObject."""
650
+ ),
651
+ ],
652
+ create_if_not_exists: Annotated[
653
+ bool | None,
654
+ Field(
655
+ description="""If true, creates the tag if it doesn't exist. Defaults to true."""
656
+ ),
657
+ ] = None,
658
+ prefab_path: Annotated[
659
+ str | None,
660
+ Field(
661
+ description="""Optional. Filesystem path to a prefab asset i.e. files that end in .prefab. Example: Assets/MyPrefab.prefab. Only used when reading/modifying a prefab."""
662
+ ),
663
+ ] = None,
664
+ ) -> Any:
665
+ """Sets the tag of a GameObject. Can create the tag if it doesn't exist."""
666
+ try:
667
+ logger.debug(f"Executing set_tag with parameters: {locals()}")
668
+
669
+ # Prepare parameters for Unity RPC call
670
+ params = {}
671
+ if gameobject_path is not None:
672
+ params['gameobject_path'] = str(gameobject_path)
673
+ if tag_name is not None:
674
+ params['tag_name'] = str(tag_name)
675
+ if create_if_not_exists is not None:
676
+ params['create_if_not_exists'] = str(create_if_not_exists)
677
+ if prefab_path is not None:
678
+ params['prefab_path'] = str(prefab_path)
679
+
680
+ # Execute Unity RPC call
681
+ result = await _unity_client.execute_request('set_tag', params)
682
+ logger.debug(f"set_tag completed successfully")
683
+ return result
684
+
685
+ except Exception as e:
686
+ logger.error(f"Failed to execute set_tag: {e}")
687
+ raise RuntimeError(f"Tool execution failed for set_tag: {e}")
688
+
689
+
690
+ async def set_layer(
691
+ gameobject_path: Annotated[
692
+ str,
693
+ Field(
694
+ description="""Path to the GameObject in the scene or in a prefab asset. e.g Body/Head/Eyes"""
695
+ ),
696
+ ],
697
+ layer: Annotated[
698
+ str | int,
699
+ Field(
700
+ description="""Name or index of the layer to assign."""
701
+ ),
702
+ ],
703
+ create_if_not_exists: Annotated[
704
+ bool | None,
705
+ Field(
706
+ description="""If true, creates the layer if it doesn't exist (only for string layer names). Defaults to true."""
707
+ ),
708
+ ] = None,
709
+ prefab_path: Annotated[
710
+ str | None,
711
+ Field(
712
+ description="""Optional. Filesystem path to a prefab asset i.e. files that end in .prefab. Example: Assets/MyPrefab.prefab. Only used when reading/modifying a prefab."""
713
+ ),
714
+ ] = None,
715
+ ) -> Any:
716
+ """Sets the layer of a GameObject. Can create the layer if it doesn't exist."""
717
+ try:
718
+ logger.debug(f"Executing set_layer with parameters: {locals()}")
719
+
720
+ # Prepare parameters for Unity RPC call
721
+ params = {}
722
+ if gameobject_path is not None:
723
+ params['gameobject_path'] = str(gameobject_path)
724
+ if layer is not None:
725
+ params['layer'] = str(layer)
726
+ if create_if_not_exists is not None:
727
+ params['create_if_not_exists'] = str(create_if_not_exists)
728
+ if prefab_path is not None:
729
+ params['prefab_path'] = str(prefab_path)
730
+
731
+ # Execute Unity RPC call
732
+ result = await _unity_client.execute_request('set_layer', params)
733
+ logger.debug(f"set_layer completed successfully")
734
+ return result
735
+
736
+ except Exception as e:
737
+ logger.error(f"Failed to execute set_layer: {e}")
738
+ raise RuntimeError(f"Tool execution failed for set_layer: {e}")
739
+
740
+
741
+ async def generate_3d_model_texture(
742
+ object_prompt: Annotated[
743
+ str,
744
+ Field(
745
+ description="""Describe what kind of object the 3D model is."""
746
+ ),
747
+ ],
748
+ provider: Annotated[
749
+ Literal['meshy'],
750
+ Field(
751
+ description="""The provider to use for generating the texture. Currently only Meshy is supported."""
752
+ ),
753
+ ],
754
+ style_prompt: Annotated[
755
+ str,
756
+ Field(
757
+ description="""Describe your desired style of the object."""
758
+ ),
759
+ ],
760
+ output_path: Annotated[
761
+ str,
762
+ Field(
763
+ description="""The file path where the generated image will be saved."""
764
+ ),
765
+ ],
766
+ model_path: Annotated[
767
+ str,
768
+ Field(
769
+ description="""Path to the 3D model for which the texture will be generated. This should be a .fbx or .glb file path. I.e. the path of where the model is currently located in the project. This model will be uploaded and used to help guide the texture generation."""
770
+ ),
771
+ ],
772
+ quality: Annotated[
773
+ Literal['standard', 'high'] | None,
774
+ Field(
775
+ description="""The quality of the generated image. Defaults to standard."""
776
+ ),
777
+ ] = None,
778
+ size: Annotated[
779
+ Literal['1024x1024', '1792x1024', '1024x1792'] | None,
780
+ Field(
781
+ description="""The size of the generated image. Defaults to 1024x1024."""
782
+ ),
783
+ ] = None,
784
+ style: Annotated[
785
+ Literal['natural', 'vivid'] | None,
786
+ Field(
787
+ description="""The style of the generated image. Defaults to natural."""
788
+ ),
789
+ ] = None,
790
+ resolution: Annotated[
791
+ Literal['1024', '2048', '4096'] | None,
792
+ Field(
793
+ description="""The texture resolution (Meshy-specific). Defaults to 1024."""
794
+ ),
795
+ ] = None,
796
+ art_style: Annotated[
797
+ Literal['realistic', 'japanese_anime', 'cartoon', 'hand_drawn'] | None,
798
+ Field(
799
+ description="""The artistic style for the texture (Meshy-specific). Defaults to realistic."""
800
+ ),
801
+ ] = None,
802
+ ) -> Any:
803
+ """Generates a texture image based on a text prompt and saves it to a specified path. Before calling this function, ensure that you know where the existing model is located in the project and use it for the model_path parameter."""
804
+ try:
805
+ logger.debug(f"Executing generate_3d_model_texture with parameters: {locals()}")
806
+
807
+ # Prepare parameters for Unity RPC call
808
+ params = {}
809
+ if object_prompt is not None:
810
+ params['object_prompt'] = str(object_prompt)
811
+ if provider is not None:
812
+ params['provider'] = str(provider)
813
+ if style_prompt is not None:
814
+ params['style_prompt'] = str(style_prompt)
815
+ if output_path is not None:
816
+ params['output_path'] = str(output_path)
817
+ if model_path is not None:
818
+ params['model_path'] = str(model_path)
819
+ if quality is not None:
820
+ params['quality'] = str(quality)
821
+ if size is not None:
822
+ params['size'] = str(size)
823
+ if style is not None:
824
+ params['style'] = str(style)
825
+ if resolution is not None:
826
+ params['resolution'] = str(resolution)
827
+ if art_style is not None:
828
+ params['art_style'] = str(art_style)
829
+
830
+ # Execute Unity RPC call
831
+ result = await _unity_client.execute_request('generate_3d_model_texture', params)
832
+ logger.debug(f"generate_3d_model_texture completed successfully")
833
+ return result
834
+
835
+ except Exception as e:
836
+ logger.error(f"Failed to execute generate_3d_model_texture: {e}")
837
+ raise RuntimeError(f"Tool execution failed for generate_3d_model_texture: {e}")
838
+
839
+
840
+ async def create_prefab(
841
+ gameobject_path: Annotated[
842
+ str,
843
+ Field(
844
+ description="""Path to the GameObject in the scene to turn into a prefab. e.g Body/Head/Eyes"""
845
+ ),
846
+ ],
847
+ prefab_name: Annotated[
848
+ str,
849
+ Field(
850
+ description="""Name for the new prefab file (without extension)."""
851
+ ),
852
+ ],
853
+ prefab_path: Annotated[
854
+ str,
855
+ Field(
856
+ description="""The folder path where the prefab should be saved. If the folder doesn't exist, it will be created automatically."""
857
+ ),
858
+ ],
859
+ ) -> Any:
860
+ """Creates a prefab from an existing GameObject in the active scene or heirarchy."""
861
+ try:
862
+ logger.debug(f"Executing create_prefab with parameters: {locals()}")
863
+
864
+ # Prepare parameters for Unity RPC call
865
+ params = {}
866
+ if gameobject_path is not None:
867
+ params['gameobject_path'] = str(gameobject_path)
868
+ if prefab_name is not None:
869
+ params['prefab_name'] = str(prefab_name)
870
+ if prefab_path is not None:
871
+ params['prefab_path'] = str(prefab_path)
872
+
873
+ # Execute Unity RPC call
874
+ result = await _unity_client.execute_request('create_prefab', params)
875
+ logger.debug(f"create_prefab completed successfully")
876
+ return result
877
+
878
+ except Exception as e:
879
+ logger.error(f"Failed to execute create_prefab: {e}")
880
+ raise RuntimeError(f"Tool execution failed for create_prefab: {e}")
881
+
882
+
883
+ async def assign_shader_to_material(
884
+ material_path: Annotated[
885
+ str,
886
+ Field(
887
+ description="""Path to the material file (e.g. 'Assets/Materials/MyMaterial.mat')."""
888
+ ),
889
+ ],
890
+ shader_path: Annotated[
891
+ str,
892
+ Field(
893
+ description="""Path to the shader file (e.g. 'Assets/Shaders/MyShader.shader')."""
894
+ ),
895
+ ],
896
+ ) -> Any:
897
+ """Assigns a shader to a material."""
898
+ try:
899
+ logger.debug(f"Executing assign_shader_to_material with parameters: {locals()}")
900
+
901
+ # Prepare parameters for Unity RPC call
902
+ params = {}
903
+ if material_path is not None:
904
+ params['material_path'] = str(material_path)
905
+ if shader_path is not None:
906
+ params['shader_path'] = str(shader_path)
907
+
908
+ # Execute Unity RPC call
909
+ result = await _unity_client.execute_request('assign_shader_to_material', params)
910
+ logger.debug(f"assign_shader_to_material completed successfully")
911
+ return result
912
+
913
+ except Exception as e:
914
+ logger.error(f"Failed to execute assign_shader_to_material: {e}")
915
+ raise RuntimeError(f"Tool execution failed for assign_shader_to_material: {e}")
916
+
917
+
918
+ async def create_prefab_variant(
919
+ base_prefab_path: Annotated[
920
+ str,
921
+ Field(
922
+ description="""The path to the base prefab asset."""
923
+ ),
924
+ ],
925
+ variant_prefab_name: Annotated[
926
+ str,
927
+ Field(
928
+ description="""Name for the new prefab variant file (without extension)."""
929
+ ),
930
+ ],
931
+ variant_prefab_path: Annotated[
932
+ str,
933
+ Field(
934
+ description="""The folder path where the prefab variant should be saved. If the folder doesn't exist, it will be created automatically."""
935
+ ),
936
+ ],
937
+ ) -> Any:
938
+ """Creates a variant of an existing prefab asset in the assets folder."""
939
+ try:
940
+ logger.debug(f"Executing create_prefab_variant with parameters: {locals()}")
941
+
942
+ # Prepare parameters for Unity RPC call
943
+ params = {}
944
+ if base_prefab_path is not None:
945
+ params['base_prefab_path'] = str(base_prefab_path)
946
+ if variant_prefab_name is not None:
947
+ params['variant_prefab_name'] = str(variant_prefab_name)
948
+ if variant_prefab_path is not None:
949
+ params['variant_prefab_path'] = str(variant_prefab_path)
950
+
951
+ # Execute Unity RPC call
952
+ result = await _unity_client.execute_request('create_prefab_variant', params)
953
+ logger.debug(f"create_prefab_variant completed successfully")
954
+ return result
955
+
956
+ except Exception as e:
957
+ logger.error(f"Failed to execute create_prefab_variant: {e}")
958
+ raise RuntimeError(f"Tool execution failed for create_prefab_variant: {e}")
959
+
960
+
961
+ async def duplicate_asset(
962
+ original_asset_path: Annotated[
963
+ str,
964
+ Field(
965
+ description="""The path to the original asset."""
966
+ ),
967
+ ],
968
+ new_asset_name: Annotated[
969
+ str,
970
+ Field(
971
+ description="""Name for the duplicated asset file (without extension)."""
972
+ ),
973
+ ],
974
+ destination_path: Annotated[
975
+ str,
976
+ Field(
977
+ description="""The folder path where the new asset should be saved. If the folder doesn't exist, it will be created automatically."""
978
+ ),
979
+ ],
980
+ ) -> Any:
981
+ """Duplicates an asset in the assets folder."""
982
+ try:
983
+ logger.debug(f"Executing duplicate_asset with parameters: {locals()}")
984
+
985
+ # Prepare parameters for Unity RPC call
986
+ params = {}
987
+ if original_asset_path is not None:
988
+ params['original_asset_path'] = str(original_asset_path)
989
+ if new_asset_name is not None:
990
+ params['new_asset_name'] = str(new_asset_name)
991
+ if destination_path is not None:
992
+ params['destination_path'] = str(destination_path)
993
+
994
+ # Execute Unity RPC call
995
+ result = await _unity_client.execute_request('duplicate_asset', params)
996
+ logger.debug(f"duplicate_asset completed successfully")
997
+ return result
998
+
999
+ except Exception as e:
1000
+ logger.error(f"Failed to execute duplicate_asset: {e}")
1001
+ raise RuntimeError(f"Tool execution failed for duplicate_asset: {e}")
1002
+
1003
+
1004
+ async def rename_asset(
1005
+ current_asset_path: Annotated[
1006
+ str,
1007
+ Field(
1008
+ description="""The current path to the asset (including file name and extension) within the Assets folder."""
1009
+ ),
1010
+ ],
1011
+ new_asset_name: Annotated[
1012
+ str,
1013
+ Field(
1014
+ description="""The new name for the asset (including extension if applicable)."""
1015
+ ),
1016
+ ],
1017
+ ) -> Any:
1018
+ """Renames an asset in the Unity Assets folder."""
1019
+ try:
1020
+ logger.debug(f"Executing rename_asset with parameters: {locals()}")
1021
+
1022
+ # Prepare parameters for Unity RPC call
1023
+ params = {}
1024
+ if current_asset_path is not None:
1025
+ params['current_asset_path'] = str(current_asset_path)
1026
+ if new_asset_name is not None:
1027
+ params['new_asset_name'] = str(new_asset_name)
1028
+
1029
+ # Execute Unity RPC call
1030
+ result = await _unity_client.execute_request('rename_asset', params)
1031
+ logger.debug(f"rename_asset completed successfully")
1032
+ return result
1033
+
1034
+ except Exception as e:
1035
+ logger.error(f"Failed to execute rename_asset: {e}")
1036
+ raise RuntimeError(f"Tool execution failed for rename_asset: {e}")
1037
+
1038
+
1039
+ async def check_compile_errors(
1040
+ ) -> Any:
1041
+ """Checks if there are compile errors in Unity project."""
1042
+ try:
1043
+ logger.debug(f"Executing check_compile_errors with parameters: {locals()}")
1044
+
1045
+ # Prepare parameters for Unity RPC call
1046
+ params = {}
1047
+
1048
+ # Execute Unity RPC call
1049
+ result = await _unity_client.execute_request('check_compile_errors', params)
1050
+ logger.debug(f"check_compile_errors completed successfully")
1051
+ return result
1052
+
1053
+ except Exception as e:
1054
+ logger.error(f"Failed to execute check_compile_errors: {e}")
1055
+ raise RuntimeError(f"Tool execution failed for check_compile_errors: {e}")
1056
+
1057
+
1058
+ async def add_nested_object_to_prefab(
1059
+ prefab_path: Annotated[
1060
+ str,
1061
+ Field(
1062
+ description="""Path to the target prefab that will contain the nested object."""
1063
+ ),
1064
+ ],
1065
+ object_path: Annotated[
1066
+ str,
1067
+ Field(
1068
+ description="""Path to the object (e.g., FBX) that will be nested."""
1069
+ ),
1070
+ ],
1071
+ nested_name: Annotated[
1072
+ str | None,
1073
+ Field(
1074
+ description="""Optional new name for the nested object instance."""
1075
+ ),
1076
+ ] = None,
1077
+ ) -> Any:
1078
+ """Adds an object from the Assets folder as a nested object inside an existing prefab."""
1079
+ try:
1080
+ logger.debug(f"Executing add_nested_object_to_prefab with parameters: {locals()}")
1081
+
1082
+ # Prepare parameters for Unity RPC call
1083
+ params = {}
1084
+ if prefab_path is not None:
1085
+ params['prefab_path'] = str(prefab_path)
1086
+ if object_path is not None:
1087
+ params['object_path'] = str(object_path)
1088
+ if nested_name is not None:
1089
+ params['nested_name'] = str(nested_name)
1090
+
1091
+ # Execute Unity RPC call
1092
+ result = await _unity_client.execute_request('add_nested_object_to_prefab', params)
1093
+ logger.debug(f"add_nested_object_to_prefab completed successfully")
1094
+ return result
1095
+
1096
+ except Exception as e:
1097
+ logger.error(f"Failed to execute add_nested_object_to_prefab: {e}")
1098
+ raise RuntimeError(f"Tool execution failed for add_nested_object_to_prefab: {e}")
1099
+
1100
+
1101
+ async def create_scene(
1102
+ scene_name: Annotated[
1103
+ str,
1104
+ Field(
1105
+ description="""Name of the new scene (with or without .unity extension)."""
1106
+ ),
1107
+ ],
1108
+ scene_path: Annotated[
1109
+ str | None,
1110
+ Field(
1111
+ description="""The folder path where the scene should be created. If the folder doesn't exist, it will be created automatically. Defaults to 'Assets/Scenes'."""
1112
+ ),
1113
+ ] = None,
1114
+ add_to_editor: Annotated[
1115
+ bool | None,
1116
+ Field(
1117
+ description="""Whether to add the scene to the build settings. Defaults to true."""
1118
+ ),
1119
+ ] = None,
1120
+ ) -> Any:
1121
+ """Creates a new Unity scene and optionally adds it to the build settings."""
1122
+ try:
1123
+ logger.debug(f"Executing create_scene with parameters: {locals()}")
1124
+
1125
+ # Prepare parameters for Unity RPC call
1126
+ params = {}
1127
+ if scene_name is not None:
1128
+ params['scene_name'] = str(scene_name)
1129
+ if scene_path is not None:
1130
+ params['scene_path'] = str(scene_path)
1131
+ if add_to_editor is not None:
1132
+ params['add_to_editor'] = str(add_to_editor)
1133
+
1134
+ # Execute Unity RPC call
1135
+ result = await _unity_client.execute_request('create_scene', params)
1136
+ logger.debug(f"create_scene completed successfully")
1137
+ return result
1138
+
1139
+ except Exception as e:
1140
+ logger.error(f"Failed to execute create_scene: {e}")
1141
+ raise RuntimeError(f"Tool execution failed for create_scene: {e}")
1142
+
1143
+
1144
+ async def generate_3d_model_from_image(
1145
+ image_url: Annotated[
1146
+ str,
1147
+ Field(
1148
+ description="""URL of the input image to generate the 3D model from."""
1149
+ ),
1150
+ ],
1151
+ output_path: Annotated[
1152
+ str,
1153
+ Field(
1154
+ description="""The file path where the generated model will be saved. The file extension should be .glb."""
1155
+ ),
1156
+ ],
1157
+ provider: Annotated[
1158
+ Literal['Meshy4', 'Meshy5', 'Hunyuan3D21'] | None,
1159
+ Field(
1160
+ description="""Optional. The AI provider to use for 3D model generation. Options: 'Meshy4' (uses Meshy 4.0 model), 'Meshy5' (uses Meshy 5.0 model), 'Hunyuan3D21' (uses Hunyuan 3D 2.1 model). Defaults to 'Meshy5'."""
1161
+ ),
1162
+ ] = None,
1163
+ provider_options: Annotated[
1164
+ str | None,
1165
+ Field(
1166
+ description="""Optional. JSON string containing provider-specific options. For FAL provider: {"textured_mesh": "true/false", "seed": "12345", "num_inference_steps": "50", "guidance_scale": "7.5", "octree_resolution": "256"}. For Meshy provider (image-to-3D): {"ai_model": "meshy-4/meshy-5", "topology": "triangle/quad", "target_polycount": "50000", "symmetry_mode": "auto/x/y/z", "should_remesh": "true/false", "should_texture": "true/false", "enable_pbr": "true/false", "texture_prompt": "realistic wood texture", "texture_image_url": "url", "moderation": "true/false"}."""
1167
+ ),
1168
+ ] = None,
1169
+ ) -> Any:
1170
+ """Generates a 3D model from an input image using various AI providers. Supports multiple providers with different capabilities and options."""
1171
+ try:
1172
+ logger.debug(f"Executing generate_3d_model_from_image with parameters: {locals()}")
1173
+
1174
+ # Prepare parameters for Unity RPC call
1175
+ params = {}
1176
+ if image_url is not None:
1177
+ params['image_url'] = str(image_url)
1178
+ if output_path is not None:
1179
+ params['output_path'] = str(output_path)
1180
+ if provider is not None:
1181
+ params['provider'] = str(provider)
1182
+ if provider_options is not None:
1183
+ params['provider_options'] = str(provider_options)
1184
+
1185
+ # Execute Unity RPC call
1186
+ result = await _unity_client.execute_request('generate_3d_model_from_image', params)
1187
+ logger.debug(f"generate_3d_model_from_image completed successfully")
1188
+ return result
1189
+
1190
+ except Exception as e:
1191
+ logger.error(f"Failed to execute generate_3d_model_from_image: {e}")
1192
+ raise RuntimeError(f"Tool execution failed for generate_3d_model_from_image: {e}")
1193
+
1194
+
1195
+ async def generate_3d_model_from_text(
1196
+ prompt: Annotated[
1197
+ str,
1198
+ Field(
1199
+ description="""The text prompt to generate the 3D model from."""
1200
+ ),
1201
+ ],
1202
+ output_path: Annotated[
1203
+ str,
1204
+ Field(
1205
+ description="""The file path where the generated model will be saved. The file extension should be .glb."""
1206
+ ),
1207
+ ],
1208
+ provider_options: Annotated[
1209
+ str | None,
1210
+ Field(
1211
+ description="""Optional. JSON string containing provider-specific options. For Meshy provider (text-to-3D): {"art_style": "realistic/sculpture/pbr", "negative_prompt": "low quality, low resolution", "enable_refinement": "true/false"}. Note: Text-to-3D uses Meshy provider by default."""
1212
+ ),
1213
+ ] = None,
1214
+ ) -> Any:
1215
+ """Generates a 3D model from a text prompt using various AI providers. Supports multiple providers with different capabilities and options for text-to-3D generation."""
1216
+ try:
1217
+ logger.debug(f"Executing generate_3d_model_from_text with parameters: {locals()}")
1218
+
1219
+ # Prepare parameters for Unity RPC call
1220
+ params = {}
1221
+ if prompt is not None:
1222
+ params['prompt'] = str(prompt)
1223
+ if output_path is not None:
1224
+ params['output_path'] = str(output_path)
1225
+ if provider_options is not None:
1226
+ params['provider_options'] = str(provider_options)
1227
+
1228
+ # Execute Unity RPC call
1229
+ result = await _unity_client.execute_request('generate_3d_model_from_text', params)
1230
+ logger.debug(f"generate_3d_model_from_text completed successfully")
1231
+ return result
1232
+
1233
+ except Exception as e:
1234
+ logger.error(f"Failed to execute generate_3d_model_from_text: {e}")
1235
+ raise RuntimeError(f"Tool execution failed for generate_3d_model_from_text: {e}")
1236
+
1237
+
1238
+ async def add_asset_to_scene(
1239
+ asset_path: Annotated[
1240
+ str,
1241
+ Field(
1242
+ description="""Path to the asset within the Assets folder (e.g., 'Models/Chair.fbx' or 'Prefabs/Player.prefab')."""
1243
+ ),
1244
+ ],
1245
+ instance_name: Annotated[
1246
+ str | None,
1247
+ Field(
1248
+ description="""Optional name for the instantiated object in the scene. If not provided, uses the asset's name."""
1249
+ ),
1250
+ ] = None,
1251
+ position: Annotated[
1252
+ str | None,
1253
+ Field(
1254
+ description="""Optional comma-separated position coordinates (e.g., 'x,y,z'). Defaults to '0,0,0'."""
1255
+ ),
1256
+ ] = None,
1257
+ ) -> Any:
1258
+ """Adds an existing asset from the Assets folder into the current scene."""
1259
+ try:
1260
+ logger.debug(f"Executing add_asset_to_scene with parameters: {locals()}")
1261
+
1262
+ # Prepare parameters for Unity RPC call
1263
+ params = {}
1264
+ if asset_path is not None:
1265
+ params['asset_path'] = str(asset_path)
1266
+ if instance_name is not None:
1267
+ params['instance_name'] = str(instance_name)
1268
+ if position is not None:
1269
+ params['position'] = str(position)
1270
+
1271
+ # Execute Unity RPC call
1272
+ result = await _unity_client.execute_request('add_asset_to_scene', params)
1273
+ logger.debug(f"add_asset_to_scene completed successfully")
1274
+ return result
1275
+
1276
+ except Exception as e:
1277
+ logger.error(f"Failed to execute add_asset_to_scene: {e}")
1278
+ raise RuntimeError(f"Tool execution failed for add_asset_to_scene: {e}")
1279
+
1280
+
1281
+ async def open_scene(
1282
+ scene_path: Annotated[
1283
+ str,
1284
+ Field(
1285
+ description="""Path to the scene file within the Assets folder (e.g., 'Scenes/MainMenu.unity'). The '.unity' extension is optional."""
1286
+ ),
1287
+ ],
1288
+ ) -> Any:
1289
+ """Opens a scene from the Assets folder."""
1290
+ try:
1291
+ logger.debug(f"Executing open_scene with parameters: {locals()}")
1292
+
1293
+ # Prepare parameters for Unity RPC call
1294
+ params = {}
1295
+ if scene_path is not None:
1296
+ params['scene_path'] = str(scene_path)
1297
+
1298
+ # Execute Unity RPC call
1299
+ result = await _unity_client.execute_request('open_scene', params)
1300
+ logger.debug(f"open_scene completed successfully")
1301
+ return result
1302
+
1303
+ except Exception as e:
1304
+ logger.error(f"Failed to execute open_scene: {e}")
1305
+ raise RuntimeError(f"Tool execution failed for open_scene: {e}")
1306
+
1307
+
1308
+ async def set_sibling_index(
1309
+ gameobject_path: Annotated[
1310
+ str,
1311
+ Field(
1312
+ description="""Path to the GameObject in the scene or in a prefab asset. e.g Body/Head/Eyes"""
1313
+ ),
1314
+ ],
1315
+ index: Annotated[
1316
+ int,
1317
+ Field(
1318
+ description="""Index to set"""
1319
+ ),
1320
+ ],
1321
+ prefab_path: Annotated[
1322
+ str | None,
1323
+ Field(
1324
+ description="""Optional. Filesystem path to a prefab asset i.e. files that end in .prefab. Example: Assets/MyPrefab.prefab. Only used when reading/modifying a prefab."""
1325
+ ),
1326
+ ] = None,
1327
+ ) -> Any:
1328
+ """Sets the sibling index.
1329
+
1330
+ Use this to change the sibling index of the GameObject. If a GameObject shares a parent with other GameObjects and are on the same level (i.e. they share the same direct parent), these GameObjects are known as siblings. The sibling index shows where each GameObject sits in this sibling hierarchy.
1331
+
1332
+ Use SetSiblingIndex to change the GameObject's place in this hierarchy. When the sibling index of a GameObject is changed, its order in the Hierarchy window will also change. This is useful if you are intentionally ordering the children of a GameObject such as when using Layout Group components."""
1333
+ try:
1334
+ logger.debug(f"Executing set_sibling_index with parameters: {locals()}")
1335
+
1336
+ # Prepare parameters for Unity RPC call
1337
+ params = {}
1338
+ if gameobject_path is not None:
1339
+ params['gameobject_path'] = str(gameobject_path)
1340
+ if index is not None:
1341
+ params['index'] = str(index)
1342
+ if prefab_path is not None:
1343
+ params['prefab_path'] = str(prefab_path)
1344
+
1345
+ # Execute Unity RPC call
1346
+ result = await _unity_client.execute_request('set_sibling_index', params)
1347
+ logger.debug(f"set_sibling_index completed successfully")
1348
+ return result
1349
+
1350
+ except Exception as e:
1351
+ logger.error(f"Failed to execute set_sibling_index: {e}")
1352
+ raise RuntimeError(f"Tool execution failed for set_sibling_index: {e}")
1353
+
1354
+
1355
+ async def create_terrain(
1356
+ name: Annotated[
1357
+ str,
1358
+ Field(
1359
+ description="""The name of the new terrain GameObject."""
1360
+ ),
1361
+ ],
1362
+ width: Annotated[
1363
+ str | None,
1364
+ Field(
1365
+ description="""Width of the terrain in world units. Default is 500."""
1366
+ ),
1367
+ ] = None,
1368
+ length: Annotated[
1369
+ str | None,
1370
+ Field(
1371
+ description="""Length of the terrain in world units. Default is 500."""
1372
+ ),
1373
+ ] = None,
1374
+ height: Annotated[
1375
+ str | None,
1376
+ Field(
1377
+ description="""Maximum height of the terrain in world units. Default is 600."""
1378
+ ),
1379
+ ] = None,
1380
+ resolution: Annotated[
1381
+ str | None,
1382
+ Field(
1383
+ description="""Resolution of the terrain's heightmap. Must be 2^n + 1 (e.g., 33, 65, 129, 257, 513). Default is 129."""
1384
+ ),
1385
+ ] = None,
1386
+ position: Annotated[
1387
+ str | None,
1388
+ Field(
1389
+ description="""Optional. Comma-separated position coordinates (e.g., 'x,y,z')."""
1390
+ ),
1391
+ ] = None,
1392
+ ) -> Any:
1393
+ """Creates a new terrain in the Unity scene with specified dimensions and resolution."""
1394
+ try:
1395
+ logger.debug(f"Executing create_terrain with parameters: {locals()}")
1396
+
1397
+ # Prepare parameters for Unity RPC call
1398
+ params = {}
1399
+ if name is not None:
1400
+ params['name'] = str(name)
1401
+ if width is not None:
1402
+ params['width'] = str(width)
1403
+ if length is not None:
1404
+ params['length'] = str(length)
1405
+ if height is not None:
1406
+ params['height'] = str(height)
1407
+ if resolution is not None:
1408
+ params['resolution'] = str(resolution)
1409
+ if position is not None:
1410
+ params['position'] = str(position)
1411
+
1412
+ # Execute Unity RPC call
1413
+ result = await _unity_client.execute_request('create_terrain', params)
1414
+ logger.debug(f"create_terrain completed successfully")
1415
+ return result
1416
+
1417
+ except Exception as e:
1418
+ logger.error(f"Failed to execute create_terrain: {e}")
1419
+ raise RuntimeError(f"Tool execution failed for create_terrain: {e}")
1420
+
1421
+
1422
+ async def list_objects_with_high_polygon_count(
1423
+ threshold: Annotated[
1424
+ int | None,
1425
+ Field(
1426
+ description="""The minimum polygon count threshold to consider an object as having high polygon count. Defaults to 1000."""
1427
+ ),
1428
+ ] = None,
1429
+ max_results: Annotated[
1430
+ int | None,
1431
+ Field(
1432
+ description="""Maximum number of results to return. Defaults to 100."""
1433
+ ),
1434
+ ] = None,
1435
+ include_inactive: Annotated[
1436
+ bool | None,
1437
+ Field(
1438
+ description="""Whether to include inactive GameObjects in the results. Defaults to false."""
1439
+ ),
1440
+ ] = None,
1441
+ ) -> Any:
1442
+ """Lists GameObjects in the active scene that have a high polygon count and select them in editor, useful for performance optimization."""
1443
+ try:
1444
+ logger.debug(f"Executing list_objects_with_high_polygon_count with parameters: {locals()}")
1445
+
1446
+ # Prepare parameters for Unity RPC call
1447
+ params = {}
1448
+ if threshold is not None:
1449
+ params['threshold'] = str(threshold)
1450
+ if max_results is not None:
1451
+ params['max_results'] = str(max_results)
1452
+ if include_inactive is not None:
1453
+ params['include_inactive'] = str(include_inactive)
1454
+
1455
+ # Execute Unity RPC call
1456
+ result = await _unity_client.execute_request('list_objects_with_high_polygon_count', params)
1457
+ logger.debug(f"list_objects_with_high_polygon_count completed successfully")
1458
+ return result
1459
+
1460
+ except Exception as e:
1461
+ logger.error(f"Failed to execute list_objects_with_high_polygon_count: {e}")
1462
+ raise RuntimeError(f"Tool execution failed for list_objects_with_high_polygon_count: {e}")
1463
+
1464
+
1465
+ async def play_game(
1466
+ ) -> Any:
1467
+ """Starts the game in the Unity Editor."""
1468
+ try:
1469
+ logger.debug(f"Executing play_game with parameters: {locals()}")
1470
+
1471
+ # Prepare parameters for Unity RPC call
1472
+ params = {}
1473
+
1474
+ # Execute Unity RPC call
1475
+ result = await _unity_client.execute_request('play_game', params)
1476
+ logger.debug(f"play_game completed successfully")
1477
+ return result
1478
+
1479
+ except Exception as e:
1480
+ logger.error(f"Failed to execute play_game: {e}")
1481
+ raise RuntimeError(f"Tool execution failed for play_game: {e}")
1482
+
1483
+
1484
+ async def stop_game(
1485
+ ) -> Any:
1486
+ """Stops the game in the Unity Editor."""
1487
+ try:
1488
+ logger.debug(f"Executing stop_game with parameters: {locals()}")
1489
+
1490
+ # Prepare parameters for Unity RPC call
1491
+ params = {}
1492
+
1493
+ # Execute Unity RPC call
1494
+ result = await _unity_client.execute_request('stop_game', params)
1495
+ logger.debug(f"stop_game completed successfully")
1496
+ return result
1497
+
1498
+ except Exception as e:
1499
+ logger.error(f"Failed to execute stop_game: {e}")
1500
+ raise RuntimeError(f"Tool execution failed for stop_game: {e}")
1501
+
1502
+
1503
+ async def create_panel_settings_asset(
1504
+ asset_name: Annotated[
1505
+ str,
1506
+ Field(
1507
+ description="""Name of the new PanelSettings asset (without extension)."""
1508
+ ),
1509
+ ],
1510
+ output_path: Annotated[
1511
+ str,
1512
+ Field(
1513
+ description="""The folder path where the PanelSettings asset should be saved. If the folder doesn't exist, it will be created automatically."""
1514
+ ),
1515
+ ],
1516
+ theme_style_sheet_path: Annotated[
1517
+ str | None,
1518
+ Field(
1519
+ description="""Optional. Path to a USS (Unity Style Sheet) file to use as the theme for the panel."""
1520
+ ),
1521
+ ] = None,
1522
+ default_theme_type: Annotated[
1523
+ Literal['Default', 'Dark', 'Light', 'Runtime', 'Custom'] | None,
1524
+ Field(
1525
+ description="""Optional. The default theme type to use. Defaults to 'Default'."""
1526
+ ),
1527
+ ] = None,
1528
+ scale_mode: Annotated[
1529
+ Literal['ConstantPixelSize', 'ScaleWithScreenSize', 'ConstantPhysicalSize'] | None,
1530
+ Field(
1531
+ description="""Optional. The scale mode for the panel. Defaults to 'ConstantPhysicalSize'."""
1532
+ ),
1533
+ ] = None,
1534
+ reference_resolution: Annotated[
1535
+ str | None,
1536
+ Field(
1537
+ description="""Optional. Comma-separated reference resolution (e.g., 'width,height'). Used when scale mode is 'ScaleWithScreenSize'. Defaults to '1920,1080'."""
1538
+ ),
1539
+ ] = None,
1540
+ ) -> Any:
1541
+ """Creates a new PanelSettings asset for UI Toolkit in Unity."""
1542
+ try:
1543
+ logger.debug(f"Executing create_panel_settings_asset with parameters: {locals()}")
1544
+
1545
+ # Prepare parameters for Unity RPC call
1546
+ params = {}
1547
+ if asset_name is not None:
1548
+ params['asset_name'] = str(asset_name)
1549
+ if output_path is not None:
1550
+ params['output_path'] = str(output_path)
1551
+ if theme_style_sheet_path is not None:
1552
+ params['theme_style_sheet_path'] = str(theme_style_sheet_path)
1553
+ if default_theme_type is not None:
1554
+ params['default_theme_type'] = str(default_theme_type)
1555
+ if scale_mode is not None:
1556
+ params['scale_mode'] = str(scale_mode)
1557
+ if reference_resolution is not None:
1558
+ params['reference_resolution'] = str(reference_resolution)
1559
+
1560
+ # Execute Unity RPC call
1561
+ result = await _unity_client.execute_request('create_panel_settings_asset', params)
1562
+ logger.debug(f"create_panel_settings_asset completed successfully")
1563
+ return result
1564
+
1565
+ except Exception as e:
1566
+ logger.error(f"Failed to execute create_panel_settings_asset: {e}")
1567
+ raise RuntimeError(f"Tool execution failed for create_panel_settings_asset: {e}")
1568
+
1569
+
1570
+ def register_tools(mcp: FastMCP, unity_client: UnityRpcClient) -> None:
1571
+ """Register all tools from unity_functions_schema with the MCP server."""
1572
+ global _mcp, _unity_client
1573
+ _mcp = mcp
1574
+ _unity_client = unity_client
1575
+
1576
+ # Register create_game_object
1577
+ mcp.tool()(create_game_object)
1578
+ # Register delete_game_object
1579
+ mcp.tool()(delete_game_object)
1580
+ # Register remove_component
1581
+ mcp.tool()(remove_component)
1582
+ # Register set_transform
1583
+ mcp.tool()(set_transform)
1584
+ # Register set_property
1585
+ mcp.tool()(set_property)
1586
+ # Register save_scene
1587
+ mcp.tool()(save_scene)
1588
+ # Register create_material
1589
+ mcp.tool()(create_material)
1590
+ # Register assign_material
1591
+ mcp.tool()(assign_material)
1592
+ # Register assign_material_to_fbx
1593
+ mcp.tool()(assign_material_to_fbx)
1594
+ # Register add_component
1595
+ mcp.tool()(add_component)
1596
+ # Register duplicate_game_object
1597
+ mcp.tool()(duplicate_game_object)
1598
+ # Register parent_game_object
1599
+ mcp.tool()(parent_game_object)
1600
+ # Register rename_game_object
1601
+ mcp.tool()(rename_game_object)
1602
+ # Register set_tag
1603
+ mcp.tool()(set_tag)
1604
+ # Register set_layer
1605
+ mcp.tool()(set_layer)
1606
+ # Register generate_3d_model_texture
1607
+ mcp.tool()(generate_3d_model_texture)
1608
+ # Register create_prefab
1609
+ mcp.tool()(create_prefab)
1610
+ # Register assign_shader_to_material
1611
+ mcp.tool()(assign_shader_to_material)
1612
+ # Register create_prefab_variant
1613
+ mcp.tool()(create_prefab_variant)
1614
+ # Register duplicate_asset
1615
+ mcp.tool()(duplicate_asset)
1616
+ # Register rename_asset
1617
+ mcp.tool()(rename_asset)
1618
+ # Register check_compile_errors
1619
+ mcp.tool()(check_compile_errors)
1620
+ # Register add_nested_object_to_prefab
1621
+ mcp.tool()(add_nested_object_to_prefab)
1622
+ # Register create_scene
1623
+ mcp.tool()(create_scene)
1624
+ # Register generate_3d_model_from_image
1625
+ mcp.tool()(generate_3d_model_from_image)
1626
+ # Register generate_3d_model_from_text
1627
+ mcp.tool()(generate_3d_model_from_text)
1628
+ # Register add_asset_to_scene
1629
+ mcp.tool()(add_asset_to_scene)
1630
+ # Register open_scene
1631
+ mcp.tool()(open_scene)
1632
+ # Register set_sibling_index
1633
+ mcp.tool()(set_sibling_index)
1634
+ # Register create_terrain
1635
+ mcp.tool()(create_terrain)
1636
+ # Register list_objects_with_high_polygon_count
1637
+ mcp.tool()(list_objects_with_high_polygon_count)
1638
+ # Register play_game
1639
+ mcp.tool()(play_game)
1640
+ # Register stop_game
1641
+ mcp.tool()(stop_game)
1642
+ # Register create_panel_settings_asset
1643
+ mcp.tool()(create_panel_settings_asset)