26
26
from ...types import PaginatedList
27
27
from ...types .exceptions import MCPClientInitializationError
28
28
from ...types .media import ImageFormat
29
- from ...types .tools import ToolResult , ToolResultContent , ToolResultStatus
29
+ from ...types .tools import ToolResultContent , ToolResultStatus
30
30
from .mcp_agent_tool import MCPAgentTool
31
- from .mcp_types import MCPTransport
31
+ from .mcp_types import MCPToolResult , MCPTransport
32
32
33
33
logger = logging .getLogger (__name__ )
34
34
@@ -57,7 +57,8 @@ class MCPClient:
57
57
It handles the creation, initialization, and cleanup of MCP connections.
58
58
59
59
The connection runs in a background thread to avoid blocking the main application thread
60
- while maintaining communication with the MCP service.
60
+ while maintaining communication with the MCP service. When structured content is available
61
+ from MCP tools, it will be returned as the last item in the content array of the ToolResult.
61
62
"""
62
63
63
64
def __init__ (self , transport_callable : Callable [[], MCPTransport ]):
@@ -170,11 +171,13 @@ def call_tool_sync(
170
171
name : str ,
171
172
arguments : dict [str , Any ] | None = None ,
172
173
read_timeout_seconds : timedelta | None = None ,
173
- ) -> ToolResult :
174
+ ) -> MCPToolResult :
174
175
"""Synchronously calls a tool on the MCP server.
175
176
176
177
This method calls the asynchronous call_tool method on the MCP session
177
- and converts the result to the ToolResult format.
178
+ and converts the result to the ToolResult format. If the MCP tool returns
179
+ structured content, it will be included as the last item in the content array
180
+ of the returned ToolResult.
178
181
179
182
Args:
180
183
tool_use_id: Unique identifier for this tool use
@@ -183,7 +186,7 @@ def call_tool_sync(
183
186
read_timeout_seconds: Optional timeout for the tool call
184
187
185
188
Returns:
186
- ToolResult : The result of the tool call
189
+ MCPToolResult : The result of the tool call
187
190
"""
188
191
self ._log_debug_with_thread ("calling MCP tool '%s' synchronously with tool_use_id=%s" , name , tool_use_id )
189
192
if not self ._is_session_active ():
@@ -205,11 +208,11 @@ async def call_tool_async(
205
208
name : str ,
206
209
arguments : dict [str , Any ] | None = None ,
207
210
read_timeout_seconds : timedelta | None = None ,
208
- ) -> ToolResult :
211
+ ) -> MCPToolResult :
209
212
"""Asynchronously calls a tool on the MCP server.
210
213
211
214
This method calls the asynchronous call_tool method on the MCP session
212
- and converts the result to the ToolResult format.
215
+ and converts the result to the MCPToolResult format.
213
216
214
217
Args:
215
218
tool_use_id: Unique identifier for this tool use
@@ -218,7 +221,7 @@ async def call_tool_async(
218
221
read_timeout_seconds: Optional timeout for the tool call
219
222
220
223
Returns:
221
- ToolResult : The result of the tool call
224
+ MCPToolResult : The result of the tool call
222
225
"""
223
226
self ._log_debug_with_thread ("calling MCP tool '%s' asynchronously with tool_use_id=%s" , name , tool_use_id )
224
227
if not self ._is_session_active ():
@@ -235,15 +238,27 @@ async def _call_tool_async() -> MCPCallToolResult:
235
238
logger .exception ("tool execution failed" )
236
239
return self ._handle_tool_execution_error (tool_use_id , e )
237
240
238
- def _handle_tool_execution_error (self , tool_use_id : str , exception : Exception ) -> ToolResult :
241
+ def _handle_tool_execution_error (self , tool_use_id : str , exception : Exception ) -> MCPToolResult :
239
242
"""Create error ToolResult with consistent logging."""
240
- return ToolResult (
243
+ return MCPToolResult (
241
244
status = "error" ,
242
245
toolUseId = tool_use_id ,
243
246
content = [{"text" : f"Tool execution failed: { str (exception )} " }],
244
247
)
245
248
246
- def _handle_tool_result (self , tool_use_id : str , call_tool_result : MCPCallToolResult ) -> ToolResult :
249
+ def _handle_tool_result (self , tool_use_id : str , call_tool_result : MCPCallToolResult ) -> MCPToolResult :
250
+ """Maps MCP tool result to the agent's MCPToolResult format.
251
+
252
+ This method processes the content from the MCP tool call result and converts it to the format
253
+ expected by the framework.
254
+
255
+ Args:
256
+ tool_use_id: Unique identifier for this tool use
257
+ call_tool_result: The result from the MCP tool call
258
+
259
+ Returns:
260
+ MCPToolResult: The converted tool result
261
+ """
247
262
self ._log_debug_with_thread ("received tool result with %d content items" , len (call_tool_result .content ))
248
263
249
264
mapped_content = [
@@ -254,7 +269,15 @@ def _handle_tool_result(self, tool_use_id: str, call_tool_result: MCPCallToolRes
254
269
255
270
status : ToolResultStatus = "error" if call_tool_result .isError else "success"
256
271
self ._log_debug_with_thread ("tool execution completed with status: %s" , status )
257
- return ToolResult (status = status , toolUseId = tool_use_id , content = mapped_content )
272
+ result = MCPToolResult (
273
+ status = status ,
274
+ toolUseId = tool_use_id ,
275
+ content = mapped_content ,
276
+ )
277
+ if call_tool_result .structuredContent :
278
+ result ["structuredContent" ] = call_tool_result .structuredContent
279
+
280
+ return result
258
281
259
282
async def _async_background_thread (self ) -> None :
260
283
"""Asynchronous method that runs in the background thread to manage the MCP connection.
0 commit comments