Commit Graph

612 Commits (3ef2d3779055fb0575eec6e185fc7f14f2197192)

Author SHA1 Message Date
GitHub Actions 3ef2d37790 chore: bump version to 9.1.0 2026-01-22 01:00:33 +00:00
Marcus Sanatan 7f44e4b53e
Add CLI (#606)
* feat: Add CLI for Unity MCP server

- Add click-based CLI with 15+ command groups
- Commands: gameobject, component, scene, asset, script, editor, prefab, material, lighting, ui, audio, animation, code
- HTTP transport to communicate with Unity via MCP server
- Output formats: text, json, table
- Configuration via environment variables or CLI options
- Comprehensive usage guide and unit tests

* Update based on AI feedback

* Fixes main.py error

* Update for further error fix

* Update based on AI

* Update script.py

* Update with better coverage and Tool Readme

* Log a message with implicit URI changes

Small update for #542

* Minor fixes (#602)

* Log a message with implicit URI changes

Small update for #542

* Log a message with implicit URI changes

Small update for #542

* Add helper scripts to update forks

* fix: improve HTTP Local URL validation UX and styling specificity

- Rename CSS class from generic "error" to "http-local-url-error" for better specificity
- Rename "invalid-url" class to "http-local-invalid-url" for clarity
- Disable httpServerCommandField when URL is invalid or transport not HTTP Local
- Clear field value and tooltip when showing validation errors
- Ensure field is re-enabled when URL becomes valid

* Docker mcp gateway (#603)

* Log a message with implicit URI changes

Small update for #542

* Update docker container to default to stdio

Replaces #541

* fix: Rider config path and add MCP registry manifest (#604)

- Fix RiderConfigurator to use correct GitHub Copilot config path:
  - Windows: %LOCALAPPDATA%\github-copilot\intellij\mcp.json
  - macOS: ~/Library/Application Support/github-copilot/intellij/mcp.json
  - Linux: ~/.config/github-copilot/intellij/mcp.json
- Add mcp.json for GitHub MCP Registry support:
  - Enables users to install via coplaydev/unity-mcp
  - Uses uvx with mcpforunityserver from PyPI

* Use click.echo instead of print statements

* Standardize whitespace

* Minor tweak in docs

* Use `wait` params

* Unrelated but project scoped tools should be off by default

* Update lock file

* Whitespace cleanup

* Update custom_tool_service.py to skip global registration for any tool name that already exists as a built‑in.

* Avoid silently falling back to the first Unity session when a specific unity_instance was requested but not found.

If a client passes a unity_instance that doesn’t match any session, this code will still route the command to the first available session, which can send commands to the wrong project in multi‑instance environments. Instead, when a unity_instance is provided but no matching session_id is found, return an error (e.g. 400/404 with "Unity instance '' not found") and only default to the first session when no unity_instance was specified.

Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>

* Update docs/CLI_USAGE.md

Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>

* Updated the CLI command registration to only swallow missing optional modules and to surface real import-time failures, so broken command modules don’t get silently ignored.

* Sorted __all__ alphabetically to satisfy RUF022 in __init__.py.

* Validate --params is a JSON object before merging.

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

---------

Co-authored-by: Shutong Wu <51266340+Scriptwonder@users.noreply.github.com>
Co-authored-by: dsarno <david@lighthaus.us>
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-01-21 20:53:13 -04:00
dsarno f54b1cb552
fix: Rider config path and add MCP registry manifest (#604)
- Fix RiderConfigurator to use correct GitHub Copilot config path:
  - Windows: %LOCALAPPDATA%\github-copilot\intellij\mcp.json
  - macOS: ~/Library/Application Support/github-copilot/intellij/mcp.json
  - Linux: ~/.config/github-copilot/intellij/mcp.json
- Add mcp.json for GitHub MCP Registry support:
  - Enables users to install via coplaydev/unity-mcp
  - Uses uvx with mcpforunityserver from PyPI
2026-01-21 13:02:13 -08:00
Marcus Sanatan 1ad4f09d11
Docker mcp gateway (#603)
* Log a message with implicit URI changes

Small update for #542

* Update docker container to default to stdio

Replaces #541
2026-01-21 16:00:11 -04:00
Marcus Sanatan 810d756be9
Minor fixes (#602)
* Log a message with implicit URI changes

Small update for #542

* Log a message with implicit URI changes

Small update for #542

* Add helper scripts to update forks

* fix: improve HTTP Local URL validation UX and styling specificity

- Rename CSS class from generic "error" to "http-local-url-error" for better specificity
- Rename "invalid-url" class to "http-local-invalid-url" for clarity
- Disable httpServerCommandField when URL is invalid or transport not HTTP Local
- Clear field value and tooltip when showing validation errors
- Ensure field is re-enabled when URL becomes valid
2026-01-21 14:41:16 -04:00
Alex Hvesuk 1cc582636d
Add localhost setup feedback and remove UI issues (#587) 2026-01-21 14:14:13 -04:00
Vladimir Ivanov abd596ff4a
use localhost to ping server if server binds to 0.0.0.0 (#542)
Co-authored-by: vladimir.ivanov <terakriper@gmail.com>
2026-01-21 13:17:52 -04:00
Shutong Wu d2408f07b4
Update README with citation (#591)
* Update README with citation and AI tools information

Added citation for research and details about Unity AI tools.

* Update README.md spacing

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Marcus Sanatan <msanatan@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-21 13:09:22 -04:00
Marcus Sanatan b69ee80da9
Project scoped tools (#596)
* feat: Add project-scoped tools flag to control custom tool registration behavior

Add `--project-scoped-tools` CLI flag and `UNITY_MCP_PROJECT_SCOPED_TOOLS` environment variable to control whether custom tools are registered globally or scoped to specific Unity projects.

Closes #416

* Add .meta file

* feat: Add project-scoped tools toggle for local HTTP transport

Add UI toggle in Connection section to control project-scoped tools flag when using HTTP Local transport. The toggle:
- Defaults to enabled (true)
- Persists state in EditorPrefs
- Only displays when HTTP Local transport is selected
- Automatically appends `--project-scoped-tools` flag to uvx server command
- Updates manual config display when toggled

* Update Server/src/services/custom_tool_service.py

Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>

* Pass project_scoped_tools flag directly without environment variable conversion

Remove unnecessary environment variable conversion for project_scoped_tools flag.

* fix: Improve error handling and logging in global custom tool registration

Split exception handling to distinguish between expected RuntimeError (service not initialized) and unexpected errors.

---------

Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
2026-01-21 13:07:52 -04:00
Shutong Wu d96dad3e9a
Create pull_request_template.md
Add a pull request template for contributors.
2026-01-20 22:36:54 -05:00
dsarno 8eb684ddc2
fix: comprehensive performance optimizations, claude code config, and stability improvements (issue #577) (#595)
* fix: reduce per-frame GC allocations causing editor hitches (issue #577)

Eliminate memory allocations that occurred every frame, which triggered
garbage collection spikes (~28ms) approximately every second.

Changes:
- EditorStateCache: Skip BuildSnapshot() entirely when state unchanged
  (check BEFORE building). Increased poll interval from 0.25s to 1.0s.
  Cache DeepClone() results to avoid allocations on GetSnapshot().

- TransportCommandDispatcher: Early exit before lock/list allocation
  when Pending.Count == 0, eliminating per-frame allocations when idle.

- StdioBridgeHost: Same early exit pattern for commandQueue.

- MCPForUnityEditorWindow: Throttle OnEditorUpdate to 2-second intervals
  instead of every frame, preventing expensive socket checks 60+/sec.

Fixes GitHub issue #577: High performance impact even when MCP server is off

* fix: prevent multiple domain reloads when calling refresh_unity (issue #577)

Root Cause:
- send_command() had a hardcoded retry loop (min 6 attempts) on connection errors
- Each retry resent the refresh_unity command, causing Unity to reload 6 times
- retry_on_reload=False only controlled reload-state retries, not connection retries

The Fix:
1. Unity C# (MCPForUnity/Editor):
   - Added --reinstall flag to uvx commands in dev mode
   - Ensures local development changes are picked up by uvx/Claude Code
   - Applies to all client configurators (Claude Code, Codex, etc.)

2. Python Server (Server/src):
   - Added max_attempts parameter to send_command()
   - Pass max_attempts=0 when retry_on_reload=False
   - Fixed type handling in refresh_unity.py (handle MCPResponse objects)
   - Added timeout to connection error recovery conditions
   - Recovery logic now returns success instead of error to prevent client retries

Changes:
- MCPForUnity/Editor: Added --reinstall to dev mode uvx commands
- Server/refresh_unity.py: Fixed type handling, improved error recovery
- Server/unity_connection.py: Added max_attempts param, disable retries when retry_on_reload=False

Result: refresh_unity with compile=request now triggers only 1 domain reload instead of 6

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* fix: UI and server stability improvements

Unity Editor (C#):
- Fix "Resuming..." stuck state when manually clicking End Session
  Clear ResumeStdioAfterReload and ResumeHttpAfterReload flags in
  OnConnectionToggleClicked and EndOrphanedSessionAsync to prevent
  UI from getting stuck showing "Resuming..." with disabled button
- Remove unsupported --reinstall flag from all uvx command builders
  uvx does not support --reinstall and shows warning when used
  Use --no-cache --refresh instead for dev mode cache busting

Python Server:
- Add "aborted" to connection error patterns in refresh_unity
  Handle WinError 10053 (connection aborted) gracefully during
  Unity domain reload, treating it as expected behavior
- Add WindowsSafeRotatingFileHandler to suppress log rotation errors
  Windows file locking prevents log rotation when file is open by
  another process; catch PermissionError to avoid noisy stack traces
- Fix packaging: add py-modules = ["main"] to pyproject.toml
  setuptools.packages.find only discovers packages (directories with
  __init__.py), must explicitly list standalone module files

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* docs: improve refresh_unity connection loss handling documentation

Add detailed comments and logging to clarify why connection loss during
compile is treated as success (expected domain reload behavior, not failure).
This addresses PR feedback about potentially masking real connection errors.

The logic is intentional and correct:
- Connection loss only treated as success when compile='request'
- Domain reload causing disconnect is expected Unity behavior
- Subsequent wait_for_ready loop validates Unity becomes ready
- Prevents multiple domain reload loops (issue #577)

Added logging for observability:
- Info log when expected disconnect detected
- Warning log for non-recoverable errors

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* fix: add missing logger import in refresh_unity

Missing logger import causes NameError at runtime when connection
loss handling paths are triggered (lines 82 and 91).

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* fix: address code review feedback on thread safety and semantics

Addresses four issues raised in code review:

1. EditorStateCache.GetSnapshot() - Remove shared cached clone
   - Revert to always returning fresh DeepClone() to prevent mutation bugs
   - Main GC optimization remains: state-change detection prevents
     unnecessary _cached rebuilds (the expensive operation)
   - Removed _cachedClone and _cachedCloneSequence fields

2. refresh_unity.py - Fix blocking reason terminology mismatch
   - Changed "asset_refresh" to "asset_import" to match activityPhase
     values from EditorStateCache.cs
   - Ensures asset import is correctly detected as blocking state

3. TransportCommandDispatcher - Fix unsynchronized Count access
   - Moved Pending.Count check inside PendingLock
   - Prevents data races and InvalidOperationException from concurrent
     dictionary access

4. StdioBridgeHost - Fix unsynchronized Count access
   - Moved commandQueue.Count check inside lockObj
   - Ensures all collection access is properly serialized

All changes maintain the GC allocation optimizations while fixing
thread safety violations and semantic contract changes.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* fix: address code review feedback on thread safety and timeout handling

- refresh_unity.py: Track readiness explicitly and return failure on timeout
  instead of silently returning success when wait loop exits without confirming
  ready_for_tools=true

- McpClientConfiguratorBase.cs: Add thread safety guard for Configure() call
  in CheckStatusWithProjectDir(). Changed default attemptAutoRewrite to false
  and added runtime check to prevent calling Configure() from background threads.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-20 18:11:25 -08:00
Jos van der Westhuizen cd10472bc6
Fix blog post URL in README
Corrected the URL in the blog post reference.
2026-01-20 18:02:17 -08:00
Jos van der Westhuizen 5d26862715
Update readme: update coplay mcp comparison blog link 2026-01-20 16:48:00 -08:00
dsarno aaf6308b33
fix: Add special handling for UIDocument serialization to prevent infinite loops (#586)
* fix: search inactive objects when setActive=true in modify

When trying to activate an inactive GameObject via manage_gameobject modify with setActive=true, the lookup would fail because inactive objects were not included in the search by default.

Now automatically sets searchInactive=true when setActive=true is specified, allowing inactive objects to be found and activated.

* fix: Add special handling for UIDocument serialization to prevent infinite loops (#585)

UIDocument.rootVisualElement contains circular parent/child references that
can cause infinite serialization loops. This adds special handling similar to
Transform and Camera components.

The fix:
- Safely serializes panelSettings, visualTreeAsset, sortingOrder, enabled, parentUI
- Explicitly skips rootVisualElement to prevent circular reference issues
- Includes a note explaining why rootVisualElement is skipped

Tested on Unity 2021.3 and Unity 6.3.

* refactor: Extract SerializeAssetReference helper and align UIDocument structure

- Add SerializeAssetReference() helper for consistent asset reference serialization
- UIDocument now uses same return structure as Camera (typeName, instanceID, properties)
- Reduces code duplication in special-case handlers
- Enhanced test coverage to verify structure matches Camera pattern

* fix: Handle UIDocument subclasses and add negative assertion for rootVisualElement

Address code review feedback:
- Add IsOrDerivedFrom() helper to detect UIDocument and any subclasses by walking
  the base-type chain, ensuring derived types also get special-case handling
- Add negative assertion verifying rootVisualElement is NOT in serialized output
2026-01-19 08:21:36 -08:00
dsarno 0158165064
docs: Streamline README for faster onboarding (#583)
* docs: Streamline README for faster onboarding

Major restructuring to reduce README from ~500 lines to ~200 lines while preserving all essential information.

Changes:
- Add prominent "Quick Start" section at top with prerequisites and 5-step setup
- Highlight Git package URL with GitHub TIP admonition for visibility
- Collapse detailed content into expandable sections:
  - Features & Tools
  - Manual Configuration (with nested stdio legacy config)
  - Multiple Unity Instances
  - Roslyn Script Validation
  - Troubleshooting
  - Contributing
  - Telemetry & Privacy
- Keep Star History and Coplay sections always visible
- Condense tools/resources from verbose lists to compact bullet format
- Add step 5 for client connection (toggle for Cursor/Windsurf/Antigravity)

The goal is 1-2 screens of visible content for new users to get started quickly,
with all details accessible via dropdowns for those who need them.

* docs: Address review feedback

- Add `text` language identifier to Git URL code blocks for linter compliance
- Clarify step 5 client connection instructions with clearer categorization
- Add nested dropdown for manual Roslyn DLL installation option

* docs: Indent nested Roslyn manual installation dropdown

* docs: Add wiki links to Troubleshooting section
2026-01-19 07:50:10 -08:00
dsarno f4e441c563
fix: Filter EditorApplication.isCompiling false positives in Play mode (#582)
EditorApplication.isCompiling can return true in Play mode even when Unity
is not actually compiling, causing MCP tools to incorrectly return
"busy/compiling" errors.

This adds a GetActualIsCompiling() helper that double-checks with
CompilationPipeline.isCompiling via reflection when in Play mode to filter
out these false positives.

Fixes #549
2026-01-19 07:31:53 -08:00
dsarno 8252e6debc
fix: search inactive objects when setActive=true in modify (#581)
When trying to activate an inactive GameObject via manage_gameobject modify with setActive=true, the lookup would fail because inactive objects were not included in the search by default.

Now automatically sets searchInactive=true when setActive=true is specified, allowing inactive objects to be found and activated.
2026-01-19 07:04:54 -08:00
cyanxwh e617753b4e
fix: Add Prefab Stage support for GameObject lookup (#573)
* Enhance Prefab Stage support in GameObject lookup and scene management

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: unify path matching and restore fast path lookup

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 06:46:29 -08:00
GitHub Actions 2cdc386b55 chore: bump version to 9.0.8 2026-01-19 14:07:05 +00:00
whatevertogo 322a3d1846
fix: resolve Claude Code HTTP Remote UV path override not being detected in System Requirements .#550
* fix: resolve UV path override not being detected in System Requirements

Fixes #538

The System Requirements panel showed "UV Package Manager: Not Found" even
when a valid UV path override was configured in Advanced Settings.

Root cause: PlatformDetectorBase.DetectUv() only searched PATH with bare
command names ("uvx", "uv") and never consulted PathResolverService which
respects the user's override setting.

Changes:
- Refactor DetectUv() to use PathResolverService.GetUvxPath() which checks
  override path first, then system PATH, then falls back to "uvx"
- Add TryValidateUvExecutable() to verify executables by running --version
  instead of just checking File.Exists
- Prioritize PATH environment variable in EnumerateUvxCandidates() for
  better compatibility with official uv install scripts
- Fix process output read order (ReadToEnd before WaitForExit) to prevent
  potential deadlocks

Co-Authored-By: ChatGLM 4.7 <noreply@zhipuai.com>

* fix: improve uv/uvx detection robustness on macOS and Linux

- Read both stdout and stderr when validating uv/uvx executables
- Respect WaitForExit timeout return value instead of ignoring it
- Fix version parsing to handle extra tokens like "(Homebrew 2025-01-01)"
- Resolve bare commands ("uv"/"uvx") to absolute paths after validation
- Rename FindExecutableInPath to FindUvxExecutableInPath for clarity

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: unify process execution with ExecPath.TryRun and add Windows PATH augmentation

Replace direct Process.Start calls with ExecPath.TryRun across all platform detectors.
This change:
- Fixes potential deadlocks by using async output reading
- Adds proper timeout handling with process termination
- Removes redundant fallback logic and simplifies version parsing
- Adds Windows PATH augmentation with common uv, npm, and Python installation paths

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: improve version parsing to handle both spaces and parentheses

The version extraction logic now properly handles outputs like:
- "uvx 0.9.18" -> "0.9.18"
- "uvx 0.9.18 (hash date)" -> "0.9.18"
- "uvx 0.9.18 extra info" -> "0.9.18"

Uses Math.Min to find the first occurrence of either space or parenthesis.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: improve platform detectors with absolute path resolution

- Add absolute path resolution in TryValidatePython and TryValidateUvWithPath for better UI display
- Fix BuildAugmentedPath to avoid PATH duplication
- Add comprehensive comments for version parsing logic
- Ensure cross-platform consistency across all three detectors
- Fix override path validation logic with clear state handling
- Fix platform detector path resolution and Python version detection
- Use UserProfile consistently in GetClaudeCliPath instead of Personal
- All platforms now use protected BuildAugmentedPath method

This change improves user experience by displaying full paths in the UI
while maintaining robust fallback behavior if path resolution fails.

Co-Authored-By: GLM4.7 <noreply@zhipuai.com>

* fix: improve error handling in PathResolverService by logging exceptions

* Remove .meta files added after fork and update .gitignore

* Update .gitignore

* save .meta

* refactor: unify uv/uvx naming and path detection across platforms

- Rename TryValidateUvExecutable -> TryValidateUvxExecutable for consistency
- Add cross-platform FindInPath() helper in ExecPath.cs
- Remove platform-specific where/which implementations in favor of unified helper
- Add Windows-specific DetectUv() override with enhanced uv/uvx detection
- Add WinGet shim path support for Windows uvx installation
- Update UI labels: "UV Path" -> "UVX Path"
- Only show uvx path status when override is configured

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: improve validation light(uvxPathStatus) logic for UVX path overrides and system paths

* refactor: streamline UV version validation and unify path detection methods across platform detectors

* fix: add type handling for Claude Code client in config JSON builder

* fix: correct command from 'uvx' to 'uv' for Python version listing in WindowsPlatformDetector

* feat: add uvx path fallback with warning UI

  - When override path is invalid, automatically fall back to system path
  - Add HasUvxPathFallback flag to track fallback state
  - Show yellow warning indicator when using fallback
  - Display clear messages for invalid override paths
  - Updated all platform detectors (Windows, macOS, Linux) to support fallback logic

* refactor: remove GetDetails method from PlatformDetectorBase

* Update ExecPath.cs

update Windows Path lookup

---------

Co-authored-by: ChatGLM 4.7 <noreply@zhipuai.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Shutong Wu <51266340+Scriptwonder@users.noreply.github.com>
2026-01-17 18:34:40 -05:00
dsarno 1ab0fd4ba4
Fix ULF detection in Claude licensing (#569)
Detect ULF by Signature before entitlement XML and log license source for debugging.
2026-01-15 13:34:50 -08:00
dsarno a4f74dab43
Workflow cleanup (#568)
* Remove unused GitHub workflow files

* Allow Unity workflows to run in forks

Also adjust Claude NL suite licensing checks so it can run in the top-level repo.
2026-01-15 12:48:15 -08:00
dsarno 10e93b8548
fix: parse and validate read_console types (#565) 2026-01-15 10:34:31 -08:00
dsarno cf177b50af
Replace asmdef GUID references (#564) 2026-01-15 07:52:53 -08:00
David Sarno 98796264ef Remove unnecessary allowNudge guard from PR #558
The allowNudge parameter was attempting to fix Unity 6 compilation loops
by skipping QueuePlayerLoopUpdate, but this was not the root cause.

The actual issue (fixed by #559's Unity 6+ preprocessor guard) is that
EditorApplication.update callbacks don't survive domain reloads properly
in Unity 6+.

Since #559 skips WaitForUnityReadyAsync entirely on Unity 6+ when compile
is requested, the allowNudge guard is redundant and can be removed.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-14 23:12:52 -08:00
Matthew 87d0f1d422
fix: Prevent infinite compilation loop in Unity 6 when using wait_for_ready (#559)
* fix: Prevent infinite compilation loop in Unity 6 when using wait_for_ready

Skip WaitForUnityReadyAsync when compileRequested is true. The
EditorApplication.update polling doesn't survive domain reloads
properly in Unity 6, causing infinite compilation loops.

When compilation is requested, return immediately and let the
client poll editor_state resource instead.

Fixes #557

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: Use actuallyWaited for hint message consistency

Address code review feedback: when compile was requested and we skip
WaitForUnityReadyAsync, the hint should correctly indicate that the
client needs to poll editor_state, not claim the editor is ready.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: Gate Unity 6 fix with version check and rename variable

Address code review feedback:
- Use UNITY_6000_0_OR_NEWER preprocessor directive to only apply the
  compilation wait bypass on Unity 6+, preserving original behavior
  for earlier versions
- Rename actuallyWaited to shouldWaitForReady for clarity, as it
  represents the decision to wait rather than a post-hoc result

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 23:12:30 -08:00
dsarno b6fa293cd3
Guard refresh wait nudge during compile (#558) 2026-01-14 20:14:44 -08:00
dsarno 3f08ac0e43
Fix local HTTP server UI check (#556)
* Fix local HTTP server UI check

* Fix connection section cleanup
2026-01-14 19:57:17 -08:00
GitHub Actions b611b268ef chore: bump version to 9.0.7 2026-01-15 00:10:23 +00:00
David Sarno 12fa0b7707 Fix PyPI publish by inlining steps in release workflow
The pypa/gh-action-pypi-publish action does not support being called
from nested composite actions due to GitHub Actions context variable
limitations (github.action_repository not propagating correctly).

Inline the publish steps directly in release.yml to avoid the issue.
See: https://github.com/pypa/gh-action-pypi-publish/issues/338

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 16:09:27 -08:00
GitHub Actions 218f5f556d chore: bump version to 9.0.6 2026-01-14 23:54:36 +00:00
David Sarno 7fbdbddbc9 Pin pypi-publish action to v1.12.4
v1.13.0 introduced Docker container name issues with uppercase
repository names. Pin to v1.12.4 which was working previously.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 15:53:55 -08:00
GitHub Actions 8df89587ec chore: bump version to 9.0.5 2026-01-14 23:46:48 +00:00
David Sarno 6b87f603aa Fix PyPI publish action for uppercase repo names
Disable attestations to avoid Docker image reference error caused by
uppercase letters in repository name (CoplayDev/unity-mcp). Docker
requires lowercase image references.

The trusted publishing (OIDC) already provides supply chain security.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 15:39:42 -08:00
dsarno 485292f07b
Update README for version 9.0.3 2026-01-14 15:12:00 -08:00
GitHub Actions 787e667c76 chore: bump version to 9.0.4 2026-01-14 23:07:07 +00:00
dsarno 39bff4ae27
Fix PlayMode tests stalling when unfocused (python refresh utility), improve domain reload recovery and refresh tool (#554)
* Fix test job state management after domain reload

- TestRunnerService.RunFinished: Always clean up job state even when
  _runCompletionSource is null (happens after PlayMode domain reload)
- TestJobManager: Detect and clear stale jobs (5+ min without updates)
  on startup to recover from stuck state after domain reload
- refresh_unity.py: Add "could not connect" to retryable errors when
  wait_for_ready=True, so connection failures during domain reload
  trigger waiting instead of immediate failure

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add focus nudge to handle OS-level throttling during PlayMode tests

When Unity is unfocused, macOS App Nap (and similar OS features) can
throttle the process, causing PlayMode tests to stall even with Unity
No Throttling mode enabled.

Changes:
- Add ApplyNoThrottlingPreemptive() to TestRunnerNoThrottle for early
  throttle prevention before PlayMode Execute()
- Add focus_nudge.py utility that temporarily focuses Unity and returns
  focus to the original app (supports macOS, Windows, Linux)
- Integrate focus nudge into get_test_job polling - when tests appear
  stalled (unfocused + no progress for 10s), automatically nudge Unity

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Fix code review issues in focus_nudge.py

- Remove redundant time import (already imported at module level)
- Escape window titles in PowerShell script to prevent injection
- Remove unused Callable import

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Improve focus nudge logging and fix skipped tests

- Improve logging in focus_nudge.py: rate limit skip and focus return at INFO level
- Improve logging in run_tests.py: show nudge completion status
- Fix path resolution in test_logging_stdout.py and test_transport_framing.py
- Add PlayMode tests to UnityMCPTests project for testing PlayMode runner

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add troubleshooting note about focus permission requests

When running PlayMode tests with Unity in the background, the focus
nudge feature may trigger OS permission prompts (especially on macOS
for accessibility/automation). Document this expected behavior.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 15:02:40 -08:00
dsarno b874922cb0
Fix manage_components set_property for object references (#551) 2026-01-13 22:23:18 -08:00
dsarno f4a8b05094
Clean up Unity and Python tests (#548)
* Test suite audit: remove placeholders, consolidate duplicates, fix stale tests

Python tests:
- Delete 3 vestigial placeholder files (test_script_editing.py, test_find_in_file_minimal.py, test_resources_api.py)
- Remove empty skip-marked tests from test_transport_framing.py and test_logging_stdout.py
- Consolidate DummyMCP/setup_tools() into test_helpers.py
- Fix flaky timing in test_telemetry_queue_worker.py (200ms → 500ms)
- Remove placeholder from test_instance_routing_comprehensive.py

C# tests:
- Consolidate MCPToolParameterTests.cs (755 → 361 lines, -52%)
- Fix 3 tests with stale "future feature" comments - features ARE implemented:
  - AutoGrow arrays (Phase 1.2)
  - Path normalization (Phase 1.1)
  - Bulk array mapping (Phase 3.1)
- Strengthen assertions in ManageGameObjectTests.cs and CommandRegistryTests.cs

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Address code review feedback: remove dead code, fix silent test skips

- Remove unused tools_struct setup in test_edit_normalization_and_noop.py
- Create test texture in EndToEnd_PropertyHandling_AllScenarios so
  texture-dependent scenarios (4, 5, 10) actually run instead of silently skipping
- Add texture cleanup in finally block

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 20:26:20 -08:00
Shutong Wu 53c0ed26ef
Refactor ClaudeCodeConfigurator to use JsonFileMcpConfigurator (#545)
The old CLI file map does not seem to work for the latest CC(V2.1.4), with errors that cannot recognize any symbols after uvx.exe, whether it be --no-cache, --refresh, or --from. I did not find any documentation change of why this cannot use.
I temporarily revert the current Claude Code registration to the old JSON way, which still works. Will look for a fix that could retain the CLI command usage.
2026-01-11 02:07:47 -05:00
Shutong Wu f2d56cfb22
Add support for 'standard' shader alias
Fix the no-parameter-material generation issue in URP setting
2026-01-10 23:17:44 -05:00
Berkant 4c9beaffde
feat: add test coverage tracking with pytest-cov (#512)
* feat: add test coverage tracking with pytest-cov

  - Add pytest-cov>=4.1.0 to dev dependencies
  - Configure coverage in pyproject.toml (run, report, html)
  - Integrate coverage reports into CI workflow
  - Update .gitignore for coverage artifacts
  - Document coverage usage in docs/README-DEV.md

  Current coverage baseline: 34.45%

* fix: correct TOML escaping and remove redundant

* docs: add Chinese translation for code coverage section

* fix: regenerate uv.lock to resolve merge conflict
2026-01-08 17:32:44 -04:00
Marcus Sanatan 49587a84cc
Update URL for v9 (#537) 2026-01-08 17:30:58 -04:00
Marcus Sanatan 41664178aa
CI Updates (#536)
* Update the major tag of a version as well when publishing to Docker

Useful for the asset store releases

* feat: trigger publish workflows automatically after version bump and release creation

It should work in theory, and correctly release to Docker and pypi via tags.

* feat: consolidate release workflows into single pipeline with reusable actions

Refactored version bump, Docker publish, and PyPI publish workflows into a unified release pipeline that runs sequentially. Created reusable composite actions for Docker and PyPI publishing to eliminate duplication.

Changes:
- Rename bump-version.yml to release.yml with three jobs: bump, publish_docker, publish_pypi
- Create .github/actions/publish-docker/action.yml with configurable inputs for image, version, branch
2026-01-08 16:37:52 -04:00
GitHub Actions 85198a07ea chore: bump version to 9.0.3 2026-01-08 16:01:52 +00:00
dsarno 7d58053f87
fix: replace Editor-only McpLog with Debug.LogWarning in Runtime assembly (#535)
- UnityTypeConverters.cs referenced McpLog (Editor-only) from Runtime asmdef
- This caused CS0103 build errors in player builds
- Replaced with UnityEngine.Debug.LogWarning for runtime compatibility

Also cleaned up test file:
- Removed stale NL test artifacts (Build marker, Tail test comments)
- Removed unused local functions causing CS8321 warnings
2026-01-08 07:59:05 -08:00
GitHub Actions bf6603d89e chore: bump version to 9.0.2 2026-01-08 15:18:45 +00:00
dsarno cba0933d33
Fixes Windows installation failures caused by long path issues when cloning the full repository via git URL (MAX_PATH 260 char limit exceeded by files in TestProjects/). (#534)
* fix: use PyPI as default server source instead of git URL

Fixes Windows installation failures caused by long path issues when
cloning the full repository (MAX_PATH 260 char limit exceeded).

- Change default from git+https://github.com/CoplayDev/unity-mcp to
  mcpforunityserver=={version} PyPI package
- Rename GetMcpServerGitUrl() to GetMcpServerPackageSource()
- Keep deprecated wrapper for backwards compatibility
- Update UI help text to show local dev override example only
- Update tests to expect PyPI package reference

* fix: use forward slashes in deployment path display

Fixes UI rendering issue where backslashes in Windows paths were
interpreted as escape sequences (e.g. \U, \u showing as boxes).

Convert backslashes to forward slashes for display in:
- Target path label
- Backup path label
2026-01-08 07:14:44 -08:00
GitHub Actions 275422e765 chore: bump version to 9.0.1 2026-01-08 05:50:55 +00:00
Marcus Sanatan a17df1e4c9
feat(batch_execute): improve error handling with success detection and fail-fast support (#531)
- Add DetermineCallSucceeded() to check command success via IMcpResponse interface or JObject/JToken 'success' field
- Track invocationFailureCount and set anyCommandFailed flag when commands fail
- Implement fail-fast behavior to stop batch execution on first failure when failFast=true
- Update commandResults to use computed callSucceeded value instead of hardcoded true

feat(game_object_create): enhance asset
2026-01-08 01:44:32 -04:00