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.
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.
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.
- 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
CodeRabbit follow-up on #1262: the API-level default is omitting the
parameter (nothing crosses the wire); passing 'none' explicitly maps to
the same no-rig import. Say "omitted or 'none'" instead of calling
'none' the default, and regenerate the reference page.
Claude-Session: https://claude.ai/code/session_01Cya1SZmg7CJgJS61nhjLH4
Review responses (CodeRabbit + Copilot):
- Document the 'legacy' animation_type value in the C# XML summary, MCP tool
description, param help, and CLI help (Copilot x4).
- SKILL.md: drop multi-material zones as a GLB-only trigger (both formats keep
slots), define out_glb in the glTF branch example, document the full
animation_type contract, probe both Principled emission socket names
('Emission Color' 4.x / 'Emission' 3.x), keep use_active_scene=True in the
Notes GLB example, and distinguish FBX vertex-color data transfer from URP
Lit shader display.
- bridge-fidelity.md: make export_apply conditional (static-only; skinned/
shape-key meshes need False) and document export_animations' active/NLA-
stashed semantics.
Regenerate website/docs/reference for the updated tool description — fixes the
"Check docs reference is fresh" CI failure ("differs: asset_gen/import_model_file.md").
Claude-Session: https://claude.ai/code/session_01Cya1SZmg7CJgJS61nhjLH4
PR #1157 review (Copilot + CodeRabbit) flagged that several tool pages
had truncated frontmatter, e.g. manage_asset rendering as:
description: "Performs asset operations (import, create, modify, delete, etc"
Root cause: the generator used `description.split(".")[0]` to derive the
frontmatter blurb. That cuts at the FIRST period — including periods
inside abbreviations and parenthesized lists ("etc.) in Unity."), so
the rendered description stopped mid-clause.
Fix: introduce `_first_sentence()` that splits on real sentence
boundaries — `.` / `!` / `?` followed by whitespace + capital, or a
paragraph break — and falls back to the whole string if no boundary
exists. Also caps absurdly long single-sentence descriptions at ~240
chars to keep frontmatter compact.
All three call sites that used the old split:
- frontmatter `description:` in render_tool_page
- group-index bullets in render_group_index
- catalog-index bullets in render_catalog_index
Regenerated all 43 tool pages + 9 group landings + catalog index +
resources catalog. Verified `--check` passes round-trip and full
website build is clean.
manage_asset now reads: "Performs asset operations (import, create,
modify, delete, etc.) in Unity."
Hand-written examples on five high-traffic tool pages (preserved across
regeneration by the generator) and a proper nested Tools sidebar so
groups are collapsible categories instead of a flat list.
Examples (in <!-- examples:start --><!-- examples:end --> blocks):
- manage_gameobject: create primitives, modify (move + reparent),
delete by tag, duplicate, multi-instance routing
- manage_scene: load, paged get_hierarchy, save, create from template,
additive multi-scene editing
- manage_material: create, assign to renderer, set_material_shader_property,
tint via MaterialPropertyBlock (mode: property_block) for batching
- manage_script: REWRITTEN to match the tool's actual surface
(create / read / delete only). The previous draft conflated it with
script_apply_edits / validate_script — those examples moved to:
- script_apply_edits: replace_method, insert_method (with position
anchor), delete_method, anchor_insert (regex anchor), multi-op
atomic transaction
- batch_execute: 9-op spawn-three-colored-cubes payload, parallel/
fail_fast semantics, batch-size limits
Generator fixes (tools/generate_docs_reference.py):
- Examples-preservation regex now requires markers at line boundaries
(re.MULTILINE + ^/$ anchors). Previously the generator's own warning
banner referenced the literal `<!-- examples:start --><!-- examples:end -->`
strings and the lazy regex matched THOSE first — capturing empty
content and overwriting real examples with the placeholder
- --check mode now reads existing examples from the committed location
(passes `examples_source=TOOLS_OUT`) instead of the empty tempdir,
so CI drift detection no longer false-positives every run
- Emits `_category_.json` per group dir + a sidebar_class_name on the
catalog index — Docusaurus then renders Tools → group → tool as a
proper nested tree, with the duplicate catalog-as-child entry
CSS-hidden via .sidebar-hidden
Sidebar (sidebars.js):
- Reference > Tools is now a single category, link points to the
catalog index, items autogenerate from website/docs/reference/tools/
using the new `_category_.json` metadata for nesting
Verified: build clean, generator --check exits 0, examples survive
end-to-end regeneration round-trip.
- HomeHero: building_scene.gif rendered below the install block in a
bordered, rounded frame with a one-line caption. lazy-loaded, sized
1200x675 to avoid layout shift. Asset copied from docs/images/ into
website/static/img/ so the docs site is self-contained.
- /reference/cli: new page documenting the mcp-for-unity CLI —
invocation (uvx and uv run), how it talks to Unity over HTTP,
global flags table, command-group → MCP-tool mapping (29 groups
cross-linked to their generated tool reference pages), Click
--help discovery, source pointers.
- /reference/manifest: new page documenting manifest.json — its
relationship to package.json (UPM) and pyproject.toml (PyPI),
per-field reference (top-level, server, tools), MCPB bundle
generation path.
- sidebars.js: uncommented both reference items.
Verified: build clean. Smoke test: / renders gif, /reference/cli +
/reference/manifest both 200, gif fetch returns 2.2 MB.
Typography upgrade matching modern AI-product docs sites (e.g. benchflow):
- Satoshi (Fontshare, weights 300/400/500/700/900) for body and headings
- JetBrains Mono (Google Fonts, 400/500/700) for monospace
- Loaded via stylesheet links + preconnect hints in docusaurus.config.js
- custom.css updates: --ifm-font-family-base, --ifm-font-family-monospace,
tighter heading letter-spacing, slightly bumped line-height for Satoshi,
brand color shifted to indigo (#4f46e5) to pair with the new sans
- Inline code nudged 0.88em to sit on Satoshi's baseline
Emojis removed across all in-house content for a cleaner, professional
tone:
- generator banner: dropped the gear glyph
- generator parameter table: required column is now "yes" / "—" instead
of an emoji checkbox (regenerated all 43 tool pages)
- install.md: status-text instead of green-dot emoji
- SECURITY.md: Yes / No instead of check/cross
- ISSUE_TEMPLATE/config.yml: plain link labels, no leading emoji
Verified:
- npm run build succeeds (5.7s client, 4.5s server)
- generator --check exits 0 (deterministic regeneration)
- HTML head includes both font stylesheets + preconnect hints
- CSS bundle resolves Satoshi and JetBrains Mono font-family stacks
Introduces tools/generate_docs_reference.py — the single Python script
that emits every reference page under website/docs/reference/ from the
live @mcp_for_unity_tool and @mcp_for_unity_resource registries.
What lands:
- tools/generate_docs_reference.py: introspects function signatures
(Annotated[Type, "description"]), preserves hand-authored examples
between <!-- examples:start --><!-- examples:end --> markers, supports
--write (default) and --check (CI drift detection) modes.
- tools/hooks/pre-commit: installed via tools/install-hooks.sh; when a
staged change touches Server/src/services/{tools,resources,registry},
regenerates the reference and re-stages it. Contributors don't have
to remember.
- .github/workflows/docs-generate.yml: runs --check on every PR and on
pushes to beta. Fails with a one-line fix command if the committed
reference drifts from the registry. Also runs a count sanity check
(#decorators must equal #generated md files).
- website/docs/reference/: 43 tool pages across 9 groups (animation,
core, docs, probuilder, profiling, scripting_ext, testing, ui, vfx)
+ group landing pages + 25-resource catalog. Sidebar wired with
Docusaurus's autogenerated mode so new tools appear automatically.
- README.md: "Available Tools" / "Available Resources" lists retired —
these were drifting on every release. Replaced with a single link to
the generated reference. (Root README slim is M5.)
Source of truth: Python. The C# attributes carry only Name/Group/
Description; the Python @decorator owns the richest typing via
Annotated[...], which is what MCP clients actually see over the wire.
Tested:
- generator runs clean (43 tools, 9 groups, 25 resources, deterministic)
- --check exits 0 against committed output
- pre-commit hook installs via existing tools/install-hooks.sh path