mcpforunityserver 8.5.0__py3-none-any.whl → 9.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) 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 +207 -62
  26. {mcpforunityserver-8.5.0.dist-info → mcpforunityserver-9.1.0.dist-info}/METADATA +4 -2
  27. mcpforunityserver-9.1.0.dist-info/RECORD +96 -0
  28. {mcpforunityserver-8.5.0.dist-info → mcpforunityserver-9.1.0.dist-info}/WHEEL +1 -1
  29. {mcpforunityserver-8.5.0.dist-info → mcpforunityserver-9.1.0.dist-info}/entry_points.txt +1 -0
  30. {mcpforunityserver-8.5.0.dist-info → mcpforunityserver-9.1.0.dist-info}/top_level.txt +1 -2
  31. services/custom_tool_service.py +179 -19
  32. services/resources/__init__.py +6 -1
  33. services/resources/active_tool.py +1 -1
  34. services/resources/custom_tools.py +2 -2
  35. services/resources/editor_state.py +283 -21
  36. services/resources/gameobject.py +243 -0
  37. services/resources/layers.py +1 -1
  38. services/resources/prefab_stage.py +1 -1
  39. services/resources/project_info.py +1 -1
  40. services/resources/selection.py +1 -1
  41. services/resources/tags.py +1 -1
  42. services/resources/unity_instances.py +1 -1
  43. services/resources/windows.py +1 -1
  44. services/state/external_changes_scanner.py +245 -0
  45. services/tools/__init__.py +6 -1
  46. services/tools/batch_execute.py +24 -9
  47. services/tools/debug_request_context.py +8 -2
  48. services/tools/execute_custom_tool.py +6 -1
  49. services/tools/execute_menu_item.py +6 -3
  50. services/tools/find_gameobjects.py +89 -0
  51. services/tools/find_in_file.py +26 -19
  52. services/tools/manage_asset.py +19 -43
  53. services/tools/manage_components.py +131 -0
  54. services/tools/manage_editor.py +9 -8
  55. services/tools/manage_gameobject.py +120 -79
  56. services/tools/manage_material.py +80 -31
  57. services/tools/manage_prefabs.py +7 -1
  58. services/tools/manage_scene.py +34 -13
  59. services/tools/manage_script.py +62 -19
  60. services/tools/manage_scriptable_object.py +22 -10
  61. services/tools/manage_shader.py +8 -1
  62. services/tools/manage_vfx.py +738 -0
  63. services/tools/preflight.py +110 -0
  64. services/tools/read_console.py +81 -18
  65. services/tools/refresh_unity.py +153 -0
  66. services/tools/run_tests.py +202 -41
  67. services/tools/script_apply_edits.py +15 -7
  68. services/tools/set_active_instance.py +12 -7
  69. services/tools/utils.py +60 -6
  70. transport/legacy/port_discovery.py +2 -2
  71. transport/legacy/unity_connection.py +129 -26
  72. transport/plugin_hub.py +191 -19
  73. transport/unity_instance_middleware.py +93 -2
  74. transport/unity_transport.py +17 -6
  75. utils/focus_nudge.py +321 -0
  76. __init__.py +0 -0
  77. mcpforunityserver-8.5.0.dist-info/RECORD +0 -66
  78. routes/__init__.py +0 -0
  79. {mcpforunityserver-8.5.0.dist-info → mcpforunityserver-9.1.0.dist-info}/licenses/LICENSE +0 -0
@@ -27,7 +27,7 @@ def get_unity_instance_middleware() -> 'UnityInstanceMiddleware':
27
27
  if _unity_instance_middleware is None:
28
28
  # Auto-initialize if not set (lazy singleton) to handle import order or test cases
29
29
  _unity_instance_middleware = UnityInstanceMiddleware()
30
-
30
+
31
31
  return _unity_instance_middleware
32
32
 
33
33
 
@@ -83,17 +83,108 @@ class UnityInstanceMiddleware(Middleware):
83
83
  with self._lock:
84
84
  self._active_by_key.pop(key, None)
85
85
 
86
+ async def _maybe_autoselect_instance(self, ctx) -> str | None:
87
+ """
88
+ Auto-select the sole Unity instance when no active instance is set.
89
+
90
+ Note: This method both *discovers* and *persists* the selection via
91
+ `set_active_instance` as a side-effect, since callers expect the selection
92
+ to stick for subsequent tool/resource calls in the same session.
93
+ """
94
+ try:
95
+ # Import here to avoid circular dependencies / optional transport modules.
96
+ from transport.unity_transport import _current_transport
97
+
98
+ transport = _current_transport()
99
+ if PluginHub.is_configured():
100
+ try:
101
+ sessions_data = await PluginHub.get_sessions()
102
+ sessions = sessions_data.sessions or {}
103
+ ids: list[str] = []
104
+ for session_info in sessions.values():
105
+ project = getattr(
106
+ session_info, "project", None) or "Unknown"
107
+ hash_value = getattr(session_info, "hash", None)
108
+ if hash_value:
109
+ ids.append(f"{project}@{hash_value}")
110
+ if len(ids) == 1:
111
+ chosen = ids[0]
112
+ self.set_active_instance(ctx, chosen)
113
+ logger.info(
114
+ "Auto-selected sole Unity instance via PluginHub: %s",
115
+ chosen,
116
+ )
117
+ return chosen
118
+ except (ConnectionError, ValueError, KeyError, TimeoutError, AttributeError) as exc:
119
+ logger.debug(
120
+ "PluginHub auto-select probe failed (%s); falling back to stdio",
121
+ type(exc).__name__,
122
+ exc_info=True,
123
+ )
124
+ except Exception as exc:
125
+ if isinstance(exc, (SystemExit, KeyboardInterrupt)):
126
+ raise
127
+ logger.debug(
128
+ "PluginHub auto-select probe failed with unexpected error (%s); falling back to stdio",
129
+ type(exc).__name__,
130
+ exc_info=True,
131
+ )
132
+
133
+ if transport != "http":
134
+ try:
135
+ # Import here to avoid circular imports in legacy transport paths.
136
+ from transport.legacy.unity_connection import get_unity_connection_pool
137
+
138
+ pool = get_unity_connection_pool()
139
+ instances = pool.discover_all_instances(force_refresh=True)
140
+ ids = [getattr(inst, "id", None) for inst in instances]
141
+ ids = [inst_id for inst_id in ids if inst_id]
142
+ if len(ids) == 1:
143
+ chosen = ids[0]
144
+ self.set_active_instance(ctx, chosen)
145
+ logger.info(
146
+ "Auto-selected sole Unity instance via stdio discovery: %s",
147
+ chosen,
148
+ )
149
+ return chosen
150
+ except (ConnectionError, ValueError, KeyError, TimeoutError, AttributeError) as exc:
151
+ logger.debug(
152
+ "Stdio auto-select probe failed (%s)",
153
+ type(exc).__name__,
154
+ exc_info=True,
155
+ )
156
+ except Exception as exc:
157
+ if isinstance(exc, (SystemExit, KeyboardInterrupt)):
158
+ raise
159
+ logger.debug(
160
+ "Stdio auto-select probe failed with unexpected error (%s)",
161
+ type(exc).__name__,
162
+ exc_info=True,
163
+ )
164
+ except Exception as exc:
165
+ if isinstance(exc, (SystemExit, KeyboardInterrupt)):
166
+ raise
167
+ logger.debug(
168
+ "Auto-select path encountered an unexpected error (%s)",
169
+ type(exc).__name__,
170
+ exc_info=True,
171
+ )
172
+
173
+ return None
174
+
86
175
  async def _inject_unity_instance(self, context: MiddlewareContext) -> None:
87
176
  """Inject active Unity instance into context if available."""
88
177
  ctx = context.fastmcp_context
89
178
 
90
179
  active_instance = self.get_active_instance(ctx)
180
+ if not active_instance:
181
+ active_instance = await self._maybe_autoselect_instance(ctx)
91
182
  if active_instance:
92
183
  # If using HTTP transport (PluginHub configured), validate session
93
184
  # But for stdio transport (no PluginHub needed or maybe partially configured),
94
185
  # we should be careful not to clear instance just because PluginHub can't resolve it.
95
186
  # The 'active_instance' (Name@hash) might be valid for stdio even if PluginHub fails.
96
-
187
+
97
188
  session_id: str | None = None
98
189
  # Only validate via PluginHub if we are actually using HTTP transport
99
190
  # OR if we want to support hybrid mode. For now, let's be permissive.
@@ -9,6 +9,7 @@ from typing import Awaitable, Callable, TypeVar
9
9
  from fastmcp import Context
10
10
 
11
11
  from transport.plugin_hub import PluginHub
12
+ from models.models import MCPResponse
12
13
  from models.unity_response import normalize_unity_response
13
14
  from services.tools import get_unity_instance_from_context
14
15
 
@@ -91,12 +92,22 @@ async def send_with_unity_instance(
91
92
  if not isinstance(params, dict):
92
93
  raise TypeError(
93
94
  "Command parameters must be a dict for HTTP transport")
94
- raw = await PluginHub.send_command_for_instance(
95
- unity_instance,
96
- command_type,
97
- params,
98
- )
99
- return normalize_unity_response(raw)
95
+ try:
96
+ raw = await PluginHub.send_command_for_instance(
97
+ unity_instance,
98
+ command_type,
99
+ params,
100
+ )
101
+ return normalize_unity_response(raw)
102
+ except Exception as exc:
103
+ # NOTE: asyncio.TimeoutError has an empty str() by default, which is confusing for clients.
104
+ err = str(exc) or f"{type(exc).__name__}"
105
+ # Fail fast with a retry hint instead of hanging for COMMAND_TIMEOUT.
106
+ # The client can decide whether retrying is appropriate for the command.
107
+ return normalize_unity_response(
108
+ MCPResponse(success=False, error=err,
109
+ hint="retry").model_dump()
110
+ )
100
111
 
101
112
  if unity_instance:
102
113
  kwargs.setdefault("instance_id", unity_instance)
utils/focus_nudge.py ADDED
@@ -0,0 +1,321 @@
1
+ """
2
+ Focus nudge utility for handling OS-level throttling of background Unity.
3
+
4
+ When Unity is unfocused, the OS (especially macOS App Nap) can heavily throttle
5
+ the process, causing PlayMode tests to stall. This utility temporarily brings
6
+ Unity to focus, allows it to process, then returns focus to the original app.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import asyncio
12
+ import logging
13
+ import platform
14
+ import shutil
15
+ import subprocess
16
+ import time
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+ # Minimum seconds between nudges to avoid focus thrashing
21
+ _MIN_NUDGE_INTERVAL_S = 5.0
22
+ _last_nudge_time: float = 0.0
23
+
24
+
25
+ def _is_available() -> bool:
26
+ """Check if focus nudging is available on this platform."""
27
+ system = platform.system()
28
+ if system == "Darwin":
29
+ return shutil.which("osascript") is not None
30
+ elif system == "Windows":
31
+ # PowerShell is typically available on Windows
32
+ return shutil.which("powershell") is not None
33
+ elif system == "Linux":
34
+ return shutil.which("xdotool") is not None
35
+ return False
36
+
37
+
38
+ def _get_frontmost_app_macos() -> str | None:
39
+ """Get the name of the frontmost application on macOS."""
40
+ try:
41
+ result = subprocess.run(
42
+ [
43
+ "osascript", "-e",
44
+ 'tell application "System Events" to get name of first process whose frontmost is true'
45
+ ],
46
+ capture_output=True,
47
+ text=True,
48
+ timeout=5,
49
+ )
50
+ if result.returncode == 0:
51
+ return result.stdout.strip()
52
+ except Exception as e:
53
+ logger.debug(f"Failed to get frontmost app: {e}")
54
+ return None
55
+
56
+
57
+ def _focus_app_macos(app_name: str) -> bool:
58
+ """Focus an application by name on macOS."""
59
+ try:
60
+ result = subprocess.run(
61
+ ["osascript", "-e", f'tell application "{app_name}" to activate'],
62
+ capture_output=True,
63
+ text=True,
64
+ timeout=5,
65
+ )
66
+ return result.returncode == 0
67
+ except Exception as e:
68
+ logger.debug(f"Failed to focus app {app_name}: {e}")
69
+ return False
70
+
71
+
72
+ def _get_frontmost_app_windows() -> str | None:
73
+ """Get the title of the frontmost window on Windows."""
74
+ try:
75
+ # PowerShell command to get active window title
76
+ script = '''
77
+ Add-Type @"
78
+ using System;
79
+ using System.Runtime.InteropServices;
80
+ public class Win32 {
81
+ [DllImport("user32.dll")]
82
+ public static extern IntPtr GetForegroundWindow();
83
+ [DllImport("user32.dll")]
84
+ public static extern int GetWindowText(IntPtr hWnd, System.Text.StringBuilder text, int count);
85
+ }
86
+ "@
87
+ $hwnd = [Win32]::GetForegroundWindow()
88
+ $sb = New-Object System.Text.StringBuilder 256
89
+ [Win32]::GetWindowText($hwnd, $sb, 256)
90
+ $sb.ToString()
91
+ '''
92
+ result = subprocess.run(
93
+ ["powershell", "-Command", script],
94
+ capture_output=True,
95
+ text=True,
96
+ timeout=5,
97
+ )
98
+ if result.returncode == 0:
99
+ return result.stdout.strip()
100
+ except Exception as e:
101
+ logger.debug(f"Failed to get frontmost window: {e}")
102
+ return None
103
+
104
+
105
+ def _focus_app_windows(window_title: str) -> bool:
106
+ """Focus a window by title on Windows. For Unity, uses Unity Editor pattern."""
107
+ try:
108
+ # For Unity, we use a pattern match since the title varies
109
+ if window_title == "Unity":
110
+ script = '''
111
+ Add-Type @"
112
+ using System;
113
+ using System.Runtime.InteropServices;
114
+ public class Win32 {
115
+ [DllImport("user32.dll")]
116
+ public static extern bool SetForegroundWindow(IntPtr hWnd);
117
+ [DllImport("user32.dll")]
118
+ public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
119
+ }
120
+ "@
121
+ $unity = Get-Process | Where-Object {$_.MainWindowTitle -like "*Unity*"} | Select-Object -First 1
122
+ if ($unity) {
123
+ [Win32]::ShowWindow($unity.MainWindowHandle, 9)
124
+ [Win32]::SetForegroundWindow($unity.MainWindowHandle)
125
+ }
126
+ '''
127
+ else:
128
+ # Try to find window by title - escape special PowerShell characters
129
+ safe_title = window_title.replace("'", "''").replace("`", "``")
130
+ script = f'''
131
+ Add-Type @"
132
+ using System;
133
+ using System.Runtime.InteropServices;
134
+ public class Win32 {{
135
+ [DllImport("user32.dll")]
136
+ public static extern bool SetForegroundWindow(IntPtr hWnd);
137
+ [DllImport("user32.dll")]
138
+ public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
139
+ }}
140
+ "@
141
+ $proc = Get-Process | Where-Object {{$_.MainWindowTitle -eq '{safe_title}'}} | Select-Object -First 1
142
+ if ($proc) {{
143
+ [Win32]::ShowWindow($proc.MainWindowHandle, 9)
144
+ [Win32]::SetForegroundWindow($proc.MainWindowHandle)
145
+ }}
146
+ '''
147
+ result = subprocess.run(
148
+ ["powershell", "-Command", script],
149
+ capture_output=True,
150
+ text=True,
151
+ timeout=5,
152
+ )
153
+ return result.returncode == 0
154
+ except Exception as e:
155
+ logger.debug(f"Failed to focus window {window_title}: {e}")
156
+ return False
157
+
158
+
159
+ def _get_frontmost_app_linux() -> str | None:
160
+ """Get the window ID of the frontmost window on Linux."""
161
+ try:
162
+ result = subprocess.run(
163
+ ["xdotool", "getactivewindow"],
164
+ capture_output=True,
165
+ text=True,
166
+ timeout=5,
167
+ )
168
+ if result.returncode == 0:
169
+ return result.stdout.strip()
170
+ except Exception as e:
171
+ logger.debug(f"Failed to get active window: {e}")
172
+ return None
173
+
174
+
175
+ def _focus_app_linux(window_id: str) -> bool:
176
+ """Focus a window by ID on Linux, or Unity by name."""
177
+ try:
178
+ if window_id == "Unity":
179
+ # Find Unity window by name pattern
180
+ result = subprocess.run(
181
+ ["xdotool", "search", "--name", "Unity"],
182
+ capture_output=True,
183
+ text=True,
184
+ timeout=5,
185
+ )
186
+ if result.returncode == 0 and result.stdout.strip():
187
+ window_id = result.stdout.strip().split("\n")[0]
188
+ else:
189
+ return False
190
+
191
+ result = subprocess.run(
192
+ ["xdotool", "windowactivate", window_id],
193
+ capture_output=True,
194
+ text=True,
195
+ timeout=5,
196
+ )
197
+ return result.returncode == 0
198
+ except Exception as e:
199
+ logger.debug(f"Failed to focus window {window_id}: {e}")
200
+ return False
201
+
202
+
203
+ def _get_frontmost_app() -> str | None:
204
+ """Get the frontmost application/window (platform-specific)."""
205
+ system = platform.system()
206
+ if system == "Darwin":
207
+ return _get_frontmost_app_macos()
208
+ elif system == "Windows":
209
+ return _get_frontmost_app_windows()
210
+ elif system == "Linux":
211
+ return _get_frontmost_app_linux()
212
+ return None
213
+
214
+
215
+ def _focus_app(app_or_window: str) -> bool:
216
+ """Focus an application/window (platform-specific)."""
217
+ system = platform.system()
218
+ if system == "Darwin":
219
+ return _focus_app_macos(app_or_window)
220
+ elif system == "Windows":
221
+ return _focus_app_windows(app_or_window)
222
+ elif system == "Linux":
223
+ return _focus_app_linux(app_or_window)
224
+ return False
225
+
226
+
227
+ async def nudge_unity_focus(
228
+ focus_duration_s: float = 0.5,
229
+ force: bool = False,
230
+ ) -> bool:
231
+ """
232
+ Temporarily focus Unity to allow it to process, then return focus.
233
+
234
+ Args:
235
+ focus_duration_s: How long to keep Unity focused (seconds)
236
+ force: If True, ignore the minimum interval between nudges
237
+
238
+ Returns:
239
+ True if nudge was performed, False if skipped or failed
240
+ """
241
+ global _last_nudge_time
242
+
243
+ if not _is_available():
244
+ logger.debug("Focus nudging not available on this platform")
245
+ return False
246
+
247
+ # Rate limit nudges
248
+ now = time.monotonic()
249
+ if not force and (now - _last_nudge_time) < _MIN_NUDGE_INTERVAL_S:
250
+ logger.info("Skipping nudge - too soon since last nudge")
251
+ return False
252
+
253
+ # Get current frontmost app
254
+ original_app = _get_frontmost_app()
255
+ if original_app is None:
256
+ logger.debug("Could not determine frontmost app")
257
+ return False
258
+
259
+ # Check if Unity is already focused (no nudge needed)
260
+ if "Unity" in original_app:
261
+ logger.debug("Unity already focused, no nudge needed")
262
+ return False
263
+
264
+ logger.info(f"Nudging Unity focus (will return to {original_app})")
265
+ _last_nudge_time = now
266
+
267
+ # Focus Unity
268
+ if not _focus_app("Unity"):
269
+ logger.warning("Failed to focus Unity")
270
+ return False
271
+
272
+ # Wait for Unity to process
273
+ await asyncio.sleep(focus_duration_s)
274
+
275
+ # Return focus to original app
276
+ if original_app and original_app != "Unity":
277
+ if _focus_app(original_app):
278
+ logger.info(f"Returned focus to {original_app}")
279
+ else:
280
+ logger.warning(f"Failed to return focus to {original_app}")
281
+
282
+ return True
283
+
284
+
285
+ def should_nudge(
286
+ status: str,
287
+ editor_is_focused: bool,
288
+ last_update_unix_ms: int | None,
289
+ current_time_ms: int | None = None,
290
+ stall_threshold_ms: int = 10_000,
291
+ ) -> bool:
292
+ """
293
+ Determine if we should nudge Unity based on test job state.
294
+
295
+ Args:
296
+ status: Job status ("running", "succeeded", "failed")
297
+ editor_is_focused: Whether Unity reports being focused
298
+ last_update_unix_ms: Last time the job was updated (Unix ms)
299
+ current_time_ms: Current time (Unix ms), or None to use current time
300
+ stall_threshold_ms: How long without updates before considering it stalled
301
+
302
+ Returns:
303
+ True if conditions suggest a nudge would help
304
+ """
305
+ # Only nudge running jobs
306
+ if status != "running":
307
+ return False
308
+
309
+ # Only nudge unfocused Unity
310
+ if editor_is_focused:
311
+ return False
312
+
313
+ # Check if job appears stalled
314
+ if last_update_unix_ms is None:
315
+ return True # No updates yet, might be stuck at start
316
+
317
+ if current_time_ms is None:
318
+ current_time_ms = int(time.time() * 1000)
319
+
320
+ time_since_update_ms = current_time_ms - last_update_unix_ms
321
+ return time_since_update_ms > stall_threshold_ms
__init__.py DELETED
File without changes
@@ -1,66 +0,0 @@
1
- __init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- main.py,sha256=OH_Ux5Aj43q1lXPu4AS8zafRnFHZWFYCDZbswReQOac,18011
3
- core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- core/config.py,sha256=czkTtNji1crQcQbUvmdx4OL7f-RBqkVhj_PtHh-w7rs,1623
5
- core/logging_decorator.py,sha256=D9CD7rFvQz-MBG-G4inizQj0Ivr6dfc9RBmTrw7q8mI,1383
6
- core/telemetry.py,sha256=eHjYgzd8f7eTwSwF2Kbi8D4TtJIcdaDjKLeo1c-0hVA,19829
7
- core/telemetry_decorator.py,sha256=ycSTrzVNCDQHSd-xmIWOpVfKFURPxpiZe_XkOQAGDAo,6705
8
- mcpforunityserver-8.5.0.dist-info/licenses/LICENSE,sha256=bv5lDJZQEqxBgjjc1rkRbkEwpSIHF-8N-1Od0VnEJFw,1066
9
- models/__init__.py,sha256=JlscZkGWE9TRmSoBi99v_LSl8OAFNGmr8463PYkXin4,179
10
- models/models.py,sha256=heXuvdBtdats1SGwW8wKFFHM0qR4hA6A7qETn5s9BZ0,1827
11
- models/unity_response.py,sha256=oJ1PTsnNc5VBC-9OgM59C0C-R9N-GdmEdmz_yph4GSU,1454
12
- routes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
- services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
- services/custom_tool_service.py,sha256=ZOb6LsOQc3C9n3iLn5b7QaG3WJ25M-Id3WG_iE1YhMY,11960
15
- services/registry/__init__.py,sha256=QCwcYThvGF0kBt3WR6DBskdyxkegJC7NymEChgJA-YM,470
16
- services/registry/resource_registry.py,sha256=T_Kznqgvt5kKgV7mU85nb0LlFuB4rg-Tm4Cjhxt-IcI,1467
17
- services/registry/tool_registry.py,sha256=9tMwOP07JE92QFYUS4KvoysO0qC9pkBD5B79kjRsSPw,1304
18
- services/resources/__init__.py,sha256=O5heeMcgCswnQX1qG2nNtMeAZIaLut734qD7t5UsA0k,2801
19
- services/resources/active_tool.py,sha256=YTbsiy_hmnKH2q7IoM7oYD7pJkoveZTszRiL1PlhO9M,1474
20
- services/resources/custom_tools.py,sha256=8lyryGhN3vD2LwMt6ZyKIp5ONtxdI1nfcCAlYjlfQnQ,1704
21
- services/resources/editor_state.py,sha256=acrSyMfdulRgYQIn7wKHqKqyw4uED_oUf9GU-4o4GAg,1497
22
- services/resources/layers.py,sha256=q4UQ5PUVUVhmM5l3oXID1wa_wOWAS8l5BGXadBgFuwY,1080
23
- services/resources/menu_items.py,sha256=9SNycjwTXoeS1ZHra0Y1fTyCjSEdPCo34JyxtuqauG8,1021
24
- services/resources/prefab_stage.py,sha256=C3mn3UapKYVOA8QUNmLsYreG5YiXdlvGm9ypHQeKBeQ,1382
25
- services/resources/project_info.py,sha256=gSVSFfwP0u2FmxSowOkdbNoSSQHxfQtLfndvoCXTVSw,1323
26
- services/resources/selection.py,sha256=4rI5Bdkes4uxtMc_5jQhUaqUl-iprhIiTWqnOJl8tmg,1839
27
- services/resources/tags.py,sha256=7EhmQjMotz85DSSr7cVKYIy7LPT5mmPfrEySr1mTE6w,1049
28
- services/resources/tests.py,sha256=xDvvgesPSU93nLD_ERQopOpkpq69pbMEqmFsJd0jekI,2063
29
- services/resources/unity_instances.py,sha256=fR0cVopGQnmF41IFDycwlo2XniKstfJWLGobgJeiabE,4348
30
- services/resources/windows.py,sha256=--QVsb0oyoBpSjK2D4kPcZFSe2zdR-t_KSHP-e2QNoY,1427
31
- services/tools/__init__.py,sha256=3Qav7fAowZ1_TbDRdZQQQES53gv2lTs-2D7PGECnlbM,2353
32
- services/tools/batch_execute.py,sha256=_ByjffeXQB9j64mcjaxJmrnbSJrMn0f9_6Zh9BBI_2c,2898
33
- services/tools/debug_request_context.py,sha256=WQBtQdXSH5stw2MAwIM32H6jGwUVQOgU2r35VUWLlYo,2765
34
- services/tools/execute_custom_tool.py,sha256=K2qaO4-FTPz0_3j53hhDP9idjC002ugc8C03FtHGTbY,1376
35
- services/tools/execute_menu_item.py,sha256=FAC-1v_TwOcy6GSxkogDsVxeRtdap0DsPlIngf8uJdU,1184
36
- services/tools/find_in_file.py,sha256=xp80lqRN2cdZc3XGJWlCpeQEy6WnwyKOj2l5WiHNx0Q,6379
37
- services/tools/manage_asset.py,sha256=Kpqr82cmXH7wxXub3O0D8whksORSqn9nDRjskDe_A_w,7534
38
- services/tools/manage_editor.py,sha256=_HZRT-_hBakH0g6p7BpxTv3gWpxsaV6KNGRol-qknwo,3243
39
- services/tools/manage_gameobject.py,sha256=kYIouvt-iNUEsY0VIWp4FqagLjo7Up2TwKDhB4Nfxmo,14213
40
- services/tools/manage_material.py,sha256=wZB2H4orhL6wG9TTnmnk-Lj2Gj_zvg7koxW3t319BLU,3545
41
- services/tools/manage_prefabs.py,sha256=73XzznjFNOm1SazW_Y7l6uGIE7wosMpAIVQs8xpvK9A,3037
42
- services/tools/manage_scene.py,sha256=3BhIsbbtGiMNqBMQMqEsB4ajYmtx-VwWl-krOkFR_Bw,4648
43
- services/tools/manage_script.py,sha256=lPA5HcS4Al0RiQVz-S6qahFTcPqsk3GSLLXJWHri8P4,27557
44
- services/tools/manage_scriptable_object.py,sha256=Oi03CJLgepaWR59V-nJiAjnCC8at4YqFhRGpACruqgw,3150
45
- services/tools/manage_shader.py,sha256=HHnHKh7vLij3p8FAinNsPdZGEKivgwSUTxdgDydfmbs,2882
46
- services/tools/read_console.py,sha256=gZWEf0Ru0hvN9oJUZqZ4w-mMBBLm5Z5KAUPv282XbYQ,4091
47
- services/tools/run_tests.py,sha256=LBVwGasLvmF4k1FiX3DdBQ8udh89WZJFiVHfJRWGvOs,3313
48
- services/tools/script_apply_edits.py,sha256=qPm_PsmsK3mYXnziX_btyk8CaB66LTqpDFA2Y4ebZ4U,47504
49
- services/tools/set_active_instance.py,sha256=B18Y8Jga0pKsx9mFywXr1tWfy0cJVopIMXYO-UJ1jOU,4136
50
- services/tools/utils.py,sha256=4ZgfIu178eXZqRyzs8X77B5lKLP1f73OZoGBSDNokJ4,2409
51
- transport/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
- transport/models.py,sha256=6wp7wsmSaeeJEvUGXPF1m6zuJnxJ1NJlCC4YZ9oQIq0,1226
53
- transport/plugin_hub.py,sha256=55R00ohrmUI0mk_smc_8BsYTvrQMPX4wwsvqXprj0Vk,15596
54
- transport/plugin_registry.py,sha256=nW-7O7PN0QUgSWivZTkpAVKKq9ZOe2b2yeIdpaNt_3I,4359
55
- transport/unity_instance_middleware.py,sha256=a-ULWU9b86w0CbYN3meyLxWGxTBXL5CQmBKZmmQ0xZQ,6197
56
- transport/unity_transport.py,sha256=dvwCjo2jRvnFXd8ruOL36C8W4P1VIQ91qreS2750lPM,3307
57
- transport/legacy/port_discovery.py,sha256=qM_mtndbYjAj4qPSZEWVeXFOt5_nKczG9pQqORXTBJ0,12768
58
- transport/legacy/stdio_port_registry.py,sha256=j4iARuP6wetppNDG8qKeuvo1bJKcSlgEhZvSyl_uf0A,2313
59
- transport/legacy/unity_connection.py,sha256=ujUX9WX7Gb-fxQveHts3uiepTPzFq8i7-XG7u5gSPuM,32668
60
- utils/module_discovery.py,sha256=My48ofB1BUqxiBoAZAGbEaLQYdsrDhMm8MayBP_bUSQ,2005
61
- utils/reload_sentinel.py,sha256=s1xMWhl-r2XwN0OUbiUv_VGUy8TvLtV5bkql-5n2DT0,373
62
- mcpforunityserver-8.5.0.dist-info/METADATA,sha256=3YWJc7I-EKxcLzMgG0MweNSJm3QR_VYCNTTwwB45UNE,5712
63
- mcpforunityserver-8.5.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
64
- mcpforunityserver-8.5.0.dist-info/entry_points.txt,sha256=vCtkqw-J9t4pj7JwUZcB54_keVx7DpAR3fYzK6i-s6g,44
65
- mcpforunityserver-8.5.0.dist-info/top_level.txt,sha256=YKU5e5dREMfCnoVpmlsTm9bku7oqnrzSZ9FeTgjoxJw,58
66
- mcpforunityserver-8.5.0.dist-info/RECORD,,
routes/__init__.py DELETED
File without changes