tools.py
1 from collections import defaultdict 2 import os 3 import socket 4 from typing import List, Sequence, Union 5 from urllib.parse import urlparse 6 7 from google.adk.tools.base_toolset import BaseToolset 8 from google.adk.tools.mcp_tool.mcp_session_manager import SseConnectionParams 9 from google.adk.tools.mcp_tool.mcp_toolset import MCPToolset 10 from mcp.client.stdio import StdioServerParameters 11 12 13 def _tcp_check(host: str, port: int) -> None: 14 """Fail fast if the MCP gateway is unreachable.""" 15 try: 16 with socket.create_connection((host, port), timeout=5): 17 pass 18 except OSError as e: 19 raise RuntimeError(f"cannot reach {host}:{port}: {e}") from e 20 21 22 def create_mcp_toolsets( 23 tools_cfg: Sequence[str], 24 ) -> List[BaseToolset]: 25 """Return MCPToolset objects - let ADK handle async initialization naturally.""" 26 if not tools_cfg: 27 return [] 28 29 tools_by_server: defaultdict[str, list[str]] = defaultdict(list) 30 for raw in tools_cfg: 31 if not raw.startswith("mcp/") or ":" not in raw: 32 raise ValueError(f"Bad MCP spec: {raw}") 33 server, tool = raw[4:].split(":", 1) 34 # Use just the tool name, not server:tool format 35 tools_by_server[server].append(tool) 36 37 endpoint = os.environ["MCPGATEWAY_ENDPOINT"] 38 conn_params: Union[SseConnectionParams, StdioServerParameters] 39 if endpoint.startswith(("http://", "https://")): 40 parsed = urlparse(endpoint) 41 if not parsed.hostname: 42 raise ValueError("invalid MCP gateway URL") 43 host, port = parsed.hostname, parsed.port or 80 44 _tcp_check(host, port) 45 conn_params = SseConnectionParams(url=endpoint) 46 else: 47 host, port_str = endpoint.split(":") 48 _tcp_check(host, int(port_str)) 49 conn_params = StdioServerParameters( 50 command="socat", 51 args=["STDIO", f"TCP:{endpoint}"], 52 ) 53 54 result: list[BaseToolset] = [] 55 for tool_list in tools_by_server.values(): 56 toolset = MCPToolset(connection_params=conn_params, tool_filter=tool_list) 57 result.append(toolset) 58 59 return result