Skip to content

Commit 13fb859

Browse files
committed
chore: MCP metadata parsing logic updated.
1 parent b8ce49c commit 13fb859

File tree

1 file changed

+32
-36
lines changed
  • pydantic_ai_slim/pydantic_ai

1 file changed

+32
-36
lines changed

pydantic_ai_slim/pydantic_ai/mcp.py

Lines changed: 32 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -271,55 +271,51 @@ async def direct_call_tool(
271271
return messages.ToolReturn(return_value=return_value, metadata=result.meta) if result.meta else return_value
272272

273273
parts_with_metadata = [await self._map_tool_result_part(part) for part in result.content]
274-
parts_only = [mapped_part for mapped_part, _ in parts_with_metadata]
274+
parts_only = [part for part, _ in parts_with_metadata]
275275
any_part_has_metadata = any(metadata is not None for _, metadata in parts_with_metadata)
276-
if not any_part_has_metadata and result.meta is None:
277-
# There is no metadata in the tool result or its parts, return just the mapped values
278-
return parts_only[0] if len(parts_only) == 1 else parts_only
279-
elif not any_part_has_metadata and result.meta is not None:
280-
# There is no metadata in the tool result parts, but there is metadata in the tool result
281-
return messages.ToolReturn(
282-
return_value=(parts_only[0] if len(parts_only) == 1 else parts_only),
283-
metadata=result.meta,
284-
)
285-
else:
276+
return_values: list[Any] = []
277+
user_contents: list[Any] = []
278+
parts_metadata: dict[int, dict[str, Any]] = {}
279+
return_metadata: dict[str, Any] = {}
280+
if any_part_has_metadata:
286281
# There is metadata in the tool result parts and there may be a metadata in the tool result, return a ToolReturn object
287-
return_values: list[Any] = []
288-
user_contents: list[Any] = []
289-
return_metadata: dict[str, Any] = {}
290-
return_metadata.setdefault('content', [])
291-
for idx, (mapped_part, part_metadata) in enumerate(parts_with_metadata):
282+
for idx, (part, part_metadata) in enumerate(parts_with_metadata):
292283
if part_metadata is not None:
293-
# Merge the metadata dictionaries, with part metadata taking precedence
294-
return_metadata['content'].append({str(idx): part_metadata})
295-
if isinstance(mapped_part, messages.BinaryContent):
296-
identifier = mapped_part.identifier
284+
parts_metadata[idx] = part_metadata
285+
if isinstance(part, messages.BinaryContent):
286+
identifier = part.identifier
297287

298288
return_values.append(f'See file {identifier}')
299-
user_contents.append([f'This is file {identifier}:', mapped_part])
289+
user_contents.append([f'This is file {identifier}:', part])
300290
else:
301-
user_contents.append(mapped_part)
291+
user_contents.append(part)
302292

303-
if result.meta is not None and return_metadata.get('content', None) is not None:
304-
# Merge the tool result metadata into the return metadata, with part metadata taking precedence
305-
return_metadata['result'] = result.meta
306-
elif result.meta is not None and return_metadata.get('content', None) is None:
293+
if len(parts_metadata) > 0:
294+
if result.meta is not None and len(result.meta) > 0:
295+
# Merge the tool result metadata and parts metadata into the return metadata
296+
return_metadata = {'result': result.meta, 'content': parts_metadata}
297+
else:
298+
# Only parts metadata exists
299+
if len(parts_metadata) == 1:
300+
# If there is only one content metadata, unwrap it
301+
return_metadata = parts_metadata[0]
302+
else:
303+
return_metadata = {'content': parts_metadata}
304+
else:
305+
if result.meta is not None and len(result.meta) > 0:
307306
return_metadata = result.meta
308-
elif (
309-
result.meta is None
310-
and return_metadata.get('content', None) is not None
311-
and len(return_metadata['content']) == 1
312-
):
313-
# If there is only one content metadata, unwrap it
314-
return_metadata = return_metadata['content'][0]
315-
# TODO: What else should we cover here?
307+
# TODO: What else should we cover here?
316308

317-
# Finally, construct and return the ToolReturn object
318-
return messages.ToolReturn(
309+
# Finally, construct and return the ToolReturn object
310+
return (
311+
messages.ToolReturn(
319312
return_value=return_values,
320313
content=user_contents,
321314
metadata=return_metadata,
322315
)
316+
if len(return_metadata) > 0
317+
else (parts_only[0] if len(parts_only) == 1 else parts_only)
318+
)
323319

324320
async def call_tool(
325321
self,

0 commit comments

Comments
 (0)