1721 Commits

Author SHA1 Message Date
github-actions[bot] c21bf496bc Merge pull request #1321 from CoplayDev/beta-version-10.1.3-beta.4-31207888075
chore: update Unity package to beta version 10.1.3-beta.4
2026-08-07 18:49:57 +00:00
GitHub Actions eb64a223ca chore: update Unity package to beta version 10.1.3-beta.4 2026-08-07 18:49:52 +00:00
Shutong Wu 270463cefb Merge pull request #1320 from CoplayDev/fix/stdio-configurable-command-timeout
fix: make stdio bridge command timeout configurable (default 5m)
2026-08-07 14:38:28 -04:00
Andriy Mykhaylyshyn 7997788edb fix: reject non-finite timeout env overrides; test env paths
Address CodeRabbit review on #1320:

- _env_float now requires math.isfinite(value): "inf"/"Infinity"/"1e309"/
  "nan" are positive-or-parseable but would produce unusable socket/timeout
  behaviour, so they now fall back to the default like other invalid input.
- test_config_default_values clears the two env vars first so ambient env
  can't mask the defaults.
- Added coverage for valid overrides and for invalid/zero/negative/
  non-finite values falling back to defaults.
2026-08-07 21:25:58 +03:00
Andriy Mykhaylyshyn d8d06cbd5a fix: make stdio bridge command timeout configurable (default 5m)
Long-running tool calls (asset imports, test runs, batched edits) were
cut off ~30-90s into execution, so the task could never finish. On the
stdio transport this was governed by hardcoded values on both hops:

- Unity side: StdioBridgeHost.FrameIOTimeoutMs (30s const) capped every
  command's execution and frame I/O; on timeout the client reconnected
  and re-sent, which force-closed the prior client and made the bridge
  restart on a new port (the repeated "StdioBridgeHost started on port
  6400/6402" churn).
- Server side: ServerConfig.connection_timeout (30s socket recv) and
  command_total_timeout (90s cross-retry ceiling) cut the command off
  first.

Unlike the WebSocket transport (WebSocketTransportClient reads a per-call
timeout off the wire), the stdio bridge had no way to raise these.

Make all three configurable with a 5-minute default:
- FrameIOTimeoutMs: 30s -> 300s, env UNITY_MCP_STDIO_COMMAND_TIMEOUT_MS.
  ReceiveTimeout now scales with it (max(60s, timeout)).
- connection_timeout: 30s -> 300s, env UNITY_MCP_CONNECTION_TIMEOUT.
- command_total_timeout: 90s -> 600s, env UNITY_MCP_COMMAND_TOTAL_TIMEOUT.

Invalid/non-positive env values fall back to the default so a bad
override can't disable the timeout. Updates the config characterization
test to the new defaults.
2026-08-07 21:00:55 +03:00
github-actions[bot] 9f84072c38 Merge pull request #1317 from CoplayDev/beta-version-10.1.3-beta.3-30827275259
chore: update Unity package to beta version 10.1.3-beta.3
2026-08-03 15:35:27 +00:00
GitHub Actions 061af62f31 chore: update Unity package to beta version 10.1.3-beta.3 2026-08-03 15:35:22 +00:00
Shutong Wu 5595c7be99 Merge pull request #1300 from kpkhxlgy0/codex/codedom-assembly-dedup
fix: deduplicate CodeDom assembly references
2026-08-03 11:23:34 -04:00
XiaoLongHan d2247e942e perf: cache CodeDom assembly paths 2026-08-03 14:42:32 +08:00
github-actions[bot] 84dfa7639c Merge pull request #1315 from CoplayDev/beta-version-10.1.3-beta.2-30767776542
chore: update Unity package to beta version 10.1.3-beta.2
2026-08-02 21:35:14 +00:00
GitHub Actions 3b17083080 chore: update Unity package to beta version 10.1.3-beta.2 2026-08-02 21:35:09 +00:00
Shutong Wu 8bf889cf50 Merge pull request #1250 from beast-ofcourse/fix/execute-code-bom-phantom-error
fix(execute_code): skip phantom CodeDom BOM error from mcs compiler
2026-08-02 17:23:27 -04:00
Shutong Wu 054674d5de Merge pull request #1314 from Scriptwonder/fix/ci-compile-check
ci: license-free compile check on every PR (incl. forks)
2026-08-02 17:05:15 -04:00
Shutong Wu 73c71bc988 ci: add license-free compile check for every PR
Every PR to this repo comes from a fork -- including maintainers', who
work from Scriptwonder/unity-mcp. GitHub withholds secrets from runs
triggered by a fork's pull request, so unity-tests.yml skips and reports
a green check having compiled nothing. Across the last 60 runs of that
workflow: 51 pull_request (all skipped), 9 pull_request_target, and zero
push/workflow_call. No PR has ever been compile-verified.

Unity refuses to open a project without an activated license, so there is
no way to compile via the Editor without secrets. This sidesteps that: it
never launches Unity. It pulls the PUBLIC unityci/editor image purely to
read reference assemblies out of it, and drives Roslyn -- Unity's own
bundled csc -- directly. A compiler needs no license.

Compiles MCPForUnity.Runtime and MCPForUnity.Editor for win, osx and
linux. The existing Unity matrix is linux-only, so the UNITY_EDITOR_WIN
and UNITY_EDITOR_OSX branches have never been compiled anywhere in CI.

Runtime targets netstandard2.1 and Editor targets .NET 4.8, matching what
Unity does; feeding both BCLs to one compile double-defines System.Object.

Reference manifests and defines are captured from Unity's generated
csprojs rather than globbed: Editor/Data holds the whole .NET 4.8 BCL plus
vendored libraries Unity deliberately does not reference (ExCSS.Unity
redefines System.Tuple, cscompmgd.dll redefines Microsoft.CSharp.
CompilerError). Both need regenerating when defaultVersion changes.

Verified locally against 2021.3.45f2: all six compiles pass, and a probe
error behind #if UNITY_EDITOR_OSX fails the osx pass with exit 1 while
win and linux stay green.

This does not replace unity-tests.yml -- it compiles, it does not run
tests.
2026-08-02 16:51:19 -04:00
github-actions[bot] 95cad6c247 Merge pull request #1313 from CoplayDev/sync/main-v10.1.2-into-beta-30766000799
chore: sync main (v10.1.2) into beta
2026-08-02 20:48:26 +00:00
GitHub Actions 7b8f7f0823 chore: set beta version to 10.1.3-beta.1 after release v10.1.2 2026-08-02 20:48:20 +00:00
GitHub Actions 8cb11dbce8 chore: sync main (v10.1.2) into beta 2026-08-02 20:48:20 +00:00
Shutong Wu 4ce7dd3cc5 Merge pull request #1312 from CoplayDev/release/v10.1.2
chore: bump version to 10.1.2
v10.1.2
2026-08-02 16:48:02 -04:00
Shutong Wu 0f397d65dd Merge pull request #1311 from Scriptwonder/docs/multi-agent-http-findings
docs: record multi-agent HTTP behavior in routing docs
2026-08-02 16:47:42 -04:00
GitHub Actions 1ad15ae0c4 chore: bump version to 10.1.2 2026-08-02 20:47:32 +00:00
Shutong Wu 384dd45065 docs: record multi-agent HTTP behavior in routing docs
Measured four concurrent agents against one Editor over the HTTP
transport (527 client calls, 1498 commands through the bridge at
97.9% success). The Editor stayed healthy throughout, so the notes
below are about degradation modes, not failure.

Guide gains a section on running several agents at once: a single
Editor executes one command at a time, so reads stretched from ~5s
to ~17s behind another agent's writes and batching bought nothing
(~2-3s per call regardless of batch size). Also documents that
'Available: none' is a transient reconnect artifact rather than an
absent Editor, and tabulates when a failed call is safe to retry.

Architecture doc records two gaps found while measuring. Instance
resolution runs before dispatch and hard-fails while the registry
is briefly empty during a domain reload, which was roughly seven in
ten client-visible errors. And a timed-out command is not cancelled
in Unity: send_command pops the pending future, so a command already
executing runs to completion and its result is discarded, reporting
failure for an effect that landed. Commands still queued when the
socket drops are lost cleanly instead.

Also corrects the claim that throughput had not been measured; the
numbers support the existing no-broker decision, since serialization
comes from Unity's single-threaded main loop rather than the layer a
broker would occupy.
2026-08-02 16:41:24 -04:00
github-actions[bot] c36b0e8570 Merge pull request #1310 from CoplayDev/beta-version-10.1.1-beta.6-30765582021
chore: update Unity package to beta version 10.1.1-beta.6
2026-08-02 20:36:50 +00:00
GitHub Actions ee0bf57095 chore: update Unity package to beta version 10.1.1-beta.6 2026-08-02 20:36:46 +00:00
Shutong Wu 07e8680df9 Merge pull request #1298 from asavs/fix/gameobject-create-component-properties
fix: make component properties reachable on manage_gameobject create
2026-08-02 16:25:25 -04:00
github-actions[bot] 61c4122bb5 Merge pull request #1309 from CoplayDev/beta-version-10.1.1-beta.5-30756436245
chore: update Unity package to beta version 10.1.1-beta.5
2026-08-02 16:32:50 +00:00
GitHub Actions d3810df17d chore: update Unity package to beta version 10.1.1-beta.5 2026-08-02 16:32:46 +00:00
Shutong Wu 25e5f7e965 Merge pull request #1308 from Scriptwonder/fix/ci-fork-pr-signal
ci: retire safe-to-test gate, make skipped Unity checks visible
2026-08-02 12:29:01 -04:00
Shutong Wu 32428e820e Merge pull request #1302 from KamilDev/fix/resource-uri-prose
fix(server): address resources by URI in agent-facing prose
2026-08-02 12:21:12 -04:00
Shutong Wu 0b1f50db0c ci: retire safe-to-test gate, make skipped Unity checks visible
Fork PRs touching MCPForUnity/** get green Unity checks that verified
nothing. GitHub withholds secrets from pull_request runs originating in
a fork, so the detect step writes unity_ok=false and every real step is
gated off. Step-level `if:` produces step-conclusion `skipped`, which
contributes nothing to the job conclusion, so the job reports success
having compiled and tested nothing.

Make the skip unmissable: both workflows now emit ::warning:: and a
$GITHUB_STEP_SUMMARY block stating the check is not a pass.

Retire the safe-to-test label gate. It was the intended escape hatch but
never worked in practice -- actions/checkout's floating v4 tag has since
rolled forward to v4.4.0, which refuses to check out fork code under
pull_request_target without allow-unsafe-pr-checkout: true. Repairing it
would mean running fork-authored C# through game-ci/unity-test-runner
with UNITY_* secrets in scope, which is the classic pwn-request shape.
Removing the trigger makes both job-level `if:` gates dead code (each
began with `github.event_name != 'pull_request_target' ||`), so they go
too. To test a fork PR, review the diff and push its branch into this
repo; the push trigger runs the full suite in a trusted context.

Known tradeoff: the full-matrix label now takes effect on the next push
rather than on application, since nothing re-triggers on `labeled`.

This does not give fork PRs real signal -- it stops the absence of
signal from looking like success. A license-free compile job is the
follow-up.
2026-08-02 12:20:15 -04:00
github-actions[bot] ffd7ff7602 Merge pull request #1307 from CoplayDev/beta-version-10.1.1-beta.4-30755957460
chore: update Unity package to beta version 10.1.1-beta.4
2026-08-02 16:19:46 +00:00
GitHub Actions aa0f8729da chore: update Unity package to beta version 10.1.1-beta.4 2026-08-02 16:19:40 +00:00
Shutong Wu f7ef56602c Merge pull request #1304 from Scriptwonder/fix/1288-tool-annotations
fix: stop 34 tools forcing an approval prompt on every call (#1288)
2026-08-02 12:08:34 -04:00
github-actions[bot] fbc4894265 Merge pull request #1306 from CoplayDev/beta-version-10.1.1-beta.3-30753972755
chore: update Unity package to beta version 10.1.1-beta.3
2026-08-02 15:28:40 +00:00
GitHub Actions 5aa8e66dd3 chore: update Unity package to beta version 10.1.1-beta.3 2026-08-02 15:28:33 +00:00
Shutong Wu c82502f1e6 test: fail on duplicate tool registrations instead of silently collapsing them
Copilot review on #1304. The tools fixture keyed a dict by tool name, so two
tools registering the same name would drop one entry — hiding the registry bug
and skipping the lost entry's annotations, in a guard whose whole purpose is
catching silent regressions.

No duplicates today (48 registrations, 48 unique names — the 49th
@mcp_for_unity_tool occurrence is a docstring mention at
services/tools/__init__.py:28, not a decoration), so this is a guard hardening
rather than a fix.

Also corrects the docstring grammar Copilot flagged.
2026-08-02 11:21:05 -04:00
Shutong Wu 5f8c806414 Merge pull request #1305 from Scriptwonder/fix/1193-restore-codex-http
fix: restore HTTP transport for Codex (#1193)
2026-08-02 11:16:21 -04:00
KamilDev a0e489beec test: cover agent-facing markdown, drop dead type-hint guard
Review feedback on #1302.

The prose rule now also runs over the surfaces that tell a reader to go read a
resource: the skill agents load, and the per-tool reference pages whose example
blocks this PR fixed. Reverting those four lines makes it fail.

Scoped there deliberately. `website/docs/reference/resources/` is a generated
catalog that puts each name in a heading and its URI on the next line, and the
guides and getting-started pages name resources as the subject of a sentence
rather than instructing anyone to build a URI -- a blanket scan flags 38 lines,
none of them the defect.

Also drops the try/except around get_type_hints: it resolves for all 48
registered tools (266 annotated strings), so the except only had the power to
skip a tool's parameters silently. Without it a resolution failure surfaces as
the real error.
2026-08-01 13:36:03 +10:00
KamilDev 69267c536c fix(server): address resources by URI in agent-facing prose
A resource's name and its URI are deliberately different (`editor_state` vs
`mcpforunity://editor/state`), and the URI scheme is not derivable from the
name -- most resources are `category/thing` but several are flat
(`mcpforunity://instances`, `mcpforunity://menu-items`, `mcpforunity://tests`).

Several agent-facing strings still named resources without their URI, so an
agent following them built `mcpforunity://editor_state` and got a 404:

- server instructions listed resources by bare name and told the reader to
  "poll the `editor_state` resource's `isCompiling` field" (that field path is
  also wrong -- payloads are wrapped, so it is `data.compilation.is_compiling`)
- `refresh_unity`'s `wait_for_ready` parameter description referred to
  `editor_state.advice.ready_for_tools`
- the hint Unity returns in the `refresh_unity` result said "poll editor_state
  until ready_for_tools is true"

#1244 added a warning that names and URIs are not interchangeable, but left the
strings that trigger the mistake unchanged. Spell every resource reference as a
full URI instead, and correct the field paths while here.

Adds a regression test asserting that no agent-facing prose -- server
instructions, resource descriptions, tool and parameter descriptions, and
multi-word string literals under MCPForUnity/Editor -- mentions a resource by
its snake_case name without also giving that resource's URI.
2026-08-01 13:23:23 +10:00
XiaoLongHan 6f4c81224a fix: deduplicate CodeDom assembly references 2026-07-30 03:37:54 +08:00
Shutong Wu 267b465109 fix: restore HTTP transport for Codex (#1193)
#1292 declared Codex stdio-only. Tested against Codex CLI 0.47.0 with an
isolated CODEX_HOME, that is wrong: a bare

    [mcp_servers.unityMCP]
    url = "http://127.0.0.1:8123/mcp"

reports `transport: streamable_http` from `codex mcp get`, and Codex completes a
full MCP handshake against a live mcp-for-unity HTTP server - initialize 200,
notifications/initialized 202, SSE GET 200, tools/list 200 - with no feature flag
set at all. Adding [features] rmcp_client, the deprecated root-level
experimental_use_rmcp_client, both, or a deliberately bogus feature key all give
byte-identical results; unknown feature keys are silently ignored.

So #1292 removed a capability Codex has, for every Codex user.

Drop SupportsHttpTransport = false (the McpClient default is already true) and
delete the SupportedTransports override, since the base default is already
{ Stdio, Http }.

Delete the GetManualSnippet stdio coercion too. It was added by #1292 to stop a
stdio-only client rendering a url block, and CodexConfigurator is the only
subclass of CodexMcpConfigurator, so once Codex is HTTP-capable that branch is
unreachable.

Leave [features] rmcp_client = true alone: it is the current key name (the root
experimental_use_rmcp_client form is deprecated per openai/codex#6995), it is
harmless, and it enables the RMCP client that OAuth needs. Deliberately not
adding the deprecated key - it does nothing on current Codex and would just
linger in users' configs.

Tests now assert both transports and cover the snippet in both directions.

Caveat for review: this was verified against the Codex CLI. #1193 was reported
against Codex Desktop on Windows 11, which is untested here. #1292's remedy was
too broad, which does not mean the reporter was wrong - ask for their version and
CLI-vs-Desktop before closing #1193. If Desktop genuinely cannot do HTTP, that
belongs in Desktop-specific handling, not a blanket capability removal.
2026-07-29 00:18:25 -04:00
Shutong Wu 835bfcdd06 fix: stop 34 tools forcing an approval prompt on every call (#1288)
MCP clients gate a tool behind human approval unless it is read-only or
explicitly non-destructive, and destructiveHint defaults to true when omitted.
PR #480 set only `title=` on read_console, manage_editor and set_active_instance
despite its description claiming otherwise, so the spec default supplied
destructiveHint: true and nobody noticed.

Registering all 48 tools and dumping tools/list showed 34 of them serializing as
neither read-only nor explicitly non-destructive. find_gameobjects emitted
`annotations: null` outright.

State the hints explicitly across 10 modules. Four genuinely safe tools become
destructiveHint=False; the read-only set gets explicit hints instead of relying
on defaults; manage_editor and manage_components get explicit destructiveHint=True,
which changes no behaviour but stops them depending on the implicit default that
caused this. 34 gated -> 30, and the remaining 30 all write to the project.

find_gameobjects is deliberately not readOnlyHint=True: it calls
preflight(refresh_if_dirty=True), which can trigger a domain reload, and a
read-only promise would let a client do that unattended.

Add test_tool_annotations.py as the durable guard - it requires every tool to
state title and destructiveHint, and pins the auto-approvable set so a future
edit cannot silently flip one. Verified it fails by replaying the #480 regression.

test_tool_test_symmetry.py now excludes registry-wide guards from counting as
per-tool coverage, so one such file cannot satisfy the coverage guard for every
tool it happens to mention.

Does not fix the whole report: manage_asset(action="search") stays gated because
manage_asset can also delete. A read-only find_assets tool is the follow-up.
2026-07-29 00:18:06 -04:00
asavschaeffer 503d938b4a fix: make manage_gameobject component properties reachable on create
Fixes #1297. At action:"create", component_properties was accepted and
coerced by the C# dispatcher (ManageGameObject.cs) but only ever consumed
by the "modify" handler, so it silently did nothing. Meanwhile the shape
"create" already reads directly out of each componentsToAdd entry
({typeName, properties}) was rejected before it reached Unity, because the
Python schema typed components_to_add as list[str].

- GameObjectComponentHelpers.cs: factor the componentProperties loop +
  error aggregation out of GameObjectModify.cs into a shared
  ApplyComponentProperties helper, so both actions apply it identically.
- GameObjectCreate.cs: call the new helper after components are added,
  destroying the partially-created object and returning the error if any
  property fails to set (matching how component-add failures are handled).
- GameObjectModify.cs: switch to the shared helper (behavior-preserving
  refactor, no functional change on the modify path).
- manage_gameobject.py: widen components_to_add to accept
  {"typeName": ..., "properties": {...}} objects alongside plain strings,
  matching what GameObjectCreate.cs already reads.
- Regenerated website/docs/reference/tools/core/manage_gameobject.md via
  tools/generate_docs_reference.py for the updated parameter docs.

Tested: Server/tests/test_manage_gameobject.py exercises the Python
contract end-to-end, including a real fastmcp/pydantic schema validation
run of the issue's exact repro payloads (confirmed the pre-fix
ValidationError reproduces on the unmodified file, and is gone after).
Added TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/
ManageGameObjectCreateTests.cs coverage for the C# side, but this was not
run against a live Editor.
2026-07-28 15:59:38 -07:00
Shutong Wu fc70dda75d Merge pull request #1281 from ananttheant/fix/typos-migration-v8-docs
Beta Release (PyPI Pre-release) / Unity tests gate (push) Failing after 1s
Beta Release (PyPI Pre-release) / Python tests gate (push) Failing after 0s
Beta Release (PyPI Pre-release) / Update Unity package to beta version (push) Has been cancelled
Beta Release (PyPI Pre-release) / Publish beta to PyPI (pre-release) (push) Has been cancelled
Docs — Reference Drift Check / Check docs reference is fresh (push) Has been cancelled
Docs — Build & Deploy / Build site (push) Has been cancelled
Docs — Build & Deploy / Deploy to GitHub Pages (push) Has been cancelled
docs: fix typos in v8 migration guide
2026-07-28 18:15:35 -04:00
github-actions[bot] 5fdf544e94 Merge pull request #1296 from CoplayDev/beta-version-10.1.1-beta.2-30388780929
chore: update Unity package to beta version 10.1.1-beta.2
2026-07-28 18:56:11 +00:00
GitHub Actions 2d3b099165 chore: update Unity package to beta version 10.1.1-beta.2 2026-07-28 18:56:05 +00:00
Shutong Wu 94f192bfa3 Merge pull request #1291 from Scriptwonder/fix/1276-deferred-reload-compiling
fix: trust the pipeline flag when a domain reload is deferred (#1276)
2026-07-28 14:44:04 -04:00
Shutong Wu 70a96ec362 Merge pull request #1290 from Scriptwonder/fix/1279-windows-headless-stdin
fix: redirect stdin from NUL when launching the server on Windows (#1279)
2026-07-28 14:42:01 -04:00
Shutong Wu 334f3c0805 Merge pull request #1292 from Scriptwonder/fix/1193-codex-stdio-only
fix: advertise Codex as stdio-only (#1193)
2026-07-28 14:41:28 -04:00
Shutong Wu 5496c1243f Merge pull request #1293 from Scriptwonder/fix/server-cli-run-tests-and-camera
fix: repair dead camera CLI, add run_tests clear_stuck (#1272), refresh uv.lock
2026-07-28 14:40:26 -04:00
Shutong Wu e8fe7fe034 Merge pull request #1294 from Scriptwonder/test/graphics-assume-to-ignore
test: report unavailable-pipeline graphics tests as Skipped, not Inconclusive
2026-07-28 14:39:37 -04:00