FunctionTool adapts a Python callable and its tool definition to the BaseTool interface. It keeps executable behavior and LLM-facing metadata together, so agents can pass context uniformly and execute local or remote tools through the same abstraction. section 4.4.1 section 4.4.3
FunctionTool handles the main differences between ordinary functions and agent tools:
- Inspects the callable signature during initialization and records whether it accepts an ExecutionContext parameter. section 4.4.3
- Passes context only to context-aware functions, leaving simple signatures such as search_web(query) unchanged. section 4.4.3
- Derives the tool name, description, and input schema from the function unless explicit metadata overrides them. section 4.4.3
- Lets the @tool decorator create the wrapper with concise syntax and optional custom metadata. section 4.4.3
Wrapping a calculator
Define calculator(expression: str) -> float, then create calc_tool = FunctionTool(calculator). The wrapper exposes the name "calculator", the function docstring, generated parameters, and execution through the common tool interface.
Listing 4.8 Creating FunctionTool from the MCP tool
def _create_mcp_tool(mcp_tool, connection: dict) -> FunctionTool:
"""Create a FunctionTool that wraps an MCP tool."""
async def call_mcp(**kwargs):
async with stdio_client(StdioServerParameters(**connection)) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
result = await session.call_tool(mcp_tool.name, kwargs)
return _extract_text_content(result)
tool_definition = {
"type": "function",
"function": {
"name": mcp_tool.name,
"description": mcp_tool.description,
"parameters": mcp_tool.inputSchema,
}
}
return FunctionTool(
func=call_mcp,
name=mcp_tool.name,
description=mcp_tool.description,
tool_definition=tool_definition
)
Trace how an MCP tool becomes a FunctionTool with an explicitly supplied remote schema and a wrapper that calls the MCP server. section 4.4.4
