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\MetaObject;
18: use Nexus\Mcp\Core\Schema\Result;
19: use Nexus\Mcp\Core\Schema\Root;
20:
21: /**
22: * The client's response to a roots/list request from the server.
23: * This result contains an array of Root objects, each representing a root directory or file
24: * that the server can operate on.
25: *
26: * @see https://modelcontextprotocol.io/specification/2025-11-25/schema#listrootsresult
27: */
28: final readonly class ListRootsResult extends Result implements ClientResult
29: {
30: /**
31: * @var list<Root>
32: */
33: public array $roots;
34:
35: /**
36: * @param list<Root> $roots
37: */
38: public function __construct(array $roots, MetaObject $meta = new MetaObject())
39: {
40: Assert::that($roots)
41: ->isList('"result.roots" must be a list, non-list array given.')
42: ->values()->isInstanceOf(Root::class)
43: ;
44:
45: $this->roots = $roots;
46:
47: parent::__construct($meta);
48: }
49:
50: #[\Override]
51: public static function fromArray(array $data): static
52: {
53: Assert::that($data)->hasOffset('roots', '"result" missing the required "roots" key.');
54: Assert::that($data['roots'])
55: ->isList('"result.roots" must be a list, {type} given.')
56: ->values()
57: ->isArray('each "result.root" must be an object, {type} given.')
58: ->isMap('each "result.root" must be a string-keyed object.')
59: ;
60: $roots = array_map(Root::fromArray(...), $data['roots']);
61:
62: $meta = new MetaObject();
63:
64: if (\array_key_exists('_meta', $data)) {
65: Assert::that($data['_meta'])
66: ->isArray('"result._meta" must be an object, {type} given.')
67: ->isMap('"result._meta" must be a string-keyed object.')
68: ;
69: $meta = MetaObject::fromArray($data['_meta']);
70: }
71:
72: return new self($roots, $meta);
73: }
74:
75: #[\Override]
76: public function toArray(): array
77: {
78: return [
79: ...parent::toArray(),
80: 'roots' => array_map(static fn(Root $root): array => $root->toArray(), $this->roots),
81: ];
82: }
83:
84: #[\Override]
85: public function jsonSerialize(): array
86: {
87: return $this->toArray();
88: }
89: }
90: