Skip to content

Commit 5234189

Browse files
committed
Accept Image and Audio helpers as prompt message content
Tools already convert the Image/Audio helpers to ImageContent/AudioContent; prompt messages rejected them with a pydantic validation error, forcing UserMessage(Image(...).to_image_content()). Message.__init__ now performs the same conversion, so UserMessage(Image(...)) works, including via the dict form.
1 parent 02a0c5e commit 5234189

2 files changed

Lines changed: 31 additions & 5 deletions

File tree

‎src/mcp/server/mcpserver/prompts/base.py‎

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
from mcp.server.mcpserver.utilities.context_injection import find_context_parameter, inject_context
1515
from mcp.server.mcpserver.utilities.func_metadata import func_metadata
16+
from mcp.server.mcpserver.utilities.types import Audio, Image
1617
from mcp.shared._callable_inspection import is_async_callable
1718
from mcp.shared.exceptions import MCPError
1819

@@ -22,14 +23,22 @@
2223

2324

2425
class Message(BaseModel):
25-
"""Base class for all prompt messages."""
26+
"""Base class for all prompt messages.
27+
28+
`content` may be a plain string (wrapped in `TextContent`), an `Image` or `Audio`
29+
helper (converted to `ImageContent` / `AudioContent`), or any ready-made content block.
30+
"""
2631

2732
role: Literal["user", "assistant"]
2833
content: ContentBlock
2934

30-
def __init__(self, content: str | ContentBlock, **kwargs: Any):
35+
def __init__(self, content: str | ContentBlock | Image | Audio, **kwargs: Any):
3136
if isinstance(content, str):
3237
content = TextContent(type="text", text=content)
38+
elif isinstance(content, Image):
39+
content = content.to_image_content()
40+
elif isinstance(content, Audio):
41+
content = content.to_audio_content()
3342
super().__init__(content=content, **kwargs)
3443

3544

@@ -38,7 +47,7 @@ class UserMessage(Message):
3847

3948
role: Literal["user", "assistant"] = "user"
4049

41-
def __init__(self, content: str | ContentBlock, **kwargs: Any):
50+
def __init__(self, content: str | ContentBlock | Image | Audio, **kwargs: Any):
4251
super().__init__(content=content, **kwargs)
4352

4453

@@ -47,7 +56,7 @@ class AssistantMessage(Message):
4756

4857
role: Literal["user", "assistant"] = "assistant"
4958

50-
def __init__(self, content: str | ContentBlock, **kwargs: Any):
59+
def __init__(self, content: str | ContentBlock | Image | Audio, **kwargs: Any):
5160
super().__init__(content=content, **kwargs)
5261

5362

‎tests/server/mcpserver/prompts/test_base.py‎

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,17 @@
33

44
import pytest
55
from mcp_types import (
6+
AudioContent,
67
ElicitRequest,
78
ElicitRequestFormParams,
89
EmbeddedResource,
10+
ImageContent,
911
InputRequiredResult,
1012
TextContent,
1113
TextResourceContents,
1214
)
1315

14-
from mcp.server.mcpserver import Context
16+
from mcp.server.mcpserver import Audio, Context, Image
1517
from mcp.server.mcpserver.prompts.base import AssistantMessage, Message, Prompt, UserMessage
1618

1719

@@ -243,3 +245,18 @@ def asking_prompt() -> InputRequiredResult:
243245
prompt = Prompt.from_function(asking_prompt)
244246
result = await prompt.render(None, Context())
245247
assert result is sentinel
248+
249+
250+
@pytest.mark.parametrize(
251+
("helper", "expected"),
252+
[
253+
(Image(data=b"img", format="png"), ImageContent(type="image", data="aW1n", mime_type="image/png")),
254+
(Audio(data=b"snd", format="wav"), AudioContent(type="audio", data="c25k", mime_type="audio/wav")),
255+
],
256+
)
257+
def test_message_converts_image_and_audio_helpers_to_content_blocks(
258+
helper: Image | Audio, expected: ImageContent | AudioContent
259+
) -> None:
260+
"""SDK-defined: prompt messages accept the same `Image`/`Audio` helpers tools return."""
261+
assert UserMessage(helper).content == expected
262+
assert AssistantMessage(content=helper).content == expected

0 commit comments

Comments
 (0)