cxxmcp 1.1.6
C++ MCP SDK
Loading...
Searching...
No Matches
task.hpp
Go to the documentation of this file.
1// Copyright (c) 2025 [caomengxuan666]
2
3#pragma once
4
12
13#include <cstdint>
14#include <optional>
15#include <string>
16#include <string_view>
17#include <utility>
18#include <variant>
19#include <vector>
20
24
25namespace mcp::protocol {
26
28enum class TaskStatus {
30 Working,
36 Failed,
39};
40
42inline std::string task_status_to_string(TaskStatus status) {
43 switch (status) {
44 case TaskStatus::Working:
45 return "working";
46 case TaskStatus::InputRequired:
47 return "input_required";
48 case TaskStatus::Completed:
49 return "completed";
50 case TaskStatus::Failed:
51 return "failed";
52 case TaskStatus::Cancelled:
53 return "cancelled";
54 }
55 return "working";
56}
57
60inline std::optional<TaskStatus> task_status_from_string(
61 const std::string& value) {
62 if (value == "working") {
63 return TaskStatus::Working;
64 }
65 if (value == "input_required") {
66 return TaskStatus::InputRequired;
67 }
68 if (value == "completed") {
69 return TaskStatus::Completed;
70 }
71 if (value == "failed") {
72 return TaskStatus::Failed;
73 }
74 if (value == "cancelled") {
75 return TaskStatus::Cancelled;
76 }
77 return std::nullopt;
78}
79
81template <>
83 static void serialize(Json& json, const char* key, TaskStatus value) {
84 json[key] = task_status_to_string(value);
85 }
86 static bool deserialize(const Json& json, const char* key,
87 TaskStatus& target) {
88 if (!json.contains(key) || !json.at(key).is_string()) {
89 return false;
90 }
91 auto val = task_status_from_string(json.at(key).get<std::string>());
92 if (!val.has_value()) {
93 return false;
94 }
95 target = *val;
96 return true;
97 }
98};
99
103 std::optional<std::int64_t> ttl;
105 Json extensions = Json::object();
107 std::optional<Json> meta;
108};
109
110template <>
112 static constexpr bool defined = true;
113 static auto fields() {
114 return std::make_tuple(
118 }
119 static std::vector<std::string> known_keys() { return {"ttl", "_meta"}; }
120};
122
123template <>
125 static void serialize(Json& json, const char* key,
126 const TaskRequestParameters& value) {
127 json[key] = reflect_to_json(value);
128 }
129 static bool deserialize(const Json& json, const char* key,
130 TaskRequestParameters& target) {
131 if (!json.contains(key)) {
132 return false;
133 }
134 auto result = reflect_from_json<TaskRequestParameters>(json.at(key));
135 if (!result) {
136 return false;
137 }
138 target = std::move(*result);
139 return true;
140 }
141};
142
144struct Task {
146 std::string task_id;
148 TaskStatus status = TaskStatus::Working;
150 std::optional<std::string> status_message;
152 std::string created_at;
154 std::variant<std::monostate, std::int64_t> ttl = std::monostate{};
156 std::optional<std::int64_t> poll_interval;
158 std::string last_updated_at;
160 Json extensions = Json::object();
161};
162
164template <>
165struct Reflect<Task> {
166 static constexpr bool defined = true;
167 static auto fields() {
168 return std::make_tuple(
169 field("taskId", &Task::task_id), field("status", &Task::status),
170 field("statusMessage", &Task::status_message),
171 field("createdAt", &Task::created_at),
172 nullable_field("ttl", &Task::ttl),
173 field("pollInterval", &Task::poll_interval),
174 field("lastUpdatedAt", &Task::last_updated_at),
176 {"taskId", "status", "statusMessage", "createdAt",
177 "ttl", "pollInterval", "lastUpdatedAt"}));
178 }
179 static std::vector<std::string> known_keys() {
180 return {"taskId", "status", "statusMessage", "createdAt",
181 "ttl", "pollInterval", "lastUpdatedAt"};
182 }
183};
185
189 std::optional<std::string> cursor;
191 std::optional<Json> meta;
193 Json extensions = Json::object();
194};
195
196template <>
198 static constexpr bool defined = true;
199 static auto fields() {
200 return std::make_tuple(
201 field("cursor", &TaskListParams::cursor),
202 field("_meta", &TaskListParams::meta),
203 extensions_field(&TaskListParams::extensions, {"cursor", "_meta"}));
204 }
205 static std::vector<std::string> known_keys() { return {"cursor", "_meta"}; }
206};
207
211 std::string task_id;
213 std::optional<Json> meta;
215 Json extensions = Json::object();
216};
217
218template <>
220 static constexpr bool defined = true;
221 static auto fields() {
222 return std::make_tuple(
223 field("taskId", &TaskGetParams::task_id),
224 field("_meta", &TaskGetParams::meta),
225 extensions_field(&TaskGetParams::extensions, {"taskId", "_meta"}));
226 }
227 static std::vector<std::string> known_keys() { return {"taskId", "_meta"}; }
228};
229
232
236 std::string task_id;
238 std::optional<Json> meta;
240 Json extensions = Json::object();
241};
242
243template <>
245 static constexpr bool defined = true;
246 static auto fields() {
247 return std::make_tuple(
249 field("_meta", &TaskCancelParams::meta),
250 extensions_field(&TaskCancelParams::extensions, {"taskId", "_meta"}));
251 }
252 static std::vector<std::string> known_keys() { return {"taskId", "_meta"}; }
253};
254
258 std::vector<Task> tasks;
260 std::optional<std::string> next_cursor;
262 std::optional<std::int64_t> total;
264 std::optional<Json> meta;
266 Json extensions = Json::object();
267};
268
274 std::optional<Json> meta;
276 Json extensions = Json::object();
277};
278
284 std::optional<Json> meta;
286 Json extensions = Json::object();
287};
288
294 std::optional<Json> meta;
296 Json extensions = Json::object();
297};
298
307 std::optional<Json> meta;
309 Json extensions = Json::object();
310};
311
313inline core::Error task_json_error(std::string message) {
314 return core::Error{
315 static_cast<int>(ErrorCode::InvalidRequest), std::move(message), {}};
316}
317
320 const TaskRequestParameters& parameters) {
321 return reflect_to_json(parameters);
322}
323
327 const Json& json) {
328 return reflect_from_json<TaskRequestParameters>(json);
329}
330
332inline Json task_to_json(const Task& task) { return reflect_to_json(task); }
333
337 return reflect_from_json<Task>(json);
338}
339
342 const std::optional<Json>& meta,
343 const Json& extensions) {
344 Json json = task_to_json(task);
345 if (meta.has_value()) {
346 json["_meta"] = *meta;
347 }
348 append_json_extensions(json, extensions);
349 return json;
350}
351
354 const Json& json, std::string_view context) {
355 if (!json.is_object()) {
356 return mcp::core::unexpected(
357 task_json_error(std::string(context) + " result must be an object"));
358 }
359 auto task = task_from_json(json);
360 if (!task) {
361 return mcp::core::unexpected(task.error());
362 }
363 task->extensions.erase("_meta");
364
365 TaskGetResult result;
366 result.task = *task;
367 if (json.contains("_meta")) {
368 if (!json.at("_meta").is_object()) {
369 return mcp::core::unexpected(task_json_error(
370 std::string(context) + " result _meta must be an object"));
371 }
372 result.meta = json.at("_meta");
373 }
375 json, {"taskId", "status", "statusMessage", "createdAt", "ttl",
376 "pollInterval", "lastUpdatedAt", "_meta"});
377 return result;
378}
379
382 return reflect_to_json(params);
383}
384
388 const Json& json) {
389 return reflect_from_json<TaskListParams>(json);
390}
391
394 return reflect_to_json(params);
395}
396
400 return reflect_from_json<TaskGetParams>(json);
401}
402
405 return reflect_to_json(params);
406}
407
411 const Json& json) {
412 return reflect_from_json<TaskCancelParams>(json);
413}
414
417 return task_get_params_to_json(params);
418}
419
426
429 Json json = Json::object();
430 json["tasks"] = Json::array();
431 for (const auto& task : result.tasks) {
432 json["tasks"].push_back(task_to_json(task));
433 }
434 if (result.next_cursor.has_value()) {
435 json["nextCursor"] = *result.next_cursor;
436 }
437 if (result.total.has_value()) {
438 json["total"] = *result.total;
439 }
440 if (result.meta.has_value()) {
441 json["_meta"] = *result.meta;
442 }
444 return json;
445}
446
450 const Json& json) {
451 if (!json.is_object()) {
452 return mcp::core::unexpected(
453 task_json_error("tasks/list result must be an object"));
454 }
455 if (!json.contains("tasks") || !json.at("tasks").is_array()) {
456 return mcp::core::unexpected(
457 task_json_error("tasks/list result requires a tasks array"));
458 }
459
460 TaskListResult result;
461 for (const auto& item : json.at("tasks")) {
462 const auto task = task_from_json(item);
463 if (!task) {
464 return mcp::core::unexpected(task.error());
465 }
466 result.tasks.push_back(*task);
467 }
468 if (json.contains("nextCursor")) {
469 if (!json.at("nextCursor").is_string()) {
470 return mcp::core::unexpected(
471 task_json_error("tasks/list nextCursor must be a string"));
472 }
473 result.next_cursor = json.at("nextCursor").get<std::string>();
474 }
475 if (json.contains("total")) {
476 if (!json.at("total").is_number_integer()) {
477 return mcp::core::unexpected(
478 task_json_error("tasks/list total must be an integer"));
479 }
480 const auto total = json.at("total").get<std::int64_t>();
481 if (total < 0) {
482 return mcp::core::unexpected(
483 task_json_error("tasks/list total must be non-negative"));
484 }
485 result.total = total;
486 }
487 if (json.contains("_meta")) {
488 if (!json.at("_meta").is_object()) {
489 return mcp::core::unexpected(
490 task_json_error("tasks/list result _meta must be an object"));
491 }
492 result.meta = json.at("_meta");
493 }
494 result.extensions =
495 collect_json_extensions(json, {"tasks", "nextCursor", "total", "_meta"});
496 return result;
497}
498
501 return task_operation_result_to_json(result.task, result.meta,
502 result.extensions);
503}
504
507 return task_operation_result_from_json(json, "tasks/get");
508}
509
512 return task_operation_result_to_json(result.task, result.meta,
513 result.extensions);
514}
515
518 const Json& json) {
519 const auto parsed = task_operation_result_from_json(json, "tasks/cancel");
520 if (!parsed) {
521 return mcp::core::unexpected(parsed.error());
522 }
523 TaskCancelResult result;
524 result.task = parsed->task;
525 result.meta = parsed->meta;
526 result.extensions = parsed->extensions;
527 return result;
528}
529
535 const TaskGetPayloadResult& result) {
536 Json json = Json::object();
537 if (result.payload.is_object()) {
538 for (const auto& [key, value] : result.payload.items()) {
539 json[key] = value;
540 }
541 }
542 if (result.meta.has_value()) {
543 json["_meta"] = *result.meta;
544 }
546 return json;
547}
548
552 const Json& json) {
553 if (!json.is_object()) {
554 return mcp::core::unexpected(
555 task_json_error("tasks/result result must be an object"));
556 }
557
559 result.payload = Json::object();
560 for (const auto& [key, value] : json.items()) {
561 if (key != "_meta") {
562 result.payload[key] = value;
563 }
564 }
565 if (json.contains("_meta")) {
566 if (!json.at("_meta").is_object()) {
567 return mcp::core::unexpected(
568 task_json_error("tasks/result _meta must be an object"));
569 }
570 result.meta = json.at("_meta");
571 }
572 return result;
573}
574
577 Json json = Json::object();
578 json["task"] = task_to_json(result.task);
579 if (result.meta.has_value()) {
580 json["_meta"] = *result.meta;
581 }
583 return json;
584}
585
589 const Json& json) {
590 if (!json.is_object()) {
591 return mcp::core::unexpected(
592 task_json_error("createTask result must be an object"));
593 }
594 if (!json.contains("task")) {
595 return mcp::core::unexpected(
596 task_json_error("createTask result requires task"));
597 }
598
599 const auto task = task_from_json(json.at("task"));
600 if (!task) {
601 return mcp::core::unexpected(task.error());
602 }
603
604 CreateTaskResult result;
605 result.task = *task;
606 if (json.contains("_meta")) {
607 if (!json.at("_meta").is_object()) {
608 return mcp::core::unexpected(
609 task_json_error("createTask result _meta must be an object"));
610 }
611 result.meta = json.at("_meta");
612 }
613 result.extensions = collect_json_extensions(json, {"task", "_meta"});
614 return result;
615}
616
617} // namespace mcp::protocol
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
C++17 tuple-reflection infrastructure for zero-boilerplate DTO serialization.
#define CXXMCP_REFLECT_CHECK(Struct, expected_count)
Validates that a Reflect<> specialization covers the expected number of fields.
Definition reflect.hpp:1008
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
constexpr FieldDescriptor< Struct, Field > nullable_field(const char *wire_name, Field Struct::*pointer)
Creates a FieldDescriptor whose missing wire value maps to std::monostate.
Definition reflect.hpp:134
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.
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
Result wrapper returned when a feature request creates a task.
Definition task.hpp:270
Json extensions
Unknown JSON members preserved for forward-compatible round trips.
Definition task.hpp:276
std::optional< Json > meta
Optional _meta extension object preserved on the wire.
Definition task.hpp:274
Task task
Created task snapshot.
Definition task.hpp:272
Type-specific serialization and deserialization logic.
Definition reflect.hpp:246
Primary template.
Definition reflect.hpp:199
Parameters for tasks/cancel.
Definition task.hpp:234
Json extensions
Unknown JSON members preserved for forward-compatible round trips.
Definition task.hpp:240
std::optional< Json > meta
Optional _meta extension object preserved on the wire.
Definition task.hpp:238
std::string task_id
Task identifier to cancel.
Definition task.hpp:236
Result object for tasks/cancel with task fields flattened.
Definition task.hpp:290
Json extensions
Unknown JSON members preserved for forward-compatible round trips.
Definition task.hpp:296
std::optional< Json > meta
Optional _meta extension object preserved on the wire.
Definition task.hpp:294
Task task
Cancelled task snapshot.
Definition task.hpp:292
Parameters for tasks/get.
Definition task.hpp:209
Json extensions
Unknown JSON members preserved for forward-compatible round trips.
Definition task.hpp:215
std::optional< Json > meta
Optional _meta extension object preserved on the wire.
Definition task.hpp:213
std::string task_id
Task identifier to retrieve.
Definition task.hpp:211
Result object for tasks/result (GetTaskPayloadResult equivalent).
Definition task.hpp:303
Json payload
The original request's result (polymorphic – may be any JSON value).
Definition task.hpp:305
Json extensions
Unknown JSON members preserved for forward-compatible round trips.
Definition task.hpp:309
std::optional< Json > meta
Optional _meta extension object preserved on the wire.
Definition task.hpp:307
Result object for tasks/get with task fields flattened.
Definition task.hpp:280
Task task
Retrieved task snapshot.
Definition task.hpp:282
std::optional< Json > meta
Optional _meta extension object preserved on the wire.
Definition task.hpp:284
Json extensions
Unknown JSON members preserved for forward-compatible round trips.
Definition task.hpp:286
Parameters for tasks/list.
Definition task.hpp:187
Json extensions
Unknown JSON members preserved for forward-compatible round trips.
Definition task.hpp:193
std::optional< Json > meta
Optional _meta extension object preserved on the wire.
Definition task.hpp:191
std::optional< std::string > cursor
Optional pagination cursor from a prior tasks/list result.
Definition task.hpp:189
Result object for tasks/list.
Definition task.hpp:256
Json extensions
Unknown JSON members preserved for forward-compatible round trips.
Definition task.hpp:266
std::optional< std::int64_t > total
Optional total number of tasks known to the peer.
Definition task.hpp:262
std::vector< Task > tasks
Page of tasks.
Definition task.hpp:258
std::optional< Json > meta
Optional _meta extension object preserved on the wire.
Definition task.hpp:264
std::optional< std::string > next_cursor
Optional cursor for retrieving the next page.
Definition task.hpp:260
Optional task parameters embedded in feature requests.
Definition task.hpp:101
Json extensions
Vendor or future task options preserved for forward compatibility.
Definition task.hpp:105
std::optional< std::int64_t > ttl
Optional requested time-to-live for the created task.
Definition task.hpp:103
std::optional< Json > meta
Optional _meta extension object preserved on the wire.
Definition task.hpp:107
Snapshot of an asynchronous task.
Definition task.hpp:144
std::string last_updated_at
Last update timestamp as a protocol string.
Definition task.hpp:158
std::optional< std::string > status_message
Optional human-readable status detail.
Definition task.hpp:150
Json extensions
Unknown JSON members preserved for forward-compatible round trips.
Definition task.hpp:160
std::variant< std::monostate, std::int64_t > ttl
Task time-to-live. Monostate serializes as JSON null.
Definition task.hpp:154
std::optional< std::int64_t > poll_interval
Optional recommended polling interval.
Definition task.hpp:156
std::string created_at
Creation timestamp as a protocol string.
Definition task.hpp:152
TaskStatus status
Current lifecycle status.
Definition task.hpp:148
std::string task_id
Stable task identifier used by task management methods.
Definition task.hpp:146
Json create_task_result_to_json(const CreateTaskResult &result)
Serializes a task creation result wrapper.
Definition task.hpp:576
std::string task_status_to_string(TaskStatus status)
Converts a task status to its MCP string value.
Definition task.hpp:42
core::Result< TaskGetResult > task_operation_result_from_json(const Json &json, std::string_view context)
Parses a flattened task result wrapper.
Definition task.hpp:353
std::optional< TaskStatus > task_status_from_string(const std::string &value)
Parses a task status string.
Definition task.hpp:60
core::Error task_json_error(std::string message)
Builds an InvalidRequest error for task JSON validation failures.
Definition task.hpp:313
Json task_request_parameters_to_json(const TaskRequestParameters &parameters)
Serializes optional task request parameters.
Definition task.hpp:319
core::Result< TaskCancelParams > task_cancel_params_from_json(const Json &json)
Parses tasks/cancel params.
Definition task.hpp:410
Json task_cancel_result_to_json(const TaskCancelResult &result)
Serializes a tasks/cancel result with flattened task fields.
Definition task.hpp:511
core::Result< TaskGetPayloadResult > task_get_payload_result_from_json(const Json &json)
Parses a tasks/result payload result.
Definition task.hpp:551
TaskStatus
Lifecycle status for an asynchronous MCP task.
Definition task.hpp:28
@ Completed
Task completed successfully.
@ Working
Task is still running.
@ Cancelled
Task was cancelled.
@ InputRequired
Task is blocked waiting for additional input.
core::Result< TaskResultParams > task_result_params_from_json(const Json &json)
Parses tasks/result params.
Definition task.hpp:422
Json task_operation_result_to_json(const Task &task, const std::optional< Json > &meta, const Json &extensions)
Serializes a flattened task result wrapper.
Definition task.hpp:341
Json task_list_result_to_json(const TaskListResult &result)
Serializes a tasks/list result.
Definition task.hpp:428
core::Result< CreateTaskResult > create_task_result_from_json(const Json &json)
Parses a task creation result wrapper.
Definition task.hpp:588
core::Result< TaskRequestParameters > task_request_parameters_from_json(const Json &json)
Parses optional task request parameters.
Definition task.hpp:326
Json task_cancel_params_to_json(const TaskCancelParams &params)
Serializes tasks/cancel params.
Definition task.hpp:404
core::Result< TaskCancelResult > task_cancel_result_from_json(const Json &json)
Parses a tasks/cancel result with flattened task fields.
Definition task.hpp:517
Json task_get_payload_result_to_json(const TaskGetPayloadResult &result)
Serializes a tasks/result payload result.
Definition task.hpp:534
Json task_result_params_to_json(const TaskResultParams &params)
Serializes tasks/result params.
Definition task.hpp:416
core::Result< TaskGetResult > task_get_result_from_json(const Json &json)
Parses a tasks/get result with flattened task fields.
Definition task.hpp:506
core::Result< Task > task_from_json(const Json &json)
Parses a task snapshot.
Definition task.hpp:336
core::Result< TaskListParams > task_list_params_from_json(const Json &json)
Parses tasks/list params.
Definition task.hpp:387
Json task_list_params_to_json(const TaskListParams &params)
Serializes tasks/list params.
Definition task.hpp:381
core::Result< TaskGetParams > task_get_params_from_json(const Json &json)
Parses tasks/get params.
Definition task.hpp:399
Json task_get_result_to_json(const TaskGetResult &result)
Serializes a tasks/get result with flattened task fields.
Definition task.hpp:500
Json task_get_params_to_json(const TaskGetParams &params)
Serializes tasks/get params.
Definition task.hpp:393
Json task_to_json(const Task &task)
Serializes a task snapshot.
Definition task.hpp:332
core::Result< TaskListResult > task_list_result_from_json(const Json &json)
Parses a tasks/list result.
Definition task.hpp:449