google-adk 1.0.0__py3-none-any.whl → 1.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- google/adk/agents/callback_context.py +2 -1
- google/adk/agents/readonly_context.py +3 -1
- google/adk/auth/auth_credential.py +4 -1
- google/adk/cli/browser/index.html +4 -4
- google/adk/cli/browser/{main-QOEMUXM4.js → main-PKDNKWJE.js} +59 -59
- google/adk/cli/browser/polyfills-B6TNHZQ6.js +17 -0
- google/adk/cli/cli.py +3 -2
- google/adk/cli/cli_eval.py +6 -85
- google/adk/cli/cli_tools_click.py +39 -10
- google/adk/cli/fast_api.py +53 -184
- google/adk/cli/utils/agent_loader.py +137 -0
- google/adk/cli/utils/cleanup.py +40 -0
- google/adk/cli/utils/evals.py +2 -1
- google/adk/cli/utils/logs.py +2 -7
- google/adk/code_executors/code_execution_utils.py +2 -1
- google/adk/code_executors/container_code_executor.py +0 -1
- google/adk/code_executors/vertex_ai_code_executor.py +6 -8
- google/adk/evaluation/eval_case.py +3 -1
- google/adk/evaluation/eval_metrics.py +74 -0
- google/adk/evaluation/eval_result.py +86 -0
- google/adk/evaluation/eval_set.py +2 -0
- google/adk/evaluation/eval_set_results_manager.py +47 -0
- google/adk/evaluation/eval_sets_manager.py +2 -1
- google/adk/evaluation/evaluator.py +2 -0
- google/adk/evaluation/local_eval_set_results_manager.py +113 -0
- google/adk/evaluation/local_eval_sets_manager.py +4 -4
- google/adk/evaluation/response_evaluator.py +2 -1
- google/adk/evaluation/trajectory_evaluator.py +3 -2
- google/adk/examples/base_example_provider.py +1 -0
- google/adk/flows/llm_flows/base_llm_flow.py +4 -6
- google/adk/flows/llm_flows/contents.py +3 -1
- google/adk/flows/llm_flows/instructions.py +7 -77
- google/adk/flows/llm_flows/single_flow.py +1 -1
- google/adk/models/base_llm.py +2 -1
- google/adk/models/base_llm_connection.py +2 -0
- google/adk/models/google_llm.py +4 -1
- google/adk/models/lite_llm.py +3 -2
- google/adk/models/llm_response.py +2 -1
- google/adk/runners.py +36 -4
- google/adk/sessions/_session_util.py +2 -1
- google/adk/sessions/database_session_service.py +5 -8
- google/adk/sessions/vertex_ai_session_service.py +28 -13
- google/adk/telemetry.py +4 -2
- google/adk/tools/agent_tool.py +1 -1
- google/adk/tools/apihub_tool/apihub_toolset.py +1 -1
- google/adk/tools/apihub_tool/clients/apihub_client.py +10 -3
- google/adk/tools/apihub_tool/clients/secret_client.py +1 -0
- google/adk/tools/application_integration_tool/application_integration_toolset.py +6 -2
- google/adk/tools/application_integration_tool/clients/connections_client.py +8 -1
- google/adk/tools/application_integration_tool/clients/integration_client.py +3 -1
- google/adk/tools/application_integration_tool/integration_connector_tool.py +1 -1
- google/adk/tools/base_toolset.py +40 -2
- google/adk/tools/bigquery/__init__.py +28 -0
- google/adk/tools/bigquery/bigquery_credentials.py +216 -0
- google/adk/tools/bigquery/bigquery_tool.py +116 -0
- google/adk/tools/function_parameter_parse_util.py +7 -0
- google/adk/tools/function_tool.py +33 -3
- google/adk/tools/get_user_choice_tool.py +1 -0
- google/adk/tools/google_api_tool/__init__.py +17 -11
- google/adk/tools/google_api_tool/google_api_tool.py +1 -1
- google/adk/tools/google_api_tool/google_api_toolset.py +0 -14
- google/adk/tools/google_api_tool/google_api_toolsets.py +8 -2
- google/adk/tools/google_search_tool.py +2 -2
- google/adk/tools/mcp_tool/conversion_utils.py +6 -2
- google/adk/tools/mcp_tool/mcp_session_manager.py +62 -188
- google/adk/tools/mcp_tool/mcp_tool.py +27 -24
- google/adk/tools/mcp_tool/mcp_toolset.py +76 -131
- google/adk/tools/openapi_tool/auth/credential_exchangers/base_credential_exchanger.py +1 -3
- google/adk/tools/openapi_tool/auth/credential_exchangers/service_account_exchanger.py +6 -7
- google/adk/tools/openapi_tool/common/common.py +5 -1
- google/adk/tools/openapi_tool/openapi_spec_parser/__init__.py +7 -2
- google/adk/tools/openapi_tool/openapi_spec_parser/openapi_toolset.py +2 -7
- google/adk/tools/openapi_tool/openapi_spec_parser/operation_parser.py +5 -1
- google/adk/tools/openapi_tool/openapi_spec_parser/rest_api_tool.py +11 -1
- google/adk/tools/toolbox_toolset.py +31 -3
- google/adk/utils/__init__.py +13 -0
- google/adk/utils/instructions_utils.py +131 -0
- google/adk/version.py +1 -1
- {google_adk-1.0.0.dist-info → google_adk-1.1.0.dist-info}/METADATA +12 -15
- {google_adk-1.0.0.dist-info → google_adk-1.1.0.dist-info}/RECORD +83 -78
- google/adk/agents/base_agent.py.orig +0 -330
- google/adk/cli/browser/polyfills-FFHMD2TL.js +0 -18
- google/adk/cli/fast_api.py.orig +0 -822
- google/adk/memory/base_memory_service.py.orig +0 -76
- google/adk/models/google_llm.py.orig +0 -305
- google/adk/tools/_built_in_code_execution_tool.py +0 -70
- google/adk/tools/mcp_tool/mcp_session_manager.py.orig +0 -322
- {google_adk-1.0.0.dist-info → google_adk-1.1.0.dist-info}/WHEEL +0 -0
- {google_adk-1.0.0.dist-info → google_adk-1.1.0.dist-info}/entry_points.txt +0 -0
- {google_adk-1.0.0.dist-info → google_adk-1.1.0.dist-info}/licenses/LICENSE +0 -0
@@ -12,8 +12,7 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
|
16
|
-
from contextlib import asynccontextmanager
|
15
|
+
|
17
16
|
from contextlib import AsyncExitStack
|
18
17
|
import functools
|
19
18
|
import logging
|
@@ -71,29 +70,27 @@ def retry_on_closed_resource(async_reinit_func_name: str):
|
|
71
70
|
|
72
71
|
Usage:
|
73
72
|
class MCPTool:
|
74
|
-
|
75
|
-
|
76
|
-
|
73
|
+
...
|
74
|
+
async def create_session(self):
|
75
|
+
self.session = ...
|
77
76
|
|
78
|
-
|
79
|
-
|
80
|
-
|
77
|
+
@retry_on_closed_resource('create_session')
|
78
|
+
async def use_session(self):
|
79
|
+
await self.session.call_tool()
|
81
80
|
|
82
81
|
Args:
|
83
|
-
|
82
|
+
async_reinit_func_name: The name of the async function to recreate session.
|
84
83
|
|
85
84
|
Returns:
|
86
|
-
|
85
|
+
The decorated function.
|
87
86
|
"""
|
88
87
|
|
89
88
|
def decorator(func):
|
90
|
-
@functools.wraps(
|
91
|
-
func
|
92
|
-
) # Preserves original function metadata (name, docstring)
|
89
|
+
@functools.wraps(func) # Preserves original function metadata
|
93
90
|
async def wrapper(self, *args, **kwargs):
|
94
91
|
try:
|
95
92
|
return await func(self, *args, **kwargs)
|
96
|
-
except anyio.ClosedResourceError:
|
93
|
+
except anyio.ClosedResourceError as close_err:
|
97
94
|
try:
|
98
95
|
if hasattr(self, async_reinit_func_name) and callable(
|
99
96
|
getattr(self, async_reinit_func_name)
|
@@ -105,7 +102,7 @@ def retry_on_closed_resource(async_reinit_func_name: str):
|
|
105
102
|
f'Function {async_reinit_func_name} does not exist in decorated'
|
106
103
|
' class. Please check the function name in'
|
107
104
|
' retry_on_closed_resource decorator.'
|
108
|
-
)
|
105
|
+
) from close_err
|
109
106
|
except Exception as reinit_err:
|
110
107
|
raise RuntimeError(
|
111
108
|
f'Error reinitializing: {reinit_err}'
|
@@ -117,45 +114,6 @@ def retry_on_closed_resource(async_reinit_func_name: str):
|
|
117
114
|
return decorator
|
118
115
|
|
119
116
|
|
120
|
-
@asynccontextmanager
|
121
|
-
async def tracked_stdio_client(server, errlog, process=None):
|
122
|
-
"""A wrapper around stdio_client that ensures proper process tracking and cleanup."""
|
123
|
-
our_process = process
|
124
|
-
|
125
|
-
# If no process was provided, create one
|
126
|
-
if our_process is None:
|
127
|
-
our_process = await asyncio.create_subprocess_exec(
|
128
|
-
server.command,
|
129
|
-
*server.args,
|
130
|
-
stdin=asyncio.subprocess.PIPE,
|
131
|
-
stdout=asyncio.subprocess.PIPE,
|
132
|
-
stderr=errlog,
|
133
|
-
)
|
134
|
-
|
135
|
-
# Use the original stdio_client, but ensure process cleanup
|
136
|
-
try:
|
137
|
-
async with stdio_client(server=server, errlog=errlog) as client:
|
138
|
-
yield client, our_process
|
139
|
-
finally:
|
140
|
-
# Ensure the process is properly terminated if it still exists
|
141
|
-
if our_process and our_process.returncode is None:
|
142
|
-
try:
|
143
|
-
logger.info(
|
144
|
-
f'Terminating process {our_process.pid} from tracked_stdio_client'
|
145
|
-
)
|
146
|
-
our_process.terminate()
|
147
|
-
try:
|
148
|
-
await asyncio.wait_for(our_process.wait(), timeout=3.0)
|
149
|
-
except asyncio.TimeoutError:
|
150
|
-
# Force kill if it doesn't terminate quickly
|
151
|
-
if our_process.returncode is None:
|
152
|
-
logger.warning(f'Forcing kill of process {our_process.pid}')
|
153
|
-
our_process.kill()
|
154
|
-
except ProcessLookupError:
|
155
|
-
# Process already gone, that's fine
|
156
|
-
logger.info(f'Process {our_process.pid} already terminated')
|
157
|
-
|
158
|
-
|
159
117
|
class MCPSessionManager:
|
160
118
|
"""Manages MCP client sessions.
|
161
119
|
|
@@ -166,162 +124,78 @@ class MCPSessionManager:
|
|
166
124
|
def __init__(
|
167
125
|
self,
|
168
126
|
connection_params: StdioServerParameters | SseServerParams,
|
169
|
-
exit_stack: AsyncExitStack,
|
170
127
|
errlog: TextIO = sys.stderr,
|
171
128
|
):
|
172
129
|
"""Initializes the MCP session manager.
|
173
130
|
|
174
|
-
Example usage:
|
175
|
-
```
|
176
|
-
mcp_session_manager = MCPSessionManager(
|
177
|
-
connection_params=connection_params,
|
178
|
-
exit_stack=exit_stack,
|
179
|
-
)
|
180
|
-
session = await mcp_session_manager.create_session()
|
181
|
-
```
|
182
|
-
|
183
131
|
Args:
|
184
132
|
connection_params: Parameters for the MCP connection (Stdio or SSE).
|
185
|
-
exit_stack: AsyncExitStack to manage the session lifecycle.
|
186
133
|
errlog: (Optional) TextIO stream for error logging. Use only for
|
187
134
|
initializing a local stdio MCP session.
|
188
135
|
"""
|
189
|
-
|
190
136
|
self._connection_params = connection_params
|
191
|
-
self._exit_stack = exit_stack
|
192
137
|
self._errlog = errlog
|
193
|
-
|
194
|
-
self.
|
195
|
-
self.
|
138
|
+
# Each session manager maintains its own exit stack for proper cleanup
|
139
|
+
self._exit_stack: Optional[AsyncExitStack] = None
|
140
|
+
self._session: Optional[ClientSession] = None
|
196
141
|
|
197
|
-
async def create_session(
|
198
|
-
|
199
|
-
) -> tuple[ClientSession, Optional[asyncio.subprocess.Process]]:
|
200
|
-
"""Creates a new MCP session and tracks the associated process."""
|
201
|
-
session, process = await self._initialize_session(
|
202
|
-
connection_params=self._connection_params,
|
203
|
-
exit_stack=self._exit_stack,
|
204
|
-
errlog=self._errlog,
|
205
|
-
)
|
206
|
-
self._process = process # Store reference to process
|
207
|
-
|
208
|
-
# Track the process
|
209
|
-
if process:
|
210
|
-
self._active_processes.add(process)
|
211
|
-
|
212
|
-
return session, process
|
213
|
-
|
214
|
-
@classmethod
|
215
|
-
async def _initialize_session(
|
216
|
-
cls,
|
217
|
-
*,
|
218
|
-
connection_params: StdioServerParameters | SseServerParams,
|
219
|
-
exit_stack: AsyncExitStack,
|
220
|
-
errlog: TextIO = sys.stderr,
|
221
|
-
) -> tuple[ClientSession, Optional[asyncio.subprocess.Process]]:
|
222
|
-
"""Initializes an MCP client session.
|
223
|
-
|
224
|
-
Args:
|
225
|
-
connection_params: Parameters for the MCP connection (Stdio or SSE).
|
226
|
-
exit_stack: AsyncExitStack to manage the session lifecycle.
|
227
|
-
errlog: (Optional) TextIO stream for error logging. Use only for
|
228
|
-
initializing a local stdio MCP session.
|
142
|
+
async def create_session(self) -> ClientSession:
|
143
|
+
"""Creates and initializes an MCP client session.
|
229
144
|
|
230
145
|
Returns:
|
231
146
|
ClientSession: The initialized MCP client session.
|
232
147
|
"""
|
233
|
-
|
234
|
-
|
235
|
-
if isinstance(connection_params, StdioServerParameters):
|
236
|
-
# For stdio connections, we need to track the subprocess
|
237
|
-
client, process = await cls._create_stdio_client(
|
238
|
-
server=connection_params,
|
239
|
-
errlog=errlog,
|
240
|
-
exit_stack=exit_stack,
|
241
|
-
)
|
242
|
-
elif isinstance(connection_params, SseServerParams):
|
243
|
-
# For SSE connections, create the client without a subprocess
|
244
|
-
client = sse_client(
|
245
|
-
url=connection_params.url,
|
246
|
-
headers=connection_params.headers,
|
247
|
-
timeout=connection_params.timeout,
|
248
|
-
sse_read_timeout=connection_params.sse_read_timeout,
|
249
|
-
)
|
250
|
-
else:
|
251
|
-
raise ValueError(
|
252
|
-
'Unable to initialize connection. Connection should be'
|
253
|
-
' StdioServerParameters or SseServerParams, but got'
|
254
|
-
f' {connection_params}'
|
255
|
-
)
|
148
|
+
if self._session is not None:
|
149
|
+
return self._session
|
256
150
|
|
257
|
-
# Create
|
258
|
-
|
259
|
-
session = await exit_stack.enter_async_context(ClientSession(*transports))
|
260
|
-
await session.initialize()
|
151
|
+
# Create a new exit stack for this session
|
152
|
+
self._exit_stack = AsyncExitStack()
|
261
153
|
|
262
|
-
return session, process
|
263
|
-
|
264
|
-
@staticmethod
|
265
|
-
async def _create_stdio_client(
|
266
|
-
server: StdioServerParameters,
|
267
|
-
errlog: TextIO,
|
268
|
-
exit_stack: AsyncExitStack,
|
269
|
-
) -> tuple[Any, asyncio.subprocess.Process]:
|
270
|
-
"""Create stdio client and return both the client and process.
|
271
|
-
|
272
|
-
This implementation adapts to how the MCP stdio_client is created.
|
273
|
-
The actual implementation may need to be adjusted based on the MCP library
|
274
|
-
structure.
|
275
|
-
"""
|
276
|
-
# Create the subprocess directly so we can track it
|
277
|
-
process = await asyncio.create_subprocess_exec(
|
278
|
-
server.command,
|
279
|
-
*server.args,
|
280
|
-
stdin=asyncio.subprocess.PIPE,
|
281
|
-
stdout=asyncio.subprocess.PIPE,
|
282
|
-
stderr=errlog,
|
283
|
-
)
|
284
|
-
|
285
|
-
# Create the stdio client using the MCP library
|
286
154
|
try:
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
155
|
+
if isinstance(self._connection_params, StdioServerParameters):
|
156
|
+
client = stdio_client(
|
157
|
+
server=self._connection_params, errlog=self._errlog
|
158
|
+
)
|
159
|
+
elif isinstance(self._connection_params, SseServerParams):
|
160
|
+
client = sse_client(
|
161
|
+
url=self._connection_params.url,
|
162
|
+
headers=self._connection_params.headers,
|
163
|
+
timeout=self._connection_params.timeout,
|
164
|
+
sse_read_timeout=self._connection_params.sse_read_timeout,
|
165
|
+
)
|
166
|
+
else:
|
167
|
+
raise ValueError(
|
168
|
+
'Unable to initialize connection. Connection should be'
|
169
|
+
' StdioServerParameters or SseServerParams, but got'
|
170
|
+
f' {self._connection_params}'
|
171
|
+
)
|
297
172
|
|
298
|
-
|
173
|
+
transports = await self._exit_stack.enter_async_context(client)
|
174
|
+
session = await self._exit_stack.enter_async_context(
|
175
|
+
ClientSession(*transports)
|
176
|
+
)
|
177
|
+
await session.initialize()
|
299
178
|
|
300
|
-
|
301
|
-
|
302
|
-
logger.info('Performing emergency cleanup of MCPSessionManager resources')
|
179
|
+
self._session = session
|
180
|
+
return session
|
303
181
|
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
try:
|
311
|
-
await asyncio.wait_for(proc.wait(), timeout=1.0)
|
312
|
-
except asyncio.TimeoutError:
|
313
|
-
logger.warning(f"Process {proc.pid} didn't terminate, forcing kill")
|
314
|
-
proc.kill()
|
315
|
-
self._active_processes.remove(proc)
|
316
|
-
except Exception as e:
|
317
|
-
logger.error(f'Error during process cleanup: {e}')
|
182
|
+
except Exception:
|
183
|
+
# If session creation fails, clean up the exit stack
|
184
|
+
if self._exit_stack:
|
185
|
+
await self._exit_stack.aclose()
|
186
|
+
self._exit_stack = None
|
187
|
+
raise
|
318
188
|
|
319
|
-
|
320
|
-
|
189
|
+
async def close(self):
|
190
|
+
"""Closes the session and cleans up resources."""
|
191
|
+
if self._exit_stack:
|
321
192
|
try:
|
322
|
-
|
323
|
-
logger.info('Closing file handle')
|
324
|
-
handle.close()
|
325
|
-
self._active_file_handles.remove(handle)
|
193
|
+
await self._exit_stack.aclose()
|
326
194
|
except Exception as e:
|
327
|
-
|
195
|
+
# Log the error but don't re-raise to avoid blocking shutdown
|
196
|
+
print(
|
197
|
+
f'Warning: Error during MCP session cleanup: {e}', file=self._errlog
|
198
|
+
)
|
199
|
+
finally:
|
200
|
+
self._exit_stack = None
|
201
|
+
self._session = None
|
@@ -12,6 +12,8 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
+
|
16
|
+
import logging
|
15
17
|
from typing import Optional
|
16
18
|
|
17
19
|
from google.genai.types import FunctionDeclaration
|
@@ -23,7 +25,6 @@ from .mcp_session_manager import retry_on_closed_resource
|
|
23
25
|
# Attempt to import MCP Tool from the MCP library, and hints user to upgrade
|
24
26
|
# their Python version to 3.10 if it fails.
|
25
27
|
try:
|
26
|
-
from mcp import ClientSession
|
27
28
|
from mcp.types import Tool as McpBaseTool
|
28
29
|
except ImportError as e:
|
29
30
|
import sys
|
@@ -43,6 +44,8 @@ from ..base_tool import BaseTool
|
|
43
44
|
from ..openapi_tool.openapi_spec_parser.rest_api_tool import to_gemini_schema
|
44
45
|
from ..tool_context import ToolContext
|
45
46
|
|
47
|
+
logger = logging.getLogger("google_adk." + __name__)
|
48
|
+
|
46
49
|
|
47
50
|
class MCPTool(BaseTool):
|
48
51
|
"""Turns a MCP Tool into a Vertex Agent Framework Tool.
|
@@ -53,44 +56,40 @@ class MCPTool(BaseTool):
|
|
53
56
|
|
54
57
|
def __init__(
|
55
58
|
self,
|
59
|
+
*,
|
56
60
|
mcp_tool: McpBaseTool,
|
57
|
-
mcp_session: ClientSession,
|
58
61
|
mcp_session_manager: MCPSessionManager,
|
59
62
|
auth_scheme: Optional[AuthScheme] = None,
|
60
|
-
auth_credential: Optional[AuthCredential]
|
63
|
+
auth_credential: Optional[AuthCredential] = None,
|
61
64
|
):
|
62
65
|
"""Initializes a MCPTool.
|
63
66
|
|
64
|
-
This tool wraps a MCP Tool interface and
|
65
|
-
|
66
|
-
|
67
|
-
Example:
|
68
|
-
tool = MCPTool(mcp_tool=mcp_tool, mcp_session=mcp_session)
|
67
|
+
This tool wraps a MCP Tool interface and uses a session manager to
|
68
|
+
communicate with the MCP server.
|
69
69
|
|
70
70
|
Args:
|
71
71
|
mcp_tool: The MCP tool to wrap.
|
72
|
-
|
72
|
+
mcp_session_manager: The MCP session manager to use for communication.
|
73
73
|
auth_scheme: The authentication scheme to use.
|
74
74
|
auth_credential: The authentication credential to use.
|
75
75
|
|
76
76
|
Raises:
|
77
|
-
ValueError: If mcp_tool or
|
77
|
+
ValueError: If mcp_tool or mcp_session_manager is None.
|
78
78
|
"""
|
79
79
|
if mcp_tool is None:
|
80
80
|
raise ValueError("mcp_tool cannot be None")
|
81
|
-
if
|
82
|
-
raise ValueError("
|
83
|
-
super().__init__(
|
81
|
+
if mcp_session_manager is None:
|
82
|
+
raise ValueError("mcp_session_manager cannot be None")
|
83
|
+
super().__init__(
|
84
|
+
name=mcp_tool.name,
|
85
|
+
description=mcp_tool.description if mcp_tool.description else "",
|
86
|
+
)
|
84
87
|
self._mcp_tool = mcp_tool
|
85
|
-
self._mcp_session = mcp_session
|
86
88
|
self._mcp_session_manager = mcp_session_manager
|
87
89
|
# TODO(cheliu): Support passing auth to MCP Server.
|
88
90
|
self._auth_scheme = auth_scheme
|
89
91
|
self._auth_credential = auth_credential
|
90
92
|
|
91
|
-
async def _reinitialize_session(self):
|
92
|
-
self._mcp_session = await self._mcp_session_manager.create_session()
|
93
|
-
|
94
93
|
@override
|
95
94
|
def _get_declaration(self) -> FunctionDeclaration:
|
96
95
|
"""Gets the function declaration for the tool.
|
@@ -105,7 +104,6 @@ class MCPTool(BaseTool):
|
|
105
104
|
)
|
106
105
|
return function_decl
|
107
106
|
|
108
|
-
@override
|
109
107
|
@retry_on_closed_resource("_reinitialize_session")
|
110
108
|
async def run_async(self, *, args, tool_context: ToolContext):
|
111
109
|
"""Runs the tool asynchronously.
|
@@ -117,10 +115,15 @@ class MCPTool(BaseTool):
|
|
117
115
|
Returns:
|
118
116
|
Any: The response from the tool.
|
119
117
|
"""
|
118
|
+
# Get the session from the session manager
|
119
|
+
session = await self._mcp_session_manager.create_session()
|
120
|
+
|
120
121
|
# TODO(cheliu): Support passing tool context to MCP Server.
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
122
|
+
response = await session.call_tool(self.name, arguments=args)
|
123
|
+
return response
|
124
|
+
|
125
|
+
async def _reinitialize_session(self):
|
126
|
+
"""Reinitializes the session when connection is lost."""
|
127
|
+
# Close the old session and create a new one
|
128
|
+
await self._mcp_session_manager.close()
|
129
|
+
await self._mcp_session_manager.create_session()
|