Skip to content

Commit eeab4fe

Browse files
committed
Add {SamplingMessage,CreateMessageResult}.content_as_list + update usages
1 parent 722ca3e commit eeab4fe

File tree

3 files changed

+32
-14
lines changed

3 files changed

+32
-14
lines changed

README.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -886,10 +886,9 @@ async def generate_poem(topic: str, ctx: Context[ServerSession, None]) -> str:
886886
max_tokens=100,
887887
)
888888

889-
content = result.content[0] if isinstance(result.content, list) else result.content
890-
if content.type == "text":
891-
return content.text
892-
return str(content)
889+
if all(c.type == "text" for c in result.content_as_list):
890+
return '\n'.join(c.text for c in result.content_as_list if c.type == "text")
891+
return str(result.content)
893892
```
894893

895894
_Full example: [examples/snippets/servers/sampling.py](https://github.com/modelcontextprotocol/python-sdk/blob/main/examples/snippets/servers/sampling.py)_

src/mcp/types.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -864,6 +864,12 @@ class SamplingMessage(BaseModel):
864864
"""
865865
model_config = ConfigDict(extra="allow")
866866

867+
@property
868+
def content_as_list(self) -> list[SamplingMessageContentBlock]:
869+
"""Returns the content as a list of content blocks, regardless of whether
870+
it was originally a single block or a list."""
871+
return self.content if isinstance(self.content, list) else [self.content]
872+
867873

868874
class EmbeddedResource(BaseModel):
869875
"""
@@ -1232,6 +1238,12 @@ class CreateMessageResult(Result):
12321238
'toolUse' indicates the model wants to use a tool.
12331239
"""
12341240

1241+
@property
1242+
def content_as_list(self) -> list[SamplingMessageContentBlock]:
1243+
"""Returns the content as a list of content blocks, regardless of whether
1244+
it was originally a single block or a list."""
1245+
return self.content if isinstance(self.content, list) else [self.content]
1246+
12351247

12361248
class ResourceTemplateReference(BaseModel):
12371249
"""A reference to a resource or resource template definition."""

tests/shared/test_streamable_http.py

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -210,10 +210,16 @@ async def handle_call_tool(name: str, args: dict[str, Any]) -> list[TextContent]
210210
)
211211

212212
# Return the sampling result in the tool response
213-
content = (
214-
sampling_result.content[0] if isinstance(sampling_result.content, list) else sampling_result.content
215-
)
216-
response = content.text if content.type == "text" else None
213+
if isinstance(sampling_result.content, list):
214+
response = (
215+
sampling_result.content[0].text
216+
if sampling_result.content and sampling_result.content[0].type == "text"
217+
else None
218+
)
219+
elif sampling_result.content.type == "text":
220+
response = sampling_result.content.text
221+
else:
222+
response = None
217223
return [
218224
TextContent(
219225
type="text",
@@ -1242,12 +1248,13 @@ async def sampling_callback(
12421248
nonlocal sampling_callback_invoked, captured_message_params
12431249
sampling_callback_invoked = True
12441250
captured_message_params = params
1245-
msg_content = (
1246-
params.messages[0].content[0]
1247-
if isinstance(params.messages[0].content, list)
1248-
else params.messages[0].content
1249-
)
1250-
message_received = msg_content.text if msg_content.type == "text" else None
1251+
msg_content = params.messages[0].content
1252+
if isinstance(msg_content, list):
1253+
message_received = msg_content[0].text if msg_content and msg_content[0].type == "text" else None
1254+
elif msg_content.type == "text":
1255+
message_received = msg_content.text
1256+
else:
1257+
message_received = None
12511258

12521259
return types.CreateMessageResult(
12531260
role="assistant",

0 commit comments

Comments
 (0)