diff --git a/src/mcp/server/experimental/task_result_handler.py b/src/mcp/server/experimental/task_result_handler.py index b2268bc1c8..51918f5c0e 100644 --- a/src/mcp/server/experimental/task_result_handler.py +++ b/src/mcp/server/experimental/task_result_handler.py @@ -116,7 +116,7 @@ async def handle( related_task = RelatedTaskMetadata(task_id=task_id) related_task_meta: dict[str, Any] = {RELATED_TASK_METADATA_KEY: related_task.model_dump(by_alias=True)} if result is not None: - result_data = result.model_dump(by_alias=True) + result_data = result.model_dump(by_alias=True, mode="json", exclude_none=True) existing_meta: dict[str, Any] = result_data.get("_meta") or {} result_data["_meta"] = {**existing_meta, **related_task_meta} return GetTaskPayloadResult.model_validate(result_data) diff --git a/tests/experimental/tasks/server/test_task_result_handler.py b/tests/experimental/tasks/server/test_task_result_handler.py index 8b5a03ce2b..d137c7631d 100644 --- a/tests/experimental/tasks/server/test_task_result_handler.py +++ b/tests/experimental/tasks/server/test_task_result_handler.py @@ -67,6 +67,25 @@ async def test_handle_returns_result_for_completed_task( assert "io.modelcontextprotocol/related-task" in response.meta +@pytest.mark.anyio +async def test_handle_omits_none_fields_from_result_payload( + store: InMemoryTaskStore, queue: InMemoryTaskMessageQueue, handler: TaskResultHandler +) -> None: + task = await store.create_task(TaskMetadata(ttl=60000), task_id="test-task") + await store.store_result(task.task_id, CallToolResult(content=[TextContent(type="text", text="Done!")])) + await store.update_task(task.task_id, status="completed") + + mock_session = Mock() + mock_session.send_message = AsyncMock() + + request = GetTaskPayloadRequest(params=GetTaskPayloadRequestParams(task_id=task.task_id)) + response = await handler.handle(request, mock_session, "req-1") + + payload = response.model_dump(by_alias=True, mode="json") + assert payload["content"] == [{"type": "text", "text": "Done!"}] + assert "structuredContent" not in payload + + @pytest.mark.anyio async def test_handle_raises_for_nonexistent_task( store: InMemoryTaskStore, queue: InMemoryTaskMessageQueue, handler: TaskResultHandler