Repository navigation
Description
Initial Checks
- Reproduced with mcp 2.3.0, the latest release when checked.
- Searched the issue tracker for an existing report.
Release line
2.x (current stable)
Description
A prompt handler returning a collections.UserList of messages produces one user message containing a quoted Python representation of the collection. The individual messages and their roles are lost. Returning the same messages in a list or tuple works correctly.
The example below should return a user message containing Question followed by an assistant message containing Answer.
SyncPromptResult accepts Sequence returns, but Prompt.render() only treats lists and tuples as message collections. An empty UserList also returns one text message containing "[]" instead of no messages.
A local fix and regression tests are ready for a PR. The fix handles collections.abc.Sequence while keeping strings as single messages. Eight regression cases cover sync and async handlers, lists, tuples, UserList, and empty UserList results. Four cases fail before the fix; all eight pass afterwards. The full suite passes on Windows and Linux with 100% statement and branch coverage.
I'd like to contribute the fix if you're open to an outside PR.
Example Code
from collections import UserList
from collections.abc import Sequence
import anyio
from mcp import Client
from mcp.server.mcpserver import AssistantMessage, MCPServer, Message, UserMessage
server = MCPServer()
@server.prompt()
def conversation() -> Sequence[Message]:
return UserList([UserMessage("Question"), AssistantMessage("Answer")])
async def main() -> None:
async with Client(server) as client:
result = await client.get_prompt("conversation")
print([(message.role, message.content.model_dump()) for message in result.messages])
anyio.run(main)Python & MCP Python SDK
Python 3.11.15 on Windows, mcp 2.3.0 installed from PyPI.
Also reproduced at main/v2.3.0 commit 2118f14f8a19bc158d8a1cf90af58d85d187f849.
We used AI to test and validate the issue.
Activity
Ben-Home commentedon Oct 5, 2026
ajay206 commentedon Oct 12, 2026
Hi! I reproduced this: Prompt.render() only treats list/tuple as a list of messages, so a UserList (or any other non-str Sequence) gets wrapped and JSON-dumped into a single message, and an empty UserList renders as one "[]" message.
I have a small fix ready: use a collections.abc.Sequence check that excludes str/bytes, plus tests for sync/async UserList results and the empty case. The full suite passes at 100% coverage, and ruff and pyright are clean. Could I be assigned to open the PR? Happy to defer if the reporter would rather submit theirs.
(I worked on this with help from Cursor and Grok Bot.)
inanna-malick commentedon Oct 14, 2026
A pinned standalone regression test is available for the empty
UserListcase already described here. It fails on latest stable 2.3.0 (2118f14) and current main 754254c: renderingUserList([])produces one message containing"[]"instead of no messages.Test: standalone failing reproduction, branch
repro/prompt-sequence-return(diff).From that branch, after installing its development dependencies:
Python 3.14.7 / Pydantic 2.12.5. Existing list-of-strings and multiple-message controls pass alongside the intentional failure on both versions. The branch contains only the test and its imports.
AI-assisted investigation and test reproduction, with a human in the loop.