fix: repair dead camera CLI, add run_tests clear_stuck (#1272), refresh uv.lock - #1293
Conversation
All 18 call sites passed run_command(config, "manage_camera", params) while the signature is run_command(tool, params, config), so the entire `unity-mcp camera` command group was dead at beta HEAD. test_cli.py asserted against call_args[0][2], which encoded the bug rather than catching it; it now asserts the tool name at [0][0] and params at [0][1].
A test job orphaned by a domain reload leaves TestRunStatus pinned with a CurrentJobId that blocks every subsequent run, and there was no way to clear it from the client side. Add clear_stuck to the run_tests MCP tool and --clear-stuck to the editor CLI. Both short-circuit ahead of the init_timeout validation and preflight, because neither applies to clearing and preflight's requires_no_tests gate would reject the very call that exists to release it.
The lockfile pinned mcpforunityserver 10.0.0 while pyproject.toml declared 10.1.0, and no workflow runs `uv lock`, so every contributor's first `uv run` dirtied their working tree.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughCamera CLI commands now use the updated ChangesCamera command dispatch
Stuck test recovery
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant CLI
participant run_tests
participant Unity
CLI->>run_tests: request clear_stuck=True
run_tests->>Unity: send run_tests with clear_stuck=True
Unity-->>run_tests: cleared-job response
run_tests-->>CLI: formatted result
Possibly related PRs
Suggested labels: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
|
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Pull request overview
This PR delivers three independent fixes in the Python Server/ portion of MCP for Unity: (1) repairs broken camera CLI invocation of run_command, (2) exposes a clear_stuck escape hatch for run_tests to unblock orphaned test jobs (issue #1272), and (3) refreshes uv.lock to match the declared server version.
Changes:
- Fix
unity-mcp camera ...subcommands by correctingrun_command(command_type, params, config)argument ordering and strengthening the camera CLI test assertion. - Add
clear_stucksupport to therun_testsMCP tool and the editor CLI (unity-mcp editor tests --clear-stuck), with integration tests verifying forwarding + preflight bypass behavior. - Update
Server/uv.lockto align the lockedmcpforunityserverversion withpyproject.toml.
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| Server/uv.lock | Updates locked package version for mcpforunityserver to 10.1.0. |
| Server/tests/test_cli.py | Adjusts camera CLI test assertions to validate the correct run_command argument order. |
| Server/tests/integration/test_run_tests_async.py | Adds async integration tests covering run_tests(clear_stuck=True) forwarding and preflight bypass. |
| Server/src/services/tools/run_tests.py | Adds clear_stuck parameter with deliberate short-circuit before validation/preflight. |
| Server/src/cli/commands/editor.py | Adds --clear-stuck flag to editor tests CLI command with early-return forwarding. |
| Server/src/cli/commands/camera.py | Fixes run_command argument order for all camera CLI subcommands. |
Comments suppressed due to low confidence (17)
Server/src/cli/commands/camera.py:69
format_output(...)returns a string but this command doesn't print it, sounity-mcp camera listproduces no output. Alsoformat_outputexpects a format type string; passingCLIConfigignoresconfig.format.
result = run_command("manage_camera", {"action": "list_cameras"}, config)
format_output(result, config)
Server/src/cli/commands/camera.py:83
format_output(...)returns a string but this command doesn't print it, sounity-mcp camera brain-statusproduces no output. Alsoformat_outputexpects a format type string; passingCLIConfigignoresconfig.format.
result = run_command("manage_camera", {"action": "get_brain_status"}, config)
format_output(result, config)
Server/src/cli/commands/camera.py:129
- This command formats the response but never prints it (
format_outputreturns a string), so users see no output. It also passesCLIConfigas theformat_typeargument, which ignoresconfig.format.
result = run_command("manage_camera", params, config)
format_output(result, config)
Server/src/cli/commands/camera.py:159
- This command formats the response but never prints it (
format_outputreturns a string), so users see no output. It also passesCLIConfigas theformat_typeargument, which ignoresconfig.format.
result = run_command("manage_camera", params, config)
format_output(result, config)
Server/src/cli/commands/camera.py:193
- This command formats the response but never prints it (
format_outputreturns a string), so users see no output. It also passesCLIConfigas theformat_typeargument, which ignoresconfig.format.
result = run_command("manage_camera", params, config)
format_output(result, config)
Server/src/cli/commands/camera.py:232
- This command formats the response but never prints it (
format_outputreturns a string), so users see no output. It also passesCLIConfigas theformat_typeargument, which ignoresconfig.format.
result = run_command("manage_camera", params, config)
format_output(result, config)
Server/src/cli/commands/camera.py:255
- This command formats the response but never prints it (
format_outputreturns a string), so users see no output. It also passesCLIConfigas theformat_typeargument, which ignoresconfig.format.
result = run_command("manage_camera", params, config)
format_output(result, config)
Server/src/cli/commands/camera.py:290
- This command formats the response but never prints it (
format_outputreturns a string), so users see no output. It also passesCLIConfigas theformat_typeargument, which ignoresconfig.format.
result = run_command("manage_camera", params, config)
format_output(result, config)
Server/src/cli/commands/camera.py:320
- This command formats the response but never prints it (
format_outputreturns a string), so users see no output. It also passesCLIConfigas theformat_typeargument, which ignoresconfig.format.
result = run_command("manage_camera", params, config)
format_output(result, config)
Server/src/cli/commands/camera.py:350
- This command formats the response but never prints it (
format_outputreturns a string), so users see no output. It also passesCLIConfigas theformat_typeargument, which ignoresconfig.format.
result = run_command("manage_camera", params, config)
format_output(result, config)
Server/src/cli/commands/camera.py:383
- This command formats the response but never prints it (
format_outputreturns a string), so users see no output. It also passesCLIConfigas theformat_typeargument, which ignoresconfig.format.
result = run_command("manage_camera", params, config)
format_output(result, config)
Server/src/cli/commands/camera.py:406
- This command formats the response but never prints it (
format_outputreturns a string), so users see no output. It also passesCLIConfigas theformat_typeargument, which ignoresconfig.format.
result = run_command("manage_camera", params, config)
format_output(result, config)
Server/src/cli/commands/camera.py:436
- This command formats the response but never prints it (
format_outputreturns a string), so users see no output. It also passesCLIConfigas theformat_typeargument, which ignoresconfig.format.
result = run_command("manage_camera", params, config)
format_output(result, config)
Server/src/cli/commands/camera.py:457
- This command formats the response but never prints it (
format_outputreturns a string), so users see no output. It also passesCLIConfigas theformat_typeargument, which ignoresconfig.format.
result = run_command("manage_camera", params, config)
format_output(result, config)
Server/src/cli/commands/camera.py:471
format_output(...)returns a string but this command doesn't print it, sounity-mcp camera releaseproduces no output. Alsoformat_outputexpects a format type string; passingCLIConfigignoresconfig.format.
result = run_command("manage_camera", {"action": "release_override"}, config)
format_output(result, config)
Server/src/cli/commands/camera.py:527
- This command formats the response but never prints it (
format_outputreturns a string), so users see no output. It also passesCLIConfigas theformat_typeargument, which ignoresconfig.format.
result = run_command("manage_camera", params, config)
format_output(result, config)
Server/src/cli/commands/camera.py:554
- This command formats the response but never prints it (
format_outputreturns a string), so users see no output. It also passesCLIConfigas theformat_typeargument, which ignoresconfig.format.
result = run_command("manage_camera", params, config)
format_output(result, config)
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| result = run_command("manage_camera", {"action": "ping"}, config) | ||
| format_output(result, config) |
Generated by tools/generate_docs_reference.py; the "Check docs reference is fresh" CI job flagged testing/run_tests.md as stale after clear_stuck was added.
Follow-up to the inverted-argument fix in this branch: repairing the run_command call order was necessary but not sufficient, and the group was still effectively dead. format_output(data, format_type: str = "text") returns a string. All 18 call sites called format_output(result, config) and dropped the return value, so every `unity-mcp camera` subcommand printed nothing at all. Passing the whole CLIConfig where a format string was expected also meant the branch always fell through to text, silently ignoring --format/UNITY_MCP_FORMAT. Use click.echo(format_output(result, config.format)), matching every other command module. Adds two regression tests: one asserting the group emits non-empty output, one asserting --format json yields parseable JSON. Both fail without this change. Reported by Copilot on CoplayDev#1293.
Three small, independent
Server/fixes, kept as three separate commits so they can be reviewed — or dropped — individually.1.
fix:the camera CLI is completely dead atbetaHEADrun_command's signature isrun_command(tool, params, config). All 18 call sites inServer/src/cli/commands/camera.pypassrun_command(config, "manage_camera", params)— arguments inverted. Every singleunity-mcp camerasubcommand fails.This was not caught because
Server/tests/test_cli.pyasserted againstcall_args[0][2], which encoded the bug rather than detecting it. The test now asserts the tool name at[0][0]and params at[0][1], so the inversion cannot come back silently.Found during triage, not attached to an existing issue.
2.
feat:clear_stuckescape hatch forrun_tests(fixes #1272)A test job orphaned by a domain reload leaves
TestRunStatuspinned with aCurrentJobIdthat blocks every subsequent run, with no client-side way to release it.Adds
clear_stuckto therun_testsMCP tool and--clear-stuckto the editor CLI, for parity.Both short-circuit ahead of the
init_timeoutvalidation andpreflight. That ordering is deliberate and is the whole point:preflight'srequires_no_tests=Truegate would otherwise reject the very call that exists to clear the orphaned job blocking it.Reproduced live — an orphan showed
TestRunStatus.IsRunning = FalsewithCurrentJobIdstill set, andClearStuckJob()returnedcleared=True.Four tests cover it: the flag is forwarded alone as
{"clear_stuck": True}, preflight is bypassed (monkeypatched to raise), an invalidinit_timeoutis ignored on the clear path, and the normal path still preflights.3.
chore:refreshuv.lockThe lockfile pinned
mcpforunityserver = 10.0.0whilepyproject.tomldeclared10.1.0, and no workflow runsuv lock. Every contributor's firstuv runtherefore dirtied their working tree with an unrelated lockfile diff.Worth considering a CI check so this cannot drift again.
Tests
cd Server && uv run pytest tests/— 1334 passed, 3 skipped.No Unity-side changes in this PR.
Summary by CodeRabbit
--clear-stuckoption to the editor test command to clear an orphaned running Unity test job instead of starting a new run.clear_stuckto verify Unity requests, preflight bypass, and standard behavior when the option is not provided.run_teststool reference to document the newclear_stuckparameter.