1818logger = logging .getLogger (__name__ )
1919
2020
21+ def _get_mcp_not_found_error ():
22+ """Return MCPNotFoundError class, or None when the package is unavailable."""
23+ try :
24+ from derisk_serve .agent .resource .tool .mcp_collect import MCPNotFoundError
25+ return MCPNotFoundError
26+ except ImportError :
27+ return None
28+
29+
2130def _is_valid_resource_instance (obj : Any ) -> bool :
2231 """Check if object is a valid resource instance (Resource or ToolBase)."""
2332 if isinstance (obj , Resource ):
@@ -267,10 +276,40 @@ def build_resource_by_type(
267276 if return_resource
268277 else {"name" : real_resource_name }
269278 )
270- raise ValueError (
271- f"Resource { real_resource_name } not found in { type_unique_key } "
272- )
273- # return cast(Resource, inst_items[0].resource_instance)
279+ # Not found in registered instances, try to create dynamically
280+ # This handles cases like MCP rebind where old instance exists
281+ # but code/name has changed
282+ single_item = item [0 ]
283+ try :
284+ parameter_cls = single_item .get_parameter_class ()
285+ param = parameter_cls .from_dict (
286+ resource_value if v2_resource else agent_resource .to_dict (),
287+ ignore_extra_fields = True ,
288+ )
289+ param_dict = param .to_dict ()
290+ if not return_resource :
291+ return param_dict
292+ param_dict ["system_app" ] = self .system_app
293+ resource_inst = single_item .resource_cls (** param_dict )
294+ return resource_inst
295+ except ValueError as e :
296+ # Check if this is an MCPNotFoundError (MCP deleted/recreated).
297+ mcp_not_found_cls = _get_mcp_not_found_error ()
298+ if mcp_not_found_cls and isinstance (e , mcp_not_found_cls ):
299+ logger .warning (
300+ f"Skipping unavailable MCP resource [{ single_item .key } ]: { e } . "
301+ f"Please re-bind the MCP in the application configuration."
302+ )
303+ return None
304+ logger .warning (f"Failed to build resource { single_item .key } : { str (e )} " )
305+ raise ValueError (
306+ f"Failed to build resource { single_item .key } : { str (e )} "
307+ )
308+ except Exception as e :
309+ logger .warning (f"Failed to build resource { single_item .key } : { str (e )} " )
310+ raise ValueError (
311+ f"Failed to build resource { single_item .key } : { str (e )} "
312+ )
274313 elif len (inst_items ) > 1 :
275314 raise ValueError (
276315 f"Multiple instances of resource { type_unique_key } found, "
@@ -290,6 +329,21 @@ def build_resource_by_type(
290329 param_dict ["system_app" ] = self .system_app
291330 resource_inst = single_item .resource_cls (** param_dict )
292331 return resource_inst
332+ except ValueError as e :
333+ # Check if this is an MCPNotFoundError (MCP deleted/recreated).
334+ # Catch it here before the generic re-raise so the rest of the
335+ # agent resources can still load.
336+ mcp_not_found_cls = _get_mcp_not_found_error ()
337+ if mcp_not_found_cls and isinstance (e , mcp_not_found_cls ):
338+ logger .warning (
339+ f"Skipping unavailable MCP resource [{ single_item .key } ]: { e } . "
340+ f"Please re-bind the MCP in the application configuration."
341+ )
342+ return None
343+ logger .warning (f"Failed to build resource { single_item .key } : { str (e )} " )
344+ raise ValueError (
345+ f"Failed to build resource { single_item .key } : { str (e )} "
346+ )
293347 except Exception as e :
294348 logger .warning (f"Failed to build resource { single_item .key } : { str (e )} " )
295349 raise ValueError (
@@ -320,13 +374,17 @@ def build_resource(
320374 for resource in agent_resources
321375 ]
322376 )
377+ # Filter out None entries (e.g. MCPs that were deleted/recreated)
378+ dependencies = [d for d in dependencies if d is not None ]
323379 # dependencies: List[Resource] = execute_parallel_sync([(self.build_resource_by_type, resource.type, resource) for resource in agent_resources])
324380 # dependencies: List[Resource] = []
325381 # for resource in agent_resources:
326382 # resource_inst = cast(
327383 # Resource, self.build_resource_by_type(resource.type, resource)
328384 # )
329385 # dependencies.append(resource_inst)
386+ if not dependencies :
387+ return None
330388 if len (dependencies ) == 1 :
331389 return dependencies [0 ]
332390 else :
@@ -356,13 +414,17 @@ async def a_build_resource(
356414 for resource in agent_resources
357415 ]
358416 )
359- # Summary Agent不放入resource中
417+ # Filter out None entries (e.g. MCPs that were deleted/recreated)
418+ # and Summary Agents that should not be included in the resource pack
360419 dependencies = [
361420 dependency
362421 for dependency in dependencies
363- if not await is_summary_agent_resource (dependency )
422+ if dependency is not None
423+ and not await is_summary_agent_resource (dependency )
364424 ]
365425
426+ if not dependencies :
427+ return None
366428 if len (dependencies ) == 1 :
367429 return dependencies [0 ]
368430 else :
0 commit comments