Commit Graph

674 Commits (a126ed6c3fac02d89ec1d41ae1af15c41750c002)

Author SHA1 Message Date
GitHub Actions 2c20ddcd10 chore: bump version to 9.2.0 2026-01-23 05:34:19 +00:00
Marcus Sanatan 5acef27cd7
Merge pull request #615 from CoplayDev/beta
Update main for new workflow
2026-01-23 01:19:02 -04:00
Marcus Sanatan d3e42a1c32 docs: change README installation examples from fixed version to beta branch
Remove version-specific installation examples from README.md and README-zh.md, replacing with beta branch references. Update release workflow and update_versions.py to stop modifying README files during version bumps since they no longer contain version-specific URLs.
2026-01-23 01:14:54 -04:00
Marcus Sanatan 63b666b421 Minor feedback 2026-01-22 21:45:03 -04:00
Marcus Sanatan f314a2367a
Update CI flow so that we bump from beta to main, and sync back (#614)
* feat: add release workflow concurrency control and main-to-beta sync

Add safeguards to prevent concurrent releases and ensure beta stays in sync:
- Add concurrency group to prevent overlapping release runs
- Enforce workflow runs only on main branch (fail if run elsewhere)
- Explicitly checkout and push to main (not dynamic branch)
- Fail if release tag already exists (was silently skipping)
- Add sync_beta job that merges main back into beta after release
- Add docs/guides/RELEASING.md with two

* feat: use PRs for version bumps and beta sync instead of direct pushes

For release notes to work we need for PRs from beta to main to not be squashed. We also want to enforce all changes to be via PRs, for humans. But that also limits GH Actions.

An alternative is creating a GH App with bypass permissions but that felt like overkill

Replace direct pushes to main/beta with PR-based workflow for better branch protection compatibility:
- Create temporary release/vX.Y.Z branch for version bump
- Open PR from release branch into main, enable auto-merge
- Poll for PR merge completion (up to 2 minutes) before creating tag
- Fetch merged main and create tag on merged commit
- Clean up release branch after tag creation
- Create PR to merge main into beta (skip if already
2026-01-22 21:36:54 -04:00
Marcus Sanatan f32b62d616 docs: add LLM prompt and checklist for documentation updates
Add automated documentation update workflow to ensure consistency when tools/resources change:
- Add UPDATE_DOCS_PROMPT.md with copy-paste LLM prompt that:
  - Instructs LLM to scan Server/src/services/tools/ and resources/ for decorators
  - Updates manifest.json tools array, README.md tools/resources sections, README-zh.md
  - Enforces alphabetical ordering and formatting rules (backticks, bullets)
  - References check_docs_sync.py for
2026-01-22 16:23:42 -04:00
Marcus Sanatan e73c9c1651 docs: add version update workflow documentation to development guides
Add comprehensive documentation for the version update process in both English and Chinese development guides:
- Document manifest.json and package.json version synchronization during releases
- Explain update_versions.py script usage with examples (default, --version, --dry-run)
- List all files updated by the script (package.json, manifest.json, pyproject.toml, READMEs)
- Provide guidance on manual tool updates outside release
2026-01-22 16:09:04 -04:00
Marcus Sanatan 067eddd1da refactor: consolidate version update logic into Python script
Replace inline sed/jq commands in release workflow with tools/update_versions.py script that:
- Updates MCPForUnity/package.json, manifest.json, Server/pyproject.toml
- Updates version references in Server/README.md, README.md, docs/i18n/README-zh.md
- Supports --dry-run and --version flags
- Auto-detects version from package.json if not specified
- Provides better error handling and progress output
2026-01-22 16:08:21 -04:00
Marcus Sanatan 591e93405f Update version 2026-01-22 16:02:08 -04:00
Bryan Thompson 1238eb1e84
feat: Add MCPB bundle for Claude Desktop installation (#580)
* feat: Add MCPB bundle for Claude Desktop installation

Add Model Context Protocol Bundle (MCPB) support enabling single-click
installation in Claude Desktop and other MCP hosts.

Changes:
- Add manifest.json with uvx-based server configuration
- Add icon.png for display in Claude Desktop
- Add .mcpbignore for build exclusions
- Add pre-built unity-mcp.mcpb bundle

🤖 Generated with [Claude Code](https://claude.com/claude-code)

* fix: Generate MCPB as release artifact instead of committing to repo

Address review feedback from @msanatan:
- Remove pre-built unity-mcp.mcpb and icon.png from repository
- Add tools/generate_mcpb.py script for bundle generation
- Update release.yml with new publish_mcpb job that:
  - Generates bundle using generate_mcpb.py
  - Uploads MCPB file as release artifact
- Update manifest.json to reference icon from docs/images/

The bundle is now generated automatically on each release,
keeping the repository clean while providing download artifacts.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

* fix: Use correct mcpb pack CLI syntax (positional args)

The mcpb CLI uses 'mcpb pack [directory] [output]' syntax,
not '--output' flag. Tested locally - bundle generates correctly.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: triepod-ai <199543909+triepod-ai@users.noreply.github.com>
2026-01-22 15:46:35 -04:00
dsarno 30d5bc254e
feat: Add OpenCode (opencode.ai) client configurator (#608)
* feat: Add OpenCode (opencode.ai) client configurator

Add support for the OpenCode CLI client with automatic configuration.

- Create OpenCodeConfigurator implementing IClientConfigurator
- Configure via ~/.config/opencode/opencode.json (XDG standard path)
- Use McpConfigurationHelper for atomic file writes and directory creation
- Support both new config creation and merging with existing config

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

* fix: Address code review feedback for OpenCodeConfigurator

- Add TryLoadConfig() helper to consolidate file read/parse logic
- Handle JsonException separately (log warning, return empty object to overwrite)
- Wrap Configure() in try/catch to prevent crashes, set McpStatus.Error on failure
- Respect XDG_CONFIG_HOME environment variable per XDG Base Directory spec

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

---------

Co-authored-by: akshay-kiddopia <akshay@kiddopia.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 19:46:19 -08:00
Marcus Sanatan 9682e3c3e1
Marcus/update readme on release (#607)
* chore: update version references in README files during release

- Add version update for root README.md UPM fixed version examples
- Add version update for README-zh.md UPM and pip fixed version examples
- Include README.md and README-zh.md in release commit

* Update version in README

* Update example command version

* Update simplified Chinese readme to match english one

* The readme has changed

* docs: reorganize documentation into structured subdirectories

- Move README-zh.md to docs/i18n/README-zh.md
- Move development docs to docs/development/ (README-DEV.md, README-DEV-zh.md)
- Move user guides to docs/guides/ (CLI_USAGE.md, CURSOR_HELP.md, MCP_CLIENT_CONFIGURATORS.md)
- Move migration guides to docs/migrations/ (v5_MIGRATION.md, v6_NEW_UI_CHANGES.md, v8_NEW_NETWORKING_SETUP.md)
- Move reference docs to docs/reference/ (CUSTOM_TOOLS.md, TELEMETRY.md)
- Update all internal links in README
2026-01-21 22:35:24 -04:00
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