|
4 | 4 |
|
5 | 5 | import logging |
6 | 6 | from enum import Enum |
7 | | -from typing import TYPE_CHECKING, Any |
| 7 | +from typing import TYPE_CHECKING, Any, cast |
8 | 8 |
|
9 | 9 | import mcp.types as mcp_types |
10 | 10 |
|
@@ -200,10 +200,31 @@ async def call_tool( |
200 | 200 | trace_id = get_current_trace_id() |
201 | 201 | meta = {"_hud_trace_id": trace_id} if trace_id else None |
202 | 202 |
|
| 203 | + client = cast(Any, self.client) |
203 | 204 | try: |
204 | | - return await self.client.call_tool_mcp(name, args, _meta=meta) |
| 205 | + result = await client.call_tool(name=name, arguments=args, _meta=meta) |
205 | 206 | except TypeError: |
206 | | - return await self.client.call_tool_mcp(name, args) |
| 207 | + # Fallback for clients that don't accept _meta |
| 208 | + result = await client.call_tool(name=name, arguments=args) |
| 209 | + |
| 210 | + # FastMCP and mcp-python use slightly different result shapes/types. |
| 211 | + # Normalize to mcp.types.CallToolResult for the rest of HUD. |
| 212 | + is_error = getattr(result, "isError", None) |
| 213 | + if is_error is None: |
| 214 | + is_error = getattr(result, "is_error", False) |
| 215 | + structured = getattr(result, "structuredContent", None) |
| 216 | + if structured is None: |
| 217 | + structured = getattr(result, "structured_content", None) |
| 218 | + |
| 219 | + content = getattr(result, "content", None) |
| 220 | + if content is None: |
| 221 | + content = [] |
| 222 | + |
| 223 | + return mcp_types.CallToolResult( |
| 224 | + content=content, |
| 225 | + isError=bool(is_error), |
| 226 | + structuredContent=structured, |
| 227 | + ) |
207 | 228 |
|
208 | 229 | async def list_resources(self) -> list[mcp_types.Resource]: |
209 | 230 | """Fetch resources from server and cache. |
|
0 commit comments