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\Arrayable;
18: use Nexus\Mcp\Core\Schema\Enum\ResultType;
19: use Nexus\Mcp\Core\Schema\MetaObject;
20: use Nexus\Mcp\Core\Schema\MetaObject\GenericResultMetaObject;
21: use Nexus\Mcp\Core\Schema\MetaObject\ResultMetaObject;
22: use Nexus\Mcp\Core\Schema\Prompt\PromptMessage;
23: use Nexus\Mcp\Core\Schema\Result;
24:
25: /**
26: * The result returned by the server for a `prompts/get` request.
27: *
28: * @extends Result<array{
29: * _meta?: template-type<ResultMetaObject, MetaObject, 'T'>,
30: * resultType: non-empty-string,
31: * description?: non-empty-string,
32: * messages: list<template-type<PromptMessage, Arrayable, 'T'>>,
33: * }>
34: *
35: * @see https://modelcontextprotocol.io/specification/2026-07-28/schema#getpromptresult
36: */
37: final readonly class GetPromptResult extends Result implements ServerResult
38: {
39: /**
40: * @var list<PromptMessage>
41: */
42: public array $messages;
43:
44: /**
45: * @var null|non-empty-string
46: */
47: public ?string $description;
48:
49: /**
50: * @param list<PromptMessage> $messages
51: */
52: public function __construct(array $messages, ?string $description = null, ResultMetaObject $meta = new GenericResultMetaObject())
53: {
54: Assert::that($messages)->isList('"result.messages" must be a list, non-list array given.');
55:
56: foreach ($messages as $message) {
57: Assert::that($message)->isInstanceOf(PromptMessage::class);
58: }
59:
60: Assert::that($description)->nullOr()->isNonEmptyString('"result.description" must be a non-empty string or null.');
61:
62: $this->messages = $messages;
63: $this->description = $description;
64:
65: parent::__construct(meta: $meta);
66: }
67:
68: #[\Override]
69: public static function fromArray(array $data): static
70: {
71: Assert::that($data)->hasOffset('messages', '"result" is missing the required "messages" key.');
72: Assert::that($data['messages'])->isArray('"result.messages" must be an array, {type} given.');
73:
74: $messages = [];
75:
76: foreach ($data['messages'] as $entry) {
77: Assert::that($entry)
78: ->isArray('"result.message" must be an object, {type} given.')
79: ->isMap('"result.message" must be a string-keyed object.')
80: ;
81: $messages[] = PromptMessage::fromArray($entry);
82: }
83:
84: $description = $data['description'] ?? null;
85: Assert::that($description)->nullOr()->isString('"result.description" must be a string or null, {type} given.');
86:
87: $meta = new GenericResultMetaObject();
88:
89: if (\array_key_exists('_meta', $data)) {
90: Assert::that($data['_meta'])
91: ->isArray('"result._meta" must be an object, {type} given.')
92: ->isMap('"result._meta" must be a string-keyed object.')
93: ;
94: $meta = GenericResultMetaObject::fromArray($data['_meta']);
95: }
96:
97: return new self(messages: $messages, description: $description, meta: $meta);
98: }
99:
100: #[\Override]
101: public function toArray(): array
102: {
103: $data = [];
104: $meta = $this->meta->toArray();
105:
106: if ([] !== $meta) {
107: $data['_meta'] = $meta;
108: }
109:
110: $data['resultType'] = self::getResultType();
111:
112: if (null !== $this->description) {
113: $data['description'] = $this->description;
114: }
115:
116: $data['messages'] = array_map(
117: static fn(PromptMessage $message): array => $message->toArray(),
118: $this->messages,
119: );
120:
121: return $data;
122: }
123:
124: #[\Override]
125: public function rebuildWithMeta(ResultMetaObject $meta): static
126: {
127: return new self(
128: messages: $this->messages,
129: description: $this->description,
130: meta: $meta,
131: );
132: }
133:
134: #[\Override]
135: protected function getResultType(): string
136: {
137: return ResultType::Complete->value;
138: }
139: }
140: