From 1b49523e01fb68aba63c2771cf36deab052a94d7 Mon Sep 17 00:00:00 2001 From: Josh Rubin Date: Tue, 30 Sep 2025 14:31:12 -0400 Subject: [PATCH 1/5] Added fix to always convert all items of a content list to content blocks --- src/fastmcp/tools/tool.py | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/fastmcp/tools/tool.py b/src/fastmcp/tools/tool.py index a4b20d5bb..721917abf 100644 --- a/src/fastmcp/tools/tool.py +++ b/src/fastmcp/tools/tool.py @@ -544,15 +544,10 @@ def _convert_to_content( if all(isinstance(item, ContentBlock) for item in result): return result - # If any item is a ContentBlock, convert non-ContentBlock items to TextContent - # without aggregating them - if any(isinstance(item, ContentBlock) for item in result): - return [ - _convert_to_single_content_block(item, serializer) - if not isinstance(item, ContentBlock) - else item - for item in result - ] - - # If none of the items are ContentBlocks, aggregate all items into a single TextContent - return [TextContent(type="text", text=_serialize_with_fallback(result, serializer))] + # Convert items that are not ContentBlocks + return [ + _convert_to_single_content_block(item, serializer) + if not isinstance(item, ContentBlock) + else item + for item in result + ] From 87e31cc544b515944e6f55e4b2b10b81beb36a67 Mon Sep 17 00:00:00 2001 From: Josh Rubin Date: Tue, 30 Sep 2025 14:32:30 -0400 Subject: [PATCH 2/5] Revert "Added fix to always convert all items of a content list to content blocks" This reverts commit 1b49523e01fb68aba63c2771cf36deab052a94d7. --- src/fastmcp/tools/tool.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/fastmcp/tools/tool.py b/src/fastmcp/tools/tool.py index 721917abf..a4b20d5bb 100644 --- a/src/fastmcp/tools/tool.py +++ b/src/fastmcp/tools/tool.py @@ -544,10 +544,15 @@ def _convert_to_content( if all(isinstance(item, ContentBlock) for item in result): return result - # Convert items that are not ContentBlocks - return [ - _convert_to_single_content_block(item, serializer) - if not isinstance(item, ContentBlock) - else item - for item in result - ] + # If any item is a ContentBlock, convert non-ContentBlock items to TextContent + # without aggregating them + if any(isinstance(item, ContentBlock) for item in result): + return [ + _convert_to_single_content_block(item, serializer) + if not isinstance(item, ContentBlock) + else item + for item in result + ] + + # If none of the items are ContentBlocks, aggregate all items into a single TextContent + return [TextContent(type="text", text=_serialize_with_fallback(result, serializer))] From 21bcfd52f7a2949c85d1ee020ab6dc4ba5a2c9c6 Mon Sep 17 00:00:00 2001 From: Josh Rubin Date: Tue, 30 Sep 2025 14:32:51 -0400 Subject: [PATCH 3/5] Added fix to always convert all items of a content list to content blocks --- src/fastmcp/tools/tool.py | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/fastmcp/tools/tool.py b/src/fastmcp/tools/tool.py index a4b20d5bb..721917abf 100644 --- a/src/fastmcp/tools/tool.py +++ b/src/fastmcp/tools/tool.py @@ -544,15 +544,10 @@ def _convert_to_content( if all(isinstance(item, ContentBlock) for item in result): return result - # If any item is a ContentBlock, convert non-ContentBlock items to TextContent - # without aggregating them - if any(isinstance(item, ContentBlock) for item in result): - return [ - _convert_to_single_content_block(item, serializer) - if not isinstance(item, ContentBlock) - else item - for item in result - ] - - # If none of the items are ContentBlocks, aggregate all items into a single TextContent - return [TextContent(type="text", text=_serialize_with_fallback(result, serializer))] + # Convert items that are not ContentBlocks + return [ + _convert_to_single_content_block(item, serializer) + if not isinstance(item, ContentBlock) + else item + for item in result + ] From c82e1faa4e1a5a5f62f89c4353afb8a6d7dab07b Mon Sep 17 00:00:00 2001 From: Josh Rubin Date: Tue, 30 Sep 2025 14:59:44 -0400 Subject: [PATCH 4/5] Fixed so only converted fastmcp types --- src/fastmcp/tools/tool.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/fastmcp/tools/tool.py b/src/fastmcp/tools/tool.py index 721917abf..c922dc9d2 100644 --- a/src/fastmcp/tools/tool.py +++ b/src/fastmcp/tools/tool.py @@ -544,10 +544,15 @@ def _convert_to_content( if all(isinstance(item, ContentBlock) for item in result): return result - # Convert items that are not ContentBlocks - return [ - _convert_to_single_content_block(item, serializer) - if not isinstance(item, ContentBlock) - else item - for item in result - ] + # If any item is a ContentBlock, convert non-ContentBlock items to TextContent + # without aggregating them + if any(isinstance(item, (Image, Audio, File)) for item in result): + return [ + _convert_to_single_content_block(item, serializer) + if isinstance(item, (Image, Audio, File)) + else item + for item in result + ] + + # If none of the items are ContentBlocks, aggregate all items into a single TextContent + return [TextContent(type="text", text=_serialize_with_fallback(result, serializer))] From 664b67d26fad32214728287860f22d406adbde7c Mon Sep 17 00:00:00 2001 From: William Easton Date: Fri, 3 Oct 2025 15:02:26 -0500 Subject: [PATCH 5/5] Fix exclusion of content helpers if they are in a list --- src/fastmcp/tools/tool.py | 5 ++--- tests/tools/test_tool.py | 3 +++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/fastmcp/tools/tool.py b/src/fastmcp/tools/tool.py index c922dc9d2..d1fd03f64 100644 --- a/src/fastmcp/tools/tool.py +++ b/src/fastmcp/tools/tool.py @@ -546,13 +546,12 @@ def _convert_to_content( # If any item is a ContentBlock, convert non-ContentBlock items to TextContent # without aggregating them - if any(isinstance(item, (Image, Audio, File)) for item in result): + if any(isinstance(item, ContentBlock | Image | Audio | File) for item in result): return [ _convert_to_single_content_block(item, serializer) - if isinstance(item, (Image, Audio, File)) + if not isinstance(item, ContentBlock) else item for item in result ] - # If none of the items are ContentBlocks, aggregate all items into a single TextContent return [TextContent(type="text", text=_serialize_with_fallback(result, serializer))] diff --git a/tests/tools/test_tool.py b/tests/tools/test_tool.py index ac6a78041..dc815b5bf 100644 --- a/tests/tools/test_tool.py +++ b/tests/tools/test_tool.py @@ -1087,6 +1087,9 @@ class TestConvertResultToContent: converted = _convert_to_content(result) assert converted == expected + converted = _convert_to_content([result, result]) + assert converted == expected * 2 + def test_convert_mixed_content(self): result = [ "hello",