chore(deps): upgrade Unity MCP to 0.90.0 and add the ten extension packages - #175
Merged
Conversation
…ckages Moves com.ivanmurzak.unity.mcp from 0.87.0 to 0.90.0 and pulls in the nine extension packages that were not installed before (inputsystem, navigation, animation, cinemachine, probuilder, particlesystem, splines, terrain, tilemap) alongside the timeline bump. The MCP surface goes from core-only to 187 tools, 46 prompts, 2 resources and 1 resource template. 0.88.0 was skipped: it could not compile, because a stale dependency gate let Unity build the new sources against the previous McpPlugin DLLs. 0.90.0 carries the fix, which is what the new UNITY_MCP_DEPS_3 define in ProjectSettings is for: a generation-numbered gate that a stale install cannot satisfy. ProjectSettings/Packages/com.unity.probuilder/Settings.json and ShaderGraphSettings.asset are Unity-generated and arrive with the new packages.
Nghaiz
added a commit
that referenced
this pull request
Aug 25, 2026
…cent file `com.ivanmurzak.unity.mcp` 0.90.0 and its ten extension packages (#175) installed McpPlugin.dll and McpPlugin.Common.dll with `defineConstraints: []`, while every other DLL of the same closure -- R3, ReflectorNet, SignalR, Microsoft.CodeAnalysis -- carried `- UNITY_EDITOR`. McpPlugin.dll references R3, so a player build included the first, excluded the second, and UnityLinker died with Mono.Cecil.AssemblyResolutionException: Failed to resolve assembly: 'R3' which names R3, the file that is correct, and never names McpPlugin.dll, the file that is wrong. Two .meta lines fix it: same tree, same command, Failure -> Success. Never only a compile problem. defineConstraints are evaluated per target and UNITY_EDITOR is false in every player, so the shipping Linux dedicated server was equally unbuildable -- and a build that HAD linked would have carried an HTTP bridge hosting Roslyn into the game server image, the exact thing EditorBuild.StripEditorOnlyDefines was written to prevent. Nothing in CI could see it: no job builds a Unity player, images.yml downloads a pre-built Linux artifact from a release, and build-test is `dotnet build` over the pure-.NET libraries, which never reads Assets/Plugins. Four days, unnoticed. And because these .meta files are generated by the MCP package's own NuGet installer, the next upgrade would have silently undone a hand-fix. So the fix ships with the gate. check-plugin-define-constraints.ps1 reads the bridge's package list from .nuget-installed.json rather than hardcoding DLL names, so a fourth bridge DLL is covered the day it lands. Mutation-proved, one fault, one mutant, one red: reverting McpPlugin.dll.meta turns it red naming that exact file. A first version of the gate was wrong in a way worth recording. It walked assembly references and failed any player-included plugin referencing an editor-only one -- 22 violations against a tree whose build succeeds. The BCL shims in that folder reference each other, and in a player those names resolve against Unity's own netstandard2.1 profile, not the excluded plugin copies (the same fact build-libs.ps1 records from the other direction). Separating a real break from a backfilled shim needs the Editor's playback-engine assembly set, which CI does not have. That gate would have blocked every PR on day one. The shipped one answers the narrower question truthfully, and its header says which question it declines.
Nghaiz
added a commit
that referenced
this pull request
Aug 25, 2026
* fix(client): no player could be built, and the linker blamed the innocent file `com.ivanmurzak.unity.mcp` 0.90.0 and its ten extension packages (#175) installed McpPlugin.dll and McpPlugin.Common.dll with `defineConstraints: []`, while every other DLL of the same closure -- R3, ReflectorNet, SignalR, Microsoft.CodeAnalysis -- carried `- UNITY_EDITOR`. McpPlugin.dll references R3, so a player build included the first, excluded the second, and UnityLinker died with Mono.Cecil.AssemblyResolutionException: Failed to resolve assembly: 'R3' which names R3, the file that is correct, and never names McpPlugin.dll, the file that is wrong. Two .meta lines fix it: same tree, same command, Failure -> Success. Never only a compile problem. defineConstraints are evaluated per target and UNITY_EDITOR is false in every player, so the shipping Linux dedicated server was equally unbuildable -- and a build that HAD linked would have carried an HTTP bridge hosting Roslyn into the game server image, the exact thing EditorBuild.StripEditorOnlyDefines was written to prevent. Nothing in CI could see it: no job builds a Unity player, images.yml downloads a pre-built Linux artifact from a release, and build-test is `dotnet build` over the pure-.NET libraries, which never reads Assets/Plugins. Four days, unnoticed. And because these .meta files are generated by the MCP package's own NuGet installer, the next upgrade would have silently undone a hand-fix. So the fix ships with the gate. check-plugin-define-constraints.ps1 reads the bridge's package list from .nuget-installed.json rather than hardcoding DLL names, so a fourth bridge DLL is covered the day it lands. Mutation-proved, one fault, one mutant, one red: reverting McpPlugin.dll.meta turns it red naming that exact file. A first version of the gate was wrong in a way worth recording. It walked assembly references and failed any player-included plugin referencing an editor-only one -- 22 violations against a tree whose build succeeds. The BCL shims in that folder reference each other, and in a player those names resolve against Unity's own netstandard2.1 profile, not the excluded plugin copies (the same fact build-libs.ps1 records from the other direction). Separating a real break from a backfilled shim needs the Editor's playback-engine assembly set, which CI does not have. That gate would have blocked every PR on day one. The shipped one answers the narrower question truthfully, and its header says which question it declines. * docs(replication): X-20: the linecast blocked nothing, the shot threads a body seam The row said the collider NAME would decide between two readings -- terrain or a building for real cover, the victim's own body for the mask-2049 reading. It is neither, because there was no occlusion to name. artifacts/lane-b/x20-occlusion-01, spawn pinned to slot 0, 3 of 3 clients exit 0: 240 trigger frames, every one occlusionHit[none-this-shot], occluded=0 presentFallbacks=0 resolved=6 hits=0, victim on 100 health at all 7 checkpoints. `none-this-shot` is the freshness path added on 2026-08-25, not a default -- the instrument worked and reported that the thing it was built to describe did not happen. This does NOT retroactively settle the baseline. x19-fixed-04 held at 10.1 m on an unpinned spawn; this run stands at 4.7 m pinned. Different geometry, so the question is retired rather than won, and both readings die for this run rather than one winning. What the run exposed instead. Everything upstream is now correct and the artifact says so: present.torso == frame.torso to seven digits, frame.tick == wanted.tick, aim.resolved on actor 42 at 4.65 m, nothing in the way. And the shot still misses. HitboxSet.FromSize stops torso AND arms at 1.550 and starts head at 1.580, so nothing covers 1.550..1.580 -- a 3 cm seam across a standing body. A ray through it returns Miss before the occlusion test runs, which is exactly why occluded stays 0. The logged ray arrives 1.5684 m above the target's feet, inside the seam. ScriptedTargetSolver raises BOTH endpoints by EYE_HEIGHT 1.6, which is 0.02 m inside the head box's lower edge rather than centre of mass -- so the aim point is 1.6 m at every range and the margin is two centimetres everywhere. Stated honestly, because the arithmetic has a limit: the seam is a fact of the source and needs no run. That THIS ray threaded it is derived from a log line whose aim is rounded to two decimals, and +/-0.005 in y is +/-0.024 m at 4.74 m -- wider than the seam. Consistent, not proven. Next measurement, one line: LagCompensator.Resolve already loops all four boxes; on a miss, record the nearest box and its signed miss distance instead of discarding them. The same move 3F.1 made for X-19 and #180 made for occlusion. Fix nothing before it exists -- widening a hitbox is a balance change, and guessing at 0.03 m is how a box stops matching the mesh. Filed rather than fixed, per phase-3 section 6: X-24 the 3 cm torso/head seam. A game defect: a human aiming at chest-to-chin height on a standing body gets the same nothing. X-25 the aim point. A harness defect, and the reason the seam is hit every time rather than occasionally -- it is why no lane-B combat run has ever scored a hit. Also recorded, not filed: the shooter held SL_DEFENDER (clip 8, cooldown 1.5 s) while both observers held RK44 (clip 30). Nothing in the programme selects a weapon, so the loadout follows the slot the server hands out and pinning the spawn changed which slot that was. The catalog is applied correctly -- 8-round clip and 1.5 s cadence to the value -- but two combat runs are not comparable shot-for-shot until the weapon is pinned too. * docs(ci): require-status-check is on, and the reason it was off is gone This page declined to require build-test because build-test was red, and build-test stayed red because nothing required anyone to look -- eleven merges onto a red develop. X-23 (#178) and #181 fixed the red, so the condition the page set for itself was met and the rule is now on. Done in the order section 1 asks for, with each step checked rather than assumed: the red fixed, build-test watched green once on develop at 76734c5, the two check names read back from GET /commits/{sha}/check-runs rather than copied off this page, and ci.yml confirmed to run on pull_request with no workflow-level paths filter -- the deadlock this page warns about twice. Added to the existing protect-shared-branches ruleset so main and develop stay one object rather than two that drift. Verified after the write by asking which rules apply to each ref rather than trusting the PUT: both shared branches return deletion, non_fast_forward, required_status_checks; a feature branch returns none. Two consequences recorded before they surprise someone. A direct push to main or develop is now refused -- a fresh commit has no checks and there is no bypass -- which suits a PR-only workflow and would block a hotfix pushed straight at the branch. And with no bypass actor, a CI outage blocks merging entirely; that is section 1's deliberate choice, not an oversight. Not proven, only configured, and the page says so -- the same caveat the force-push row already carries. Nobody has opened a PR with a FAILING build-test and watched the merge refuse. What is observed is the positive half. Two rules stay off, with reasons rather than silence. Required approvals would deadlock a single-owner repository, since GitHub forbids approving your own PR -- section 2's one-approval row was written for the four-person team. And strict (up-to-date) mode costs an update-and-re-run on every PR that lands after another, to prevent a failure that has not happened here; the eleven-merge streak was a branch nobody was required to look at, which is what this change fixes. * docs(replication): X-20 closed and handed its position to the defect it hid The plan called X-20 "the only thing between here and 3D — a RUN away, not an investigation away". The run happened. X-20 is closed and the arrow did not shorten: X-25 now occupies that position, and it is the same shape of work, one harness edit rather than an investigation. So `X-20 ──▶ 3D` becomes `X-25 ──▶ 3D`. X-24 (the 3 cm torso/head seam) is a game defect routed to phase 6 and deliberately NOT a blocker for 3D — X-25 stops the harness aiming into the seam, which is exactly why X-24 needs its own row rather than vanishing when the runs go green. Also corrects a claim this plan has been carrying: that the pinned re-run yields "3D's 11 verdicts". It does not. tools/lane-b/ holds combat-* and smoke and nothing else, and the combat programmes contain no grenade step and no vehicle step, so checks 4, 7, 9 and 12 are not exercised by a `-Set combat` run at all — check 7 also needs `-Sim typical`, which it does not pass. A combat run can grade checks 1, 2, 3, 5, 6 and 13. A vehicle programme set does not exist yet and is unbuilt work; AC-2 grades all eleven, so it belongs in 3D's scope rather than being rediscovered at verdict time. * docs(replication): say which half of the MCP finding was run and which was derived The report claimed the shipping Linux dedicated server "was equally unbuildable". The mechanism is sound -- defineConstraints are evaluated per target, UNITY_EDITOR is false in every player, and these .meta files carry no Server-specific platform entry -- but no server build was attempted, so that sentence asserted as measured something only reasoned. What IS measured: the Windows player's linker input listed McpPlugin.dll and McpPlugin.Common.dll among its allowed assemblies and did not list R3. Reworded to separate the two, in the same shape the section 2 verdict already uses for the ray arithmetic. The fix does not change either way, which is why this is a wording correction and not a reason to run a Linux toolchain today.
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.
Brings the Unity MCP plugin from 0.87.0 to 0.90.0 and installs the nine extension packages the project did not have, alongside the timeline bump.
The MCP surface the Editor now exposes, enumerated live rather than read off the manifest:
New extensions: inputsystem, navigation, animation, cinemachine, probuilder, particlesystem, splines, terrain, tilemap.
Why 0.88.0 was skipped
0.88.0 does not compile.
UNITY_MCP_READYrecorded only that the dependency resolver had run, never which DLL set it restored, so an upgrade saw "already installed", skipped the restore, and Unity built the new sources against the old McpPlugin DLLs. The resulting compile failure then blocked the domain reload, so the resolver could never run and unstick itself. Upstream fixed it in IvanMurzak/Unity-MCP#958 by moving the gate into a generation-numbered asmdef define that a stale install cannot satisfy.That is what the
UNITY_MCP_DEPS_3addition inProjectSettings.assetis. It is not a stray edit.Files
ProjectSettings/Packages/com.unity.probuilder/Settings.jsonandShaderGraphSettings.assetare Unity-generated and arrive with the new packages.The second commit adds the BTL description document under
tmp/, unrelated to the upgrade.Verified
Unity 6000.3.21f1, plugin 0.90.0, server 9.2.5. Editor compiles clean, MCP connects, and all 187 tools are reachable. Smoke-tested
unity-tool-list,editor-application-get-state,console-get-logsand resource enumeration against the live Editor.One known defect rides along:
console-clear-logsstill fails whenever a Unity Asset Import Worker holds the log file open. Root-caused and fixed upstream in IvanMurzak/Unity-MCP#967; useUnityEditor.LogEntries.Clear()until that merges.