Skip to content

Commit 9d78949

Browse files
shaheerzamanDouweM
andauthored
Prefer structuredContent MCP tool result when present (#2854)
Co-authored-by: Douwe Maan <[email protected]>
1 parent 5e2ede6 commit 9d78949

File tree

4 files changed

+625
-19
lines changed

4 files changed

+625
-19
lines changed

pydantic_ai_slim/pydantic_ai/mcp.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -225,13 +225,27 @@ async def direct_call_tool(
225225
except McpError as e:
226226
raise exceptions.ModelRetry(e.error.message)
227227

228-
content = [await self._map_tool_result_part(part) for part in result.content]
229-
230228
if result.isError:
231-
text = '\n'.join(str(part) for part in content)
232-
raise exceptions.ModelRetry(text)
233-
else:
234-
return content[0] if len(content) == 1 else content
229+
message: str | None = None
230+
if result.content: # pragma: no branch
231+
text_parts = [part.text for part in result.content if isinstance(part, mcp_types.TextContent)]
232+
message = '\n'.join(text_parts)
233+
234+
raise exceptions.ModelRetry(message or 'MCP tool call failed')
235+
236+
# Prefer structured content if there are only text parts, which per the docs would contain the JSON-encoded structured content for backward compatibility.
237+
# See https://github.com/modelcontextprotocol/python-sdk#structured-output
238+
if (structured := result.structuredContent) and not any(
239+
not isinstance(part, mcp_types.TextContent) for part in result.content
240+
):
241+
# The MCP SDK wraps primitives and generic types like list in a `result` key, but we want to use the raw value returned by the tool function.
242+
# See https://github.com/modelcontextprotocol/python-sdk#structured-output
243+
if isinstance(structured, dict) and len(structured) == 1 and 'result' in structured:
244+
return structured['result']
245+
return structured
246+
247+
mapped = [await self._map_tool_result_part(part) for part in result.content]
248+
return mapped[0] if len(mapped) == 1 else mapped
235249

236250
async def call_tool(
237251
self,

0 commit comments

Comments
 (0)