Skip to content

Resources cannot get unity_instance from context #431

@MyNameisPI

Description

@MyNameisPI

Hi! I discovered an issue while testing MCP resources.

Problem

When calling resources, get_unity_instance_from_context(ctx) always returns None, even after calling set_active_instance. This causes two problems:

1. unity://custom-tools always fails

{
  "success": false,
  "message": "No active Unity instance. Call set_active_instance with Name@hash from unity://instances."
}

2. Other resources fail with multiple Unity instances

Resources like unity://editor/state work with one instance (auto-select fallback), but fail with multiple:

Error reading resource 'unity://editor/state': Multiple Unity instances are connected. Call set_active_instance with Name@hash from unity://instances.

Both happen even after calling set_active_instance.

Root Cause

Resources do not have middleware that injects unity_instance into the context (unlike tools).

  • set_active_instance stores the instance in session state
  • Middleware injects it into tool contexts, but not resource contexts
  • So get_unity_instance_from_context(ctx) always returns None for resources

Steps to Reproduce

Problem 1:

  1. Call unity://custom-tools → fails
  2. Call set_active_instance with valid instance
  3. Call unity://custom-tools again → still fails

Problem 2:

  1. Open two Unity instances
  2. Call set_active_instance to select one
  3. Call unity://editor/state → fails with "Multiple Unity instances..."

Suggested Fix

Extract common logic from on_call_tool to _inject_unity_instance method, then add on_read_resource that reuses it:

# In Server/src/transport/unity_instance_middleware.py

async def _inject_unity_instance(self, context: MiddlewareContext) -> None:
    """Inject active Unity instance into context if available."""
    ctx = context.fastmcp_context
    active_instance = self.get_active_instance(ctx)
    if active_instance:
        session_id: str | None = None
        if PluginHub.is_configured():
            try:
                session_id = await PluginHub._resolve_session_id(active_instance)
            except Exception as exc:
                logger.debug(
                    "PluginHub session resolution failed for %s: %s",
                    active_instance, exc
                )
        ctx.set_state("unity_instance", active_instance)
        if session_id is not None:
            ctx.set_state("unity_session_id", session_id)

# Refactored from original on_call_tool
async def on_call_tool(self, context: MiddlewareContext, call_next):
    """Inject active Unity instance into tool context if available."""
    await self._inject_unity_instance(context)
    return await call_next(context)

# New method following the same pattern as on_call_tool
async def on_read_resource(self, context: MiddlewareContext, call_next):
    """Inject active Unity instance into resource context if available."""
    await self._inject_unity_instance(context)
    return await call_next(context)

Environment

OS: Windows
Unity MCP package version: 8.1.6
Transport mode: HTTP

Related Files

  • Server/src/services/resources/custom_tools.py
  • Server/src/services/resources/editor_state.py
  • Server/src/services/tools/__init__.pyget_unity_instance_from_context
  • Server/src/transport/unity_instance_middleware.py — middleware (tools only)

Does this approach seem reasonable? If so, I'd be happy to submit a PR with this fix.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions