What happened?
CodeMode's execute_tool returns an empty result when calling a registered tool. The tool is never actually executed — the async call_tool function is passed to the Monty sandbox as an external function, but the sandbox calls it without awaiting the coroutine.
<coroutine external_future(0)>
execute_tool result: content=[] structured_content=None meta=None
sys:1: RuntimeWarning: coroutine 'Provider.get_tool' was never awaited
Example Code
import asyncio
from fastmcp import FastMCP, Client
from fastmcp.experimental.transforms.code_mode import CodeMode
mcp = FastMCP("Test", transforms=[CodeMode()])
@mcp.tool()
async def greet(name: str) -> dict:
"""Greet someone."""
return {"greeting": f"Hello, {name}!"}
async def demo():
async with Client(mcp) as client:
# List tools — should show 'execute_tool'
tools = await client.list_tools()
print(f"Tools: {[t.name for t in tools]}")
# Call execute_tool to invoke greet
result = await client.call_tool("execute", {
"code": 'print(call_tool("greet", {"name": "World"}))'
})
print(f"Result: {result}") # Expected: {"greeting": "Hello, World!"}
# Actual: empty result
if __name__ == "__main__":
asyncio.run(demo())
Version Information
FastMCP version: 3.3.1
MCP version: 1.27.1
Python version: 3.12.4
Platform: macOS-15.7.3-arm64-arm-64bit
FastMCP root path: /Users/baadzianton/TrueConf/trueconf-server-mcp-server/.venv/lib/python3.12/site-packages
What happened?
CodeMode's execute_tool returns an empty result when calling a registered tool. The tool is never actually executed — the async
call_toolfunction is passed to the Monty sandbox as an external function, but the sandbox calls it without awaiting the coroutine.Example Code
Version Information