How to Create Custom Resource Handlers in Unity MCP: A Complete Implementation Guide

Create custom resource handlers in Unity MCP by implementing the IMcpResourceHandler interface and placing your class in the Editor/ folder; the McpHandlerDiscovery<T> system automatically registers it on Unity editor startup.

Unity MCP (Message Communication Protocol) from the isuzu-shiranui/unitymcp repository provides a discovery-based architecture for extending the MCP server with custom data sources. When you create custom resource handlers in Unity MCP, you enable external clients to query Unity-specific information—such as scene states, asset metadata, or project statistics—through a standardized JSON-RPC interface. This guide covers the automatic registration pipeline, the required interface implementation, and production-ready code examples.

Understanding the Resource Handler Architecture

A resource handler is any class that implements the IMcpResourceHandler interface defined in Editor/Core/IMcpResourceHandler.cs. Unlike manual registration systems, Unity MCP uses reflection-based discovery to find and instantiate these handlers automatically when the editor loads.

The lifecycle follows this sequence:

  1. IMcpResourceHandler defines the contract: ResourceName, Description, ResourceUri, and the FetchResource method.
  2. McpHandlerDiscovery<IMcpResourceHandler> scans loaded assemblies for non-abstract implementations of the interface.
  3. McpEditorInitializer triggers discovery on editor startup and invokes the registration callback for each found handler.
  4. McpServer.RegisterResourceHandler stores the handler in an internal dictionary and applies saved enable/disable states from McpSettings.
  5. McpServer.FetchResourceData routes incoming client requests to the matching handler's FetchResource method, executing on the Unity main thread.

Implementing the IMcpResourceHandler Interface

To create custom resource handlers in Unity MCP, your class must fulfill four requirements defined in the interface:

  • ResourceName (string): The unique identifier used in client requests (format: resourceName.action). Must be unique across the project.
  • Description (string): Human-readable explanation of what the handler provides.
  • ResourceUri (string, optional): A URL-style address (e.g., unity://myresource) for clients that prefer URI-based addressing.
  • FetchResource(JObject parameters): The method that returns a JObject containing the requested data.

Thread Safety and Unity API Access

The FetchResource method always executes on the Unity main thread because McpServer queues the call via ExecuteOnMainThread. This means your implementation can safely invoke Unity Editor APIs, access SceneManager, or query AssetDatabase without manual thread marshaling.

Complete Custom Resource Handler Example

The following implementation returns a JSON array of all currently open scenes. Place this file in Assets/Editor/OpenScenesResourceHandler.cs or any Editor/ folder assembly.

using UnityEngine;
using UnityEngine.SceneManagement;
using Newtonsoft.Json.Linq;
using UnityMCP.Editor.Resources;

namespace MyCompany.UnityMCP
{
    internal sealed class OpenScenesResourceHandler : IMcpResourceHandler
    {
        public string ResourceName => "openscenes";
        
        public string Description => "Provides a list of currently opened Unity scenes";
        
        public string ResourceUri => "unity://openscenes";

        public JObject FetchResource(JObject parameters)
        {
            var scenesArray = new JArray();
            
            foreach (var scene in SceneManager.GetAllScenes())
            {
                scenesArray.Add(new JObject
                {
                    ["name"] = scene.name,
                    ["path"] = scene.path,
                    ["isLoaded"] = scene.isLoaded,
                    ["isDirty"] = scene.isDirty
                });
            }

            return new JObject
            {
                ["success"] = true,
                ["scenes"] = scenesArray,
                ["count"] = scenesArray.Count
            };
        }
    }
}

Once Unity recompiles the scripts, McpHandlerDiscovery<IMcpResourceHandler> automatically finds this class, instantiates it, and registers it with the server via McpServer.RegisterResourceHandler (line 1057 in Editor/Core/McpServer.cs). No additional registration code is required.

Calling Your Handler from an MCP Client

External clients interact with your handler using the resourceName.command pattern. The server parses the prefix, looks up the registered handler, and forwards the parameters to FetchResource.

TypeScript Client Example

// Assumes an established McpClient instance named 'client'
client.send({
    type: "resource",
    command: "openscenes.fetch",
    id: "request-001",
    params: {}
}).then(response => {
    if (response.status === "success") {
        console.log(`Found ${response.result.count} scenes:`);
        response.result.scenes.forEach(scene => {
            console.log(`- ${scene.name} (${scene.path})`);
        });
    } else {
        console.error("Resource fetch failed:", response.message);
    }
});

URI-Based Requests

If your client prefers addressing resources by URI, you can use the ResourceUri value in the command field:

client.send({
    type: "resource",
    command: "unity://openscenes",
    id: "request-002",
    params: {}
});

Key Configuration and Constraints

When you create custom resource handlers in Unity MCP, keep these technical constraints in mind:

  • Unique Naming: The ResourceName property must be globally unique. If two handlers register with the same name, the last one discovered will overwrite the previous registration in McpServer's internal dictionary.
  • Persistence: The enabled/disabled state of each handler is stored in McpSettings. When McpEditorInitializer runs discovery, it applies these saved states automatically via RegisterResourceHandler.
  • Assembly Location: Handlers must reside in compiled assemblies accessible to the Unity Editor (typically under Assets/Editor/ or within Editor-specific Assembly Definition files).
  • Error Handling: Return a JObject with "success": false and an error message field rather than throwing exceptions, as uncaught exceptions in FetchResource may disrupt the server pipeline.

Summary

  • Implement IMcpResourceHandler from Editor/Core/IMcpResourceHandler.cs to define your handler contract.
  • Place handler classes in the Editor/ folder; McpHandlerDiscovery<T> automatically registers them on startup.
  • Use ResourceName as the unique identifier for client requests following the pattern resourceName.action.
  • Access Unity APIs freely in FetchResource because execution occurs on the main thread via the server's ExecuteOnMainThread queue.
  • Reference built-in examples such as PackagesResourceHandler.cs and AssembliesResourceHandler.cs in Editor/Handlers/ for implementation patterns.

Frequently Asked Questions

How does Unity MCP discover custom resource handlers automatically?

The McpHandlerDiscovery<T> class in Editor/Core/McpHandlerDiscovery.cs uses reflection to scan all loaded assemblies during McpEditorInitializer startup. It instantiates every non-abstract class implementing IMcpResourceHandler and invokes the registration callback provided by McpServer, requiring no manual configuration or explicit registration calls from the developer.

Can I use Unity Editor APIs inside the FetchResource method?

Yes. The McpServer.FetchResourceData method queues handler calls via ExecuteOnMainThread, ensuring FetchResource runs on the Unity main thread. This allows safe usage of SceneManager, AssetDatabase, Selection, and other Unity Editor APIs that are normally restricted to the main thread.

Where should I place custom handler files in my Unity project?

Place custom resource handler scripts in any folder named Editor (e.g., Assets/Editor/ or Assets/MyTools/Editor/) or within an Assembly Definition file marked as Editor-only. This ensures the code compiles against the Unity Editor assemblies and is available for discovery by McpHandlerDiscovery<IMcpResourceHandler> when the editor initializes.

How do I ensure my resource handler name is unique?

Set the ResourceName property to a specific, namespaced value (e.g., "mycompany.scenestats" instead of "scenes"). The McpServer.RegisterResourceHandler method stores handlers in a dictionary keyed by ResourceName, so duplicate names cause the last registered handler to overwrite previous entries without warning. Check existing handlers in Editor/Handlers/ to avoid collisions with built-in resources like "packages" or "assemblies".

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →