<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title></title>
    <description>Day dreamer, night coder, and a life long learner.</description>
    <link>/</link>
    <atom:link href="/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Wed, 29 Jul 2026 14:30:48 +0700</pubDate>
    <lastBuildDate>Wed, 29 Jul 2026 14:30:48 +0700</lastBuildDate>
    <generator>Jekyll v4.0.1</generator>
    
      <item>
        <title>UAsset Reference MCP: Indexing External Unity Packages</title>
        <description>&lt;p&gt;UAsset Reference MCP v0.3.2 fixes a gap that appears as soon as a Unity project becomes modular. A game can depend on a local Unity Package Manager package through &lt;code class=&quot;highlighter-rouge&quot;&gt;Packages/manifest.json&lt;/code&gt;, while that package’s source folder lives outside the Unity project directory. Unity imports it, resolves its GUIDs, and lets project assets reference it. A project-root-only asset scan can still miss it.&lt;/p&gt;

&lt;p&gt;The change in v0.3.2 is automatic external local UPM package indexing. The indexer now discovers active local directory packages from Unity package metadata, reads their files from their physical source folders, and stores graph nodes under canonical Unity paths such as &lt;code class=&quot;highlighter-rouge&quot;&gt;Packages/com.company.gameplay/Runtime/EnemyConfig.asset&lt;/code&gt;. The SQLite graph stays portable, and traversal still works through GUID edges rather than through filesystem assumptions.&lt;/p&gt;

&lt;h2 id=&quot;the-missing-root-is-not-optional&quot;&gt;The Missing Root Is Not Optional&lt;/h2&gt;

&lt;p&gt;Unity projects often split shared gameplay, UI, networking, or tools code into UPM packages. During development, those packages are commonly referenced as local directories so the package can be edited alongside the game.&lt;/p&gt;

&lt;p&gt;The Unity manifest might look like this:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;dependencies&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;com.company.gameplay&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;file:../../modules/com.company.gameplay&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;From Unity’s point of view, assets inside that module are part of the active project package set. A prefab in &lt;code class=&quot;highlighter-rouge&quot;&gt;Assets/Characters/Enemy.prefab&lt;/code&gt; can serialize a reference to a ScriptableObject inside &lt;code class=&quot;highlighter-rouge&quot;&gt;com.company.gameplay&lt;/code&gt;, and Unity resolves the reference through the target asset’s &lt;code class=&quot;highlighter-rouge&quot;&gt;.meta&lt;/code&gt; GUID.&lt;/p&gt;

&lt;p&gt;A scanner that only walks the project root has a different view. It can see &lt;code class=&quot;highlighter-rouge&quot;&gt;Assets/&lt;/code&gt;, embedded packages under &lt;code class=&quot;highlighter-rouge&quot;&gt;Packages/&lt;/code&gt;, and cached registry packages under &lt;code class=&quot;highlighter-rouge&quot;&gt;Library/PackageCache/&lt;/code&gt;. It cannot see &lt;code class=&quot;highlighter-rouge&quot;&gt;../../modules/com.company.gameplay&lt;/code&gt; unless it understands Unity’s package metadata. The result is an unresolved GUID even though the Unity Editor can resolve the same asset.&lt;/p&gt;

&lt;p&gt;v0.3.2 makes the scan scope match the active Unity package graph more closely:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Unity project root
  Assets/                         scanned as project assets
  Packages/com.embedded.tool/      scanned as embedded package assets
  Library/PackageCache/...         scanned as cached package assets

External local package
  ../../modules/com.company.gameplay/
                                  scanned as package assets
                                  stored as Packages/com.company.gameplay/...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The indexer is still static and offline. It does not launch Unity or ask the Editor for a package list. It reads the metadata Unity already writes, then builds the graph from files on disk.&lt;/p&gt;

&lt;h2 id=&quot;physical-sources-become-unity-paths&quot;&gt;Physical Sources Become Unity Paths&lt;/h2&gt;

&lt;p&gt;The central model is physical root versus virtual path. The physical root is where the indexer reads bytes. The virtual path is the Unity path stored in the graph.&lt;/p&gt;

&lt;p&gt;For an external package named &lt;code class=&quot;highlighter-rouge&quot;&gt;com.company.gameplay&lt;/code&gt;, the physical source might be:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/Users/vincewang/modules/com.company.gameplay/Runtime/EnemyConfig.asset
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The graph stores it as:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Packages/com.company.gameplay/Runtime/EnemyConfig.asset
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That stored path is the important part. Absolute machine paths are local development details. If the index persisted &lt;code class=&quot;highlighter-rouge&quot;&gt;/Users/...&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;../../modules/...&lt;/code&gt;, a shared snapshot would describe one developer’s folder layout instead of the Unity project model. &lt;code class=&quot;highlighter-rouge&quot;&gt;Packages/&amp;lt;package-name&amp;gt;/...&lt;/code&gt; is the path Unity users expect when talking about package assets, so it is the path the database records.&lt;/p&gt;

&lt;p&gt;The node still carries package identity:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;path:       Packages/com.company.gameplay/Runtime/EnemyConfig.asset
origin:     package
package_id: com.company.gameplay
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Reference extraction does not need a separate package traversal mode. Unity serialized references point to GUIDs, and the index resolves GUIDs across all active roots. A project asset can reference a package asset. A package asset can reference a project asset. Two packages can reference each other. Once the GUID map includes every active root, the edge model remains the same.&lt;/p&gt;

&lt;h2 id=&quot;discovery-follows-unity-metadata&quot;&gt;Discovery Follows Unity Metadata&lt;/h2&gt;

&lt;p&gt;The scanner builds a package-source plan before walking files. It reads &lt;code class=&quot;highlighter-rouge&quot;&gt;Packages/manifest.json&lt;/code&gt; for direct dependencies and &lt;code class=&quot;highlighter-rouge&quot;&gt;Packages/packages-lock.json&lt;/code&gt; when Unity has written resolved package metadata.&lt;/p&gt;

&lt;p&gt;The manifest is the authority for direct dependency declarations. A direct local dependency using a &lt;code class=&quot;highlighter-rouge&quot;&gt;file:&lt;/code&gt; directory can be discovered from the manifest alone. Relative &lt;code class=&quot;highlighter-rouge&quot;&gt;file:&lt;/code&gt; paths resolve from the project’s &lt;code class=&quot;highlighter-rouge&quot;&gt;Packages/&lt;/code&gt; directory, matching how Unity interprets those paths, not from whichever directory happened to launch the CLI.&lt;/p&gt;

&lt;p&gt;The lockfile can add resolved local-package information, including local transitive packages. That matters when a project pulls in a package that itself depends on another local package. The indexer can include the package Unity resolved without asking the user to configure extra scan roots.&lt;/p&gt;

&lt;p&gt;Discovery is intentionally narrow. The indexer follows package paths explicitly declared or resolved by Unity project metadata. It does not crawl parent folders, scan sibling repositories, expand arbitrary workspace directories, read environment variables, download missing packages, or treat local &lt;code class=&quot;highlighter-rouge&quot;&gt;.tgz&lt;/code&gt; files and &lt;code class=&quot;highlighter-rouge&quot;&gt;file://&lt;/code&gt; Git URLs as external directories. Those sources remain Unity package-resolution concerns, and cached package content continues to be handled through &lt;code class=&quot;highlighter-rouge&quot;&gt;Library/PackageCache/&lt;/code&gt; when present.&lt;/p&gt;

&lt;p&gt;Each external package candidate has to be an accessible directory with a parseable &lt;code class=&quot;highlighter-rouge&quot;&gt;package.json&lt;/code&gt;. The package manifest’s &lt;code class=&quot;highlighter-rouge&quot;&gt;name&lt;/code&gt; must match the dependency name declared by the project. A mismatch is skipped with a package-discovery warning instead of being indexed under the wrong Unity path.&lt;/p&gt;

&lt;h2 id=&quot;precedence-prevents-duplicate-package-views&quot;&gt;Precedence Prevents Duplicate Package Views&lt;/h2&gt;

&lt;p&gt;One package name must map to one active source. Otherwise the graph could index both a live local package and a stale cached copy of the same package, creating duplicate nodes and confusing dependency answers.&lt;/p&gt;

&lt;p&gt;v0.3.2 uses deterministic source precedence:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1. Embedded package under Packages/&amp;lt;name&amp;gt;
2. Active external local package from manifest or lock metadata
3. Matching package cache under Library/PackageCache
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;An embedded package wins because it is physically inside the Unity project and overrides package-manager resolution for that package name. An active external local package wins over a matching cache entry because the local source is the package Unity is using for development. The cache remains useful for registry and Git packages, but it should not compete with the current local source.&lt;/p&gt;

&lt;p&gt;The existing duplicate-GUID validation remains the final safety boundary. If two genuinely active assets claim the same Unity GUID, indexing fails before publishing a new database. External package discovery does not silently choose a GUID winner, because Unity asset identity has to stay unambiguous for graph answers to be trustworthy.&lt;/p&gt;

&lt;h2 id=&quot;incremental-refresh-tracks-package-selection&quot;&gt;Incremental Refresh Tracks Package Selection&lt;/h2&gt;

&lt;p&gt;Normal indexing is still incremental. Each logical asset uses the newer modification time of the asset file and its sibling &lt;code class=&quot;highlighter-rouge&quot;&gt;.meta&lt;/code&gt;, including assets inside external packages. Editing a package asset or its &lt;code class=&quot;highlighter-rouge&quot;&gt;.meta&lt;/code&gt; therefore participates in the same incremental path as project assets.&lt;/p&gt;

&lt;p&gt;Package selection introduces another freshness problem. The manifest or lockfile can change while the selected package assets appear unchanged. A dependency can be removed, pointed at another folder, or replaced with a different source that preserves the same virtual path, GUID, and timestamps. A file-level timestamp check is not enough to detect that package-source decision.&lt;/p&gt;

&lt;p&gt;v0.3.2 records a package-discovery fingerprint for the indexed package plan. The fingerprint is derived from the project manifest, lockfile, and selected package-source descriptors. When that fingerprint changes, the next index run discards the copied incremental staging database and performs a fresh candidate-graph reconciliation before the atomic publish step.&lt;/p&gt;

&lt;p&gt;That gives the indexer two layers of freshness. Asset and &lt;code class=&quot;highlighter-rouge&quot;&gt;.meta&lt;/code&gt; mtimes handle ordinary edits. The package-discovery fingerprint handles changes to which package sources are active. &lt;code class=&quot;highlighter-rouge&quot;&gt;force: true&lt;/code&gt; remains the explicit guaranteed-freshness path and scans all active roots unconditionally.&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;unity-asset-reference-mcp-index index /path/to/UnityProject &lt;span class=&quot;nt&quot;&gt;--force&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;MCP callers use the same public tool as before:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;index_project(path, force?)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There is no new scan-root argument. The point of this release is that active local UPM packages are project metadata, so indexing them should not require a second configuration system.&lt;/p&gt;

&lt;h2 id=&quot;warnings-are-bounded-and-localized&quot;&gt;Warnings Are Bounded and Localized&lt;/h2&gt;

&lt;p&gt;Package discovery can fail for reasons that should not make the whole project impossible to index. A package directory may be missing on one machine. A local path may be inaccessible. A &lt;code class=&quot;highlighter-rouge&quot;&gt;package.json&lt;/code&gt; file may be malformed. A package may declare a different name than the dependency key in the Unity manifest.&lt;/p&gt;

&lt;p&gt;Those cases produce &lt;code class=&quot;highlighter-rouge&quot;&gt;package-discovery&lt;/code&gt; warnings and skip the invalid source. Other valid roots continue to index. The previous good index is still replaced only after the complete candidate graph passes the existing validation and publication checks.&lt;/p&gt;

&lt;p&gt;A missing or malformed project manifest disables external-local discovery for that run and emits one bounded manifest warning. Embedded package and package-cache scanning still continue, so the indexer preserves as much useful graph data as it can without inventing package state.&lt;/p&gt;

&lt;p&gt;Ignore rules use canonical paths, not physical source paths. A configured ignore such as &lt;code class=&quot;highlighter-rouge&quot;&gt;Packages/com.company.gameplay/Samples~/**&lt;/code&gt; applies to the external package as it appears in Unity. Root-level ignores and descendant ignores are evaluated before recursion, so an ignored package root produces neither nodes nor per-file warning noise.&lt;/p&gt;

&lt;h2 id=&quot;the-release-changes-scope-not-the-public-shape&quot;&gt;The Release Changes Scope, Not the Public Shape&lt;/h2&gt;

&lt;p&gt;v0.3.2 expands what the existing indexer can see. It does not change the public query surface.&lt;/p&gt;

&lt;p&gt;The npm package was published as &lt;code class=&quot;highlighter-rouge&quot;&gt;unity-asset-reference-mcp@0.3.2&lt;/code&gt;, and the annotated &lt;code class=&quot;highlighter-rouge&quot;&gt;v0.3.2&lt;/code&gt; tag points at the published release commit. The Unity verification package stays at &lt;code class=&quot;highlighter-rouge&quot;&gt;0.2.0&lt;/code&gt;. SQLite remains schema 3. MCP and CLI inputs and successful response shapes are unchanged.&lt;/p&gt;

&lt;p&gt;The release validation covered the package-indexing behavior and the publication boundary. The release evidence records root Vitest passing across 39 test files and 298 tests, &lt;code class=&quot;highlighter-rouge&quot;&gt;npm run typecheck&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;npm run build&lt;/code&gt;, package dry-runs for both the root package and Unity package, &lt;code class=&quot;highlighter-rouge&quot;&gt;git diff --check&lt;/code&gt;, a successful GitHub Actions release workflow, and npm registry verification returning exactly &lt;code class=&quot;highlighter-rouge&quot;&gt;0.3.2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The exclusions are as important as the feature. v0.3.2 does not add manual root configuration, filesystem watchers, Unity Editor callbacks, package downloads, local package mutation, schema migration, or new MCP tools. It reads the active local packages Unity already knows about, represents them with Unity’s virtual package paths, and lets the existing GUID graph answer cross-boundary dependency questions.&lt;/p&gt;

&lt;p&gt;External local package indexing makes the graph match modular Unity projects more closely. Package assets no longer disappear just because their source folder sits outside the game repository. The index still publishes portable SQLite data, still resolves by GUID, and still keeps package discovery explicit enough to warn when local machine state does not match the project’s package declarations.&lt;/p&gt;
</description>
        <pubDate>Fri, 24 Jul 2026 00:00:00 +0700</pubDate>
        <link>/2026/uasset-reference-mcp-external-upm-package-indexing/</link>
        <guid isPermaLink="true">/2026/uasset-reference-mcp-external-upm-package-indexing/</guid>
        
        
        <category>tools</category>
        
      </item>
    
      <item>
        <title>UAsset Reference MCP: Modeling Unity Addressables Separately</title>
        <description>&lt;p&gt;Addressables changed the unused-asset question in UAsset Reference MCP. A texture, prefab, or scene can be unreferenced by serialized assets and still be intentionally loaded through an Addressables entry.&lt;/p&gt;

&lt;p&gt;That means a reference graph needs two different kinds of evidence. One answers whether a serialized asset points to another asset. The other answers whether an asset is reachable because the project declares it as Addressable content.&lt;/p&gt;

&lt;h2 id=&quot;serialized-references-and-addressables-answer-different-questions&quot;&gt;Serialized References and Addressables Answer Different Questions&lt;/h2&gt;

&lt;p&gt;The first release of UAsset Reference MCP focused on Unity’s serialized reference records. In text mode, Unity writes links as &lt;code class=&quot;highlighter-rouge&quot;&gt;{fileID, guid, type}&lt;/code&gt; values. Those records are direct asset-to-asset edges.&lt;/p&gt;

&lt;p&gt;Addressables are not the same shape. An Addressables group file describes entries, labels, read-only state, group membership, and an address that can be loaded at runtime. That metadata does not mean another asset serialized a field reference to the entry. It means the project author declared the entry as loadable content.&lt;/p&gt;

&lt;p&gt;Flattening both concepts into one edge type would make the graph easier to query but harder to trust. A developer reviewing unused assets needs to know why an asset is reachable.&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Serialized edge:
Assets/Scenes/Battle.unity -&amp;gt; Assets/Prefabs/Enemy.prefab

Addressables reachability:
Addressables group &quot;RemoteCharacters&quot; contains Assets/Prefabs/Enemy.prefab
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Those statements support different decisions. The scene edge explains a concrete dependency. The Addressables entry explains runtime availability.&lt;/p&gt;

&lt;h2 id=&quot;normalized-tables-keep-the-model-honest&quot;&gt;Normalized Tables Keep the Model Honest&lt;/h2&gt;

&lt;p&gt;UAsset Reference MCP stores Addressables metadata in separate SQLite tables instead of hiding it inside the regular &lt;code class=&quot;highlighter-rouge&quot;&gt;edges&lt;/code&gt; table.&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;addressable_groups
addressable_entries
addressable_entry_labels
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The group table records the Addressables group identity and source file. The entries table records the asset GUID, address, owning group, read-only state, and indexed source bytes. Labels live in their own table because one entry can have multiple labels, and queries need deterministic filtering.&lt;/p&gt;

&lt;p&gt;This structure keeps regular graph traversal simple while still letting the query layer answer Addressables-specific questions. &lt;code class=&quot;highlighter-rouge&quot;&gt;find_unused_assets&lt;/code&gt; can treat Addressables entries as roots when configured to do so, while &lt;code class=&quot;highlighter-rouge&quot;&gt;get_addressable_info&lt;/code&gt; can explain the exact group and labels that make one asset reachable.&lt;/p&gt;

&lt;h2 id=&quot;reachability-is-a-review-signal&quot;&gt;Reachability Is a Review Signal&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;reachableOnlyBecauseAddressable&lt;/code&gt; is deliberately a review signal. It tells the user that an asset is not reachable through scenes or serialized asset references, but it is reachable through Addressables metadata.&lt;/p&gt;

&lt;p&gt;That distinction matters because Unity projects often load content through code:&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;Addressables&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LoadAssetAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GameObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;EnemyBoss&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Static graph indexing does not prove whether string-based runtime loading is used correctly. It can show that the asset is declared as an Addressables entry and that no serialized edge points at it. A developer still needs to review the loading code before deleting or moving the asset.&lt;/p&gt;

&lt;p&gt;The tool avoids presenting Addressables reachability as deletion safety. It reports the graph evidence and leaves the production decision with the engineer.&lt;/p&gt;

&lt;h2 id=&quot;mcp-tools-make-addressables-queryable&quot;&gt;MCP Tools Make Addressables Queryable&lt;/h2&gt;

&lt;p&gt;The Addressables release added read-only MCP tools for common inspection paths.&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;get_addressable_info(asset)
search_addressables(query?, group?, label?, pathPrefix?, type?, reachableOnlyBecauseAddressable?, limit?)
list_addressable_groups()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;get_addressable_info&lt;/code&gt; resolves one asset or Addressables address and returns membership, owning group, labels, reference counts, and reachability signals. &lt;code class=&quot;highlighter-rouge&quot;&gt;search_addressables&lt;/code&gt; gives agents bounded discovery across entries. &lt;code class=&quot;highlighter-rouge&quot;&gt;list_addressable_groups&lt;/code&gt; gives a compact inventory of groups, labels, entry counts, and indexed source bytes.&lt;/p&gt;

&lt;p&gt;The tools are intentionally read-only. They help an agent explain the project; they do not rewrite Addressables configuration, move entries between groups, or predict bundle output.&lt;/p&gt;

&lt;h2 id=&quot;verification-uses-real-project-exports&quot;&gt;Verification Uses Real Project Exports&lt;/h2&gt;

&lt;p&gt;Addressables parsing has more edge cases than plain &lt;code class=&quot;highlighter-rouge&quot;&gt;.meta&lt;/code&gt; GUID scanning. Group files can have different layouts, entries can be read-only, labels can be absent, and generated metadata can vary between package versions.&lt;/p&gt;

&lt;p&gt;The implementation was verified against Unity-side exports from a real project. The verification flow compares what Unity reports with what the Node indexer stored. That gives the parser a concrete contract: group identity, entry identity, labels, and reachability data must match the project Unity understands.&lt;/p&gt;

&lt;p&gt;The result is still scoped. Stage 1 models Addressables discovery and query behavior. Group schemas, profiles, providers, packing, compression, build/load paths, content-update settings, and bundle analysis remain outside this release.&lt;/p&gt;

&lt;p&gt;Addressables support is useful because it keeps the asset graph from pretending every reachable asset is reachable for the same reason. Serialized references, Addressables entries, and runtime string loads need separate evidence. UAsset Reference MCP models the first two directly and makes the third explicit as a limitation.&lt;/p&gt;

</description>
        <pubDate>Tue, 21 Jul 2026 00:00:00 +0700</pubDate>
        <link>/2026/uasset-reference-mcp-addressables-discovery/</link>
        <guid isPermaLink="true">/2026/uasset-reference-mcp-addressables-discovery/</guid>
        
        
        <category>tools</category>
        
      </item>
    
      <item>
        <title>UAsset Reference MCP: Building a Unity Asset Reference Graph</title>
        <description>&lt;p&gt;UAsset Reference MCP turns a Unity project’s serialized assets into a queryable reference graph. The indexer reads Unity’s &lt;code class=&quot;highlighter-rouge&quot;&gt;.meta&lt;/code&gt; GUIDs and YAML reference records, stores the result in SQLite, then exposes that database through a CLI, an MCP server, and a local web viewer.&lt;/p&gt;

&lt;p&gt;The goal is to answer asset questions before they become production problems. If a developer wants to delete a material, rename a prefab folder, split an Addressables group, or understand why a scene pulls in a dependency chain, the graph gives them a concrete answer instead of a manual search across the Project window.&lt;/p&gt;

&lt;h2 id=&quot;unity-already-stores-the-asset-graph&quot;&gt;Unity Already Stores the Asset Graph&lt;/h2&gt;

&lt;p&gt;Unity assets have stable identity through &lt;code class=&quot;highlighter-rouge&quot;&gt;.meta&lt;/code&gt; files. A prefab, scene, material, texture, script, or Addressables asset has a GUID that other serialized files can reference.&lt;/p&gt;

&lt;p&gt;When a project uses text serialization, Unity writes asset references into YAML-like files as records such as &lt;code class=&quot;highlighter-rouge&quot;&gt;{fileID, guid, type}&lt;/code&gt;. That format is not a guess. It is the same reference information Unity uses to reconnect serialized fields to project assets.&lt;/p&gt;

&lt;p&gt;UAsset Reference MCP builds on that property. The indexer scans project assets, parses each asset’s &lt;code class=&quot;highlighter-rouge&quot;&gt;.meta&lt;/code&gt; GUID, extracts serialized reference records, resolves those GUIDs back to asset paths, and stores the result as directed edges.&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Assets/Scenes/Battle.unity
  -&amp;gt; Assets/Prefabs/Enemy.prefab
  -&amp;gt; Assets/Materials/BattleFloor.mat

Assets/Prefabs/Enemy.prefab
  -&amp;gt; Assets/Textures/Enemy_Diffuse.png
  -&amp;gt; Assets/Animations/Enemy.controller
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That graph becomes useful once it is durable. A one-off scan can answer one question, but a SQLite index lets command-line tools, MCP clients, and the web viewer share the same model.&lt;/p&gt;

&lt;h2 id=&quot;sqlite-is-the-boundary-between-indexing-and-querying&quot;&gt;SQLite Is the Boundary Between Indexing and Querying&lt;/h2&gt;

&lt;p&gt;The indexer writes &lt;code class=&quot;highlighter-rouge&quot;&gt;.asset-memory/index.db&lt;/code&gt; inside the Unity project. That database stores assets as nodes, references as edges, unresolved references as broken links, and Addressables metadata in normalized tables.&lt;/p&gt;

&lt;p&gt;SQLite keeps the tool simple. There is no service to deploy, no graph database to run, and no MCP client lock-in. The MCP server can expose curated tools for agents, while external scripts can still inspect the artifact directly when needed.&lt;/p&gt;

&lt;p&gt;The core workflow looks like this:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;unity-asset-reference-mcp-index index /path/to/UnityProject &lt;span class=&quot;nt&quot;&gt;--force&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After indexing, the project has a local graph database:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/path/to/UnityProject
└── .asset-memory
    └── index.db
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The same index can support impact analysis, dependency tracing, unused-asset review, broken-reference reporting, and JSON export without rescanning the project for every query.&lt;/p&gt;

&lt;h2 id=&quot;mcp-gives-agents-a-curated-query-surface&quot;&gt;MCP Gives Agents a Curated Query Surface&lt;/h2&gt;

&lt;p&gt;The MCP server runs over stdio and works with MCP-compatible hosts. Instead of giving an agent raw SQL access, it exposes specific tools with bounded behavior.&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;mcpServers&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;unity-asset-graph&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;command&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;npx&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;args&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;-y&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;unity-asset-reference-mcp&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;--project&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;/path/to/UnityProject&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;An agent can then ask practical Unity questions through tools such as &lt;code class=&quot;highlighter-rouge&quot;&gt;find_references&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;get_dependencies&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;trace_path&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;find_unused_assets&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;search_assets&lt;/code&gt;, and &lt;code class=&quot;highlighter-rouge&quot;&gt;get_overview&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That boundary matters. The agent receives a project-specific graph interface, not a general file-system search habit. It can answer, “what references this prefab?” or “why is this texture reachable?” with graph data instead of scanning every YAML file during the conversation.&lt;/p&gt;

&lt;h2 id=&quot;verification-keeps-the-parser-honest&quot;&gt;Verification Keeps the Parser Honest&lt;/h2&gt;

&lt;p&gt;The Node indexer parses Unity serialization outside the Unity Editor. That keeps indexing scriptable and agent-friendly, but it also means the parser needs a way to prove its results against Unity’s own view of the project.&lt;/p&gt;

&lt;p&gt;The companion Unity package exports a verification file from the Editor:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Tools &amp;gt; Asset Reference Memory &amp;gt; Export Verification
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The CLI compares that export against the SQLite graph:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;unity-asset-reference-mcp-index verify-index /path/to/UnityProject &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;--verify&lt;/span&gt; /path/to/UnityProject/.asset-memory/verify.json
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This makes parser accuracy measurable. Missed edges, extra edges, and unresolved references can be reported as data instead of discovered later through a broken production workflow.&lt;/p&gt;

&lt;h2 id=&quot;what-this-series-will-cover&quot;&gt;What This Series Will Cover&lt;/h2&gt;

&lt;p&gt;This first post sets the boundary of the tool: Unity text serialization in, SQLite graph out, MCP and viewer queries on top. The rest of the series can go deeper into the implementation details that made the asset useful in real projects.&lt;/p&gt;

&lt;p&gt;Future posts can cover the GUID and YAML parser, the SQLite schema, incremental indexing, Addressables modeling, MCP tool design, the web viewer, and the Unity verification harness.&lt;/p&gt;

&lt;p&gt;The useful part is not that Unity assets can be scanned. The useful part is turning Unity’s existing serialized reference data into a durable graph that both developers and agents can query before changing a project.&lt;/p&gt;
</description>
        <pubDate>Wed, 08 Jul 2026 00:00:00 +0700</pubDate>
        <link>/2026/uasset-reference-mcp-unity-asset-graph/</link>
        <guid isPermaLink="true">/2026/uasset-reference-mcp-unity-asset-graph/</guid>
        
        
        <category>tools</category>
        
      </item>
    
  </channel>
</rss>
