cxxmcp 1.1.6
C++ MCP SDK
Loading...
Searching...
No Matches
completion.hpp
Go to the documentation of this file.
1// Copyright (c) 2025 [caomengxuan666]
2
3#pragma once
4
11
12#include <cstddef>
13#include <cstdint>
14#include <limits>
15#include <map>
16#include <optional>
17#include <string>
18#include <utility>
19#include <vector>
20
24
25namespace mcp::protocol {
26
30 std::string type;
33 std::string name;
35 std::optional<std::string> uri;
37 std::string title;
39 Json extensions = Json::object();
40};
41
44 return CompletionReference{"ref/prompt", std::move(name)};
45}
46
50 ref.type = "ref/resource";
51 ref.name = uri;
52 ref.uri = std::move(uri);
53 return ref;
54}
55
59 std::string name;
61 std::string value;
63 Json extensions = Json::object();
64};
65
66template <>
68 static constexpr bool defined = true;
69 static auto fields() {
70 return std::make_tuple(
74 }
75 static std::vector<std::string> known_keys() { return {"name", "value"}; }
76};
77
85 std::optional<std::map<std::string, std::string>> arguments;
86};
87
88template <>
90 static constexpr bool defined = true;
91 static auto fields() {
92 return std::make_tuple(field("arguments", &CompletionContext::arguments));
93 }
94 static std::vector<std::string> known_keys() { return {"arguments"}; }
95};
96
104 std::optional<CompletionContext> typed_context;
106 Json context = Json::object();
108 std::optional<Json> meta;
110 Json extensions = Json::object();
111};
112
116 static constexpr std::size_t kMaxValues = 100;
118 std::vector<std::string> values;
120 std::optional<int> total;
123 std::optional<bool> has_more;
125 Json extensions = Json::object();
126
128 bool has_more_results() const noexcept { return has_more.value_or(false); }
129};
130
136 std::optional<Json> meta;
138 Json extensions = Json::object();
139};
140
143inline core::Error completion_json_error(std::string message) {
144 return core::Error{
145 static_cast<int>(ErrorCode::InvalidRequest), std::move(message), {}};
146}
147
150 Json json = Json::object();
151 json["type"] = ref.type;
152 if (ref.uri.has_value()) {
153 json["uri"] = *ref.uri;
154 } else if (!ref.name.empty()) {
155 json["name"] = ref.name;
156 }
157 if (!ref.title.empty()) {
158 json["title"] = ref.title;
159 }
161 return json;
162}
163
167 const Json& json) {
168 if (!json.is_object()) {
169 return mcp::core::unexpected(
170 completion_json_error("completion ref must be an object"));
171 }
172 if (!json.contains("type") || !json.at("type").is_string()) {
173 return mcp::core::unexpected(
174 completion_json_error("completion ref requires a string type"));
175 }
177 ref.type = json.at("type").get<std::string>();
178 if (ref.type == "ref/prompt") {
179 if (!json.contains("name") || !json.at("name").is_string()) {
180 return mcp::core::unexpected(
181 completion_json_error("completion prompt ref requires string name"));
182 }
183 ref.name = json.at("name").get<std::string>();
184 if (json.contains("uri")) {
185 return mcp::core::unexpected(
186 completion_json_error("completion prompt ref must not contain uri"));
187 }
188 } else if (ref.type == "ref/resource") {
189 if (!json.contains("uri") || !json.at("uri").is_string()) {
190 return mcp::core::unexpected(
191 completion_json_error("completion resource ref requires string uri"));
192 }
193 ref.uri = json.at("uri").get<std::string>();
194 if (json.contains("name")) {
195 return mcp::core::unexpected(completion_json_error(
196 "completion resource ref must not contain name"));
197 }
198 } else {
199 return mcp::core::unexpected(
200 completion_json_error("completion ref type is not supported"));
201 }
202 if (json.contains("title")) {
203 if (ref.type != "ref/prompt") {
204 return mcp::core::unexpected(completion_json_error(
205 "completion resource ref must not contain title"));
206 }
207 if (!json.at("title").is_string()) {
208 return mcp::core::unexpected(
209 completion_json_error("completion ref title must be a string"));
210 }
211 ref.title = json.at("title").get<std::string>();
212 }
213 ref.extensions =
214 collect_json_extensions(json, {"type", "name", "uri", "title"});
215 return ref;
216}
217
220 return reflect_to_json(argument);
221}
222
226 const Json& json) {
227 return reflect_from_json<CompletionArgument>(json);
228}
229
232 return reflect_to_json(context);
233}
234
237 const Json& json) {
238 return reflect_from_json<CompletionContext>(json);
239}
240
243 Json json = Json::object();
244 json["ref"] = completion_reference_to_json(params.ref);
245 json["argument"] = completion_argument_to_json(params.argument);
246 if (params.typed_context.has_value()) {
247 json["context"] = completion_context_to_json(*params.typed_context);
248 } else if (!params.context.empty()) {
249 json["context"] = params.context;
250 }
251 if (params.meta.has_value()) {
252 json["_meta"] = *params.meta;
253 }
255 return json;
256}
257
261 const Json& json) {
262 if (!json.is_object()) {
263 return mcp::core::unexpected(
264 completion_json_error("completion params must be an object"));
265 }
266 if (!json.contains("ref")) {
267 return mcp::core::unexpected(
268 completion_json_error("completion params require ref"));
269 }
270 if (!json.contains("argument")) {
271 return mcp::core::unexpected(
272 completion_json_error("completion params require argument"));
273 }
274
275 const auto ref = completion_reference_from_json(json.at("ref"));
276 if (!ref) {
277 return mcp::core::unexpected(ref.error());
278 }
279 const auto argument = completion_argument_from_json(json.at("argument"));
280 if (!argument) {
281 return mcp::core::unexpected(argument.error());
282 }
283
284 CompleteParams params;
285 params.ref = *ref;
286 params.argument = *argument;
287 if (json.contains("context")) {
288 if (!json.at("context").is_object()) {
289 return mcp::core::unexpected(
290 completion_json_error("completion context must be an object"));
291 }
292 params.context = json.at("context");
293 if (json.at("context").contains("arguments")) {
294 const auto typed = completion_context_from_json(json.at("context"));
295 if (typed) {
296 params.typed_context = *typed;
297 }
298 }
299 }
300 if (json.contains("_meta")) {
301 if (!json.at("_meta").is_object()) {
302 return mcp::core::unexpected(
303 completion_json_error("completion _meta must be an object"));
304 }
305 params.meta = json.at("_meta");
306 }
307 params.extensions =
308 collect_json_extensions(json, {"ref", "argument", "context", "_meta"});
309 return params;
310}
311
314 Json json = Json::object();
315 json["values"] = completion.values;
316 if (completion.total.has_value()) {
317 json["total"] = *completion.total;
318 }
319 if (completion.has_more.has_value()) {
320 json["hasMore"] = *completion.has_more;
321 }
322 append_json_extensions(json, completion.extensions);
323 return json;
324}
325
329 const Json& json) {
330 if (!json.is_object()) {
331 return mcp::core::unexpected(
332 completion_json_error("completion result must be an object"));
333 }
334 if (!json.contains("values") || !json.at("values").is_array()) {
335 return mcp::core::unexpected(
336 completion_json_error("completion result requires a values array"));
337 }
338 if (json.at("values").size() > CompletionResult::kMaxValues) {
339 return mcp::core::unexpected(
340 completion_json_error("completion result has too many values"));
341 }
342
343 CompletionResult completion;
344 for (const auto& item : json.at("values")) {
345 if (!item.is_string()) {
346 return mcp::core::unexpected(
347 completion_json_error("completion values must be strings"));
348 }
349 completion.values.push_back(item.get<std::string>());
350 }
351 if (json.contains("total")) {
352 if (!json.at("total").is_number_integer()) {
353 return mcp::core::unexpected(completion_json_error(
354 "completion total must be a non-negative integer"));
355 }
356 const auto total = json.at("total").get<std::int64_t>();
357 if (total < 0 || total > std::numeric_limits<int>::max()) {
358 return mcp::core::unexpected(completion_json_error(
359 "completion total must be a non-negative integer"));
360 }
361 completion.total = static_cast<int>(total);
362 }
363 if (json.contains("hasMore")) {
364 if (!json.at("hasMore").is_boolean()) {
365 return mcp::core::unexpected(
366 completion_json_error("completion hasMore must be a boolean"));
367 }
368 completion.has_more = json.at("hasMore").get<bool>();
369 }
370 completion.extensions =
371 collect_json_extensions(json, {"values", "total", "hasMore"});
372 return completion;
373}
374
377 Json json =
378 Json{{"completion", completion_result_to_json(result.completion)}};
379 if (result.meta.has_value()) {
380 json["_meta"] = *result.meta;
381 }
383 return json;
384}
385
389 const Json& json) {
390 if (!json.is_object()) {
391 return mcp::core::unexpected(
392 completion_json_error("completion result envelope must be an object"));
393 }
394 if (!json.contains("completion")) {
395 return mcp::core::unexpected(completion_json_error(
396 "completion result envelope requires completion"));
397 }
398 const auto completion = completion_result_from_json(json.at("completion"));
399 if (!completion) {
400 return mcp::core::unexpected(completion.error());
401 }
402 CompleteResult result;
403 result.completion = *completion;
404 if (json.contains("_meta")) {
405 if (!json.at("_meta").is_object()) {
406 return mcp::core::unexpected(
407 completion_json_error("completion result _meta must be an object"));
408 }
409 result.meta = json.at("_meta");
410 }
411 result.extensions = collect_json_extensions(json, {"completion", "_meta"});
412 return result;
413}
414
415} // namespace mcp::protocol
core::Result< CompletionContext > completion_context_from_json(const Json &json)
Parses a CompletionContext struct from JSON.
Definition completion.hpp:236
Json completion_context_to_json(const CompletionContext &context)
Serializes a CompletionContext struct to JSON.
Definition completion.hpp:231
Json completion_result_to_json(const CompletionResult &completion)
Serializes completion candidates.
Definition completion.hpp:313
core::Result< CompletionArgument > completion_argument_from_json(const Json &json)
Parses a completion argument.
Definition completion.hpp:225
core::Result< CompletionReference > completion_reference_from_json(const Json &json)
Parses a completion reference.
Definition completion.hpp:166
core::Result< CompleteResult > complete_result_from_json(const Json &json)
Parses a completion/complete result.
Definition completion.hpp:388
CompletionReference prompt_completion_reference(std::string name)
Builds a prompt completion reference.
Definition completion.hpp:43
core::Error completion_json_error(std::string message)
Builds an InvalidRequest error for completion JSON validation failures.
Definition completion.hpp:143
Json complete_result_to_json(const CompleteResult &result)
Serializes a completion/complete result.
Definition completion.hpp:376
Json completion_argument_to_json(const CompletionArgument &argument)
Serializes a completion argument.
Definition completion.hpp:219
Json completion_reference_to_json(const CompletionReference &ref)
Serializes a completion reference.
Definition completion.hpp:149
core::Result< CompleteParams > complete_params_from_json(const Json &json)
Parses completion/complete params.
Definition completion.hpp:260
CompletionReference resource_completion_reference(std::string uri)
Builds a resource completion reference.
Definition completion.hpp:48
core::Result< CompletionResult > completion_result_from_json(const Json &json)
Parses completion candidates.
Definition completion.hpp:328
Json complete_params_to_json(const CompleteParams &params)
Serializes completion/complete params.
Definition completion.hpp:242
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.
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.
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
Parameters for completion/complete.
Definition completion.hpp:98
std::optional< Json > meta
Optional _meta extension object preserved on the wire.
Definition completion.hpp:108
Json extensions
Unknown JSON members preserved for forward-compatible round trips.
Definition completion.hpp:110
CompletionArgument argument
Argument being completed.
Definition completion.hpp:102
std::optional< CompletionContext > typed_context
Typed contextual argument values used to improve completions.
Definition completion.hpp:104
Json context
Optional contextual argument values used to improve completions (raw).
Definition completion.hpp:106
CompletionReference ref
Prompt or resource-template reference.
Definition completion.hpp:100
Result object for completion/complete.
Definition completion.hpp:132
CompletionResult completion
Completion payload nested under the protocol completion field.
Definition completion.hpp:134
Json extensions
Unknown JSON members preserved for forward-compatible round trips.
Definition completion.hpp:138
std::optional< Json > meta
Optional _meta extension object preserved on the wire.
Definition completion.hpp:136
Argument value being completed.
Definition completion.hpp:57
Json extensions
Unknown JSON members preserved for forward-compatible round trips.
Definition completion.hpp:63
std::string value
Current argument value or prefix supplied by the caller.
Definition completion.hpp:61
std::string name
Argument name within the referenced object.
Definition completion.hpp:59
Contextual argument values used to improve completions.
Definition completion.hpp:83
std::optional< std::map< std::string, std::string > > arguments
Previously supplied argument name-value pairs.
Definition completion.hpp:85
Reference to the prompt or resource template being completed.
Definition completion.hpp:28
std::string name
Name of the referenced prompt.
Definition completion.hpp:33
Json extensions
Unknown JSON members preserved for forward-compatible round trips.
Definition completion.hpp:39
std::string title
Optional human-readable reference title.
Definition completion.hpp:37
std::optional< std::string > uri
URI of the referenced resource or resource template.
Definition completion.hpp:35
std::string type
Reference kind, for example a prompt or resource-template reference.
Definition completion.hpp:30
Completion candidates returned by the server.
Definition completion.hpp:114
std::vector< std::string > values
Candidate values.
Definition completion.hpp:118
static constexpr std::size_t kMaxValues
Maximum number of completion values allowed by the MCP model.
Definition completion.hpp:116
std::optional< int > total
Optional total number of matches known to the server.
Definition completion.hpp:120
std::optional< bool > has_more
Optional pagination signal.
Definition completion.hpp:123
Json extensions
Unknown JSON members preserved for forward-compatible round trips.
Definition completion.hpp:125
bool has_more_results() const noexcept
Convenience predicate treating a missing signal as false.
Definition completion.hpp:128
Primary template.
Definition reflect.hpp:199