def retry_on_closed_resource(async_reinit_func_name: str):
  """Decorator to automatically reinitialize session and retry action.

  When MCP session was closed, the decorator will automatically recreate the
  session and retry the action with the same parameters.

  Note:
  1. async_reinit_func_name is the name of the class member function that
  reinitializes the MCP session.
  2. Both the decorated function and the async_reinit_func_name must be async
  functions.

  Usage:
  class MCPTool:
      ...
      async def create_session(self):
          self.session = ...

      @retry_on_closed_resource('create_session')
      async def use_session(self):
          await self.session.call_tool()

  Args:
      async_reinit_func_name: The name of the async function to recreate session.

  Returns:
      The decorated function.
  """

  def decorator(func):
    @functools.wraps(func)  # Preserves original function metadata
    async def wrapper(self, *args, **kwargs):
      try:
        return await func(self, *args, **kwargs)
      except anyio.ClosedResourceError as close_err:
        try:
          if hasattr(self, async_reinit_func_name) and callable(
              getattr(self, async_reinit_func_name)
          ):
            async_init_fn = getattr(self, async_reinit_func_name)
            await async_init_fn()
          else:
            raise ValueError(
                f'Function {async_reinit_func_name} does not exist in decorated'
                ' class. Please check the function name in'
                ' retry_on_closed_resource decorator.'
            ) from close_err
        except Exception as reinit_err:
          raise RuntimeError(
              f'Error reinitializing: {reinit_err}'
          ) from reinit_err
        return await func(self, *args, **kwargs)

    return wrapper

  return decorator
Decorator to automatically reinitialize session and retry action.

  When MCP session was closed, the decorator will automatically recreate the
  session and retry the action with the same parameters.

  Note:
  1. async_reinit_func_name is the name of the class member function that
  reinitializes the MCP session.
  2. Both the decorated function and the async_reinit_func_name must be async
  functions.

  Usage:
  class MCPTool:
      ...
      async def create_session(self):
          self.session = ...

      @retry_on_closed_resource('create_session')
      async def use_session(self):
          await self.session.call_tool()

  Args:
      async_reinit_func_name: The name of the async function to recreate session.

  Returns:
      The decorated function.
  
src/google/adk/tools/mcp_tool/mcp_session_manager.py