mcpforunityserver 9.0.8__py3-none-any.whl → 9.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. cli/__init__.py +3 -0
  2. cli/commands/__init__.py +3 -0
  3. cli/commands/animation.py +87 -0
  4. cli/commands/asset.py +310 -0
  5. cli/commands/audio.py +133 -0
  6. cli/commands/batch.py +184 -0
  7. cli/commands/code.py +189 -0
  8. cli/commands/component.py +212 -0
  9. cli/commands/editor.py +487 -0
  10. cli/commands/gameobject.py +510 -0
  11. cli/commands/instance.py +101 -0
  12. cli/commands/lighting.py +128 -0
  13. cli/commands/material.py +268 -0
  14. cli/commands/prefab.py +144 -0
  15. cli/commands/scene.py +255 -0
  16. cli/commands/script.py +240 -0
  17. cli/commands/shader.py +238 -0
  18. cli/commands/ui.py +263 -0
  19. cli/commands/vfx.py +439 -0
  20. cli/main.py +248 -0
  21. cli/utils/__init__.py +31 -0
  22. cli/utils/config.py +58 -0
  23. cli/utils/connection.py +191 -0
  24. cli/utils/output.py +195 -0
  25. main.py +174 -60
  26. {mcpforunityserver-9.0.8.dist-info → mcpforunityserver-9.2.0.dist-info}/METADATA +3 -2
  27. {mcpforunityserver-9.0.8.dist-info → mcpforunityserver-9.2.0.dist-info}/RECORD +37 -14
  28. {mcpforunityserver-9.0.8.dist-info → mcpforunityserver-9.2.0.dist-info}/WHEEL +1 -1
  29. {mcpforunityserver-9.0.8.dist-info → mcpforunityserver-9.2.0.dist-info}/entry_points.txt +1 -0
  30. {mcpforunityserver-9.0.8.dist-info → mcpforunityserver-9.2.0.dist-info}/top_level.txt +1 -1
  31. services/custom_tool_service.py +168 -13
  32. services/resources/__init__.py +6 -1
  33. services/tools/__init__.py +6 -1
  34. services/tools/refresh_unity.py +66 -16
  35. transport/legacy/unity_connection.py +26 -8
  36. transport/plugin_hub.py +17 -0
  37. __init__.py +0 -0
  38. {mcpforunityserver-9.0.8.dist-info → mcpforunityserver-9.2.0.dist-info}/licenses/LICENSE +0 -0
cli/commands/shader.py ADDED
@@ -0,0 +1,238 @@
1
+ """Shader CLI commands for managing Unity shaders."""
2
+
3
+ import sys
4
+ import click
5
+ from typing import Optional
6
+
7
+ from cli.utils.config import get_config
8
+ from cli.utils.output import format_output, print_error, print_success
9
+ from cli.utils.connection import run_command, UnityConnectionError
10
+
11
+
12
+ @click.group()
13
+ def shader():
14
+ """Shader operations - create, read, update, delete shaders."""
15
+ pass
16
+
17
+
18
+ @shader.command("read")
19
+ @click.argument("path")
20
+ def read_shader(path: str):
21
+ """Read a shader file.
22
+
23
+ \\b
24
+ Examples:
25
+ unity-mcp shader read "Assets/Shaders/MyShader.shader"
26
+ """
27
+ config = get_config()
28
+
29
+ # Extract name from path
30
+ import os
31
+ name = os.path.splitext(os.path.basename(path))[0]
32
+ directory = os.path.dirname(path)
33
+
34
+ try:
35
+ result = run_command("manage_shader", {
36
+ "action": "read",
37
+ "name": name,
38
+ "path": directory or "Assets/",
39
+ }, config)
40
+
41
+ # If successful, display the contents nicely
42
+ if result.get("success") and result.get("data", {}).get("contents"):
43
+ click.echo(result["data"]["contents"])
44
+ else:
45
+ click.echo(format_output(result, config.format))
46
+ except UnityConnectionError as e:
47
+ print_error(str(e))
48
+ sys.exit(1)
49
+
50
+
51
+ @shader.command("create")
52
+ @click.argument("name")
53
+ @click.option(
54
+ "--path", "-p",
55
+ default="Assets/Shaders",
56
+ help="Directory to create shader in."
57
+ )
58
+ @click.option(
59
+ "--contents", "-c",
60
+ default=None,
61
+ help="Shader code (reads from stdin if not provided)."
62
+ )
63
+ @click.option(
64
+ "--file", "-f",
65
+ "file_path",
66
+ default=None,
67
+ type=click.Path(exists=True),
68
+ help="Read shader code from file."
69
+ )
70
+ def create_shader(name: str, path: str, contents: Optional[str], file_path: Optional[str]):
71
+ """Create a new shader.
72
+
73
+ \\b
74
+ Examples:
75
+ unity-mcp shader create "MyShader" --path "Assets/Shaders"
76
+ unity-mcp shader create "MyShader" --file local_shader.shader
77
+ echo "Shader code..." | unity-mcp shader create "MyShader"
78
+ """
79
+ config = get_config()
80
+
81
+ # Get contents from file, option, or stdin
82
+ if file_path:
83
+ with open(file_path, 'r') as f:
84
+ shader_contents = f.read()
85
+ elif contents:
86
+ shader_contents = contents
87
+ else:
88
+ # Read from stdin if available
89
+ import sys
90
+ if not sys.stdin.isatty():
91
+ shader_contents = sys.stdin.read()
92
+ else:
93
+ # Provide default shader template
94
+ shader_contents = f'''Shader "Custom/{name}"
95
+ {{
96
+ Properties
97
+ {{
98
+ _Color ("Color", Color) = (1,1,1,1)
99
+ _MainTex ("Albedo (RGB)", 2D) = "white" {{}}
100
+ }}
101
+ SubShader
102
+ {{
103
+ Tags {{ "RenderType"="Opaque" }}
104
+ LOD 200
105
+
106
+ CGPROGRAM
107
+ #pragma surface surf Standard fullforwardshadows
108
+ #pragma target 3.0
109
+
110
+ sampler2D _MainTex;
111
+ fixed4 _Color;
112
+
113
+ struct Input
114
+ {{
115
+ float2 uv_MainTex;
116
+ }};
117
+
118
+ void surf (Input IN, inout SurfaceOutputStandard o)
119
+ {{
120
+ fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
121
+ o.Albedo = c.rgb;
122
+ o.Alpha = c.a;
123
+ }}
124
+ ENDCG
125
+ }}
126
+ FallBack "Diffuse"
127
+ }}
128
+ '''
129
+
130
+ try:
131
+ result = run_command("manage_shader", {
132
+ "action": "create",
133
+ "name": name,
134
+ "path": path,
135
+ "contents": shader_contents,
136
+ }, config)
137
+ click.echo(format_output(result, config.format))
138
+ if result.get("success"):
139
+ print_success(f"Created shader: {path}/{name}.shader")
140
+ except UnityConnectionError as e:
141
+ print_error(str(e))
142
+ sys.exit(1)
143
+
144
+
145
+ @shader.command("update")
146
+ @click.argument("path")
147
+ @click.option(
148
+ "--contents", "-c",
149
+ default=None,
150
+ help="New shader code."
151
+ )
152
+ @click.option(
153
+ "--file", "-f",
154
+ "file_path",
155
+ default=None,
156
+ type=click.Path(exists=True),
157
+ help="Read shader code from file."
158
+ )
159
+ def update_shader(path: str, contents: Optional[str], file_path: Optional[str]):
160
+ """Update an existing shader.
161
+
162
+ \\b
163
+ Examples:
164
+ unity-mcp shader update "Assets/Shaders/MyShader.shader" --file updated.shader
165
+ echo "New shader code" | unity-mcp shader update "Assets/Shaders/MyShader.shader"
166
+ """
167
+ config = get_config()
168
+
169
+ import os
170
+ name = os.path.splitext(os.path.basename(path))[0]
171
+ directory = os.path.dirname(path)
172
+
173
+ # Get contents from file, option, or stdin
174
+ if file_path:
175
+ with open(file_path, 'r') as f:
176
+ shader_contents = f.read()
177
+ elif contents:
178
+ shader_contents = contents
179
+ else:
180
+ import sys
181
+ if not sys.stdin.isatty():
182
+ shader_contents = sys.stdin.read()
183
+ else:
184
+ print_error(
185
+ "No shader contents provided. Use --contents, --file, or pipe via stdin.")
186
+ sys.exit(1)
187
+
188
+ try:
189
+ result = run_command("manage_shader", {
190
+ "action": "update",
191
+ "name": name,
192
+ "path": directory or "Assets/",
193
+ "contents": shader_contents,
194
+ }, config)
195
+ click.echo(format_output(result, config.format))
196
+ if result.get("success"):
197
+ print_success(f"Updated shader: {path}")
198
+ except UnityConnectionError as e:
199
+ print_error(str(e))
200
+ sys.exit(1)
201
+
202
+
203
+ @shader.command("delete")
204
+ @click.argument("path")
205
+ @click.option(
206
+ "--force", "-f",
207
+ is_flag=True,
208
+ help="Skip confirmation prompt."
209
+ )
210
+ def delete_shader(path: str, force: bool):
211
+ """Delete a shader.
212
+
213
+ \\b
214
+ Examples:
215
+ unity-mcp shader delete "Assets/Shaders/OldShader.shader"
216
+ unity-mcp shader delete "Assets/Shaders/OldShader.shader" --force
217
+ """
218
+ config = get_config()
219
+
220
+ if not force:
221
+ click.confirm(f"Delete shader '{path}'?", abort=True)
222
+
223
+ import os
224
+ name = os.path.splitext(os.path.basename(path))[0]
225
+ directory = os.path.dirname(path)
226
+
227
+ try:
228
+ result = run_command("manage_shader", {
229
+ "action": "delete",
230
+ "name": name,
231
+ "path": directory or "Assets/",
232
+ }, config)
233
+ click.echo(format_output(result, config.format))
234
+ if result.get("success"):
235
+ print_success(f"Deleted shader: {path}")
236
+ except UnityConnectionError as e:
237
+ print_error(str(e))
238
+ sys.exit(1)
cli/commands/ui.py ADDED
@@ -0,0 +1,263 @@
1
+ """UI CLI commands - placeholder for future implementation."""
2
+
3
+ import sys
4
+ import click
5
+ from typing import Optional, Any
6
+
7
+ from cli.utils.config import get_config
8
+ from cli.utils.output import format_output, print_error, print_success
9
+ from cli.utils.connection import run_command, UnityConnectionError
10
+
11
+
12
+ @click.group()
13
+ def ui():
14
+ """UI operations - create and modify UI elements."""
15
+ pass
16
+
17
+
18
+ @ui.command("create-canvas")
19
+ @click.argument("name")
20
+ @click.option(
21
+ "--render-mode",
22
+ type=click.Choice(
23
+ ["ScreenSpaceOverlay", "ScreenSpaceCamera", "WorldSpace"]),
24
+ default="ScreenSpaceOverlay",
25
+ help="Canvas render mode."
26
+ )
27
+ def create_canvas(name: str, render_mode: str):
28
+ """Create a new Canvas.
29
+
30
+ \b
31
+ Examples:
32
+ unity-mcp ui create-canvas "MainUI"
33
+ unity-mcp ui create-canvas "WorldUI" --render-mode WorldSpace
34
+ """
35
+ config = get_config()
36
+
37
+ try:
38
+ # Step 1: Create empty GameObject
39
+ result = run_command("manage_gameobject", {
40
+ "action": "create",
41
+ "name": name,
42
+ }, config)
43
+
44
+ if not (result.get("success") or result.get("data") or result.get("result")):
45
+ click.echo(format_output(result, config.format))
46
+ return
47
+
48
+ # Step 2: Add Canvas components
49
+ for component in ["Canvas", "CanvasScaler", "GraphicRaycaster"]:
50
+ run_command("manage_components", {
51
+ "action": "add",
52
+ "target": name,
53
+ "componentType": component,
54
+ }, config)
55
+
56
+ # Step 3: Set render mode
57
+ render_mode_value = {"ScreenSpaceOverlay": 0,
58
+ "ScreenSpaceCamera": 1, "WorldSpace": 2}.get(render_mode, 0)
59
+ run_command("manage_components", {
60
+ "action": "set_property",
61
+ "target": name,
62
+ "componentType": "Canvas",
63
+ "property": "renderMode",
64
+ "value": render_mode_value,
65
+ }, config)
66
+
67
+ click.echo(format_output(result, config.format))
68
+ print_success(f"Created Canvas: {name}")
69
+ except UnityConnectionError as e:
70
+ print_error(str(e))
71
+ sys.exit(1)
72
+
73
+
74
+ @ui.command("create-text")
75
+ @click.argument("name")
76
+ @click.option(
77
+ "--parent", "-p",
78
+ required=True,
79
+ help="Parent Canvas or UI element."
80
+ )
81
+ @click.option(
82
+ "--text", "-t",
83
+ default="New Text",
84
+ help="Initial text content."
85
+ )
86
+ @click.option(
87
+ "--position",
88
+ nargs=2,
89
+ type=float,
90
+ default=(0, 0),
91
+ help="Anchored position X Y."
92
+ )
93
+ def create_text(name: str, parent: str, text: str, position: tuple):
94
+ """Create a UI Text element (TextMeshPro).
95
+
96
+ \b
97
+ Examples:
98
+ unity-mcp ui create-text "TitleText" --parent "MainUI" --text "Hello World"
99
+ """
100
+ config = get_config()
101
+
102
+ try:
103
+ # Step 1: Create empty GameObject with parent
104
+ result = run_command("manage_gameobject", {
105
+ "action": "create",
106
+ "name": name,
107
+ "parent": parent,
108
+ "position": list(position),
109
+ }, config)
110
+
111
+ if not (result.get("success") or result.get("data") or result.get("result")):
112
+ click.echo(format_output(result, config.format))
113
+ return
114
+
115
+ # Step 2: Add RectTransform and TextMeshProUGUI
116
+ run_command("manage_components", {
117
+ "action": "add",
118
+ "target": name,
119
+ "componentType": "TextMeshProUGUI",
120
+ }, config)
121
+
122
+ # Step 3: Set text content
123
+ run_command("manage_components", {
124
+ "action": "set_property",
125
+ "target": name,
126
+ "componentType": "TextMeshProUGUI",
127
+ "property": "text",
128
+ "value": text,
129
+ }, config)
130
+
131
+ click.echo(format_output(result, config.format))
132
+ print_success(f"Created Text: {name}")
133
+ except UnityConnectionError as e:
134
+ print_error(str(e))
135
+ sys.exit(1)
136
+
137
+
138
+ @ui.command("create-button")
139
+ @click.argument("name")
140
+ @click.option(
141
+ "--parent", "-p",
142
+ required=True,
143
+ help="Parent Canvas or UI element."
144
+ )
145
+ @click.option(
146
+ "--text", "-t",
147
+ default="Button",
148
+ help="Button label text."
149
+ )
150
+ def create_button(name: str, parent: str, text: str): # text current placeholder
151
+ """Create a UI Button.
152
+
153
+ \b
154
+ Examples:
155
+ unity-mcp ui create-button "StartButton" --parent "MainUI" --text "Start Game"
156
+ """
157
+ config = get_config()
158
+
159
+ try:
160
+ # Step 1: Create empty GameObject with parent
161
+ result = run_command("manage_gameobject", {
162
+ "action": "create",
163
+ "name": name,
164
+ "parent": parent,
165
+ }, config)
166
+
167
+ if not (result.get("success") or result.get("data") or result.get("result")):
168
+ click.echo(format_output(result, config.format))
169
+ return
170
+
171
+ # Step 2: Add Button and Image components
172
+ for component in ["Image", "Button"]:
173
+ run_command("manage_components", {
174
+ "action": "add",
175
+ "target": name,
176
+ "componentType": component,
177
+ }, config)
178
+
179
+ # Step 3: Create child label GameObject
180
+ label_name = f"{name}_Label"
181
+ label_result = run_command("manage_gameobject", {
182
+ "action": "create",
183
+ "name": label_name,
184
+ "parent": name,
185
+ }, config)
186
+
187
+ # Step 4: Add TextMeshProUGUI to label and set text
188
+ run_command("manage_components", {
189
+ "action": "add",
190
+ "target": label_name,
191
+ "componentType": "TextMeshProUGUI",
192
+ }, config)
193
+ run_command("manage_components", {
194
+ "action": "set_property",
195
+ "target": label_name,
196
+ "componentType": "TextMeshProUGUI",
197
+ "property": "text",
198
+ "value": text,
199
+ }, config)
200
+
201
+ click.echo(format_output(result, config.format))
202
+ print_success(f"Created Button: {name} (with label '{text}')")
203
+ except UnityConnectionError as e:
204
+ print_error(str(e))
205
+ sys.exit(1)
206
+
207
+
208
+ @ui.command("create-image")
209
+ @click.argument("name")
210
+ @click.option(
211
+ "--parent", "-p",
212
+ required=True,
213
+ help="Parent Canvas or UI element."
214
+ )
215
+ @click.option(
216
+ "--sprite", "-s",
217
+ default=None,
218
+ help="Sprite asset path."
219
+ )
220
+ def create_image(name: str, parent: str, sprite: Optional[str]):
221
+ """Create a UI Image.
222
+
223
+ \b
224
+ Examples:
225
+ unity-mcp ui create-image "Background" --parent "MainUI"
226
+ unity-mcp ui create-image "Icon" --parent "MainUI" --sprite "Assets/Sprites/icon.png"
227
+ """
228
+ config = get_config()
229
+
230
+ try:
231
+ # Step 1: Create empty GameObject with parent
232
+ result = run_command("manage_gameobject", {
233
+ "action": "create",
234
+ "name": name,
235
+ "parent": parent,
236
+ }, config)
237
+
238
+ if not (result.get("success") or result.get("data") or result.get("result")):
239
+ click.echo(format_output(result, config.format))
240
+ return
241
+
242
+ # Step 2: Add Image component
243
+ run_command("manage_components", {
244
+ "action": "add",
245
+ "target": name,
246
+ "componentType": "Image",
247
+ }, config)
248
+
249
+ # Step 3: Set sprite if provided
250
+ if sprite:
251
+ run_command("manage_components", {
252
+ "action": "set_property",
253
+ "target": name,
254
+ "componentType": "Image",
255
+ "property": "sprite",
256
+ "value": sprite,
257
+ }, config)
258
+
259
+ click.echo(format_output(result, config.format))
260
+ print_success(f"Created Image: {name}")
261
+ except UnityConnectionError as e:
262
+ print_error(str(e))
263
+ sys.exit(1)