Skip to content

fix: read_console severity, screenshot color space, execute_code assembly leak, manage_scene package paths - #1353

Merged
Scriptwonder merged 7 commits into
CoplayDev:betafrom
Scriptwonder:fix/console-severity-screenshot-color-execute-code-cache
Sep 1, 2026
Merged

Scriptwonder merged 7 commits into
CoplayDev:betafrom
Scriptwonder:fix/console-severity-screenshot-color-execute-code-cache

Conversation

@Scriptwonder

@Scriptwonder Scriptwonder commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Six triaged quick-fix issues, batched because each is small and they touch disjoint files. Happy to split into separate PRs if you'd rather review them independently — the commits are already separated one-per-issue, so git cherry-pick is clean.

Every issue below was verified against the current code rather than taken at the reporter's word; two reports turned out to have the wrong diagnosis (noted inline).


fix(read_console): correct the LogEntry.mode bit table — closes #1348

The reporter suspected a Unity 6000.5-specific bit shift. It isn't version-specific — the table was simply wrong, and had been since it was written.

The constants never matched UnityEditor.ConsoleWindow.Mode:

table said Unity's actual value
1 << 2 Warning Log
ScriptingError 1 << 9 1 << 8
ScriptingWarning 1 << 10 1 << 9
ScriptingLog 1 << 11 1 << 10

So Logs surfaced as Warnings and Warnings as Errors. Entries carrying only ScriptingError matched nothing in the table and were classified correctly only by accident — InferTypeFromMessage finding the literal "LogError" in the appended stack trace.

The reporter's three reflected samples are each independently consistent with that off-by-one, which is what confirmed it.

Replaces the table with Unity's real values and rewrites GetLogTypeFromMode to test Exception and Assert before the error mask, since Unity sets the Error bit alongside both. 15 mapping test cases added, including the two modes captured from a live 6000.5.4f1 console.

fix(screenshot): match downscale RenderTexture color space to the source — closes #1328

The reporter guessed this was server-side. There is no Python-side resize at all — no PIL anywhere in Server/src.

DownscaleTexture called RenderTexture.GetTemporary(...) without a RenderTextureReadWrite argument, so it defaulted to Default = sRGB in a Linear-colorspace project. Graphics.Blit then sampled the linear-flagged capture with no decode while the sRGB target applied the encode on store:

11/255 → 1.055 * (11/255)^(1/2.4) - 0.055 → 60

which is exactly the value reported. The direct EncodeToPNG path never goes through DownscaleTexture — precisely why the on-disk PNG was correct and only the inline preview was washed out.

The temp RT and the destination Texture2D now both follow the source's color space. GraphicsFormatUtility.IsSRGBFormat and Texture.graphicsFormat are both 2019.1+, so no compat shim is needed.

Note: the regression only reproduces in a Linear-colorspace project; in Gamma the new tests assert the already-correct identity round-trip. They self-skip under -nographics.

fix(execute_code): cache compiled assemblies — closes #1351

Every call Assembly.Load()s a fresh in-memory MCPDynamic image, and Mono cannot unload a non-collectible assembly, so the count only dropped at domain reload. The existing caches (_cachedAssemblyPaths, RoslynCompiler.ResetCache) hold reference paths, not compiled output — #d2247e94 addressed paths, not this.

Caches the compiled assembly keyed on compiler + wrapped source, cleared in the existing OnDomainReload() alongside the path caches, and capped at 64 entries so a stream of genuinely distinct snippets cannot itself become the leak.

Honest limit: distinct snippets still accumulate until the next domain reload. That's a Mono constraint, not something fixable in-process. This fixes the repeated-identical-snippet case, which is the one users actually hit.

feat(manage_scene): accept Packages/ paths — closes #1197

HandleCommand stripped any leading Assets/ and re-rooted the remainder under Application.dataPath, so Packages/com.foo/Samples/X.unity was rewritten to Assets/Packages/com.foo/Samples/X.unity and could never resolve.

Paths are now rooted at Assets or Packages. The existence checks in LoadScene/LoadSceneAdditive move from File.Exists to the AssetDatabase — ManageAsset.cs:165 already carries the comment "Virtual paths like 'Packages/...' don't work with File.Exists()", so the correct pattern was already in the codebase; this reuses it rather than inventing one.

One correction found while self-reviewing: the first pass replaced File.Exists with the AssetDatabase lookup, which fixed Packages/ but narrowed Assets/ — the AssetDatabase does not know about a scene file until it is imported, so a scene written by an external tool before a refresh would have become unloadable. The check now accepts either answer. The guard exists only to give a clearer error than EditorSceneManager.OpenScene would, so accepting is the safe direction; SceneAssetExists_FindsUnimportedFileOnDisk pins it.

@camnewnham volunteered to test this on the issue.

docs: two reported documentation gaps — closes #1220, #1219


Verification

  • Python: uv run pytest tests/ — 1374 passed, 3 skipped.
  • Unity 2021.3.45f2 (package floor): tools/check-unity-versions.sh compile-check passed.
  • Unity 6000.4.11f1: compile-check passed, 0 CS errors, Csc confirmed rebuilding both MCPForUnity.Runtime.dll and MCPForUnity.Editor.dll.
  • 2022.3.62f1 and 6000.0.75f1 aren't installed locally — leaving those to CI.

New tests: 15 read_console severity-mapping cases, 3 ScreenshotUtility downscale cases, 2 execute_code cache cases, 11 manage_scene package-path cases (all 11 pass on 6000.4.11f1).

@coderabbitai

coderabbitai Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@Scriptwonder
Scriptwonder force-pushed the fix/console-severity-screenshot-color-execute-code-cache branch 2 times, most recently from 5129ed1 to 83bffb4 Compare August 31, 2026 21:57
The constants never matched UnityEditor.ConsoleWindow.Mode. 1<<2 is Unity's
Log bit but was labelled Warning, and every scripting bit was off by one
(ScriptingError is 1<<8, not 1<<9). Logs surfaced as Warnings and Warnings
as Errors; entries carrying only ScriptingError matched nothing in the table
and were classified by InferTypeFromMessage finding "LogError" in the
appended stack trace.

Replaces the table with Unity's real values and rewrites GetLogTypeFromMode
to check Exception and Assert before the error mask, since Unity sets the
Error bit alongside both.

Fixes CoplayDev#1348
DownscaleTexture called RenderTexture.GetTemporary without a
RenderTextureReadWrite argument, so it defaulted to sRGB in a Linear
colorspace project. Graphics.Blit then sampled the linear-flagged capture
with no decode while the target applied the encode on store, turning 11 into
60 exactly as reported. The direct EncodeToPNG path never goes through
DownscaleTexture, which is why the on-disk PNG was correct and only the
inline preview was washed out.

Fixes CoplayDev#1328
… call

Every invocation emitted a fresh in-memory "MCPDynamic" assembly via
Assembly.Load, and Mono cannot unload a non-collectible assembly, so the
count only dropped at domain reload. The existing caches hold reference
paths, not compiled output.

Caches the compiled assembly keyed on compiler + wrapped source, cleared on
domain reload alongside the path caches and capped at 64 entries so a stream
of distinct snippets cannot become the leak itself. Distinct snippets still
accumulate until the next reload; that is a Mono limitation.

Fixes CoplayDev#1351
HandleCommand stripped any leading Assets/ and re-rooted the remainder under
Application.dataPath, so Packages/com.foo/Samples/X.unity became
Assets/Packages/com.foo/Samples/X.unity and could never resolve.

Paths are now rooted at Assets or Packages, and the existence checks in
LoadScene/LoadSceneAdditive move from File.Exists to the AssetDatabase --
the pattern ManageAsset.cs already documents, and the only one that works
for packages resolved through Library/PackageCache.

Fixes CoplayDev#1197
Two reported documentation gaps:

- resources/read takes a server key separate from the mcpforunity:// URI.
  Codex exposes tools as mcp__unityMCP__* but wants server: "unityMCP" on a
  resource read, which the server instructions never mentioned. Distinct
  from the name-vs-URI mistake CoplayDev#1302 fixed.
- com.unity.ai.assistant can livelock AssetDatabase::InitialRefresh on Unity
  6000.5.x, before any MCP assembly loads, which presents as an MCP
  connection failure. Documents the packages-lock.json deletion people miss.

Fixes CoplayDev#1220
Fixes CoplayDev#1219
The reference pages are generated from the Python annotations by
tools/generate_docs_reference.py; the hand-edited row drifted from what the
generator emits, failing the Docs -- Reference Drift Check.
Swapping File.Exists for an AssetDatabase lookup fixed Packages/ resolution but
narrowed Assets/: the AssetDatabase does not know about a scene file until it is
imported, so a scene written by an external tool before a refresh became
unloadable where it previously opened.

Accept either answer. The AssetDatabase is the only one that resolves
Packages/... (embedded packages live in Library/PackageCache); File.Exists still
covers the not-yet-imported case. The guard only exists to produce a clearer
error than EditorSceneManager.OpenScene would, so accepting is the safe
direction.
@Scriptwonder
Scriptwonder force-pushed the fix/console-severity-screenshot-color-execute-code-cache branch from 83bffb4 to 1a1566e Compare August 31, 2026 22:52
@Scriptwonder
Scriptwonder marked this pull request as ready for review September 1, 2026 15:45
Copilot AI lite review requested due to automatic review settings September 1, 2026 15:45
@Scriptwonder
Scriptwonder merged commit 3d40864 into CoplayDev:beta Sep 1, 2026
9 checks passed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR batches several targeted fixes across the Unity Editor package, Python server tool metadata, tests, and website docs to improve correctness and usability of core MCP-for-Unity workflows (console reading, screenshots, execute_code, and scene path handling).

Changes:

  • Fixes read_console severity classification by correcting LogEntry.mode bit mappings and updating the mode→LogType precedence; adds mapping tests.
  • Fixes downscaled inline screenshot previews in Linear color-space projects by matching RenderTexture/Texture2D color space to the source; adds downscale tests.
  • Adds Packages/ support to manage_scene path handling (plus AssetDatabase-aware existence checks) and updates docs/tests accordingly; adds execute_code compiled-assembly caching and tests; updates troubleshooting/instructions docs for Codex resource server key naming and Unity AI Assistant import hang.

Reviewed changes

Copilot reviewed 12 out of 14 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
website/docs/reference/tools/core/manage_scene.md Documents Packages/-rooted scene paths and adds a package-scene load example.
website/docs/guides/troubleshooting.md Adds troubleshooting entries for Unity 6.5 AI Assistant import hang and Codex resources/read server-key mismatch.
TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ScreenshotUtilityDownscaleTests.cs.meta New meta for downscale tests.
TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ScreenshotUtilityDownscaleTests.cs Adds coverage for downscale color-space correctness and non-upscale behavior.
TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ReadConsoleTests.cs Adds test cases validating LogEntry.mode severity mapping and precedence.
TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageScenePackagePathTests.cs.meta New meta for manage_scene package path tests.
TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageScenePackagePathTests.cs Adds tests for Packages/ rooting and AssetDatabase/disk existence behavior.
TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ExecuteCodeTests.cs Adds tests asserting assembly reuse for identical snippets and independence for different snippets.
Server/src/services/tools/manage_scene.py Updates tool parameter description to mention Assets/ and Packages/ roots.
Server/src/main.py Updates server instructions to clarify Codex’s resource server key vs mcpforunity:// resource URIs.
MCPForUnity/Runtime/Helpers/ScreenshotUtility.cs Fixes downscale path to preserve the source texture’s color space when blitting/reading back.
MCPForUnity/Editor/Tools/ReadConsole.cs Corrects mode-bit constants and improves severity inference precedence.
MCPForUnity/Editor/Tools/ManageScene.cs Adds Packages/ rooting support and replaces file existence checks with AssetDatabase-aware logic.
MCPForUnity/Editor/Tools/ExecuteCode.cs Adds a compiled-snippet cache to reduce repeated assembly loads for identical snippets.
Files not reviewed (2)
  • TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageScenePackagePathTests.cs.meta: Generated file
  • TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ScreenshotUtilityDownscaleTests.cs.meta: Generated file

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines 178 to 182
@@ -180,6 +182,11 @@ public static object HandleCommand(JObject @params)
{
Comment on lines 204 to +208
string wrappedSource = WrapUserCode(code);

string cacheKey = compiler + "\n" + wrappedSource;
if (_compiledCache.TryGetValue(cacheKey, out CompiledSnippet cached))
return InvokeCompiled(cached.Assembly, cached.Compiler);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants