22MCP Resources package - Auto-discovers and registers all resources in this directory.
33"""
44import logging
5+ import inspect
56from pathlib import Path
7+ from typing import get_type_hints
68
79from fastmcp import FastMCP
810from telemetry_decorator import telemetry_resource
1618__all__ = ['register_all_resources' ]
1719
1820
21+ def _create_fixed_wrapper (original_func , has_other_params ):
22+ """
23+ Factory function to create a wrapper that calls original_func with unity_instance=None.
24+ This avoids closure issues in loops.
25+ """
26+ if has_other_params :
27+ # Has other parameters (like mode)
28+ async def fixed_wrapper (* args , ** kwargs ):
29+ return await original_func (* args , ** kwargs , unity_instance = None )
30+ else :
31+ # No other parameters, just unity_instance
32+ async def fixed_wrapper ():
33+ return await original_func (unity_instance = None )
34+
35+ return fixed_wrapper
36+
37+
1938def register_all_resources (mcp : FastMCP ):
2039 """
2140 Auto-discover and register all resources in the resources/ directory.
@@ -36,18 +55,76 @@ def register_all_resources(mcp: FastMCP):
3655 logger .warning ("No MCP resources registered!" )
3756 return
3857
58+ registered_count = 0
3959 for resource_info in resources :
4060 func = resource_info ['func' ]
4161 uri = resource_info ['uri' ]
4262 resource_name = resource_info ['name' ]
4363 description = resource_info ['description' ]
4464 kwargs = resource_info ['kwargs' ]
4565
46- # Apply the @mcp.resource decorator and telemetry
47- wrapped = telemetry_resource (resource_name )(func )
48- wrapped = mcp .resource (uri = uri , name = resource_name ,
49- description = description , ** kwargs )(wrapped )
50- resource_info ['func' ] = wrapped
51- logger .debug (f"Registered resource: { resource_name } - { description } " )
66+ # Check if URI contains query parameters (e.g., {?unity_instance})
67+ has_query_params = '{?' in uri
68+
69+ if has_query_params :
70+ # Register two versions for backward compatibility:
71+ # 1. Template version with query parameters (for multi-instance)
72+ wrapped_template = telemetry_resource (resource_name )(func )
73+ wrapped_template = mcp .resource (uri = uri , name = resource_name ,
74+ description = description , ** kwargs )(wrapped_template )
75+ logger .debug (f"Registered resource template: { resource_name } - { uri } " )
76+ registered_count += 1
77+
78+ # 2. Fixed version without query parameters (for single-instance/default)
79+ # Remove query parameters from URI
80+ fixed_uri = uri .split ('{?' )[0 ]
81+ fixed_name = f"{ resource_name } _default"
82+ fixed_description = f"{ description } (default instance)"
83+
84+ # Create a wrapper function that doesn't accept unity_instance parameter
85+ # This wrapper will call the original function with unity_instance=None
86+ sig = inspect .signature (func )
87+ params = list (sig .parameters .values ())
88+
89+ # Filter out unity_instance parameter
90+ fixed_params = [p for p in params if p .name != 'unity_instance' ]
91+
92+ # Create wrapper using factory function to avoid closure issues
93+ has_other_params = len (fixed_params ) > 0
94+ fixed_wrapper = _create_fixed_wrapper (func , has_other_params )
95+
96+ # Update signature to match filtered parameters
97+ if has_other_params :
98+ fixed_wrapper .__signature__ = sig .replace (parameters = fixed_params )
99+ fixed_wrapper .__annotations__ = {
100+ k : v for k , v in func .__annotations__ .items ()
101+ if k != 'unity_instance'
102+ }
103+ else :
104+ fixed_wrapper .__signature__ = inspect .Signature (parameters = [])
105+ fixed_wrapper .__annotations__ = {
106+ k : v for k , v in func .__annotations__ .items ()
107+ if k == 'return'
108+ }
109+
110+ # Preserve function metadata
111+ fixed_wrapper .__name__ = fixed_name
112+ fixed_wrapper .__doc__ = func .__doc__
113+
114+ wrapped_fixed = telemetry_resource (fixed_name )(fixed_wrapper )
115+ wrapped_fixed = mcp .resource (uri = fixed_uri , name = fixed_name ,
116+ description = fixed_description , ** kwargs )(wrapped_fixed )
117+ logger .debug (f"Registered resource (fixed): { fixed_name } - { fixed_uri } " )
118+ registered_count += 1
119+
120+ resource_info ['func' ] = wrapped_template
121+ else :
122+ # No query parameters, register as-is
123+ wrapped = telemetry_resource (resource_name )(func )
124+ wrapped = mcp .resource (uri = uri , name = resource_name ,
125+ description = description , ** kwargs )(wrapped )
126+ resource_info ['func' ] = wrapped
127+ logger .debug (f"Registered resource: { resource_name } - { description } " )
128+ registered_count += 1
52129
53- logger .info (f"Registered { len (resources )} MCP resources " )
130+ logger .info (f"Registered { registered_count } MCP resources ( { len (resources )} unique) " )
0 commit comments