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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions