Repository navigation
chore: bump version to 10.3.0 - #1425
Merged
Merged
Conversation
ReadUserScopeConfig merged duplicate normalized project keys from
~/.claude.json ("D:/Dev/X" vs "D:\Dev\X") last-entry-wins, on the
assumption the last is most recent. JSON property order is not
correlated with recency across variants: when the last duplicate is a
stale entry without mcpServers it shadows the real registration, and
CheckStatus reports NotConfigured despite a working
`claude mcp add --scope local` setup (observed live 2026-07-20).
Merge by preferring the entry that actually carries a UnityMCP
registration (then any mcpServers, then last-wins as before).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
`claude mcp add --scope local` keys the registration in ~/.claude.json by the git MAIN repo root. When the Unity project is a linked worktree (e.g. C:/Dev/stay-booping -> repo C:/Dev/stay) that key is a sibling path, so ReadUserScopeConfig's ancestor walk never finds it and CheckStatus reports NotConfigured while the CLI itself resolves the worktree fine (`claude mcp list` shows Connected). Parse the main root from the worktree's .git pointer file and retry the walk from there. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
When a command outlives the broker's patience, the Python side closes the socket, reconnects and resends the same payload. The bridge queued that resend as a brand-new command behind the still-executing original, so the work ran twice — visibly so for commands with side effects such as a long ExecuteMenuItem or a build. The enqueue path now looks for an in-flight command with the same payload that was queued by a different connection, and attaches the new caller to that command's completion source rather than queueing a copy. Comparing the owning connection as well as the payload is what keeps this safe: a single connection handles one command at a time, so two identical payloads on one connection are sequential and genuinely distinct requests. QueuedCommand gains an Owner field, held for identity comparison only and never dereferenced. Closes #1130
The test sampled Dictionary.Count directly by reflection while listener tasks could be adding entries under lockObj, and Dictionary does not support concurrent reads and writes. Sleeping on the main thread stops ProcessCommands from draining the queue but does nothing to synchronise against the socket threads that fill it. Replaces the reflection with an internal QueuedCommandCount accessor that takes lockObj, documented as diagnostics-only. Addresses CodeRabbit review on #1361.
…3553983134 chore: sync main (v10.2.0) into beta
… too DiscoverAllTools queried TypeCache and then materialised every type in every loaded assembly anyway, calling GetCustomAttribute on each one before merging the two sets — so the fast path never saved anything. The result is cached, so that walk ran once per domain reload, and again whenever a tool is toggled in the editor window. A reload therefore paid for two full assembly walks: this one and the one in CommandRegistry.AutoDiscoverCommands that #1364 removed. Now TypeCache-only, matching CommandRegistry and ResourceDiscoveryService. Ordered by FullName for the same reason #1364 sorts: a duplicate tool name overwrites the previous registration, so order decides the winner, and TypeCache documents no order. Relates to #1336
…ypes FullName is not a total order: two assemblies can declare the same full type name, and OrderBy leaves their relative position to the input, which TypeCache does not define. If those types also resolve to the same tool name, the later registration overwrites the earlier one, so the winner could differ between domain reloads. Ordering now falls back to Assembly.FullName. The comparison moved into an internal InRegistrationOrder helper so it can be tested directly: two identically named types cannot coexist in one assembly, so the test emits them into separate dynamic assemblies to construct a real tie and asserts the result does not depend on input order. Addresses CodeRabbit review on #1369.
Unity talks straight to the BlenderMCP addon socket, so a Blender to Unity handoff is one blender_bridge call: export (GLB/FBX) from Blender, import through the shared model pipeline, place in the open scene and normalize the size from measured bounds. Other actions: status, scene/object info, viewport screenshot, run Python in Blender, check the blender-mcp checkout for updates, and sync its addon.py into Blender's addons folder. The informational "Blender -> Unity Handoff" row in the Asset Gen tab becomes a real panel: socket host/port with Test Connection, blender-mcp checkout and Blender addons dir (Select/Clear, resolved path and addon-in-sync state), and Sync Addon / Check Updates / Import Selection buttons. Settings live in EditorPrefs under MCPForUnity.Blender.* via BlenderBridgePrefs; no machine-specific defaults. BlenderDetection gains user addons dir discovery. Menu items under Window/MCP for Unity/Blender Bridge drive the same handler.
Registers blender_bridge in the asset_gen group with typed parameters that map to the C# handler (snake_case to camelCase, None stripped), and adds the `unity-mcp blender` CLI group (status, scene-info, object-info, screenshot, run-python, import-model, check-updates, sync-addon).
…ection Python: registration group, parameter mapping, non-dict result handling and CLI flag mapping. Unity EditMode: framing-free JSON parse/unwrap, handler validation errors that need no Blender, and PickAddonsDir/ParseVersion.
- Run socket and git work on the thread pool: HandleCommand is async, the panel and menu await it, and Unity API calls happen after the await on the editor thread. Buttons are disabled while a call is in flight. - BlenderSocketClient takes an explicit BlenderEndpoint (EditorPrefs is main-thread only) and rejects responses whose status is neither success nor error instead of returning a null payload. - Canonicalize screenshot output_folder through AssetGenPaths so "Assets/../x" cannot escape the project. - Pass target_size through unchanged; 0 now keeps the imported scale as the CLI documents (the pipeline only rescales when > 0). - Embed export-script values as one JSON literal parsed inside Blender, so names with quotes or placeholder-looking text cannot alter the program. - Suppress Ruff A002 on the public `format` parameter. - Document the existing asset_gen group in CLAUDE.md, dev-setup and the tool-groups guide. - XML docs on the new C# members; tests for invalid status, output_folder traversal and the export-script builder.
- Screenshot and export paths get a timestamp plus random suffix so concurrent commands (menu + MCP) started in the same second never share a file. - check_updates strips user info from git remote URLs before returning them, so a token embedded in https://user:token@host/... never reaches the MCP response or the editor log. - Tool count in the tool-groups guide and README is 48 with blender_bridge.
… compare - import_model: auto_animate (default on) creates a looping AnimatorController next to the asset with one state per imported clip and assigns it, so a rigged model moves instead of sitting frozen with a null controller; FBX clips are marked looping on the importer first. save_prefab stores the placed instance under <asset folder>/Prefabs. ensure_bloom enables camera post-processing and adds a Bloom override to the global volume (through manage_graphics) when the model has emissive materials. - New actions: compare_screenshot composites Blender's viewport (left) and a Unity capture framed on the placed object (right) into one PNG; setup_bloom runs the Bloom setup on its own. - Export prefers the addon's export_scene command (validated parameters, no code execution) and falls back to the execute_code script on older addons. - Python tool, CLI (--no-animate, --save-prefab, --ensure-bloom, compare-screenshot, setup-bloom), tests and generated docs updated.
A core.autocrlf checkout gives tools/compile-defines.txt and tools/compile-refs/*.txt CRLF endings; the read loops kept the CR, so every -define: carried a stray \r and every LIBCACHE/ reference failed to resolve, failing the Editor build on TestRunner types. Strip the CR when reading and pin those manifests to LF in .gitattributes. Also normalise REPO/UNITY_DATA/OUT through pwd -W so Git Bash's /x/... paths do not reach Roslyn as X:\x/..., and document the Windows recipe in the header.
The lock's own-project entry still said 10.1.0 while pyproject.toml said 10.2.0, so uv sync --locked failed and CI silently re-resolved. update_versions.py now rewrites the mcpforunityserver entry, release.yml stages the lock in the bump commit, and python-tests.yml runs uv sync --locked --extra dev so pytest uses the pinned dev dependencies instead of whatever uv pip install fetches on the day.
…orPrefs McpCiBoot wrote UseHttpTransport=false to the developer's EditorPrefs and still lost to the value EditorConfigurationCache had already read: on a machine whose prefs choose HTTP with auto-start, UNITY_MCP_ALLOW_BATCH let HttpAutoStartHandler run and BridgeControlService.StartAsync stopped the stdio bridge the harness was talking to. Keep the override in SessionState so it survives domain reloads, dies with the editor process, and never touches the user's real preference.
Discovery is parameterised by platform so it can be tested for every OS from any OS, but it used pathlib.Path, which picks the host separator; four tests failed on Windows with \home\dev\Unity. Use PurePosixPath/PureWindowsPath by target.
…face - /register-tools is no longer registered in remote-hosted mode. It carried no API-key check, so any caller could replace tool definitions for every tenant; the plugin registers tools over the hub WebSocket and never calls this route. - debug_request_context redacts the values of secret-bearing argv flags. It handed --api-key-service-token to every authenticated tenant. - ApiKeyService caps its cache at 1024 entries (expired first, negatives never evict a validated key) so unauthenticated key guesses cannot grow memory, and logs a sha256 fingerprint instead of eight literal characters of the key.
set -x printed the expanded -password/-serial arguments into the job log and left GitHub's secret masking as the only protection.
…ent in remote URLs - setup_bloom returns an error response when manage_graphics could not add the Bloom override instead of reporting success with a failure payload. - RedactRemoteUrl also drops query strings and fragments, so ?token=... or #access_token=... never reach the check_updates response. - Tests for the failure mapping and the extra redaction cases.
perf(discovery): drop the redundant assembly walk from tool discovery too
…693125446 chore: update Unity package to beta version 10.2.1-beta.2
fix: Claude Code registrations invisible to CheckStatus (duplicate path-variant keys, git worktrees)
…694138160 chore: update Unity package to beta version 10.2.1-beta.3
On a tr-TR editor "Warning".ToUpper() gives "WARNİNG", so the validate parser's ^(ERROR|WARNING|INFO): regex misses it and the diagnostic comes back as severity info, line 0.
fix: upper-case Roslyn severity with the invariant culture
fix(tests): recover jobs after reload, bound focus nudges, and fix CI
Signed-off-by: pumisj <pumisj@naver.com>
…ore-1407 fix(windows): preserve window state and Unicode focus metadata
feat: Blender Bridge — drive BlenderMCP from the Unity Editor (tool + Asset Gen panel)
…ey row - Editor DropdownFields open a native GenericMenu that turns every '/' in a model id into a submenu; menu items now show U+2215 instead (passed via the ctor, since formatListItemCallback is not public before Unity 6). - Cap each model menu at 25 entries, keep the saved selection, and point to Search for the rest of large live catalogs. - The fal 3D row reuses the 2D fal key and toggle like the audio row, instead of a second key field and an out-of-sync Enabled toggle. - Rebuild model controls only on catalog Changed events, scoped by provider, and keep failed compatibility checks visible across rebuilds. - Skip the selector for providers with no models (Sketchfab showed "No models found") and show verification state only for fal/OpenRouter.
With a saved selection missing from the catalog, the caveat label kept its validation-description background with no text, which showed as an empty blue bar under the audio row.
…he cap - A paid-generation (or selection) preflight no longer waits on the request gate that background catalog refreshes take turns through. With a full refresh in flight it could queue behind several paced requests and hit its 60 s timeout. Without a key it still honors the public pacing interval. - Raise the fal/OpenRouter cache read cap from 2 MB to 16 MB (~25x today's ~0.6 MB catalog) and log a warning when a cache is skipped, instead of silently re-fetching after every domain reload once the catalog outgrows it.
Resolves McpAssetGenSection.cs against the Blender Bridge panel from #1375: keep blenderPanel?.Refresh() next to the catalog refresh, and drop the old AddBlenderHandoffRow call that beta replaced with the panel.
…talog feat: auto-discover live fal and OpenRouter asset models
…ll state - Probe the BlenderMCP addon socket automatically (in the background) when the panel is built, each time the Generative tab is shown, and after a host/port change. One probe at a time; a request during a probe re-runs it so the shown result always belongs to the current endpoint. Test Connection is a manual re-check and no longer disables the action buttons. - Detect Microsoft Store Blender (per-user %LOCALAPPDATA%\Packages\ BlenderFoundation.Blender* folder; the WindowsApps install dir is unreadable), Steam's default library on Windows/macOS/Linux, and Linux per-user flatpak. A Store-only machine was reported as "Blender app not found". - The addons line now says when the resolved folder does not exist yet and whether addon.py is installed, and is green only when the addon is installed (and matches the checkout when one is set). It used to show a nonexistent folder in green. - Replace the yellow "pick your checkout" banner with a neutral note: the checkout is optional and only for addon developers (Sync Addon / Check Updates). Rename the import button to "Import Blender Selection (GLB)" and explain what it needs in its tooltip.
…ion-ux Blender Bridge panel: auto-detect the addon and report the real install state
…n parse it
The file ended in "assetBundleVariant:" with no space and no final newline.
Unity 6 reads that last line as a key without its ':' separator, logs
"YAML Parsing error 'Parser Failure at line 11'", and ignores the asset
("does not have a valid GUID"). Unity 2021.3 and 2022.3 accept the file.
On the 6000.0 and 6000.4 legs of Beta Release, the error is logged during the
SetUp of the four DomainReloadResilienceTests, which fail on the unhandled log
message. The full EditMode suite is then skipped, so every Beta Release run
since #1389 (91eb0f4) is red and nothing has published.
Reproduced on 6000.6.4f1: the original bytes give the same error and no GUID;
the same bytes plus a final newline import normally. No other tracked .meta
file ends in a bare "key:".
test: end ExecPathBatchShimTests.cs.meta with a newline so Unity 6 can parse it
Contributor
|
Important Review skippedBot user detected. To trigger a single review, invoke the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Automated version bump to 10.3.0.