- McpToolsSection: add the asset_gen -> "Asset Gen" group display name so
the tool-group tab no longer falls back to the raw "Asset_gen".
- Update the asset_gen group blurb (registry + CLI) to include audio gen.
- Regenerate the tool reference docs from the Python registry: add the
missing generate_audio.md and refresh the asset_gen landscape/index.
Claude-Session: https://claude.ai/code/session_015KYy51gwBuhDuLZXXoqc98
Security (from a dynamic security audit of the branch):
- H1: UnityWebRequestTransport disables auto-redirect on auth-bearing
requests (redirectLimit=0) so a provider 3xx can't re-send the API key
to a redirect host.
- H2/P8: per-kind result-extension allowlist in AssetGenJobManager.WriteFile
(+ defense-in-depth in the audio/image import pipelines) — a provider
can no longer land a .cs/.asmdef/.meta/.asset under Assets/ (Editor RCE).
- H3: ProviderHttp.RequireHost pins the submit URL and the provider-supplied
response_url to https://queue.fal.run before the fal key is attached
(both fal image + audio adapters).
Correctness (from code review):
- C1: Tripo image->3D now sends model_version.
- C2/C3/C6/C10: FalAudioAdapter.BuildBody is catalog-driven — duration-
required models (CassetteAI SFX/Music, Stable Audio) send a default
duration when the caller passes 0 (fixes the default-input 422),
fractional durations floor to >=1, Lyria stays prompt-only and its GUI
no longer advertises a duration it ignores, and the clamp ceilings come
from the catalog (no more duplicated 190/30/180).
- C4: an unmapped fal poll status now fails fast instead of polling to the
600s timeout (both fal adapters).
- C5: a stale/invalid selected-model pref is cleared on dropdown fallback.
- C7: the audio fal-key status refreshes when the shared 2D fal key changes.
Cleanup: extract AssetGenModelCatalog.ResolveModel (dedupes the model-
resolution chain across the three generate tools) + DefaultModelId no-alloc.
Verified: full EditMode suite 1166 tests, 0 failures (+19 new regression
tests); 34 Python asset-gen tests pass.
Claude-Session: https://claude.ai/code/session_015KYy51gwBuhDuLZXXoqc98
Wraps each category (3D Models / 2D Images / Sound) in its own darker rounded panel
so they read as distinct blocks, and moves the per-provider key status (saved/not set)
up into the header row to the right of the provider name — reclaiming a line per
provider. Verified live: 3 panels (bg alpha 0.20), status inline in each header.
Claude-Session: https://claude.ai/code/session_01GCxmdd4qo7MG6J4M6WcT9Y
The provider row is a vertical (column) container, so the setting-dropdown-inline
class's flex-grow:1 stretched the DropdownField vertically. Wrap the Model dropdown
in a horizontal .setting-row with a .setting-label (matching the Format row) and use
a label-less DropdownField. Verified live: all 5 model dropdowns now render at 18px
inside setting-row containers instead of ~400px boxes.
Claude-Session: https://claude.ai/code/session_01GCxmdd4qo7MG6J4M6WcT9Y
Phases 4-5. Extends the existing Asset Gen tab (no new window): per-provider
'Model' dropdowns on the image + 3D rows with price/duration/use-case metadata, a
fal audio row (no key field — reuses the shared fal key) with a model dropdown and
the Stable Audio license caveat, and a Refresh button that re-validates key
presence + the curated catalog. Selecting a model writes the per-(kind,provider)
pref that generate_* reads as its default. fal has no public list-models API, so
Refresh is a curated re-validate (the plan's gated fallback), never a network fetch.
Characterization tests assert the new builders + three-phase lifecycle.
Claude-Session: https://claude.ai/code/session_01GCxmdd4qo7MG6J4M6WcT9Y
Two related stdio connection-UI reliability bugs surfaced while testing
with a live domain-reload cycle:
1. Start Session race (severe). StdioTransportClient.StartAsync returned
true unconditionally, then callers immediately verified — but
VerifyAsync only reads StdioBridgeHost.IsRunning, which is still false
while the previous port releases after a reload (Start() defers the
bind to an editor-idle retry, or falls back to a new port after
BusyPortFallbackWindowSeconds). Result: "Connection verification
failed: Bridge not running", and Start Session only connected after
several clicks. StartAsync now waits (bounded, ReadyWaitTimeoutSeconds)
for the bridge to actually bind before reporting success.
2. Health-indicator flash. VerifyBridgeConnectionInternalAsync flipped the
indicator to Unhealthy on a single transient verify miss during a
reload/port-hop, then recovered — misleading. It now debounces via
UnhealthyVerificationThreshold (mirrors the #1207 orphan-session
debounce), resetting on any reachable result.
Both decisions are pure, unit-tested helpers (ShouldKeepWaitingForReady,
ShouldReportUnhealthy). 16 EditMode tests green (4 readiness + 5 debounce
+ 7 existing #1207 orphan, no regression).
Claude-Session: https://claude.ai/code/session_015JRaRFZy4piZzZtW5NabJS
Review follow-up: a streak accumulated while no session was running (detector
inert, counter still counting) survived into a freshly started session and
could satisfy orphan detection before the first post-start probe refreshed.
Reset on the not-running -> running transition, which covers every start path
(manual Connect, auto-start, resume) since UpdateConnectionStatus runs on the
UI tick.
The orphaned-session detector ended an active session on a SINGLE stale
reachability reading, and the reading came from a lone 50ms TCP connect
cached for 0.75s — trivially false-negative on a machine busy with test
runs or domain reloads. Evidence bundles in #1207 show 13 teardowns and
147 socket closures in one session from exactly this loop, wedging the
bridge in no_unity_session churn until manual recovery.
- Require 3 consecutive failed polls (0.75s cadence) before declaring a
session orphaned; probe readings taken while the editor is compiling or
importing don't count toward teardown, and detection is skipped entirely
while busy.
- Raise the probe's connect wait 50ms -> 250ms, as an overall budget shared
across candidate hosts so the worst-case main-thread wait cannot multiply.
- Honor UNITY_MCP_SESSION_RESOLVE_MAX_WAIT_S above 20s (ceiling now 120s;
default unchanged): the old ceiling equalled the default, silently
neutering the documented escape hatch for projects whose reloads or test
boundaries legitimately exceed 20s. Same treatment for
UNITY_MCP_SESSION_READY_WAIT_SECONDS, and both now share one bounded
env-read helper.
The remaining piece of #1207 (keepalive reload-awareness in
WebSocketTransportClient) is untouched here: the resume machinery reworked
in #1234 already covers reload boundaries, and the detector debounce
removes the dominant churn source dsarno identified.
Auto-start died for the whole session whenever startup included a compile:
the ctor latched SessionState before the delayCall ran, and the reload wiped
the delayCall. Reload-resume died at multi-pass compiles: the one-shot flag
was consumed before the deferred (delayCall) resume ran, and the next
boundary deleted it again.
- Replace delayCall with EditorApplication.update ticks that the
[InitializeOnLoad] ctor re-arms on every domain load; latch only when the
deferred work actually dispatches, retry (bounded per domain) while editor
services are still initializing, and skip the subscription entirely in the
common case where auto-start is off and nothing is pending.
- Move the resume flag from EditorPrefs (per-user machine-global, survives
crashes, leaks across concurrently open editors) to SessionState; keep it
until the resume succeeds, is cancelled, or exhausts its retries, instead
of consuming it at boundaries where the bridge is down. Manual Connect,
End Session, transport switch, and orphan cleanup cancel a pending resume
through a named seam (CancelPendingResume), which also aborts an in-flight
retry loop; exhaustion erases the flag so later reloads don't replay 49s
failure loops.
- Serialize TransportManager.StartAsync per mode: concurrent starts coalesce
onto one in-flight attempt, so a manual Connect can no longer race the
resume/auto-start loops into bouncing a just-established session
(WebSocketTransportClient.StartAsync tears down a live connection first).
- A SessionState connect-pending marker lets the next domain load finish an
auto-start whose connect phase a reload killed — connect-only, never
re-spawning (StartLocalHttpServer stops a still-booting server first).
Whether a launch-process handle exists is now answered live by
ServerManagementService.HasManagedServerLaunchHandle; without one (post-
reload, or an externally started server) the wait polls to the 5-minute
hard cap instead of fail-fasting.
- Busy gate uses EditorStateCache.GetActualIsCompiling (now internal, with
the CompilationPipeline reflection bound once as a delegate): raw
isCompiling stays true all play session under
Recompile-After-Finished-Playing (#549).
- One-time (per session) migration deletes the legacy EditorPrefs flag.
The stdio sibling has the same defect class (StdioBridgeReloadHandler.cs:65
delete-when-not-running, :133 delayCall) — follow-up, kept out of scope here,
along with the remaining stdio copies of the isCompiling probe.
- Remove OceanMarkTests (geometry/color mapping + construction) per request;
the mark is verified visually in-Editor.
- With the test gone, MapSvgPoint/FromHex no longer need to be `internal`,
and they (plus the SvgOrigin/SvgSize consts) are only used by the Painter2D
path — move them inside `#if UNITY_2022_1_OR_NEWER` and make them `private`,
so the 2021.3 fallback carries no unused members.
Result of a /simplify pass; reuse/altitude/efficiency angles came back clean
(logo-injection duplication left at 2 call sites per the repo's 3+-uses rule).
Addresses AI review (Copilot + CodeRabbit) on #1231:
- PollUvInstall: bail out (and detach) if the window/UI was torn down while
the task ran, guarding against dereferencing UI fields after teardown.
- OnEnable: resume polling if an install was still in flight when the window
was disabled, so completion is still processed (button reset, deps re-checked).
- OceanMark.LoadBrandTexture: log a warning instead of silently swallowing
asset-load failures on the 2021.3 raster-fallback path.
Declined CodeRabbit's "use a compat shim" suggestion for OceanMark's
#if UNITY_2022_1_OR_NEWER: per UnityCompatShims.cs policy, shims are for
[Obsolete] APIs, 3+ gated call sites, or announced removals — Painter2D is a
new API used via static dispatch in one self-contained file, which the policy
explicitly says to handle with #if, not a shim.
- Setup wizard: de-box the title beside the logo; footer buttons size to
content and sit together on one row (Refresh no longer stretches
full-width and overflows); rename the deps-step "Done" button to "Next".
- Client Configuration dialog: show the count + only failures + next step
instead of enumerating every successfully configured client.
- Main window header: version pill never shrinks/clips (flex-shrink 0);
title stays at natural width.
- Tabs: flex-shrink so all six stay reachable when docked narrow.
- Connection status label wraps/shrinks instead of sliding under the
Disconnect button (scoped to #connection-section).
Add the Ocean split-cube brand mark to the Editor UI and land three
low-risk installation-flow improvements.
Logo:
- OceanMark: reusable UI Toolkit control drawing the mark in Painter2D
vector (geometry transcribed from logo-mark.svg, brand colors baked in),
crisp at any DPI with no new package dependency. Painter2D is 2022.1+,
so it is guarded by #if UNITY_2022_1_OR_NEWER with a raster fallback
(package-icon.png) on the 2021.3 floor.
- Embedded in the main window header (#header-left group) and the
setup-wizard header.
- Ship package-icon.png inside the package (listing icon + 2021.3 fallback).
Installation polish:
- One-click uv install: UvInstaller builds the official installer command
per platform; setup wizard runs it off-thread with a confirm dialog and
re-checks dependencies.
- Claude CLI auto-discovery: consolidate the weaker resolver into
ExecPath.ResolveClaude() and add the ~/.claude/local (migrate-installer)
location both resolvers missed.
- Setup wizard clarity: success/next-step copy after configuring clients.
Tests: EditMode coverage for the geometry/color mapping, per-platform uv
command, and the Claude override contract.
Verified: compiles clean on 2021.3.45f2 (fallback path) and 6000.4.11f1
(Painter2D path).
Informational row (not a keyed provider) with a best-effort "Blender app detected"
status and a pointer to the blender-to-unity workflow / import_model_file. BlenderMCP
runs in the AI client and isn't detectable from Unity, so this reports only the
locally installed Blender app.
- BlenderDetection helper: checks well-known install paths + PATH per platform; the
pure DetectIn(candidates, exists) core is unit-tested with a fake predicate.
- McpAssetGenSection: AddBlenderHandoffRow() appended after the provider rows.
- README: note the tab's best-effort detection + that BlenderMCP lives in the AI client.
Verified: package compiles clean; EditMode 972/1018 pass, 0 failures (4 new
BlenderDetection tests) via tools/local_harness.py.
Claude-Session: https://claude.ai/code/session_015DAUrMR5UaSEzEn2wNPrEP
Security review + code review of the asset-gen feature surfaced concrete issues;
this fixes them and adds regression tests (request-shaping layer, FakeHttpTransport).
Security
- SafeZipExtractor enforces an extension allowlist; ModelImportPipeline passes an
inert model/texture allowlist so a provider archive can't drop a .cs/.dll under
Assets/ and have the Editor compile/load it (code execution on import).
- AssetGenJobManager refuses non-http(s) download URLs before fetching
(file:// SSRF / local-file read into the project).
Provider correctness
- Meshy image->3D polls /openapi/v1/image-to-3d/{id} (was the v2 text URL).
- Meshy text->3D honors texture=true via the preview->refine two-phase flow.
- OpenRouter image->image attaches the reference image (content image_url part).
- fal image->image uses the /edit endpoint + image_urls array; width/height
forwarded as image_size.
- Sketchfab search forwards categories/count/cursor/downloadable; preview doc
corrected (returns metadata, not a base64 thumbnail).
- Job import calls AssetDatabase.Refresh() before importing a freshly written file.
Local image input (image_path)
- New LocalImage helper; image_path is read and sent inline as a base64 data URI
for Meshy / fal / OpenRouter. Tripo rejects local images with a clear error
(needs a hosted image_url; its upload flow is not wired).
Cleanup (no behavior change)
- Shared AssetGenPaths + ProviderHttp helpers, HttpResult.Ok, MissingKeyMessage,
cached glTFast probe, dead-field / per-frame-alloc removal, CLI _emit.
Docs: README + manual-verification updated (image_path support; transparency is
import-flag-only; width/height fal-only).
Verified: package compiles clean; Python 1306 passed / 3 skipped. Meshy refine,
fal /edit, and image_path data-URI paths are unit-tested at the request layer
only -- live smoke per provider (real keys) still pending.
Claude-Session: https://claude.ai/code/session_015DAUrMR5UaSEzEn2wNPrEP
Drop Hunyuan (Tencent TC3-HMAC) — high effort and not testable by the maintainer:
delete HunyuanAdapter + TencentCloud3Signer (+tests), unwire from AssetGenProviders,
SecureKeyStoreConstants, the GUI provider list, and Python/CLI/README/manual-verify docs.
Refresh model defaults to current (2026) SOTA, verified against provider docs:
- fal: fal-ai/flux/dev -> fal-ai/flux-2 (FLUX.2 dev; cheaper and higher quality)
- Tripo: v2.5-20250123 -> v3.1-20260211 (current recommended model)
- Meshy: drop deprecated art_style (errors on Meshy-6); pin ai_model=meshy-6
- OpenRouter: gemini-2.5-flash-image-preview (delisted) -> gemini-2.5-flash-image
Fix two tests that asserted the now-implemented 'meshy' provider throws (repointed to the
now-removed 'hunyuan'). They were silently wrong: the headless --full runs never executed
EditMode tests (Unity -quit exits before -runTests; compile-only). A real -runTests run
now passes 62/62 AssetGen EditMode tests; Python suite 1299 passed.
Claude-Session: https://claude.ai/code/session_01Tjpb5gYgUe2AUJuRdXr7Lv
New 'Asset Gen' tab in MCPForUnityEditorWindow: per-provider API-key entry backed by
SecureKeyStore (never EditorPrefs/project — field never reads the stored key back),
enable toggles, Test presence-check, Clear; non-secret prefs (default format, output
root, auto-normalize); glTFast-missing notice pointing to the Dependencies tab. No
Generate button / prompt — generation is MCP/CLI only. Wired exactly like the Advanced
tab. Compiles clean on Unity 2021.3.45f2.
Claude-Session: https://claude.ai/code/session_01Tjpb5gYgUe2AUJuRdXr7Lv
Convert the local MCP HTTP server launch from a visible-terminal model to a
headless background launch and make startup diagnosable and robust.
- Launch windowless via TerminalLauncher.CreateHeadlessProcessStartInfo;
combined stdout/stderr redirected to a per-port log at
Library/MCPForUnity/Logs/server-launch-{port}.log (truncated each launch)
- Replace the per-launch confirmation dialog with a one-time confirm gated on
the new EditorPrefs key HttpServerLaunchConfirmed; the quiet auto-start path
skips it and does not set the flag
- Prepend platform uv/uvx PATH entries so bare uvx/uv resolves under
GUI-launched Unity's minimal non-login PATH (notably macOS)
- Replace the fixed ~30-attempt reachability waits with open-ended polling
tied to the launched process's liveness (5-minute hard cap), emitting a
tail-of-log failure report when the server dies — in both
HttpAutoStartHandler and McpConnectionSection
- Simplify quit-time cleanup to a handshake-scoped StopManagedLocalHttpServer
so headless servers are not left as invisible orphans
- Transport-aware UI button labels (Connect/Disconnect vs Start/End Session),
a transient "Starting…" state, and clearer lifecycle logging
Tests: TerminalLauncherTests covers the headless start-info contract;
ServerManagementServiceCharacterizationTests covers the one-time-confirm gate,
quiet-path bypass, and per-port log redirection.
User-reported regression from the previous commit on this PR:
"Configure All Detected Clients does not actually configure all IDEs;
after I click Configure each individual IDE still shows missing
configs, and if one is configured Configure All resets it."
Root cause was the toggle I'd put inside JsonFileMcpConfigurator.Configure():
when ConfigureAllDetectedClients walked the registry and called
configurator.Configure() on each one, any client whose status was
already Configured took the Unregister branch — so the bulk action
wiped every already-configured JSON client instead of refreshing it.
(The same trap existed for ClaudeCli even before this PR, but Claude
Code's CLI registration path is rarely hit through the bulk button so
nobody had reported it.)
Fix: move the Configure↔Unregister toggle out of the configurator and
into the UI handler. The configurator API now has two clearly-split
operations:
- IMcpClientConfigurator.Configure(): always idempotent-write. Safe to
call repeatedly. This is what ConfigureAllDetectedClients calls and
what makes the "refresh transport / server version drift" use case
work without resetting anything.
- IMcpClientConfigurator.Unregister(): removes UnityMCP from this
client's config. McpClientConfiguratorBase ships a no-op default;
JsonFileMcpConfigurator overrides with the JObject-parse + remove
path that used to be the private UnregisterFromConfig helper.
Codex's TOML still has no remove path so it inherits the no-op,
matching the previous commit's stance.
UI per-client click (OnConfigureClicked) now reads client.Status and
routes: Configured → client.Unregister(); else →
MCPServiceLocator.Client.ConfigureClient(client). The button label
toggle from GetConfigureActionLabel is preserved — it's purely
informational and stays consistent with the routed action.
Secondary fix in OnConfigureAllClientsClicked: clear the
lastStatusChecks cache after the bulk run so dropdown-switching to
any non-currently-selected client immediately reads its post-bulk
status from disk instead of waiting out the 45-second throttle. This
was the "after clicking Configure All each individual IDE still shows
missing configs" symptom even when the writes had actually succeeded.
ClaudeCli's existing internal toggle is preserved (its async path in
ConfigureClaudeCliAsync handles the Configuring…/Unregistering… UX
itself, and OnConfigureClicked still early-routes to that helper).
Community report: "the Unregister button was removed in 9.7.0 — it did a
wrong registration with stdio transport and now it's difficult to
re-register; something is stuck on stdio and I can't switch to local."
The button wasn't actually removed — the 9.7.0 UI shuffle put the
single-client Configure (which toggles to Unregister for CLI-based
clients like Claude Code) inside a "Per-client setup" foldout that
defaulted to collapsed. With Configure All sitting prominently above it,
the foldout looked like terminal styling rather than the entry point to
manual per-client management, so users who needed to wipe a bad stdio
registration and re-add with HTTP couldn't find the button.
Flip the default to expanded in both UXML and the EditorPrefs fallback.
The state still persists per-user, so anyone who explicitly collapses it
keeps that preference — only the never-touched default changes.
Helper line under the green button was visual noise — the button label
already says what it does. "Configure a single client" was redundant
inside a section titled "Client Configuration"; "Per-client setup"
reads cleaner. Also drop the now-orphan .primary-button-hint style.
Now that "Configure All Detected Clients" actually does what its name
says (auto-rewrite + per-client transport coercion + IsInstalled
filtering all landed in the recent client-config work), it's the path
we want first-run users on — not buried at the bottom of the panel.
Layout changes in McpClientConfigSection.uxml:
- Move the Configure-All button to the top of the section, right under
the "Client Configuration" header, with a one-line helper underneath.
- Wrap the dropdown / status / single-client Configure button / Claude
CLI path / project-dir / Manual Configuration foldout in a new
"Configure a single client" foldout, collapsed by default. Persist
its open/closed state via a new EditorPrefs key.
Style changes in Common.uss:
- New .primary-button class (bright green, 34px, bold) for the
one-click action so it visually distinguishes itself from the regular
blue .action-button rows.
- Light/dark-aware foldout header styling for the new client-details
foldout that matches the existing manual-command-foldout treatment.
- ToolDiscoveryService: add AppDomain fallback scan for [McpForUnityTool] types
- StdioBridgeHost: include project_scoped_tools flag in heartbeat JSON
- McpToolsSection: update tooltip and default to reflect stdio support
- models.py: add project_scoped_tools field to UnityInstanceInfo
- port_discovery.py: read project_scoped_tools from status JSON
- main.py: enable project-scoped tools when Unity instance requests it
1.Add Compat based scripts revolving around UnityCompatShims.cs, that will document our current API Compatibility changes in several files.
2.Add custom screenshot folder selection
1. Add McpLog that could log mcp calls and errors under Asset/
2. Solve issues #816 via incluging str in annotation, extracted AssignedObjectreference() helper that verify assignments and resolve component types from gameobjects.
* Initial update
* Update with docs and fix
* Update on Skybox
* Bug fix and compatability issue
* Update
* Resolve EntityIdToInstance and InstanceIdToObject conflict
* update to revert the changes
Seems EntityId is implicitly casted to Int so no need to prevent it.
* Initial update on tool list update
* clean up and doc update
* Update for Stdio mode
* UI change and doc update
* fix based on audit
* Update manage_tools.py
* Apply suggestion from @Copilot
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Add Unity MCP skill sync installer
Add an EditorWindow (McpForUnitySkillInstaller) that syncs the unity-mcp skill from a GitHub repository without cloning. The tool reads the repo tree via the GitHub API, computes git blob SHA-1s to build an incremental sync plan (added/updated/deleted), downloads raw files for changed items, validates hashes, and writes a last-synced commit to EditorPrefs. UI supports branch and CLI (codex/claude) selection, configurable install path, logging, and safety checks (aborts on truncated trees). Also add the corresponding .meta file.
* fix namespace
* fix: harden skill installer sync safety (由codex生成)
- Resolve branch head commit SHA via GitHub branches API and use it for snapshot/raw download refs
- Reject unsafe remote relative paths and enforce install-root containment for all file IO
- Handle case-only renames on case-insensitive filesystems during sync planning
- Add managed install-root marker guard to avoid destructive deletes in unmanaged directories
* meta update
* fix: freeze sync inputs and validate install path (由codex生成)
- Snapshot repo/branch/installDir before starting background sync task
- Disable config inputs while sync is running to avoid mid-run mutations
- Validate install directory explicitly with clear errors before filesystem operations
- Scope last-synced-commit key derivation to captured repo/branch values
* Update to incorporate the skill installation into current config
1. Incorporate the Config into a simple one-click in Client Configuration.
2. Simplify the logs to only 1 entry, convenient for LLM checking.
---------
Co-authored-by: Shutong Wu <51266340+Scriptwonder@users.noreply.github.com>
Extract GetUvxDevFlags() and GetUvxDevFlagsList() helpers to
AssetPathUtility, replacing duplicated if/else if/else blocks
across 6 call sites. Add 30-second TTL cache to ShouldUseUvxOffline()
to avoid redundant subprocess spawns. Simplify
ConfigureWithCapturedValues signature from two bools to a single
pre-captured flags string.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When the uvx cache already has the package, pass --offline to skip the
network dependency check that can hang for 30+ seconds on poor connections.
A lightweight probe (uvx --offline ... --help) with a 3-second timeout
determines cache warmth before building the command.
Also fixes stale LogAssert expectations in SetComponentProperties test
to match current error message format from ComponentOps refactor.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Add Cline configurator and auto-select server channel by package version
* Clean up Cline configurator branch: remove useBetaServer param and whitespace noise
- Remove deprecated `useBetaServer` parameter from GetBetaServerFromArgs/List thread-safe overloads
- Strip whitespace-only reformatting from MCPForUnityEditorWindow.cs, keeping only real changes
- Remove stale EditorPrefKeys.UseBetaServer references from CodexConfigHelperTests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>