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

> Learn to create custom resource handlers in Unity MCP by implementing IMcpResourceHandler. Our guide details automatic registration for seamless integration.

- Repository: [いすず/unitymcp](https://github.com/isuzu-shiranui/unitymcp)
- Tags: how-to-guide
- Published: 2026-03-04

---

**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](https://github.com/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`](https://github.com/isuzu-shiranui/unitymcp/blob/main/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`](https://github.com/isuzu-shiranui/unitymcp/blob/main/Assets/Editor/OpenScenesResourceHandler.cs) or any `Editor/` folder assembly.

```csharp
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`](https://github.com/isuzu-shiranui/unitymcp/blob/main/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

```typescript
// 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:

```typescript
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`](https://github.com/isuzu-shiranui/unitymcp/blob/main/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`](https://github.com/isuzu-shiranui/unitymcp/blob/main/PackagesResourceHandler.cs) and [`AssembliesResourceHandler.cs`](https://github.com/isuzu-shiranui/unitymcp/blob/main/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`](https://github.com/isuzu-shiranui/unitymcp/blob/main/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"`.