Unity API Verification Workflow with unity_reflect in MCP: A Complete Guide
The unity_reflect MCP tool exposes Unity's reflection API to AI assistants through three core actions—get_type, get_member, and search—enabling programmatic verification of type metadata, member signatures, and extension methods across loaded assemblies with intelligent caching and ambiguity resolution.
The UnityReflect class in the CoplayDev/unity-mcp repository provides a Model-Context Protocol (MCP) bridge that allows AI agents to inspect Unity's API surface without manual documentation lookups. According to the source code in MCPForUnity/Editor/Tools/UnityReflect.cs, this Editor-side utility registers with the [McpForUnityTool("unity_reflect", AutoRegister = false, Group = "docs")] attribute and processes JSON-RPC requests to deliver accurate reflection data via the HandleCommand method.
Core Actions and Request Routing
When an AI client issues a request containing an action field, UnityReflect.HandleCommand routes the payload to one of three high-level operations. Each action serves a distinct purpose in the Unity API verification workflow.
get_type: Type Resolution and Metadata
The get_type action resolves type names—full or short—and returns comprehensive metadata including base classes, interfaces, and member inventories. The entry point GetTypeInfo first attempts resolution through UnityTypeResolver.ResolveAny, which handles Unity's editor/player type precedence. If that fails, the system falls back to scanning cached assemblies using common Unity namespace prefixes defined in the NamespacePrefixes collection.
When a short name like Button matches multiple types across different namespaces, the tool returns a SuccessResponse with ambiguous: true and a sorted list of candidate full names. This forces the caller to provide a fully-qualified name for subsequent member queries, preventing incorrect API assumptions.
get_member: Detailed Member Inspection
The get_member action retrieves detailed information for specific type members via the GetMemberInfo entry point. The response includes the member_type classification (method, property, field, event, or extension_method), and for methods, an overloads array containing formatted signatures, parameter lists, return types, and [Obsolete] flags.
This action enables precise verification of method signatures before code generation, ensuring that AI assistants reference exact parameter types and generic constraints rather than approximations.
search: Fuzzy Assembly Search
The search action performs fuzzy matching across loaded assemblies through the SearchTypes method. It respects the scope parameter—unity, packages, project, or all—via the MatchesScope classification logic. The algorithm ranks candidates by exact match, prefix matching, then substring containment, capping results at 25 entries to maintain performance.
Internal Architecture and Caching Mechanisms
The unity_reflect tool implements several optimization strategies to minimize reflective enumeration overhead during a Unity session.
Assembly Caching and Domain Reloads
The GetAssemblyTypeCache method builds a dictionary mapping assemblyFullName to exportedTypes[] on first use. This cache persists across requests but invalidates automatically after domain reloads via the AssemblyReloadEvents.afterAssemblyReload event. This ensures that newly compiled scripts or package additions are immediately available without manual cache clears.
Generic Type Normalization
Before any type lookup, NormalizeGenericName converts human-readable generic syntax like List<T> or Dictionary<TKey, TValue> into CLR-compatible back-tick format (List\1, Dictionary`2). This normalization guarantees that generic type definitions are found even when the caller omits the ECMA-335 back-tick syntax required by System.Type.GetType`.
Extension Method Discovery
The FindExtensionMethods and FindExtensionMethodInfos methods scan static classes marked with [Extension] attributes in Unity assemblies. Results are cached per target type and presented as virtual members of the extended type, allowing the API verification workflow to surface LINQ-style extension methods that exist physically in separate static classes but logically belong to the target type's interface.
Implementing the Unity API Verification Workflow
The following patterns demonstrate how to invoke the unity_reflect tool directly from C# tests or via the MCP bridge.
Direct Invocation from Editor Tests
This pattern mirrors the MCP client behavior and matches the unit tests in TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/UnityReflectTests.cs:
using Newtonsoft.Json.Linq;
using MCPForUnity.Editor.Tools;
// Helper mimicking MCP JSON payload structure
static JObject InvokeReflect(string action, JObject extra = null)
{
var payload = extra ?? new JObject();
payload["action"] = action;
var result = UnityReflect.HandleCommand(payload);
return JObject.FromObject(result);
}
// Resolve Transform type and list members
var transformInfo = InvokeReflect("get_type", new JObject
{
["class_name"] = "UnityEngine.Transform"
});
Debug.Log(transformInfo.ToString());
// Get overloads for Physics.Raycast
var raycastInfo = InvokeReflect("get_member", new JObject
{
["class_name"] = "Physics",
["member_name"] = "Raycast"
});
// Search for NavMesh types in Unity scope
var searchResults = InvokeReflect("search", new JObject
{
["query"] = "NavMesh",
["scope"] = "unity"
});
MCP Client JSON Payload
When sending over the bridge from an external MCP client, the payload structure follows this format:
{
"tool": "unity_reflect",
"params": {
"action": "get_type",
"class_name": "Camera"
}
}
The Python MCP server forwards this to Unity, where HandleCommand processes it and returns a JSON response with the type's full metadata.
Handling Ambiguous Types and Generics
When resolving short names that exist in multiple namespaces, check the ambiguous flag and select from the matches array:
var buttonInfo = InvokeReflect("get_type", new JObject
{
["class_name"] = "Button"
});
if ((bool)buttonInfo["data"]["ambiguous"])
{
var candidates = buttonInfo["data"]["matches"] as JArray;
var uiButton = candidates
.First(c => c.ToString().Contains("UnityEngine.UI"));
// Re-query with fully qualified name
var resolved = InvokeReflect("get_type", new JObject
{
["class_name"] = uiButton
});
}
Generic types require no special syntax from the caller due to automatic normalization:
var listMetadata = InvokeReflect("get_type", new JObject
{
["class_name"] = "List<T>"
});
// Internal normalization converts to List`1 before lookup
Error Handling and Response Contracts
All unity_reflect actions follow a consistent MCP response contract. Successful operations return { success: true, data: object }, while validation failures or reflection exceptions return { success: false, error: string } with the stack trace. This guarantees that MCP clients always receive well-formed JSON even when requesting non-existent types or members with insufficient permissions.
The exception handling in GetTypeInfo, GetMemberInfo, and SearchTypes wraps unexpected errors in ErrorResponse objects, preventing the Unity Editor from logging unhandled exceptions while still surfacing diagnostic information to the AI assistant.
Summary
UnityReflectis an MCP tool inMCPForUnity/Editor/Tools/UnityReflect.csthat exposes Unity reflection APIs via JSON-RPC.- Three actions drive the workflow:
get_typefor type resolution,get_memberfor signature inspection, andsearchfor fuzzy assembly queries. - Assembly caching via
GetAssemblyTypeCachepersists across calls but invalidates on domain reloads to maintain accuracy. - Ambiguity detection forces explicit namespace qualification when short names match multiple types, preventing API misuse.
- Generic normalization automatically converts friendly syntax like
List<T>to CLR back-tick format (List\1`). - Extension methods are discovered via
FindExtensionMethodsand surfaced as virtual members of target types.
Frequently Asked Questions
How does unity_reflect handle ambiguous type names?
When a short name like Button matches multiple types across namespaces, the tool returns ambiguous: true with a sorted matches array containing fully-qualified names. The caller must re-query with a specific full name from this list to resolve the ambiguity and retrieve accurate member data.
What are the available search scopes in the unity_reflect tool?
The search action accepts four scope values: unity (core Unity assemblies), packages (installed Unity packages), project (user scripts), and all (everything loaded). The MatchesScope method classifies assemblies based on their origin, ensuring that searches respect the requested boundary and return relevant results.
How does the tool discover extension methods for Unity types?
FindExtensionMethods scans static classes marked with [Extension] attributes across loaded assemblies and caches the results per target type. These methods appear as extension_method entries in get_type responses and can be queried directly via get_member, allowing the API verification workflow to surface helper methods that exist in separate static classes but operate on Unity objects.
What happens to the reflection cache when Unity reloads scripts?
The assembly cache invalidates automatically via the AssemblyReloadEvents.afterAssemblyReload event. This ensures that GetAssemblyTypeCache rebuilds its dictionary of exported types after script compilation or domain reloads, preventing stale references to modified user code or newly installed packages.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →