29namespace mcp::protocol {
52 std::optional<std::string>
title;
70 std::optional<std::string>
title;
86 std::optional<std::string>
title;
158 std::optional<std::string>
title = std::nullopt,
159 std::optional<std::string>
description = std::nullopt,
160 std::optional<std::string> format = std::nullopt,
161 std::optional<std::int64_t> min_length = std::nullopt,
162 std::optional<std::int64_t> max_length = std::nullopt,
163 std::optional<std::string> default_value = std::nullopt) {
167 schema.
format = std::move(format);
176 std::optional<std::string>
title = std::nullopt,
177 std::optional<std::string>
description = std::nullopt,
178 std::optional<double> minimum = std::nullopt,
179 std::optional<double> maximum = std::nullopt,
180 std::optional<double> default_value = std::nullopt) {
192 std::optional<std::string>
title = std::nullopt,
193 std::optional<std::string>
description = std::nullopt,
194 std::optional<std::int64_t> minimum = std::nullopt,
195 std::optional<std::int64_t> maximum = std::nullopt,
196 std::optional<std::int64_t> default_value = std::nullopt) {
208 std::optional<std::string>
title = std::nullopt,
209 std::optional<std::string>
description = std::nullopt,
210 std::optional<bool> default_value = std::nullopt) {
220 std::vector<std::string> values,
221 std::optional<std::string>
title = std::nullopt,
222 std::optional<std::string>
description = std::nullopt,
223 std::optional<std::string> default_value = std::nullopt) {
225 schema.
values = std::move(values);
241 title_ = std::move(value);
247 description_ = std::move(value);
254 std::optional<std::string> default_value = std::nullopt,
255 std::optional<std::string> format = std::nullopt);
259 std::optional<std::string> default_value = std::nullopt,
260 std::optional<std::string> format = std::nullopt);
263 std::string name, std::optional<double> minimum = std::nullopt,
264 std::optional<double> maximum = std::nullopt,
265 std::optional<double> default_value = std::nullopt);
268 std::string name, std::optional<double> minimum = std::nullopt,
269 std::optional<double> maximum = std::nullopt,
270 std::optional<double> default_value = std::nullopt);
273 std::string name, std::optional<std::int64_t> minimum = std::nullopt,
274 std::optional<std::int64_t> maximum = std::nullopt,
275 std::optional<std::int64_t> default_value = std::nullopt);
278 std::string name, std::optional<std::int64_t> minimum = std::nullopt,
279 std::optional<std::int64_t> maximum = std::nullopt,
280 std::optional<std::int64_t> default_value = std::nullopt);
283 std::optional<bool> default_value = std::nullopt);
286 std::optional<bool> default_value = std::nullopt);
290 std::optional<std::string> default_value = std::nullopt);
294 std::optional<std::string> default_value = std::nullopt);
297 std::string name, std::vector<std::string> values,
298 std::optional<std::string> default_value = std::nullopt);
301 std::string name, std::vector<std::string> values,
302 std::optional<std::string> default_value = std::nullopt);
306 return add_required(std::move(name), std::move(schema));
311 return add_optional(std::move(name), std::move(schema));
319 static bool validate_name(
const std::string& name);
324 std::optional<std::string> title_;
325 std::optional<std::string> description_;
326 std::map<std::string, PrimitiveSchema> properties_;
327 std::vector<std::string> required_;
344 std::optional<std::string>
url;
350 std::optional<TaskRequestParameters>
task;
381 static constexpr bool defined =
true;
382 static auto fields() {
383 return std::make_tuple(
384 field(
"elicitationId",
388 {
"elicitationId",
"_meta"}));
390 static std::vector<std::string> known_keys() {
391 return {
"elicitationId",
"_meta"};
398 case ElicitationAction::Accept:
400 case ElicitationAction::Decline:
402 case ElicitationAction::Cancel:
411 const std::string& value) {
412 if (value ==
"accept") {
413 return ElicitationAction::Accept;
415 if (value ==
"decline") {
416 return ElicitationAction::Decline;
418 if (value ==
"cancel") {
419 return ElicitationAction::Cancel;
429 static bool deserialize(
const Json& json,
const char* key,
431 if (!json.contains(key) || !json.at(key).is_string()) {
435 if (!val.has_value()) {
446 case ElicitationMode::Form:
448 case ElicitationMode::Url:
457 const std::string& value) {
458 if (value ==
"form") {
459 return ElicitationMode::Form;
461 if (value ==
"url") {
462 return ElicitationMode::Url;
470 const std::string& value)
noexcept {
471 return value ==
"email" || value ==
"uri" || value ==
"date" ||
472 value ==
"date-time";
477 Json json = Json::object();
478 json[
"type"] =
"string";
479 if (schema.
title.has_value()) {
480 json[
"title"] = *schema.
title;
485 if (schema.
format.has_value()) {
486 json[
"format"] = *schema.
format;
503 Json json = Json::object();
504 json[
"type"] =
"number";
505 if (schema.
title.has_value()) {
506 json[
"title"] = *schema.
title;
511 if (schema.
minimum.has_value()) {
512 json[
"minimum"] = *schema.
minimum;
514 if (schema.
maximum.has_value()) {
515 json[
"maximum"] = *schema.
maximum;
526 Json json = Json::object();
527 json[
"type"] =
"integer";
528 if (schema.
title.has_value()) {
529 json[
"title"] = *schema.
title;
534 if (schema.
minimum.has_value()) {
535 json[
"minimum"] = *schema.
minimum;
537 if (schema.
maximum.has_value()) {
538 json[
"maximum"] = *schema.
maximum;
549 Json json = Json::object();
550 json[
"type"] =
"boolean";
551 if (schema.
title.has_value()) {
552 json[
"title"] = *schema.
title;
566 Json json = Json::object();
567 json[
"type"] = schema.
multi_select ?
"array" :
"string";
571 json[
"items"] = Json::object();
572 json[
"items"][
"anyOf"] = Json::array();
573 for (std::size_t index = 0; index < schema.
values.size(); ++index) {
574 json[
"items"][
"anyOf"].push_back(
579 json[
"items"] =
Json{{
"type",
"string"}, {
"enum", Json::array()}};
580 for (
const auto& value : schema.
values) {
581 json[
"items"][
"enum"].push_back(value);
595 json[
"oneOf"] = Json::array();
596 for (std::size_t index = 0; index < schema.
values.size(); ++index) {
597 json[
"oneOf"].push_back(
Json{{
"const", schema.
values[index]},
601 json[
"enum"] = Json::array();
602 for (
const auto& value : schema.
values) {
603 json[
"enum"].push_back(value);
609 if (schema.
title.has_value()) {
610 json[
"title"] = *schema.
title;
623inline Json primitive_schema_to_json(
const PrimitiveSchema& schema);
627 Json json = Json::object();
628 json[
"type"] =
"object";
629 if (schema.
title.has_value()) {
630 json[
"title"] = *schema.
title;
635 json[
"properties"] = Json::object();
636 for (
const auto& [name, property] : schema.
properties) {
650 static_cast<int>(ErrorCode::InvalidRequest), std::move(message), {}};
655 const Json& choices, std::vector<std::string>& values,
656 std::vector<std::string>& titles, std::string_view context) {
657 if (!choices.is_array()) {
658 return mcp::core::unexpected(
661 for (
const auto& choice : choices) {
662 if (!choice.is_object() || !choice.contains(
"const") ||
663 !choice.at(
"const").is_string() || !choice.contains(
"title") ||
664 !choice.at(
"title").is_string()) {
666 std::string(context) +
" entries require string const and title"));
668 values.push_back(choice.at(
"const").get<std::string>());
669 titles.push_back(choice.at(
"title").get<std::string>());
676 const std::vector<std::string>& values) {
677 for (
const auto& value : values) {
678 if (std::find(allowed.begin(), allowed.end(), value) == allowed.end()) {
694 if (!json.is_object()) {
695 return mcp::core::unexpected(
698 if (!json.contains(
"type") || !json.at(
"type").is_string() ||
699 json.at(
"type").get<std::string>() !=
"object") {
700 return mcp::core::unexpected(
703 if (!json.contains(
"properties") || !json.at(
"properties").is_object()) {
704 return mcp::core::unexpected(
709 if (json.contains(
"title")) {
710 if (!json.at(
"title").is_string()) {
711 return mcp::core::unexpected(
714 schema.
title = json.at(
"title").get<std::string>();
716 if (json.contains(
"description")) {
717 if (!json.at(
"description").is_string()) {
719 "elicitation schema description must be a string"));
721 schema.
description = json.at(
"description").get<std::string>();
723 for (
const auto& [name, property_json] : json.at(
"properties").items()) {
726 return mcp::core::unexpected(property.error());
730 if (json.contains(
"required")) {
731 if (!json.at(
"required").is_array()) {
733 "elicitation schema required must be an array"));
735 for (
const auto& item : json.at(
"required")) {
736 if (!item.is_string()) {
738 "elicitation schema required entries must be strings"));
740 schema.
required.push_back(item.get<std::string>());
744 json, {
"type",
"title",
"description",
"properties",
"required"});
753 Json json = Json::object();
754 json[
"message"] = request.
message;
759 if (request.
task.has_value()) {
762 if (request.
meta.has_value()) {
763 json[
"_meta"] = *request.
meta;
767 if (request.
mode == ElicitationMode::Url) {
771 if (request.
url.has_value()) {
772 json[
"url"] = *request.
url;
777 json[
"requestedSchema"] =
786 if (!json.is_object()) {
787 return mcp::core::unexpected(
790 if (!json.contains(
"message") || !json.at(
"message").is_string()) {
792 "elicitation request requires a string message"));
795 if (json.contains(
"mode")) {
796 if (!json.at(
"mode").is_string()) {
797 return mcp::core::unexpected(
800 const auto parsed_mode =
803 return mcp::core::unexpected(
810 request.
message = json.at(
"message").get<std::string>();
813 if (json.contains(
"requestState")) {
816 if (json.contains(
"task")) {
819 return mcp::core::unexpected(task.error());
821 request.
task = *task;
823 if (json.contains(
"_meta")) {
824 if (!json.at(
"_meta").is_object()) {
826 "elicitation request _meta must be an object"));
828 request.
meta = json.at(
"_meta");
831 json, {
"message",
"mode",
"elicitationId",
"url",
"requestedSchema",
832 "requested_schema",
"requestState",
"task",
"_meta"});
834 if (mode == ElicitationMode::Url) {
835 if (!json.contains(
"elicitationId") ||
836 !json.at(
"elicitationId").is_string()) {
837 return mcp::core::unexpected(
840 if (!json.contains(
"url") || !json.at(
"url").is_string()) {
841 return mcp::core::unexpected(
844 request.
elicitation_id = json.at(
"elicitationId").get<std::string>();
845 request.
url = json.at(
"url").get<std::string>();
849 const auto schema_key =
850 json.contains(
"requestedSchema") ?
"requestedSchema" :
"requested_schema";
851 if (!json.contains(schema_key)) {
852 return mcp::core::unexpected(
857 return mcp::core::unexpected(schema.error());
866 Json json = Json::object();
868 if (result.
content.has_value()) {
869 json[
"content"] = *result.
content;
871 if (result.
meta.has_value()) {
872 json[
"_meta"] = *result.
meta;
882 if (!json.is_object()) {
883 return mcp::core::unexpected(
886 if (!json.contains(
"action") || !json.at(
"action").is_string()) {
887 return mcp::core::unexpected(
893 if (!action.has_value()) {
894 return mcp::core::unexpected(
900 if (json.contains(
"content")) {
901 result.
content = json.at(
"content");
903 if (json.contains(
"_meta")) {
904 if (!json.at(
"_meta").is_object()) {
905 return mcp::core::unexpected(
908 result.
meta = json.at(
"_meta");
921 using Property = std::decay_t<
decltype(property)>;
922 if constexpr (std::is_same_v<Property, StringSchema>) {
923 if (!value.is_string()) {
925 "elicitation content field '" + name +
"' must be a string"));
927 const auto string_value = value.get<std::string>();
928 if (property.min_length.has_value() &&
929 string_value.size() <
930 static_cast<std::size_t
>(*
property.min_length)) {
931 return mcp::core::unexpected(
933 "' is shorter than minLength"));
935 if (property.max_length.has_value() &&
936 string_value.size() >
937 static_cast<std::size_t
>(*property.max_length)) {
938 return mcp::core::unexpected(
940 "' is longer than maxLength"));
942 }
else if constexpr (std::is_same_v<Property, NumberSchema>) {
943 if (!value.is_number()) {
945 "elicitation content field '" + name +
"' must be numeric"));
947 const auto number = value.get<
double>();
950 "elicitation content field '" + name +
"' must be finite"));
952 if (property.minimum.has_value() && number < *property.minimum) {
954 "elicitation content field '" + name +
"' is below minimum"));
956 if (property.maximum.has_value() && number > *property.maximum) {
958 "elicitation content field '" + name +
"' is above maximum"));
960 }
else if constexpr (std::is_same_v<Property, IntegerSchema>) {
961 if (!value.is_number_integer()) {
963 "elicitation content field '" + name +
"' must be an integer"));
965 const auto integer = value.get<std::int64_t>();
966 if (property.minimum.has_value() && integer < *
property.minimum) {
968 "elicitation content field '" + name +
"' is below minimum"));
970 if (property.maximum.has_value() && integer > *property.maximum) {
972 "elicitation content field '" + name +
"' is above maximum"));
974 }
else if constexpr (std::is_same_v<Property, BooleanSchema>) {
975 if (!value.is_boolean()) {
977 "elicitation content field '" + name +
"' must be a boolean"));
980 if (property.multi_select) {
981 if (!value.is_array()) {
983 "elicitation content field '" + name +
"' must be an array"));
985 if (property.min_items.has_value() &&
986 value.size() <
static_cast<std::size_t
>(*property.min_items)) {
987 return mcp::core::unexpected(
989 "' has too few selections"));
991 if (property.max_items.has_value() &&
992 value.size() >
static_cast<std::size_t
>(*property.max_items)) {
993 return mcp::core::unexpected(
995 "' has too many selections"));
997 for (
const auto& item : value) {
998 if (!item.is_string()) {
1000 "elicitation content field '" + name +
1001 "' selections must be strings"));
1003 const auto enum_value = item.get<std::string>();
1004 if (std::find(property.values.begin(), property.values.end(),
1005 enum_value) ==
property.values.end()) {
1006 return mcp::core::unexpected(
1008 name +
"' must match enum values"));
1011 }
else if (!value.is_string()) {
1013 "elicitation content field '" + name +
"' must be a string"));
1015 const auto enum_value = value.get<std::string>();
1016 if (std::find(property.values.begin(), property.values.end(),
1017 enum_value) ==
property.values.end()) {
1018 return mcp::core::unexpected(
1020 "' must match an enum value"));
1038 if (!content.is_object()) {
1039 return mcp::core::unexpected(
1043 for (
const auto& required : schema.
required) {
1044 if (!content.contains(required)) {
1046 "elicitation content requires field '" + required +
"'"));
1050 for (
const auto& [name, property] : schema.
properties) {
1051 if (!content.contains(name)) {
1072 if (result.
action != ElicitationAction::Accept) {
1075 if (!result.
content.has_value()) {
1079 return mcp::core::unexpected(
1095 return reflect_from_json<ElicitationCompleteNotificationParams>(json);
1099inline bool ElicitationSchema::Builder::validate_name(
const std::string& name) {
1100 return !name.empty();
1104inline ElicitationSchema::Builder& ElicitationSchema::Builder::add_required(
1105 std::string name, PrimitiveSchema schema) {
1106 required_.push_back(name);
1107 properties_.insert_or_assign(std::move(name), std::move(schema));
1112inline ElicitationSchema::Builder& ElicitationSchema::Builder::add_optional(
1113 std::string name, PrimitiveSchema schema) {
1114 properties_.insert_or_assign(std::move(name), std::move(schema));
1119 std::string name, std::optional<std::string> default_value,
1120 std::optional<std::string> format) {
1121 if (!validate_name(name)) {
1126 schema.
format = std::move(format);
1127 return add_required(std::move(name), std::move(schema));
1131 std::string name, std::optional<std::string> default_value,
1132 std::optional<std::string> format) {
1133 if (!validate_name(name)) {
1138 schema.
format = std::move(format);
1139 return add_optional(std::move(name), std::move(schema));
1143 std::string name, std::optional<double> minimum,
1144 std::optional<double> maximum, std::optional<double> default_value) {
1145 if (!validate_name(name)) {
1152 return add_required(std::move(name), std::move(schema));
1156 std::string name, std::optional<double> minimum,
1157 std::optional<double> maximum, std::optional<double> default_value) {
1158 if (!validate_name(name)) {
1165 return add_optional(std::move(name), std::move(schema));
1169 std::string name, std::optional<std::int64_t> minimum,
1170 std::optional<std::int64_t> maximum,
1171 std::optional<std::int64_t> default_value) {
1172 if (!validate_name(name)) {
1179 return add_required(std::move(name), std::move(schema));
1183 std::string name, std::optional<std::int64_t> minimum,
1184 std::optional<std::int64_t> maximum,
1185 std::optional<std::int64_t> default_value) {
1186 if (!validate_name(name)) {
1193 return add_optional(std::move(name), std::move(schema));
1197 std::string name, std::optional<bool> default_value) {
1198 if (!validate_name(name)) {
1203 return add_required(std::move(name), std::move(schema));
1207 std::string name, std::optional<bool> default_value) {
1208 if (!validate_name(name)) {
1213 return add_optional(std::move(name), std::move(schema));
1217 std::string name, std::optional<std::string> default_value) {
1218 return required_string(std::move(name), std::move(default_value),
1219 std::string(
"email"));
1223 std::string name, std::optional<std::string> default_value) {
1224 return optional_string(std::move(name), std::move(default_value),
1225 std::string(
"email"));
1229 std::string name, std::vector<std::string> values,
1230 std::optional<std::string> default_value) {
1231 if (!validate_name(name)) {
1235 schema.
values = std::move(values);
1237 return add_required(std::move(name), std::move(schema));
1241 std::string name, std::vector<std::string> values,
1242 std::optional<std::string> default_value) {
1243 if (!validate_name(name)) {
1247 schema.
values = std::move(values);
1249 return add_optional(std::move(name), std::move(schema));
1255 if (properties_.empty()) {
1257 "elicitation schema requires at least one property"));
1260 schema.
title = title_;
1273 [](
const auto& value) ->
Json {
1274 using Value = std::decay_t<
decltype(value)>;
1275 if constexpr (std::is_same_v<Value, StringSchema>) {
1277 }
else if constexpr (std::is_same_v<Value, NumberSchema>) {
1279 }
else if constexpr (std::is_same_v<Value, IntegerSchema>) {
1281 }
else if constexpr (std::is_same_v<Value, BooleanSchema>) {
1293 if (!json.is_object()) {
1295 "elicitation property schema must be an object"));
1297 if (!json.contains(
"type") || !json.at(
"type").is_string()) {
1299 "elicitation property schema requires a string type"));
1302 const auto type = json.at(
"type").get<std::string>();
1303 if (type ==
"array") {
1306 if (json.contains(
"title")) {
1307 if (!json.at(
"title").is_string()) {
1309 "elicitation multi-select title must be a string"));
1311 schema.
title = json.at(
"title").get<std::string>();
1313 if (json.contains(
"description")) {
1314 if (!json.at(
"description").is_string()) {
1316 "elicitation multi-select description must be a string"));
1318 schema.
description = json.at(
"description").get<std::string>();
1320 if (!json.contains(
"items") || !json.at(
"items").is_object()) {
1321 return mcp::core::unexpected(
1324 const auto& items = json.at(
"items");
1325 if (items.contains(
"type") &&
1326 (!items.at(
"type").is_string() ||
1327 items.at(
"type").get<std::string>() !=
"string")) {
1329 "elicitation multi-select items type must be string"));
1331 if (items.contains(
"enum")) {
1332 if (!items.at(
"enum").is_array()) {
1334 "elicitation multi-select enum must be an array"));
1336 for (
const auto& item : items.at(
"enum")) {
1337 if (!item.is_string()) {
1339 "elicitation multi-select enum values must be strings"));
1341 schema.
values.push_back(item.get<std::string>());
1343 }
else if (items.contains(
"anyOf") || items.contains(
"oneOf")) {
1344 const auto choices_key = items.contains(
"anyOf") ?
"anyOf" :
"oneOf";
1347 "elicitation multi-select choices");
1348 if (!parsed_choices) {
1349 return mcp::core::unexpected(parsed_choices.error());
1353 "elicitation multi-select requires enum, anyOf, or oneOf items"));
1355 if (json.contains(
"minItems")) {
1356 if (!json.at(
"minItems").is_number_integer()) {
1358 "elicitation multi-select minItems must be an integer"));
1360 schema.
min_items = json.at(
"minItems").get<std::int64_t>();
1363 "elicitation multi-select minItems must be non-negative"));
1366 if (json.contains(
"maxItems")) {
1367 if (!json.at(
"maxItems").is_number_integer()) {
1369 "elicitation multi-select maxItems must be an integer"));
1371 schema.
max_items = json.at(
"maxItems").get<std::int64_t>();
1374 "elicitation multi-select maxItems must be non-negative"));
1380 "elicitation multi-select minItems must be <= maxItems"));
1382 if (json.contains(
"default")) {
1383 if (!json.at(
"default").is_array()) {
1385 "elicitation multi-select default must be an array"));
1387 for (
const auto& item : json.at(
"default")) {
1388 if (!item.is_string()) {
1390 "elicitation multi-select default values must be strings"));
1396 "elicitation multi-select default must match enum values"));
1400 json, {
"type",
"title",
"description",
"minItems",
"maxItems",
"items",
1404 if (json.contains(
"oneOf")) {
1405 if (type !=
"string") {
1407 "elicitation titled enum type must be string"));
1411 if (json.contains(
"title")) {
1412 if (!json.at(
"title").is_string()) {
1414 "elicitation titled enum title must be a string"));
1416 schema.
title = json.at(
"title").get<std::string>();
1418 if (json.contains(
"description")) {
1419 if (!json.at(
"description").is_string()) {
1421 "elicitation titled enum description must be a string"));
1423 schema.
description = json.at(
"description").get<std::string>();
1427 "elicitation titled enum oneOf");
1428 if (!parsed_choices) {
1429 return mcp::core::unexpected(parsed_choices.error());
1431 if (json.contains(
"default")) {
1432 if (!json.at(
"default").is_string()) {
1434 "elicitation titled enum default must be a string"));
1436 schema.
default_value = json.at(
"default").get<std::string>();
1437 if (std::find(schema.
values.begin(), schema.
values.end(),
1440 "elicitation titled enum default must match an enum value"));
1444 json, {
"type",
"title",
"description",
"oneOf",
"default"});
1447 if (json.contains(
"enum")) {
1448 if (type !=
"string") {
1449 return mcp::core::unexpected(
1452 if (!json.at(
"enum").is_array()) {
1453 return mcp::core::unexpected(
1457 if (json.contains(
"title")) {
1458 if (!json.at(
"title").is_string()) {
1459 return mcp::core::unexpected(
1462 schema.
title = json.at(
"title").get<std::string>();
1464 if (json.contains(
"description")) {
1465 if (!json.at(
"description").is_string()) {
1467 "elicitation enum description must be a string"));
1469 schema.
description = json.at(
"description").get<std::string>();
1471 for (
const auto& item : json.at(
"enum")) {
1472 if (!item.is_string()) {
1473 return mcp::core::unexpected(
1476 schema.
values.push_back(item.get<std::string>());
1478 if (json.contains(
"enumNames")) {
1479 if (!json.at(
"enumNames").is_array()) {
1480 return mcp::core::unexpected(
1483 for (
const auto& item : json.at(
"enumNames")) {
1484 if (!item.is_string()) {
1486 "elicitation enumNames entries must be strings"));
1488 schema.
enum_names.push_back(item.get<std::string>());
1492 "elicitation enumNames size must match enum values"));
1495 if (json.contains(
"default")) {
1496 if (!json.at(
"default").is_string()) {
1498 "elicitation enum default must be a string"));
1500 schema.
default_value = json.at(
"default").get<std::string>();
1501 if (std::find(schema.
values.begin(), schema.
values.end(),
1504 "elicitation enum default must match an enum value"));
1508 json, {
"type",
"title",
"description",
"enum",
"enumNames",
"default"});
1512 if (type ==
"string") {
1514 if (json.contains(
"title")) {
1515 if (!json.at(
"title").is_string()) {
1517 "elicitation string title must be a string"));
1519 schema.
title = json.at(
"title").get<std::string>();
1521 if (json.contains(
"description")) {
1522 if (!json.at(
"description").is_string()) {
1524 "elicitation string description must be a string"));
1526 schema.
description = json.at(
"description").get<std::string>();
1528 if (json.contains(
"format")) {
1529 if (!json.at(
"format").is_string()) {
1531 "elicitation string format must be a string"));
1533 schema.
format = json.at(
"format").get<std::string>();
1536 "elicitation string format is not supported"));
1539 if (json.contains(
"minLength")) {
1540 if (!json.at(
"minLength").is_number_integer()) {
1542 "elicitation string minLength must be an integer"));
1544 schema.
min_length = json.at(
"minLength").get<std::int64_t>();
1547 "elicitation string minLength must be non-negative"));
1550 if (json.contains(
"maxLength")) {
1551 if (!json.at(
"maxLength").is_number_integer()) {
1553 "elicitation string maxLength must be an integer"));
1555 schema.
max_length = json.at(
"maxLength").get<std::int64_t>();
1558 "elicitation string maxLength must be non-negative"));
1564 "elicitation string minLength must be <= maxLength"));
1566 if (json.contains(
"default")) {
1567 if (!json.at(
"default").is_string()) {
1569 "elicitation string default must be a string"));
1571 schema.
default_value = json.at(
"default").get<std::string>();
1575 "minLength",
"maxLength",
"default"});
1578 if (type ==
"number") {
1580 if (json.contains(
"title")) {
1581 if (!json.at(
"title").is_string()) {
1583 "elicitation number title must be a string"));
1585 schema.
title = json.at(
"title").get<std::string>();
1587 if (json.contains(
"description")) {
1588 if (!json.at(
"description").is_string()) {
1590 "elicitation number description must be a string"));
1592 schema.
description = json.at(
"description").get<std::string>();
1594 if (json.contains(
"minimum")) {
1595 if (!json.at(
"minimum").is_number()) {
1597 "elicitation number minimum must be numeric"));
1599 const auto value = json.at(
"minimum").get<
double>();
1602 "elicitation number minimum must be finite"));
1606 if (json.contains(
"maximum")) {
1607 if (!json.at(
"maximum").is_number()) {
1609 "elicitation number maximum must be numeric"));
1611 const auto value = json.at(
"maximum").get<
double>();
1614 "elicitation number maximum must be finite"));
1618 if (json.contains(
"default")) {
1619 if (!json.at(
"default").is_number()) {
1621 "elicitation number default must be numeric"));
1623 const auto value = json.at(
"default").get<
double>();
1626 "elicitation number default must be finite"));
1632 {
"type",
"title",
"description",
"minimum",
"maximum",
"default"});
1635 if (type ==
"integer") {
1637 if (json.contains(
"title")) {
1638 if (!json.at(
"title").is_string()) {
1640 "elicitation integer title must be a string"));
1642 schema.
title = json.at(
"title").get<std::string>();
1644 if (json.contains(
"description")) {
1645 if (!json.at(
"description").is_string()) {
1647 "elicitation integer description must be a string"));
1649 schema.
description = json.at(
"description").get<std::string>();
1651 if (json.contains(
"minimum")) {
1652 if (!json.at(
"minimum").is_number_integer()) {
1654 "elicitation integer minimum must be an integer"));
1656 schema.
minimum = json.at(
"minimum").get<std::int64_t>();
1658 if (json.contains(
"maximum")) {
1659 if (!json.at(
"maximum").is_number_integer()) {
1661 "elicitation integer maximum must be an integer"));
1663 schema.
maximum = json.at(
"maximum").get<std::int64_t>();
1665 if (json.contains(
"default")) {
1666 if (!json.at(
"default").is_number_integer()) {
1668 "elicitation integer default must be an integer"));
1670 schema.
default_value = json.at(
"default").get<std::int64_t>();
1674 {
"type",
"title",
"description",
"minimum",
"maximum",
"default"});
1677 if (type ==
"boolean") {
1679 if (json.contains(
"title")) {
1680 if (!json.at(
"title").is_string()) {
1682 "elicitation boolean title must be a string"));
1684 schema.
title = json.at(
"title").get<std::string>();
1686 if (json.contains(
"description")) {
1687 if (!json.at(
"description").is_string()) {
1689 "elicitation boolean description must be a string"));
1691 schema.
description = json.at(
"description").get<std::string>();
1693 if (json.contains(
"default")) {
1694 if (!json.at(
"default").is_boolean()) {
1696 "elicitation boolean default must be a boolean"));
1701 json, {
"type",
"title",
"description",
"default"});
1705 return mcp::core::unexpected(
Fluent builder for valid elicitation object schemas.
Definition elicitation.hpp:237
Builder & optional_bool(std::string name, std::optional< bool > default_value=std::nullopt)
Adds an optional boolean field.
Definition elicitation.hpp:1206
Builder & optional_enum(std::string name, std::vector< std::string > values, std::optional< std::string > default_value=std::nullopt)
Adds an optional string enum field.
Definition elicitation.hpp:1240
Builder & required_enum(std::string name, std::vector< std::string > values, std::optional< std::string > default_value=std::nullopt)
Adds a required string enum field.
Definition elicitation.hpp:1228
Builder & optional_number(std::string name, std::optional< double > minimum=std::nullopt, std::optional< double > maximum=std::nullopt, std::optional< double > default_value=std::nullopt)
Adds an optional number field.
Definition elicitation.hpp:1155
Builder & required_integer(std::string name, std::optional< std::int64_t > minimum=std::nullopt, std::optional< std::int64_t > maximum=std::nullopt, std::optional< std::int64_t > default_value=std::nullopt)
Adds a required integer field.
Definition elicitation.hpp:1168
Builder & required_number(std::string name, std::optional< double > minimum=std::nullopt, std::optional< double > maximum=std::nullopt, std::optional< double > default_value=std::nullopt)
Adds a required number field.
Definition elicitation.hpp:1142
Builder & required_bool(std::string name, std::optional< bool > default_value=std::nullopt)
Adds a required boolean field.
Definition elicitation.hpp:1196
Builder & required_string(std::string name, std::optional< std::string > default_value=std::nullopt, std::optional< std::string > format=std::nullopt)
Adds a required string field.
Definition elicitation.hpp:1118
Builder & optional_integer(std::string name, std::optional< std::int64_t > minimum=std::nullopt, std::optional< std::int64_t > maximum=std::nullopt, std::optional< std::int64_t > default_value=std::nullopt)
Adds an optional integer field.
Definition elicitation.hpp:1182
Builder & required_property(std::string name, PrimitiveSchema schema)
Adds a required property with a pre-built primitive schema.
Definition elicitation.hpp:305
Builder & required_email(std::string name, std::optional< std::string > default_value=std::nullopt)
Adds a required string field with email format.
Definition elicitation.hpp:1216
Builder & title(std::string value)
Sets the optional form title.
Definition elicitation.hpp:240
Builder & optional_property(std::string name, PrimitiveSchema schema)
Adds an optional property with a pre-built primitive schema.
Definition elicitation.hpp:310
core::Result< ElicitationSchema > build() const
Builds the schema after validation.
Definition elicitation.hpp:1253
Builder & optional_string(std::string name, std::optional< std::string > default_value=std::nullopt, std::optional< std::string > format=std::nullopt)
Adds an optional string field.
Definition elicitation.hpp:1130
Builder & optional_email(std::string name, std::optional< std::string > default_value=std::nullopt)
Adds an optional string field with email format.
Definition elicitation.hpp:1222
Builder & description(std::string value)
Sets the optional form description.
Definition elicitation.hpp:246
std::string elicitation_action_to_string(ElicitationAction action)
Converts an elicitation action to its MCP string value.
Definition elicitation.hpp:396
Json primitive_schema_to_json(const PrimitiveSchema &schema)
Serializes any primitive elicitation property schema.
Definition elicitation.hpp:1271
Json number_schema_to_json(const NumberSchema &schema)
Serializes a number property schema.
Definition elicitation.hpp:502
bool elicitation_string_format_is_supported(const std::string &value) noexcept
Returns true for string formats allowed by the MCP elicitation schema.
Definition elicitation.hpp:469
Json elicitation_complete_notification_params_to_json(const ElicitationCompleteNotificationParams ¶ms)
Serializes URL-mode completion notification params.
Definition elicitation.hpp:1086
ElicitationMode
Elicitation interaction mode.
Definition elicitation.hpp:42
@ Url
External URL flow completed by notification.
@ Form
Inline form described by an ElicitationSchema.
core::Error elicitation_json_error(std::string message)
Builds an InvalidRequest error for elicitation JSON validation failures.
Definition elicitation.hpp:648
core::Result< core::Unit > parse_titled_enum_choices(const Json &choices, std::vector< std::string > &values, std::vector< std::string > &titles, std::string_view context)
Parses {"const": "...", "title": "..."} enum choices.
Definition elicitation.hpp:654
core::Result< core::Unit > validate_elicitation_content(const ElicitationSchema &schema, const Json &content)
Validates a form elicitation content object against the SDK's constrained ElicitationSchema model.
Definition elicitation.hpp:1036
Json elicitation_schema_to_json(const ElicitationSchema &schema)
Serializes a form elicitation object schema.
Definition elicitation.hpp:626
core::Result< PrimitiveSchema > primitive_schema_from_json(const Json &json)
Parses any primitive elicitation property schema.
Definition elicitation.hpp:1291
std::optional< ElicitationMode > elicitation_mode_from_string(const std::string &value)
Parses an elicitation mode string.
Definition elicitation.hpp:456
core::Result< core::Unit > validate_elicitation_content_property(const std::string &name, const PrimitiveSchema &schema, const Json &value)
Validates a form elicitation content object against one primitive property schema.
Definition elicitation.hpp:917
core::Result< CreateElicitationRequestParam > create_elicitation_request_param_from_json(const Json &json)
Parses elicitation/create params.
Definition elicitation.hpp:785
std::optional< ElicitationAction > elicitation_action_from_string(const std::string &value)
Parses an elicitation action string.
Definition elicitation.hpp:410
Json enum_schema_to_json(const EnumSchema &schema)
Serializes a string enum property schema.
Definition elicitation.hpp:565
core::Result< ElicitationSchema > elicitation_schema_from_json(const Json &json)
Parses a form elicitation object schema.
Definition elicitation.hpp:692
core::Result< CreateElicitationResult > create_elicitation_result_from_json(const Json &json)
Parses an elicitation/create result.
Definition elicitation.hpp:881
core::Result< ElicitationCompleteNotificationParams > elicitation_complete_notification_params_from_json(const Json &json)
Parses URL-mode completion notification params.
Definition elicitation.hpp:1094
bool enum_values_are_allowed(const std::vector< std::string > &allowed, const std::vector< std::string > &values)
Validates all selected enum values are allowed.
Definition elicitation.hpp:675
ElicitationAction
User action returned by an elicitation request.
Definition elicitation.hpp:32
@ Decline
The user declined the request.
@ Accept
The user accepted and may have supplied content.
@ Cancel
The elicitation was cancelled.
Json boolean_schema_to_json(const BooleanSchema &schema)
Serializes a boolean property schema.
Definition elicitation.hpp:548
std::string elicitation_mode_to_string(ElicitationMode mode)
Converts an elicitation mode to its MCP string value.
Definition elicitation.hpp:444
Json integer_schema_to_json(const IntegerSchema &schema)
Serializes an integer property schema.
Definition elicitation.hpp:525
Json string_schema_to_json(const StringSchema &schema)
Serializes a string property schema.
Definition elicitation.hpp:476
std::variant< StringSchema, NumberSchema, IntegerSchema, BooleanSchema, EnumSchema > PrimitiveSchema
Variant over primitive schema shapes supported by elicitation forms.
Definition elicitation.hpp:141
Json create_elicitation_result_to_json(const CreateElicitationResult &result)
Serializes an elicitation/create result.
Definition elicitation.hpp:864
Json create_elicitation_request_param_to_json(const CreateElicitationRequestParam &request)
Serializes elicitation/create params.
Definition elicitation.hpp:751
core::Result< core::Unit > validate_elicitation_result_content(const ElicitationSchema &schema, const CreateElicitationResult &result)
Validates an accepted elicitation result's content against the requested form schema.
Definition elicitation.hpp:1070
Shared JSON, JSON-RPC, error, cancellation, and progress model types.
void append_json_extensions(Json &json, const Json &extensions)
Flattens extension members into a JSON object without overwriting typed fields.
Definition types.hpp:358
nlohmann::json Json
JSON value type used by all protocol DTOs.
Definition types.hpp:28
Json collect_json_extensions(const Json &json, std::initializer_list< std::string_view > known_keys)
Collects unknown object members so typed DTOs can preserve future protocol fields and vendor extensio...
Definition types.hpp:320
bool protocol_number_is_finite(double value) noexcept
Returns true for finite JSON floating-point values accepted by MCP.
Definition types.hpp:31
constexpr FieldDescriptor< Struct, Field > field(const char *wire_name, Field Struct::*pointer)
Creates a FieldDescriptor with wire name and pointer-to-member.
Definition reflect.hpp:75
ExtensionsField< Struct > extensions_field(Json Struct::*pointer, std::vector< std::string > own_keys)
Creates an ExtensionsField descriptor.
Definition reflect.hpp:90
Json reflect_to_json(const T &obj)
Serializes a DTO to JSON using its Reflect<T> trait.
Definition reflect.hpp:701
Shared result and error primitives used by the public cxxmcp SDK.
std::monostate Unit
Success value for operations that only need to report failure.
Definition result.hpp:55
tl::expected< T, Error > Result
Alias for the SDK result type.
Definition result.hpp:64
Structured error returned by fallible SDK operations.
Definition result.hpp:35
Primitive boolean property schema for form elicitation.
Definition elicitation.hpp:100
std::optional< bool > default_value
Optional default boolean value.
Definition elicitation.hpp:106
std::optional< std::string > description
Optional display description.
Definition elicitation.hpp:104
Json extensions
Unknown JSON members preserved for forward-compatible round trips.
Definition elicitation.hpp:108
std::optional< std::string > title
Optional display title.
Definition elicitation.hpp:102
Parameters for elicitation/create.
Definition elicitation.hpp:335
std::optional< TaskRequestParameters > task
Optional task request parameters for asynchronous elicitation.
Definition elicitation.hpp:350
std::optional< Json > request_state
Optional opaque state echoed through the elicitation request lifecycle.
Definition elicitation.hpp:348
ElicitationSchema requested_schema
Form-mode schema describing requested values.
Definition elicitation.hpp:346
std::optional< std::string > url
Required in URL mode; target URL for the external interaction.
Definition elicitation.hpp:344
std::optional< Json > meta
Optional _meta extension object preserved on the wire.
Definition elicitation.hpp:352
std::optional< std::string > elicitation_id
Required in URL mode to correlate the later completion notification.
Definition elicitation.hpp:342
std::string message
User-facing message explaining what input is requested.
Definition elicitation.hpp:337
ElicitationMode mode
Interaction mode; form mode serializes requested_schema, URL mode serializes elicitation_id and url.
Definition elicitation.hpp:340
Json extensions
Unknown JSON members preserved for forward-compatible round trips.
Definition elicitation.hpp:354
Result object for elicitation/create.
Definition elicitation.hpp:358
std::optional< Json > meta
Optional _meta extension object preserved on the wire.
Definition elicitation.hpp:364
std::optional< Json > content
Optional content object supplied when the action is Accept.
Definition elicitation.hpp:362
Json extensions
Unknown JSON members preserved for forward-compatible round trips.
Definition elicitation.hpp:366
ElicitationAction action
User action taken in response to the request.
Definition elicitation.hpp:360
Parameters for notifications/elicitation/complete.
Definition elicitation.hpp:370
std::optional< Json > meta
Optional _meta extension object preserved on the wire.
Definition elicitation.hpp:374
Json extensions
Unknown JSON members preserved for forward-compatible round trips.
Definition elicitation.hpp:376
std::string elicitation_id
URL-mode elicitation id that has completed.
Definition elicitation.hpp:372
Object schema requested from a user in form elicitation.
Definition elicitation.hpp:144
static StringSchema new_string(std::optional< std::string > title=std::nullopt, std::optional< std::string > description=std::nullopt, std::optional< std::string > format=std::nullopt, std::optional< std::int64_t > min_length=std::nullopt, std::optional< std::int64_t > max_length=std::nullopt, std::optional< std::string > default_value=std::nullopt)
Creates a new string primitive schema.
Definition elicitation.hpp:157
std::map< std::string, PrimitiveSchema > properties
Properties keyed by field name.
Definition elicitation.hpp:150
static BooleanSchema new_boolean(std::optional< std::string > title=std::nullopt, std::optional< std::string > description=std::nullopt, std::optional< bool > default_value=std::nullopt)
Creates a new boolean primitive schema.
Definition elicitation.hpp:207
std::optional< std::string > title
Optional form title.
Definition elicitation.hpp:146
static Builder builder()
Creates a builder for an elicitation object schema.
Definition elicitation.hpp:331
static EnumSchema new_enum(std::vector< std::string > values, std::optional< std::string > title=std::nullopt, std::optional< std::string > description=std::nullopt, std::optional< std::string > default_value=std::nullopt)
Creates a new enum primitive schema.
Definition elicitation.hpp:219
std::vector< std::string > required
Names of required properties.
Definition elicitation.hpp:152
static NumberSchema new_number(std::optional< std::string > title=std::nullopt, std::optional< std::string > description=std::nullopt, std::optional< double > minimum=std::nullopt, std::optional< double > maximum=std::nullopt, std::optional< double > default_value=std::nullopt)
Creates a new number primitive schema.
Definition elicitation.hpp:175
static IntegerSchema new_integer(std::optional< std::string > title=std::nullopt, std::optional< std::string > description=std::nullopt, std::optional< std::int64_t > minimum=std::nullopt, std::optional< std::int64_t > maximum=std::nullopt, std::optional< std::int64_t > default_value=std::nullopt)
Creates a new integer primitive schema.
Definition elicitation.hpp:191
Json extensions
Unknown JSON members preserved for forward-compatible round trips.
Definition elicitation.hpp:154
std::optional< std::string > description
Optional form description.
Definition elicitation.hpp:148
Primitive string enum property schema for form elicitation.
Definition elicitation.hpp:112
bool multi_select
Whether this enum is represented as an array multi-select.
Definition elicitation.hpp:126
std::optional< std::int64_t > max_items
Optional maximum number of selected items for multi-select.
Definition elicitation.hpp:130
std::optional< std::string > default_value
Optional default enum value.
Definition elicitation.hpp:132
bool titled_single_select
Whether to serialize a single-select enum as titled oneOf.
Definition elicitation.hpp:124
std::optional< std::string > description
Optional display description.
Definition elicitation.hpp:116
std::vector< std::string > default_values
Optional default enum values for multi-select.
Definition elicitation.hpp:134
std::optional< std::string > title
Optional display title.
Definition elicitation.hpp:114
std::optional< std::int64_t > min_items
Optional minimum number of selected items for multi-select.
Definition elicitation.hpp:128
std::vector< std::string > enum_names
Optional display names for legacy enumNames.
Definition elicitation.hpp:120
std::vector< std::string > values
Allowed string values.
Definition elicitation.hpp:118
Json extensions
Unknown JSON members preserved for forward-compatible round trips.
Definition elicitation.hpp:136
std::vector< std::string > value_titles
Optional titles for RMCP/spec oneOf/anyOf enum entries.
Definition elicitation.hpp:122
Primitive integer property schema for form elicitation.
Definition elicitation.hpp:84
std::optional< std::string > description
Optional display description.
Definition elicitation.hpp:88
std::optional< std::int64_t > minimum
Optional inclusive minimum.
Definition elicitation.hpp:90
Json extensions
Unknown JSON members preserved for forward-compatible round trips.
Definition elicitation.hpp:96
std::optional< std::string > title
Optional display title.
Definition elicitation.hpp:86
std::optional< std::int64_t > default_value
Optional default integer value.
Definition elicitation.hpp:94
std::optional< std::int64_t > maximum
Optional inclusive maximum.
Definition elicitation.hpp:92
Type-specific serialization and deserialization logic.
Definition reflect.hpp:246
Primitive number property schema for form elicitation.
Definition elicitation.hpp:68
std::optional< std::string > description
Optional display description.
Definition elicitation.hpp:72
std::optional< std::string > title
Optional display title.
Definition elicitation.hpp:70
Json extensions
Unknown JSON members preserved for forward-compatible round trips.
Definition elicitation.hpp:80
std::optional< double > minimum
Optional inclusive minimum.
Definition elicitation.hpp:74
std::optional< double > default_value
Optional default numeric value.
Definition elicitation.hpp:78
std::optional< double > maximum
Optional inclusive maximum.
Definition elicitation.hpp:76
Primary template.
Definition reflect.hpp:199
Primitive string property schema for form elicitation.
Definition elicitation.hpp:50
std::optional< std::string > title
Optional display title.
Definition elicitation.hpp:52
std::optional< std::string > description
Optional display description.
Definition elicitation.hpp:54
std::optional< std::string > default_value
Optional default string value.
Definition elicitation.hpp:62
std::optional< std::string > format
Optional JSON Schema string format, such as email.
Definition elicitation.hpp:56
std::optional< std::int64_t > min_length
Optional minimum string length.
Definition elicitation.hpp:58
Json extensions
Unknown JSON members preserved for forward-compatible round trips.
Definition elicitation.hpp:64
std::optional< std::int64_t > max_length
Optional maximum string length.
Definition elicitation.hpp:60
Asynchronous task status and task-management payloads.
Json task_request_parameters_to_json(const TaskRequestParameters ¶meters)
Serializes optional task request parameters.
Definition task.hpp:319
core::Result< TaskRequestParameters > task_request_parameters_from_json(const Json &json)
Parses optional task request parameters.
Definition task.hpp:326