22#
33# SPDX-License-Identifier: Apache-2.0
44
5+ from collections .abc import Callable
56from typing import Any
67from urllib .parse import urlparse
78
1314
1415from .mcp_tool import (
1516 AsyncExecutor ,
17+ MCPClient ,
1618 MCPConnectionError ,
1719 MCPServerInfo ,
1820 MCPToolNotFoundError ,
@@ -145,13 +147,19 @@ def __init__(
145147 )
146148
147149 # This is a factory that creates the invocation function for the Tool
148- def create_invoke_tool (mcp_client , tool_name , tool_timeout ):
150+ def create_invoke_tool (
151+ owner_toolset : "MCPToolset" ,
152+ mcp_client : MCPClient ,
153+ tool_name : str ,
154+ tool_timeout : float ,
155+ ) -> Callable [..., Any ]:
156+ """Return a closure that keeps a strong reference to *owner_toolset* alive."""
157+
149158 def invoke_tool (** kwargs ) -> Any :
150- """Invoke a tool using the existing client and AsyncExecutor."""
151- result = AsyncExecutor .get_instance ().run (
159+ _ = owner_toolset # strong reference so GC can't collect the toolset too early
160+ return AsyncExecutor .get_instance ().run (
152161 mcp_client .call_tool (tool_name , kwargs ), timeout = tool_timeout
153162 )
154- return result
155163
156164 return invoke_tool
157165
@@ -170,7 +178,7 @@ def invoke_tool(**kwargs) -> Any:
170178 name = tool_info .name ,
171179 description = tool_info .description ,
172180 parameters = tool_info .inputSchema ,
173- function = create_invoke_tool (client , tool_info .name , self .invocation_timeout ),
181+ function = create_invoke_tool (self , client , tool_info .name , self .invocation_timeout ),
174182 )
175183 haystack_tools .append (tool )
176184
0 commit comments