adk-tool-search
ADK-native deferred tool discovery for large function and MCP catalogs.
SearchableToolset exposes four lightweight management tools initially. The model searches the
catalog, activates an exact result, and ADK exposes the selected tool on the next model step.
Selected tools execute through ADK's normal tool pipeline, preserving authentication,
confirmation, callbacks, plugins, tracing, and lifecycle behavior.
Why
Large tool catalogs increase prompt size and make tool selection less reliable. Tool search keeps full schemas out of the initial model request while retaining a searchable local catalog.
Initial request: search_tools, load_tool, unload_tool, clear_loaded_tools
↓
search_tools("weather by city")
↓
[{"name": "get_weather", "description": "...", "score": 4.2}]
↓
load_tool("get_weather")
↓
Next model step: management tools + get_weather
Install
pip install adk-tool-search
Function Tools
from google.adk.agents import LlmAgent
from adk_tool_search import SearchableToolset
def get_weather(location: str) -> dict:
"""Get current weather for a location.
Args:
location: City or coordinates.
"""
return {"location": location, "temperature": 22}
toolset = SearchableToolset(
namespace="assistant",
tools=[get_weather],
max_loaded_tools=20,
)
agent = LlmAgent(
name="assistant",
model="gemini-2.5-flash",
instruction=(
"Use search_tools to discover capabilities, load_tool to activate an exact result, "
"then call the activated tool."
),
tools=[toolset],
)
Loaded names are persisted in session state under:
adk_tool_search.loaded_tools.<namespace>
MCP Tools
Wrap the McpToolset instead of detaching its tools at startup:
from google.adk.agents import LlmAgent
from google.adk.tools.mcp_tool import McpToolset, StdioConnectionParams
from mcp import StdioServerParameters
from adk_tool_search import SearchableToolset
mcp = McpToolset(
connection_params=StdioConnectionParams(
server_params=StdioServerParameters(
command="npx",
args=["-y", "@modelcontextprotocol/server-github"],
)
)
)
github_tools = SearchableToolset(
namespace="github",
source=mcp,
tool_name_prefix="github",
)
agent = LlmAgent(
name="github_assistant",
model="gemini-2.5-flash",
tools=[github_tools],
)
The wrapper delegates source authentication and close(), so ADK retains ownership of MCP
connections and cleanup. Use one prefixed SearchableToolset per authenticated MCP server because
ADK supports one authentication configuration per toolset.
Public API
SearchableToolset
SearchableToolset(
*,
namespace: str,
tools: Iterable[BaseTool | Callable] = (),
source: BaseToolset | None = None,
always_available: Iterable[BaseTool | Callable] = (),
index_factory: Callable[[], BM25ToolIndex] | None = None,
top_k: int = 5,
max_loaded_tools: int = 20,
tool_name_prefix: str | None = None,
)
tools: static deferred tools. Mutually exclusive withsource.source: one dynamic ADK toolset, includingMcpToolset.always_available: tools exposed on every model request but excluded from search.index_factory: creates an exclusively owned index for each context-specific source snapshot.top_k: maximum search results.max_loaded_tools: active deferred-tool budget.tool_name_prefix: ADK-compatible prefix for management and active tools.
The toolset exposes:
search_tools(query)load_tool(tool_name)unload_tool(tool_name)clear_loaded_tools()
load_tool does not execute another tool internally. The selected tool is executed normally by ADK
on a subsequent model step.
ToolCatalog
Normalizes callables to stable FunctionTool instances, validates names, rejects duplicates, and
extracts descriptions and parameter metadata.
BM25ToolIndex
Indexes tool names, descriptions, argument names, and argument descriptions. It supports custom stopwords and minimum token lengths.
ToolSearchResult
Structured retrieval result containing name, description, and score.
Multiple Sources
Use one searchable toolset per source and prefix each surface:
agent = LlmAgent(
name="assistant",
model="gemini-2.5-flash",
tools=[
SearchableToolset(namespace="github", source=github_mcp, tool_name_prefix="github"),
SearchableToolset(namespace="slack", source=slack_mcp, tool_name_prefix="slack"),
],
)
This preserves independent authentication, lifecycle, catalog refresh, and loaded-tool state.
Development
uv sync --all-extras
uv run ruff format --check .
uv run ruff check .
uv run pytest
Live model tests require .env credentials:
uv run pytest -m llm
The default test suite also starts a local stdio MCP subprocess and exercises real MCP listing,
calling, and cleanup without network access. Live LLM tests use the ADK_TOOL_SEARCH_LLM_MODEL,
ADK_TOOL_SEARCH_LLM_API_BASE, and ADK_TOOL_SEARCH_LLM_API_KEY values from .env.
Release files for adk-tool-search 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| adk_tool_search-0.3.0.tar.gz | 13.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| adk_tool_search-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 22.3 kB
Release files / adk_tool_search-0.3.0.tar.gz
| Download URL | adk_tool_search-0.3.0.tar.gz |
|---|---|
| Size | 13.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3af1b15c224c08cd5562a4e1be43748482efb40b92b83e732f77dd79ac8933e5
|
|
BLAKE2b-256 checksum How to use checksums |
d7c41688102fd8f29dc5313ef06076397a2ace62d6ed923f3a48fe43f2a8d495
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 12, 2026.
Transparency logRelease files / adk_tool_search-0.3.0-py3-none-any.whl
| Download URL | adk_tool_search-0.3.0-py3-none-any.whl |
|---|---|
| Size | 8.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1438a1cdb977a7efd8006d05f718aa31d0d54b50d507cc46f88893864fddc680
|
|
BLAKE2b-256 checksum How to use checksums |
c75b36062918e480d2236d0c46e498e21c091a5bbbdb5e13a5cf38d766162ce4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 12, 2026.
Transparency log