1: <?php
2:
3: declare(strict_types=1);
4:
5: /**
6: * This file is part of the Nexus MCP SDK package.
7: *
8: * (c) 2026 John Paul E. Balandan, CPA <paulbalandan@gmail.com>
9: *
10: * For the full copyright and license information, please view
11: * the LICENSE file that was distributed with this source code.
12: */
13:
14: namespace Nexus\Mcp\Core\Schema\Result;
15:
16: use Nexus\Assert\Assert;
17: use Nexus\Mcp\Core\Schema\Cursor;
18: use Nexus\Mcp\Core\Schema\MetaObject;
19: use Nexus\Mcp\Core\Schema\Task\Task;
20:
21: /**
22: * The response to a tasks/list request.
23: *
24: * @see https://modelcontextprotocol.io/specification/2025-11-25/schema#listtasksresult
25: */
26: final readonly class ListTasksResult extends PaginatedResult implements ClientResult, ServerResult
27: {
28: /**
29: * @param list<Task> $tasks
30: */
31: public function __construct(
32: public array $tasks,
33: ?Cursor $nextCursor = null,
34: MetaObject $meta = new MetaObject(),
35: ) {
36: Assert::that($this->tasks)
37: ->isList('"result.tasks" must be a list, non-list array given.')
38: ->values()->isInstanceOf(Task::class, 'each "result.task" must be a task object, {type} given.')
39: ;
40:
41: parent::__construct($nextCursor, $meta);
42: }
43:
44: /**
45: * @param array<string, mixed> $data
46: */
47: #[\Override]
48: public static function fromArray(array $data): static
49: {
50: Assert::that($data)->hasOffset('tasks', '"result" missing the required "tasks" key.');
51: Assert::that($data['tasks'])
52: ->isList('"result.tasks" must be a list, {type} given.')
53: ->values()
54: ->isArray('each "result.task" must be an object, {type} given.')
55: ->isMap('each "result.task" must be a string-keyed object.')
56: ;
57: $tasks = array_map(Task::fromArray(...), $data['tasks']);
58:
59: $nextCursor = null;
60:
61: if (\array_key_exists('nextCursor', $data)) {
62: Assert::that($data['nextCursor'])->isString('"result.nextCursor" must be a string, {type} given.');
63: $nextCursor = new Cursor($data['nextCursor']);
64: }
65:
66: $meta = new MetaObject();
67:
68: if (\array_key_exists('_meta', $data)) {
69: Assert::that($data['_meta'])
70: ->isArray('"result._meta" must be an object, {type} given.')
71: ->isMap('"result._meta" must be a string-keyed object.')
72: ;
73: $meta = MetaObject::fromArray($data['_meta']);
74: }
75:
76: return new self($tasks, $nextCursor, $meta);
77: }
78:
79: #[\Override]
80: public function toArray(): array
81: {
82: return [
83: ...parent::toArray(),
84: 'tasks' => array_map(static fn(Task $task): array => $task->toArray(), $this->tasks),
85: ];
86: }
87: }
88: