fix(browser): route MCP register through _result_to_mcp — ToolImage→ImageContent

The browser tool's bespoke register() returned execute()'s dict RAW, so FastMCP
flat-JSON-serialized a screenshot's ToolImage (base64 inline, 250K chars) →
overflowed the agent context and wedged the run — the SAME bug main's
ImageContent converter (711eb498) fixed for every OTHER tool via
BaseTool.register→_result_to_mcp, but the browser tool bypassed that path.
Now both registration paths share the one converter: nested ToolImage anywhere
in the result becomes a native MCP ImageContent block the client SEES. One way.
This commit is contained in:
2026-07-05 04:29:07 -07:00
parent 82df3bdcb3
commit 4991923b67
@@ -32,6 +32,7 @@ from pydantic import Field
from mcp.server import FastMCP
from hanzo_tools.core import BaseTool, ToolImage
from hanzo_tools.core.unified import _result_to_mcp
# Playwright import with graceful fallback
try:
@@ -2508,9 +2509,13 @@ CATEGORIES:
Optional[str], Field(description="Trace output")
] = None,
level: Annotated[Optional[str], Field(description="Console level")] = None,
) -> dict[str, Any]:
) -> Any:
"""Complete browser automation with full Playwright API surface area."""
return await tool_instance.execute(
# One way for images: route through the SAME converter BaseTool.register
# uses, so a screenshot's ToolImage becomes a native MCP ImageContent
# block the client SEES — never a 250K-char base64 blob flattened into
# JSON text (which overflows the agent context and wedges the run).
result = await tool_instance.execute(
action=action,
url=url,
selector=selector,
@@ -2570,6 +2575,7 @@ CATEGORIES:
trace_path=trace_path,
level=level,
)
return _result_to_mcp(result)
def create_browser_tool(