Skip to main content
Glama
JVinceW

unity-asset-reference-mcp

by JVinceW
README.md
# unity-asset-reference-mcp

[![CI](https://github.com/JVinceW/uasset-reference-memory-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/JVinceW/uasset-reference-memory-mcp/actions/workflows/ci.yml)
[![npm](https://img.shields.io/npm/v/unity-asset-reference-mcp)](https://www.npmjs.com/package/unity-asset-reference-mcp)

Index a **Unity** project's assets into a reusable **SQLite reference graph**, then
query it three ways: a **CLI**, an **MCP server** (for Claude and other agents),
and a local **web viewer**. Unity-only.

- **Impact analysis** — "what references this material?" before you change it
- **Unused-asset detection** — orphans nothing loads (Addressables-aware)
- **Dependency tracing** — the full closure a scene/prefab pulls in
- **Broken-reference detection** — refs to deleted/missing assets
- **Reusable artifact** — a plain `.sqlite` any tool can open; no lock-in

It reads Unity's own serialization (`.meta` GUIDs + YAML `{fileID, guid}` refs),
so the graph is exact — no heuristics, no AST. Requires **Asset Serialization:
Force Text** (Unity's default for version control).

## Requirements

- Node.js ≥ 20
- A Unity project using **Force Text** serialization
- `better-sqlite3` (native module) downloads a prebuilt binary for your
  platform during install — no compiler needed on common platforms and Node
  versions. If none matches, it falls back to building from source, which
  needs Python and a C++ toolchain.

## Install

```bash
npm install -g unity-asset-reference-mcp
```

Prereleases publish under the `next` dist-tag, so `latest` always resolves to
the current stable release. To try a release candidate:

```bash
npm install -g unity-asset-reference-mcp@next
sh scripts/install.sh --package unity-asset-reference-mcp@next
```

### Upgrading

From **0.3.x** there is nothing to do. The index schema is unchanged at version
3, so an existing `<project>/.asset-memory/index.db` is read as-is — no reindex,
no config change.

From **0.2.x** the index must be rebuilt from schema 2 to 3. The indexer detects
this and rebuilds on the next `index_project` or `index` run; no flag or manual
migration is needed. Until then, MCP read tools return a `schema-mismatch` error
naming the fix rather than answering from an incompatible index.

Two behavior changes to expect when upgrading to 0.4.0:

- The viewer served at `/` is the new one; the previous viewer moved to
  `/legacy.html`.
- `search_assets` (and `/api/search`) now match an asset's path and GUID prefix
  as well as its name, so the same query returns more results than in 0.3.2.

Installer scripts are also available for users who prefer one command with
Node/npm checks and command verification:

```bash
# Linux/macOS, from a cloned repo
sh scripts/install.sh

# Linux/macOS, from GitHub
curl -fsSL https://raw.githubusercontent.com/JVinceW/uasset-reference-memory-mcp/main/scripts/install.sh | sh
```

```powershell
# Windows PowerShell, from a cloned repo
powershell -ExecutionPolicy Bypass -File .\scripts\install.ps1

# Windows PowerShell, from GitHub
irm https://raw.githubusercontent.com/JVinceW/uasset-reference-memory-mcp/main/scripts/install.ps1 | iex
```

This puts three commands on your `PATH`:

| Command | What |
| --- | --- |
| `unity-asset-reference-mcp-index` | the CLI indexer |
| `unity-asset-reference-mcp` | the MCP server |
| `unity-asset-reference-mcp-web` | the web viewer |

**Without a global install (npx):** the MCP server's bin name matches the package,
so `npx -y unity-asset-reference-mcp …` works directly. For the other two bins,
name the package with `-p`:

```bash
npx -y unity-asset-reference-mcp --project /path/to/UnityProject          # MCP server
npx -y -p unity-asset-reference-mcp unity-asset-reference-mcp-index index /path   # indexer
npx -y -p unity-asset-reference-mcp unity-asset-reference-mcp-web --project /path # viewer
```

## 1. Index a project

Builds `<project>/.asset-memory/index.db`.

```bash
unity-asset-reference-mcp-index index /path/to/UnityProject --force
```

Indexing uses bounded concurrency for filesystem scanning and YAML reference
extraction. The default is capped at eight workers; adjust it for a benchmark
or storage device with `--concurrency <n>`. SQLite graph writes remain
transactional and serialized:

```bash
unity-asset-reference-mcp-index index /path/to/UnityProject --concurrency 4
```

Add this to your **Unity project's** `.gitignore` — ignore the live index, but
commit the config and (optional) shared snapshot:

```gitignore
# unity-asset-reference-mcp: ignore the live index, keep config + shared snapshot
.asset-memory/index.db
.asset-memory/index.db-*
.asset-memory/*.building-*
.asset-memory/verify.json
.asset-memory/verify-report.json
```

## 2. Verify parser accuracy (optional)

Verification is a manual accuracy check. The Unity Editor exporter installs
separately from the Node tool, so neither requires the other. It is versioned on
its own cadence and is **not** part of the npm package.

Pick whichever install suits your team — all four deliver the same package:

| Method | How |
| --- | --- |
| **Git URL** | Package Manager → **Add package from git URL** |
| **Tarball** | download the `.tgz`, then **Add package from tarball** |
| **Folder** | download and unzip the `.zip`, then **Add package from disk** → pick `package.json` |
| **`.unitypackage`** | download, then **Assets → Import Package → Custom Package** |

```text
https://github.com/JVinceW/uasset-reference-memory-mcp.git?path=/unity/com.jvincew.assetreferencememory#<release-tag>
```

The `.tgz`, `.zip`, and `.unitypackage` downloads are attached to each
[release](https://github.com/JVinceW/uasset-reference-memory-mcp/releases).

The first three install it as a Package Manager package under `Packages/`, which
is upgradable in place. The `.unitypackage` instead imports the files into
`Assets/AssetReferenceMemory/`, where Unity does not track it as a package — so
upgrading means deleting that folder before importing a newer one. Prefer one of
the first three unless your workflow requires assets in the project tree.

In Unity, run **Tools > Asset Reference Memory > Export Verification**. It
writes `<project>/.asset-memory/verify.json`. Compare that export with the
index through the CLI:

```bash
unity-asset-reference-mcp-index verify-index /path/to/UnityProject \
  --verify /path/to/UnityProject/.asset-memory/verify.json
```

The command exits successfully when differences are found. It prints a bounded
summary and writes every missed/extra edge to
`<project>/.asset-memory/verify-report.json`. MCP clients use
`verify_index(verifyJsonPath)` and receive the same summary plus the report
path.

## 3. MCP server (works with any MCP client)

This is a standard **stdio MCP server** — it works with any MCP-compatible host:
Claude Code/Desktop, Cursor, Windsurf, Cline, VS Code (Copilot agent), Zed, and
others. Nothing is Claude-specific; only where you put the config differs.

**Generic config** (Claude Desktop, Cursor, Windsurf, Cline, and most hosts use
this `mcpServers` shape):

```json
{
  "mcpServers": {
    "unity-asset-graph": {
      "command": "npx",
      "args": ["-y", "unity-asset-reference-mcp", "--project", "/path/to/UnityProject"]
    }
  }
}
```

Where that config lives, per host:

| Host | Config location |
| --- | --- |
| Claude Code | `claude mcp add unity-asset-graph -- npx -y unity-asset-reference-mcp --project /path/to/UnityProject` (or `.mcp.json` in the project) |
| Claude Desktop | `claude_desktop_config.json` |
| Cursor | `.cursor/mcp.json` (project) or `~/.cursor/mcp.json` (global) |
| Windsurf | `~/.codeium/windsurf/mcp_config.json` |
| Cline | `cline_mcp_settings.json` |
| VS Code (Copilot) | `.vscode/mcp.json` — uses the key `servers` instead of `mcpServers` |

**Prerequisites:** Node ≥ 20 on `PATH` (for `npx`), and a Unity project on Force
Text serialization. You do **not** need to pre-index — call the `index_project`
tool once from the agent and it builds `<project>/.asset-memory/index.db`; the
read tools return a clear `no-index` error until you do.

**Tools exposed:** `index_project`, `index_status`, `get_dependencies`,
`find_references`, `find_unused_assets`, `trace_path`, `search_assets`,
`get_addressable_info`, `search_addressables`, `list_addressable_groups`,
`get_overview`, `get_edges`, `verify_index`, `export_graph_json`, and
`manage_adr`.

The Addressables tools provide read-only entry lookup, filtered discovery, and
group inventory. `indexedSourceBytes` is source-file size, not built bundle
size, and `reachableOnlyBecauseAddressable` is a review signal rather than
deletion safety. See
[docs/product/addressables.md](docs/product/addressables.md).

Indexing follows Unity's identity model: an asset and its sibling `.meta` are
one logical row, the GUID is stable identity, and the path is mutable. A normal
incremental refresh observes the newer asset/`.meta` modification time and
treats a GUID at a new path as one update. A new GUID at an old path is reported
as removal plus addition with a `guid-replaced` warning. Missing, orphaned, or
invalid `.meta` state is warned and skipped until Unity or source control
restores a complete pair; duplicate GUIDs stop the refresh without replacing
the last good index.

**Agent refresh policy:** before the first graph-dependent operation when
freshness is unknown, call `index_project` once in incremental mode. Reuse that
index for subsequent read-only queries, then refresh once after each coherent
batch of asset/`.meta` changes. Use `force: true` only when guaranteed freshness
is required. `index_status` reports stored index metadata; it does not scan live
assets or prove freshness, and query tools never trigger hidden indexing.

## 4. Web viewer

```bash
cd /path/to/UnityProject
unity-asset-reference-mcp-web
# asset graph viewer → http://localhost:7777
```

Run from anywhere inside a Unity project and the server finds the project root
by walking up, the way `git` locates a repository. Name one explicitly with
`--project <root>` — the same argument the MCP server and indexer take — or
point at a database elsewhere with `--db <index.db>`.

The port is chosen automatically: it starts at 7777 and moves to the next free
one, so several projects can be served at once without configuring anything.
Pin one with `--port <n>`; if that port is busy the server reports the port it
used instead of failing. The URL it prints is always the real one.

The viewer renders the dependency graph in **2D or 3D**, with an attention panel
for broken references, unused assets, and the most-referenced assets; filters by
asset type and origin; dependency/reference tracing; search; and back/forward
navigation. It reads the index through the same JSON API the server exposes.

The previous Cytoscape viewer is still bundled at
**`http://localhost:7777/legacy.html`**.

There is also a **static** flavor that needs no server at all: download
`asset-graph-viewer-static-<version>.zip` from the
[releases page](https://github.com/JVinceW/uasset-reference-memory-mcp/releases),
unzip it, open `viewer.html` in a browser, and pick a `.db`. It runs the same
queries entirely in-browser via WASM SQLite. It ships as a separate download
rather than inside the npm package so that every install does not carry ~700 KB
of WASM it will never load; all flavors share one query layer.

## Team sharing (snapshots)

Instead of every teammate re-indexing from scratch, commit a **compressed
snapshot** and let them restore it — the same idea as `codebase-memory`'s
`.codebase-memory/`.

```bash
# after indexing, export a shareable snapshot (or pass --snapshot to `index`)
unity-asset-reference-mcp-index snapshot /path/to/UnityProject
# -> .asset-memory/index.db.br  (brotli, ~85% smaller) + artifact.json + .gitattributes

# a teammate who clones + pulls restores the live index with no re-index:
unity-asset-reference-mcp-index restore /path/to/UnityProject
```

The MCP server and web viewer **auto-restore** from a snapshot on first use if the
live index is missing, so a fresh clone "just works". **Commit** these:

```
.asset-memory/config.json       # per-project settings (below)
.asset-memory/index.db.br       # compressed shared index
.asset-memory/artifact.json     # snapshot metadata (schema, commit, counts)
.asset-memory/.gitattributes    # marks the blob binary + merge=ours
```

`artifact.json` records the git commit and counts the snapshot was built at, so
you can tell when it's stale and re-run `index --snapshot`.

## Configuration

Optional per-project `.asset-memory/config.json` (see
[docs/product/configuration.md](docs/product/configuration.md)):

```json
{
  "unused": { "addressableRoots": "auto" },
  "scan":   { "ignore": ["**/ThirdParty/**", "*.bak"], "ignoreDefaults": true }
}
```

- `unused.addressableRoots` (`auto`\|`on`\|`off`) — count Addressable entries as
  roots for unused detection (query-time; `auto` = on if the project uses
  Addressables). Overridable per call.
- `scan.ignore` / `scan.ignoreDefaults` — extra ignore globs (index-time).

## The SQLite artifact

Open `.asset-memory/index.db` with any SQLite tool. Core tables: `assets`
(nodes), `edges` (references), `unresolved_refs` (broken refs),
`addressable_groups`, `addressable_entries`, `addressable_entry_labels`, and
`index_meta`. Schema:
[docs/product/asset-graph-model.md](docs/product/asset-graph-model.md).

Schema 3 normalizes Addressables into `addressable_groups`,
`addressable_entries`, and `addressable_entry_labels`. JSON exports include
each entry's read-only state, owning group identity, and sorted labels. Older
generated indexes and snapshots must be rebuilt with `index_project`; they are
not migrated in place.

## Known limitations

- **Code-based refs not tracked**: `Resources.Load("path")` and hard-coded
  Addressable address strings in C# aren't scanned yet, so `find_unused` output
  is *candidates* — verify against your loading code.
- **Asset-level granularity**: edges are asset→asset (not per-GameObject/fileID).
- **Read-only Addressables Stage 1**: group schemas, profiles, providers,
  packing/compression, build/load paths, content-update settings, and bundle
  analysis are deferred.
- Incremental re-index uses filesystem modification times for speed and can
  miss timestamp-preserving edits. Use `--force` for a guaranteed-freshness
  rebuild from current readable project contents; it still reports unreadable
  or incomplete project state rather than modifying Unity assets.

## Development

```bash
npm install
npm test        # vitest
npm run build   # tsc + Vite viewer bundle + copy web assets to dist/
npm run benchmark:indexer  # controlled 2,000-asset concurrency benchmark
```

This repo uses a Git-native, text-first development workflow (see
[docs/WORKFLOW.md](docs/WORKFLOW.md)); it is not part of the shipped package.

## License

MIT — see [LICENSE](LICENSE).