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\RequestParams;
15:
16: use Nexus\Assert\Assert;
17: use Nexus\Mcp\Core\Schema\RequestMetaObject;
18: use Nexus\Mcp\Core\Schema\Task\TaskMetadata;
19:
20: /**
21: * The parameters for a request to elicit information from the user via a URL in the client.
22: *
23: * @see https://modelcontextprotocol.io/specification/2025-11-25/schema#elicitrequesturlparams
24: */
25: final readonly class ElicitRequestUrlParams extends TaskAugmentedRequestParams implements ElicitRequestParams
26: {
27: public const string MODE = 'url';
28:
29: /**
30: * @var non-empty-string
31: */
32: public string $elicitationId;
33:
34: /**
35: * @var non-empty-string
36: */
37: public string $message;
38:
39: /**
40: * @var 'url'
41: */
42: public string $mode;
43:
44: /**
45: * @var non-empty-string
46: */
47: public string $url;
48:
49: public function __construct(
50: string $elicitationId,
51: string $message,
52: string $mode,
53: string $url,
54: ?TaskMetadata $task = null,
55: RequestMetaObject $meta = new RequestMetaObject(),
56: ) {
57: Assert::that($elicitationId)->isNonEmptyString('"params.elicitationId" must be a non-empty string.');
58: Assert::that($message)->isNonEmptyString('"params.message" must be a non-empty string.');
59: Assert::that($url)->isNonEmptyString('"params.url" must be a non-empty string.')->isUrl('"params.url" must be a valid URL.');
60: Assert::that($mode)->isIdentical(self::MODE, '"params.mode" must be {other}, {value} given.');
61:
62: $this->elicitationId = $elicitationId;
63: $this->message = $message;
64: $this->url = $url;
65: $this->mode = $mode;
66:
67: parent::__construct($task, $meta);
68: }
69:
70: /**
71: * @param array<string, mixed> $data
72: */
73: #[\Override]
74: public static function fromArray(array $data): static
75: {
76: Assert::that($data)->hasOffset('elicitationId', 'missing the required "elicitationId" key.');
77: $elicitationId = $data['elicitationId'];
78: Assert::that($elicitationId)->isString('"params.elicitationId" must be a string, {type} given.');
79:
80: Assert::that($data)->hasOffset('message', 'missing the required "message" key.');
81: $message = $data['message'];
82: Assert::that($message)->isString('"params.message" must be a string, {type} given.');
83:
84: Assert::that($data)->hasOffset('mode', 'missing the required "mode" key.');
85: $mode = $data['mode'];
86: Assert::that($mode)->isString('"params.mode" must be a string, {type} given.');
87:
88: Assert::that($data)->hasOffset('url', 'missing the required "url" key.');
89: $url = $data['url'];
90: Assert::that($url)->isString('"params.url" must be a string, {type} given.');
91:
92: $task = null;
93:
94: if (\array_key_exists('task', $data)) {
95: Assert::that($data['task'])
96: ->isArray('"params.task" must be an object, {type} given.')
97: ->isMap('"params.task" must be a string-keyed object.')
98: ;
99: $task = TaskMetadata::fromArray($data['task']);
100: }
101:
102: $meta = new RequestMetaObject();
103:
104: if (\array_key_exists('_meta', $data)) {
105: Assert::that($data['_meta'])
106: ->isArray('"params._meta" must be an object, {type} given.')
107: ->isMap('"params._meta" must be a string-keyed object.')
108: ;
109: $meta = RequestMetaObject::fromArray($data['_meta']);
110: }
111:
112: return new self($elicitationId, $message, $mode, $url, $task, $meta);
113: }
114:
115: #[\Override]
116: public function toArray(): array
117: {
118: return [
119: ...parent::toArray(),
120: 'elicitationId' => $this->elicitationId,
121: 'message' => $this->message,
122: 'mode' => $this->mode,
123: 'url' => $this->url,
124: ];
125: }
126:
127: #[\Override]
128: public function jsonSerialize(): array
129: {
130: return $this->toArray();
131: }
132: }
133: