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\Arrayable;
18: use Nexus\Mcp\Core\Schema\Elicitation\ElicitRequestedSchema;
19:
20: /**
21: * The parameters for a request to elicit non-sensitive information from the user via a form in the client.
22: *
23: * @implements Arrayable<array{mode?: 'form', message: non-empty-string, requestedSchema: array<string, mixed>}>
24: * @implements ElicitRequestParams<array{mode?: 'form', message: non-empty-string, requestedSchema: array<string, mixed>}>
25: *
26: * @see https://modelcontextprotocol.io/specification/draft/schema#elicitrequestformparams
27: */
28: final readonly class ElicitRequestFormParams implements Arrayable, ElicitRequestParams
29: {
30: public const string MODE = 'form';
31:
32: /**
33: * @var non-empty-string
34: */
35: public string $message;
36:
37: /**
38: * @var 'form'
39: */
40: public string $mode;
41:
42: public function __construct(
43: string $message,
44: public ElicitRequestedSchema $requestedSchema,
45: string $mode = self::MODE,
46: ) {
47: Assert::that($message)->isNonEmptyString('"params.message" must be a non-empty string.');
48: Assert::that($mode)->isIdentical(self::MODE, '"params.mode" must be {other}, {value} given.');
49:
50: $this->message = $message;
51: $this->mode = $mode;
52: }
53:
54: #[\Override]
55: public static function fromArray(array $data): static
56: {
57: $mode = $data['mode'] ?? self::MODE;
58: Assert::that($mode)->isString('"params.mode" must be a string, {type} given.');
59:
60: Assert::that($data)->hasOffset('message', '"params" is missing the required "message" key.');
61: $message = $data['message'];
62: Assert::that($message)->isString('"params.message" must be a string, {type} given.');
63:
64: Assert::that($data)->hasOffset('requestedSchema', '"params" is missing the required "requestedSchema" key.');
65: Assert::that($data['requestedSchema'])
66: ->isArray('"params.requestedSchema" must be an object, {type} given.')
67: ->isMap('"params.requestedSchema" must be a string-keyed object.')
68: ;
69: $requestedSchema = ElicitRequestedSchema::fromArray($data['requestedSchema']);
70:
71: return new self(message: $message, requestedSchema: $requestedSchema, mode: $mode);
72: }
73:
74: #[\Override]
75: public function toArray(): array
76: {
77: return [
78: 'mode' => $this->mode,
79: 'message' => $this->message,
80: 'requestedSchema' => $this->requestedSchema->toArray(),
81: ];
82: }
83:
84: #[\Override]
85: public function jsonSerialize(): array
86: {
87: return $this->toArray();
88: }
89: }
90: