Concept #175Mediumpython-for-gen-aigoogle-adk

How to create custom tools (Function Tools, MCP Tools, OpenAPI Tools) in Google ADK with code examples?

#google-adk#tools#function-tools#mcp#openapi#custom

Answer

Creating Custom Tools in Google ADK

Google ADK makes it easy to create tools from Python functions, MCP servers, or OpenAPI specifications. Tools are how agents interact with the outside world.


Tool Execution Flow

Quickstart Flow
Quickstart Flow


1. Function Tools (Most Common)

Any Python function with type hints and a docstring becomes a tool:

python
from google.adk.agents import Agent
import requests

def search_arxiv(query: str, max_results: int = 5) -> list[dict]:
    """Search arXiv for academic papers.

    Args:
        query: Search query for academic papers.
        max_results: Maximum number of papers to return.

    Returns:
        list[dict]: List of papers with title, authors, and summary.
    """
    # API call to arXiv
    url = f"http://export.arxiv.org/api/query?search_query={query}&max_results={max_results}"
    response = requests.get(url)
    # Parse and return results
    return [{"title": "Paper 1", "authors": ["Author A"], "summary": "..."}]

def save_notes(filename: str, content: str) -> str:
    """Save research notes to a file.

    Args:
        filename: Name of the file to save.
        content: Content to write to the file.

    Returns:
        str: Confirmation message.
    """
    with open(f"notes/{filename}", "w") as f:
        f.write(content)
    return f"Notes saved to {filename}"

# Agent automatically discovers tool signatures
agent = Agent(
    name="researcher",
    model="gemini-2.5-flash",
    instruction="Help users find and organize research papers.",
    tools=[search_arxiv, save_notes],
)

Tool with Context Access

python
def get_user_history(tool_context) -> list[str]:
    """Get the current user's query history."""
    history = tool_context.state.get("user:history", [])
    return history

def update_preferences(preference: str, value: str, tool_context) -> str:
    """Update user preferences.

    Args:
        preference: The preference key to update.
        value: The new value for the preference.
    """
    tool_context.state[f"user:pref_{preference}"] = value
    return f"Updated {preference} = {value}"

2. MCP Tools

Stdio Connection (Local)

python
from google.adk.tools.mcp_tool import McpToolset, StdioServerParameters

# Filesystem MCP server
fs_tools = McpToolset(
    connection_params=StdioServerParameters(
        command="npx",
        args=["-y", "@modelcontextprotocol/server-filesystem", "./data"],
    )
)

# Database MCP server
db_tools = McpToolset(
    connection_params=StdioServerParameters(
        command="npx",
        args=["-y", "@modelcontextprotocol/server-postgres"],
        env={"DATABASE_URL": "postgresql://localhost:5432/mydb"}
    )
)

agent = Agent(
    name="data_agent",
    model="gemini-2.5-flash",
    instruction="Help users manage files and query databases.",
    tools=[fs_tools, db_tools],
)

SSE Connection (Remote)

python
from google.adk.tools.mcp_tool import McpToolset, SseServerParams

remote_tools = McpToolset(
    connection_params=SseServerParams(
        url="https://mcp-server.example.com/sse",
        headers={"Authorization": "Bearer your-token"}
    )
)

3. OpenAPI Tools

Auto-generate tools from an API specification:

python
from google.adk.tools.openapi_tool import OpenAPIToolset

# From YAML file
yaml_toolset = OpenAPIToolset(
    spec_str=open("petstore.yaml").read(),
    spec_str_type="yaml",
)

# From JSON file
json_toolset = OpenAPIToolset(
    spec_str=open("api-spec.json").read(),
    spec_str_type="json",
)

# With authentication
auth_toolset = OpenAPIToolset(
    spec_str=open("api.yaml").read(),
    spec_str_type="yaml",
    auth={"api_key": "your-api-key"},
)

agent = Agent(
    name="api_agent",
    model="gemini-2.5-flash",
    instruction="Help users interact with the API.",
    tools=yaml_toolset.get_tools(),
)

4. Agents-as-Tools

python
from google.adk.tools import AgentTool

specialist = Agent(
    name="code_reviewer",
    model="gemini-2.5-flash",
    instruction="Review code for bugs, security issues, and best practices.",
)

main_agent = Agent(
    name="dev_assistant",
    model="gemini-2.5-flash",
    instruction="Help developers. Use the code reviewer for code analysis.",
    tools=[AgentTool(agent=specialist)],
)

Best Practices

PracticeWhy
Always add docstringsADK uses them as tool descriptions for the LLM
Use type hintsADK extracts parameter types from hints
Keep tools focusedOne tool = one action
Return structured dataDicts and lists are better than plain strings
Use
text
tool_context
Access state, save artifacts, manage context

Learn more at Function Tools and MCP Tools.