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,419 @@
1
+ """Generated MCP tools from ui_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 set_rect_transform(
17
+ gameobject_path: Annotated[
18
+ str,
19
+ Field(
20
+ description="""Path to the GameObject in the scene or in a prefab asset. e.g Body/Head/Eyes"""
21
+ ),
22
+ ],
23
+ anchor_min: Annotated[
24
+ str | None,
25
+ Field(
26
+ description="""Comma-separated anchor minimum values (x,y)."""
27
+ ),
28
+ ] = None,
29
+ anchor_max: Annotated[
30
+ str | None,
31
+ Field(
32
+ description="""Comma-separated anchor maximum values (x,y)."""
33
+ ),
34
+ ] = None,
35
+ pivot: Annotated[
36
+ str | None,
37
+ Field(
38
+ description="""Comma-separated pivot point values (x,y)."""
39
+ ),
40
+ ] = None,
41
+ size_delta: Annotated[
42
+ str | None,
43
+ Field(
44
+ description="""Comma-separated size delta values (width,height)."""
45
+ ),
46
+ ] = None,
47
+ anchored_position: Annotated[
48
+ str | None,
49
+ Field(
50
+ description="""Comma-separated anchored position values (x,y)."""
51
+ ),
52
+ ] = None,
53
+ prefab_path: Annotated[
54
+ str | None,
55
+ Field(
56
+ 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."""
57
+ ),
58
+ ] = None,
59
+ ) -> Any:
60
+ """Sets RectTransform properties of a UI GameObject."""
61
+ try:
62
+ logger.debug(f"Executing set_rect_transform with parameters: {locals()}")
63
+
64
+ # Prepare parameters for Unity RPC call
65
+ params = {}
66
+ if gameobject_path is not None:
67
+ params['gameobject_path'] = str(gameobject_path)
68
+ if anchor_min is not None:
69
+ params['anchor_min'] = str(anchor_min)
70
+ if anchor_max is not None:
71
+ params['anchor_max'] = str(anchor_max)
72
+ if pivot is not None:
73
+ params['pivot'] = str(pivot)
74
+ if size_delta is not None:
75
+ params['size_delta'] = str(size_delta)
76
+ if anchored_position is not None:
77
+ params['anchored_position'] = str(anchored_position)
78
+ if prefab_path is not None:
79
+ params['prefab_path'] = str(prefab_path)
80
+
81
+ # Execute Unity RPC call
82
+ result = await _unity_client.execute_request('set_rect_transform', params)
83
+ logger.debug(f"set_rect_transform completed successfully")
84
+ return result
85
+
86
+ except Exception as e:
87
+ logger.error(f"Failed to execute set_rect_transform: {e}")
88
+ raise RuntimeError(f"Tool execution failed for set_rect_transform: {e}")
89
+
90
+
91
+ async def create_ui_element(
92
+ element_type: Annotated[
93
+ Literal['button', 'text', 'image', 'panel', 'inputfield', 'dropdown', 'toggle', 'scrollview'],
94
+ Field(
95
+ description="""Type of UI element to create"""
96
+ ),
97
+ ],
98
+ element_name: Annotated[
99
+ str,
100
+ Field(
101
+ description="""Name for the new UI element"""
102
+ ),
103
+ ],
104
+ parent_path: Annotated[
105
+ str | None,
106
+ Field(
107
+ description="""Path to the parent GameObject e.g Body/Head/Eyes"""
108
+ ),
109
+ ] = None,
110
+ ) -> Any:
111
+ """Creates a new UI element in the scene and returns scene path where the object was created."""
112
+ try:
113
+ logger.debug(f"Executing create_ui_element with parameters: {locals()}")
114
+
115
+ # Prepare parameters for Unity RPC call
116
+ params = {}
117
+ if element_type is not None:
118
+ params['element_type'] = str(element_type)
119
+ if element_name is not None:
120
+ params['element_name'] = str(element_name)
121
+ if parent_path is not None:
122
+ params['parent_path'] = str(parent_path)
123
+
124
+ # Execute Unity RPC call
125
+ result = await _unity_client.execute_request('create_ui_element', params)
126
+ logger.debug(f"create_ui_element completed successfully")
127
+ return result
128
+
129
+ except Exception as e:
130
+ logger.error(f"Failed to execute create_ui_element: {e}")
131
+ raise RuntimeError(f"Tool execution failed for create_ui_element: {e}")
132
+
133
+
134
+ async def set_ui_text(
135
+ gameobject_path: Annotated[
136
+ str,
137
+ Field(
138
+ description="""Path to the GameObject in the scene or in a prefab asset. e.g Body/Head/Eyes"""
139
+ ),
140
+ ],
141
+ text: Annotated[
142
+ str | None,
143
+ Field(
144
+ description="""Text content to set"""
145
+ ),
146
+ ] = None,
147
+ font_size: Annotated[
148
+ int | None,
149
+ Field(
150
+ description="""Font size"""
151
+ ),
152
+ ] = None,
153
+ color: Annotated[
154
+ str | None,
155
+ Field(
156
+ description="""Color in r,g,b,a format (0-1 values)"""
157
+ ),
158
+ ] = None,
159
+ alignment: Annotated[
160
+ Literal['left', 'center', 'right'] | None,
161
+ Field(
162
+ description="""Text alignment"""
163
+ ),
164
+ ] = None,
165
+ prefab_path: Annotated[
166
+ str | None,
167
+ Field(
168
+ 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."""
169
+ ),
170
+ ] = None,
171
+ ) -> Any:
172
+ """Sets properties of a UI Text component."""
173
+ try:
174
+ logger.debug(f"Executing set_ui_text with parameters: {locals()}")
175
+
176
+ # Prepare parameters for Unity RPC call
177
+ params = {}
178
+ if gameobject_path is not None:
179
+ params['gameobject_path'] = str(gameobject_path)
180
+ if text is not None:
181
+ params['text'] = str(text)
182
+ if font_size is not None:
183
+ params['font_size'] = str(font_size)
184
+ if color is not None:
185
+ params['color'] = str(color)
186
+ if alignment is not None:
187
+ params['alignment'] = str(alignment)
188
+ if prefab_path is not None:
189
+ params['prefab_path'] = str(prefab_path)
190
+
191
+ # Execute Unity RPC call
192
+ result = await _unity_client.execute_request('set_ui_text', params)
193
+ logger.debug(f"set_ui_text completed successfully")
194
+ return result
195
+
196
+ except Exception as e:
197
+ logger.error(f"Failed to execute set_ui_text: {e}")
198
+ raise RuntimeError(f"Tool execution failed for set_ui_text: {e}")
199
+
200
+
201
+ async def set_ui_layout(
202
+ gameobject_path: Annotated[
203
+ str,
204
+ Field(
205
+ description="""Path to the GameObject in the scene or in a prefab asset. e.g Body/Head/Eyes"""
206
+ ),
207
+ ],
208
+ layout_type: Annotated[
209
+ Literal['vertical', 'horizontal', 'grid'],
210
+ Field(
211
+ description="""Type of layout to apply"""
212
+ ),
213
+ ],
214
+ spacing: Annotated[
215
+ str | None,
216
+ Field(
217
+ description="""Spacing between elements (single value for vertical/horizontal, 'x,y' for grid)"""
218
+ ),
219
+ ] = None,
220
+ padding: Annotated[
221
+ str | None,
222
+ Field(
223
+ description="""Padding in 'left,right,top,bottom' format"""
224
+ ),
225
+ ] = None,
226
+ alignment: Annotated[
227
+ Literal['upper_left', 'upper_center', 'upper_right', 'middle_left', 'middle_center', 'middle_right', 'lower_left', 'lower_center', 'lower_right'] | None,
228
+ Field(
229
+ description="""Alignment of children elements"""
230
+ ),
231
+ ] = None,
232
+ prefab_path: Annotated[
233
+ str | None,
234
+ Field(
235
+ 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."""
236
+ ),
237
+ ] = None,
238
+ ) -> Any:
239
+ """Sets layout properties for UI elements."""
240
+ try:
241
+ logger.debug(f"Executing set_ui_layout with parameters: {locals()}")
242
+
243
+ # Prepare parameters for Unity RPC call
244
+ params = {}
245
+ if gameobject_path is not None:
246
+ params['gameobject_path'] = str(gameobject_path)
247
+ if layout_type is not None:
248
+ params['layout_type'] = str(layout_type)
249
+ if spacing is not None:
250
+ params['spacing'] = str(spacing)
251
+ if padding is not None:
252
+ params['padding'] = str(padding)
253
+ if alignment is not None:
254
+ params['alignment'] = str(alignment)
255
+ if prefab_path is not None:
256
+ params['prefab_path'] = str(prefab_path)
257
+
258
+ # Execute Unity RPC call
259
+ result = await _unity_client.execute_request('set_ui_layout', params)
260
+ logger.debug(f"set_ui_layout completed successfully")
261
+ return result
262
+
263
+ except Exception as e:
264
+ logger.error(f"Failed to execute set_ui_layout: {e}")
265
+ raise RuntimeError(f"Tool execution failed for set_ui_layout: {e}")
266
+
267
+
268
+ async def add_persistent_listener(
269
+ gameobject_path: Annotated[
270
+ str,
271
+ Field(
272
+ description="""Path to the GameObject in the scene or in a prefab asset. e.g Body/Head/Eyes, containing the component with the event."""
273
+ ),
274
+ ],
275
+ component_type: Annotated[
276
+ str,
277
+ Field(
278
+ description="""Type of component containing the event (e.g., 'Button', 'Toggle')."""
279
+ ),
280
+ ],
281
+ event_name: Annotated[
282
+ str,
283
+ Field(
284
+ description="""Name of the event property (e.g., 'onClick', 'onValueChanged')."""
285
+ ),
286
+ ],
287
+ target_gameobject_path: Annotated[
288
+ str,
289
+ Field(
290
+ description="""Path to the GameObject in the scene or path in a prefab asset, containing the component with the method to call."""
291
+ ),
292
+ ],
293
+ target_component_type: Annotated[
294
+ str,
295
+ Field(
296
+ description="""Type of component containing the method to call."""
297
+ ),
298
+ ],
299
+ method_name: Annotated[
300
+ str,
301
+ Field(
302
+ description="""Name of the method to call when the event is triggered."""
303
+ ),
304
+ ],
305
+ parameter_type: Annotated[
306
+ Literal['_none', '_bool', '_int', '_float', '_string', '_void'],
307
+ Field(
308
+ description="""Type of parameter the method accepts. Defaults to none."""
309
+ ),
310
+ ],
311
+ parameter_value: Annotated[
312
+ str | None,
313
+ Field(
314
+ description="""Value to pass to the method when called. Should match the parameter_type."""
315
+ ),
316
+ ] = None,
317
+ ) -> Any:
318
+ """Adds a persistent listener to a UnityEvent on a component. This allows configuring event callbacks like Button.onClick events."""
319
+ try:
320
+ logger.debug(f"Executing add_persistent_listener with parameters: {locals()}")
321
+
322
+ # Prepare parameters for Unity RPC call
323
+ params = {}
324
+ if gameobject_path is not None:
325
+ params['gameobject_path'] = str(gameobject_path)
326
+ if component_type is not None:
327
+ params['component_type'] = str(component_type)
328
+ if event_name is not None:
329
+ params['event_name'] = str(event_name)
330
+ if target_gameobject_path is not None:
331
+ params['target_gameobject_path'] = str(target_gameobject_path)
332
+ if target_component_type is not None:
333
+ params['target_component_type'] = str(target_component_type)
334
+ if method_name is not None:
335
+ params['method_name'] = str(method_name)
336
+ if parameter_type is not None:
337
+ params['parameter_type'] = str(parameter_type)
338
+ if parameter_value is not None:
339
+ params['parameter_value'] = str(parameter_value)
340
+
341
+ # Execute Unity RPC call
342
+ result = await _unity_client.execute_request('add_persistent_listener', params)
343
+ logger.debug(f"add_persistent_listener completed successfully")
344
+ return result
345
+
346
+ except Exception as e:
347
+ logger.error(f"Failed to execute add_persistent_listener: {e}")
348
+ raise RuntimeError(f"Tool execution failed for add_persistent_listener: {e}")
349
+
350
+
351
+ async def remove_persistent_listener(
352
+ gameobject_path: Annotated[
353
+ str,
354
+ Field(
355
+ description="""Path to the GameObject in the scene or in a prefab asset. e.g Body/Head/Eyes, containing the component with the event."""
356
+ ),
357
+ ],
358
+ component_type: Annotated[
359
+ str,
360
+ Field(
361
+ description="""Type of component containing the event (e.g., 'Button', 'Toggle')."""
362
+ ),
363
+ ],
364
+ event_name: Annotated[
365
+ str,
366
+ Field(
367
+ description="""Name of the event property (e.g., 'onClick', 'onValueChanged')."""
368
+ ),
369
+ ],
370
+ listener_index: Annotated[
371
+ int,
372
+ Field(
373
+ description="""Index of the listener to remove (0-based)."""
374
+ ),
375
+ ],
376
+ ) -> Any:
377
+ """Removes a persistent listener from a UnityEvent on a component."""
378
+ try:
379
+ logger.debug(f"Executing remove_persistent_listener with parameters: {locals()}")
380
+
381
+ # Prepare parameters for Unity RPC call
382
+ params = {}
383
+ if gameobject_path is not None:
384
+ params['gameobject_path'] = str(gameobject_path)
385
+ if component_type is not None:
386
+ params['component_type'] = str(component_type)
387
+ if event_name is not None:
388
+ params['event_name'] = str(event_name)
389
+ if listener_index is not None:
390
+ params['listener_index'] = str(listener_index)
391
+
392
+ # Execute Unity RPC call
393
+ result = await _unity_client.execute_request('remove_persistent_listener', params)
394
+ logger.debug(f"remove_persistent_listener completed successfully")
395
+ return result
396
+
397
+ except Exception as e:
398
+ logger.error(f"Failed to execute remove_persistent_listener: {e}")
399
+ raise RuntimeError(f"Tool execution failed for remove_persistent_listener: {e}")
400
+
401
+
402
+ def register_tools(mcp: FastMCP, unity_client: UnityRpcClient) -> None:
403
+ """Register all tools from ui_functions_schema with the MCP server."""
404
+ global _mcp, _unity_client
405
+ _mcp = mcp
406
+ _unity_client = unity_client
407
+
408
+ # Register set_rect_transform
409
+ mcp.tool()(set_rect_transform)
410
+ # Register create_ui_element
411
+ mcp.tool()(create_ui_element)
412
+ # Register set_ui_text
413
+ mcp.tool()(set_ui_text)
414
+ # Register set_ui_layout
415
+ mcp.tool()(set_ui_layout)
416
+ # Register add_persistent_listener
417
+ mcp.tool()(add_persistent_listener)
418
+ # Register remove_persistent_listener
419
+ mcp.tool()(remove_persistent_listener)