You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Prompt handlers returning UserList are rendered as one text message #3643
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.
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.)
A pinned standalone regression test is available for the empty UserList case already described here. It fails on latest stable 2.3.0 (2118f14) and current main 754254c: rendering UserList([]) produces one message containing "[]" instead of no messages.
From that branch, after installing its development dependencies:
uv run --frozen pytest tests/server/mcpserver/prompts/test_base.py::test_prompt_render_accepts_user_list_as_a_sequence_result -q
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.
Activity
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.