17namespace mcp::server {
25struct is_result<core::Result<T>> : std::true_type {};
28inline constexpr bool always_false_v =
false;
30template <
class T,
class =
void>
35template <
class Class,
class Return,
class... Args>
37 using type = std::tuple<std::decay_t<Args>...>;
40template <
class Class,
class Return,
class... Args>
42 using type = std::tuple<std::decay_t<Args>...>;
45template <
class Return,
class... Args>
47 using type = std::tuple<std::decay_t<Args>...>;
54template <
class Handler,
class Tuple,
class =
void>
57template <
class Handler,
class... Args>
59 Handler, std::tuple<Args...>,
60 std::void_t<typename callable_argument_types<std::decay_t<Handler>>::type>>
62 typename callable_argument_types<std::decay_t<Handler>>::type,
63 std::tuple<std::decay_t<Args>...>> {};
65template <
class Handler,
class... Args>
66inline constexpr bool callable_arguments_match_v =
69template <
class Handler,
class =
void>
72template <
class Handler>
75 std::void_t<typename callable_argument_types<std::decay_t<Handler>>::type>>
78template <
class Handler>
79inline constexpr bool has_callable_arguments_v =
82template <
bool... Values>
83inline constexpr int bool_count_v = (0 + ... + (Values ? 1 : 0));
85template <
class Handler,
class... Args>
86inline constexpr bool handler_accepts_v =
87 callable_arguments_match_v<Handler, Args...> ||
88 (!callable_arguments_match_v<Handler, Args...> &&
89 std::is_invocable_v<Handler&, Args...>);
91template <
class Handler,
class... Args>
92inline constexpr bool handler_shape_accepts_v =
93 has_callable_arguments_v<Handler>
94 ? callable_arguments_match_v<Handler, Args...>
95 : std::is_invocable_v<Handler&, Args...>;
97template <
class Handler,
class Args>
98inline constexpr int tool_handler_match_count_v =
99 bool_count_v<handler_accepts_v<Handler, Args, const ToolContext&>,
100 handler_accepts_v<Handler, const ToolContext&, Args>,
101 handler_accepts_v<Handler, Args, CancellationToken>,
102 handler_accepts_v<Handler, CancellationToken, Args>,
103 handler_accepts_v<Handler, Args>,
104 handler_accepts_v<Handler, const ToolContext&>,
105 handler_accepts_v<Handler>>;
107template <
class Handler,
class Args,
class Context>
108inline constexpr int typed_context_handler_match_count_v =
109 bool_count_v<handler_accepts_v<Handler, Args, const Context&>,
110 handler_accepts_v<Handler, const Context&, Args>,
111 handler_accepts_v<Handler, Args, CancellationToken>,
112 handler_accepts_v<Handler, CancellationToken, Args>,
113 handler_accepts_v<Handler, Args>,
114 handler_accepts_v<Handler, const Context&>,
115 handler_accepts_v<Handler, CancellationToken>,
116 handler_accepts_v<Handler>>;
118template <
class Handler>
119inline constexpr int prompt_handler_exact_match_count_v = bool_count_v<
120 callable_arguments_match_v<Handler, protocol::Json, PromptContext>,
121 callable_arguments_match_v<Handler, PromptContext, protocol::Json>,
122 callable_arguments_match_v<Handler, std::string, PromptContext>,
123 callable_arguments_match_v<Handler, PromptContext, std::string>,
124 callable_arguments_match_v<Handler, protocol::Json>,
125 callable_arguments_match_v<Handler, std::string>,
126 callable_arguments_match_v<Handler, PromptContext>,
127 callable_arguments_match_v<Handler, protocol::Json, CancellationToken>,
128 callable_arguments_match_v<Handler, CancellationToken, protocol::Json>,
129 callable_arguments_match_v<Handler, std::string, CancellationToken>,
130 callable_arguments_match_v<Handler, CancellationToken, std::string>,
131 callable_arguments_match_v<Handler, CancellationToken>,
132 callable_arguments_match_v<Handler>>;
134template <
class Handler>
135inline constexpr int prompt_handler_invocable_match_count_v = bool_count_v<
136 std::is_invocable_v<Handler&, protocol::Json, PromptContext>,
137 std::is_invocable_v<Handler&, PromptContext, protocol::Json>,
138 std::is_invocable_v<Handler&, std::string, PromptContext>,
139 std::is_invocable_v<Handler&, PromptContext, std::string>,
140 std::is_invocable_v<Handler&, protocol::Json>,
141 std::is_invocable_v<Handler&, std::string>,
142 std::is_invocable_v<Handler&, PromptContext>,
143 std::is_invocable_v<Handler&, protocol::Json, CancellationToken>,
144 std::is_invocable_v<Handler&, CancellationToken, protocol::Json>,
145 std::is_invocable_v<Handler&, std::string, CancellationToken>,
146 std::is_invocable_v<Handler&, CancellationToken, std::string>,
147 std::is_invocable_v<Handler&, CancellationToken>,
148 std::is_invocable_v<Handler&>>;
150template <
class Handler>
151inline constexpr int prompt_handler_match_count_v =
152 prompt_handler_exact_match_count_v<Handler> > 0
153 ? prompt_handler_exact_match_count_v<Handler>
154 : prompt_handler_invocable_match_count_v<Handler>;
156template <
class Handler>
157inline constexpr int resource_handler_exact_match_count_v = bool_count_v<
158 callable_arguments_match_v<Handler, protocol::Json, ResourceContext>,
159 callable_arguments_match_v<Handler, ResourceContext, protocol::Json>,
160 callable_arguments_match_v<Handler, std::string, ResourceContext>,
161 callable_arguments_match_v<Handler, ResourceContext, std::string>,
162 callable_arguments_match_v<Handler, protocol::Json>,
163 callable_arguments_match_v<Handler, std::string>,
164 callable_arguments_match_v<Handler, ResourceContext>,
165 callable_arguments_match_v<Handler, protocol::Json, CancellationToken>,
166 callable_arguments_match_v<Handler, CancellationToken, protocol::Json>,
167 callable_arguments_match_v<Handler, std::string, CancellationToken>,
168 callable_arguments_match_v<Handler, CancellationToken, std::string>,
169 callable_arguments_match_v<Handler, CancellationToken>,
170 callable_arguments_match_v<Handler>>;
172template <
class Handler>
173inline constexpr int resource_handler_invocable_match_count_v = bool_count_v<
174 std::is_invocable_v<Handler&, protocol::Json, ResourceContext>,
175 std::is_invocable_v<Handler&, ResourceContext, protocol::Json>,
176 std::is_invocable_v<Handler&, std::string, ResourceContext>,
177 std::is_invocable_v<Handler&, ResourceContext, std::string>,
178 std::is_invocable_v<Handler&, protocol::Json>,
179 std::is_invocable_v<Handler&, std::string>,
180 std::is_invocable_v<Handler&, ResourceContext>,
181 std::is_invocable_v<Handler&, protocol::Json, CancellationToken>,
182 std::is_invocable_v<Handler&, CancellationToken, protocol::Json>,
183 std::is_invocable_v<Handler&, std::string, CancellationToken>,
184 std::is_invocable_v<Handler&, CancellationToken, std::string>,
185 std::is_invocable_v<Handler&, CancellationToken>,
186 std::is_invocable_v<Handler&>>;
188template <
class Handler>
189inline constexpr int resource_handler_match_count_v =
190 resource_handler_exact_match_count_v<Handler> > 0
191 ? resource_handler_exact_match_count_v<Handler>
192 : resource_handler_invocable_match_count_v<Handler>;
194template <
class Handler>
195inline constexpr int json_extension_handler_match_count_v = bool_count_v<
198 handler_accepts_v<Handler, const protocol::Json&, const SessionContext&>,
201 handler_accepts_v<Handler, const SessionContext&, const protocol::Json&>,
202 handler_accepts_v<Handler, const protocol::Json&, CancellationToken>,
203 handler_accepts_v<Handler, CancellationToken, const protocol::Json&>,
204 handler_accepts_v<Handler, const protocol::Json&>,
205 handler_accepts_v<Handler, const SessionContext&, CancellationToken>,
206 handler_accepts_v<Handler, CancellationToken, const SessionContext&>,
207 handler_accepts_v<Handler, const SessionContext&>,
208 handler_accepts_v<Handler, CancellationToken>, handler_accepts_v<Handler>>;
210template <
class Handler>
211inline constexpr int completion_handler_match_count_v = bool_count_v<
220 handler_accepts_v<Handler, std::string, const CompletionContext&>,
221 handler_accepts_v<Handler, const CompletionContext&, std::string>,
230 handler_accepts_v<Handler, std::string, CancellationToken>,
231 handler_accepts_v<Handler, CancellationToken, std::string>,
232 handler_accepts_v<Handler, const protocol::CompleteParams&>,
233 handler_accepts_v<Handler, const protocol::CompletionArgument&>,
234 handler_accepts_v<Handler, std::string>,
235 handler_accepts_v<Handler, CancellationToken>>;
237template <
class Handler,
class Args>
238constexpr void require_unambiguous_tool_handler() {
239 static_assert(tool_handler_match_count_v<Handler, Args> <= 1,
240 "ambiguous tool handler signature: use one explicit callable "
241 "shape instead of a generic/default-argument handler");
244template <
class Handler,
class Args,
class Context>
245constexpr void require_unambiguous_typed_context_handler(
246 std::string_view label) {
249 typed_context_handler_match_count_v<Handler, Args, Context> <= 1,
250 "ambiguous typed handler signature: use one explicit callable "
251 "shape instead of a generic/default-argument handler");
254template <
class Handler>
255constexpr void require_unambiguous_prompt_handler() {
256 static_assert(prompt_handler_match_count_v<Handler> <= 1,
257 "ambiguous prompt handler signature: use one explicit callable "
258 "shape instead of a generic/default-argument handler");
261template <
class Handler>
262constexpr void require_unambiguous_resource_handler() {
264 resource_handler_match_count_v<Handler> <= 1,
265 "ambiguous resource handler signature: use one explicit callable shape "
266 "instead of a generic/default-argument handler");
269template <
class Handler>
270constexpr void require_unambiguous_json_extension_handler() {
271 static_assert(json_extension_handler_match_count_v<Handler> <= 1,
272 "ambiguous JSON extension handler signature: use one explicit "
273 "callable shape instead of a generic/default-argument handler");
276template <
class Handler>
277constexpr void require_unambiguous_completion_handler() {
279 completion_handler_match_count_v<Handler> <= 1,
280 "ambiguous completion handler signature: use one explicit callable shape "
281 "instead of a generic/default-argument handler");
285inline protocol::Json value_to_json(T&& value) {
286 using Value = std::decay_t<T>;
287 if constexpr (std::is_same_v<Value, protocol::Json>) {
288 return std::forward<T>(value);
289 }
else if constexpr (protocol::has_reflect_v<Value>) {
290 return protocol::reflect_to_json(value);
292 return protocol::Json(std::forward<T>(value));
297inline protocol::Json value_to_tool_structured_content(T&& value) {
298 auto json = value_to_json(std::forward<T>(value));
299 if (json.is_object()) {
302 return protocol::Json{{
"value", std::move(json)}};
305template <
class Handler>
306inline bool callable_is_empty(
const Handler&)
noexcept {
310template <
class Return,
class... Args>
311inline bool callable_is_empty(
312 const std::function<Return(Args...)>& handler)
noexcept {
316template <
class Return,
class... Args>
317inline bool callable_is_empty(Return (*handler)(Args...)) noexcept {
318 return handler ==
nullptr;
321template <
class Handler>
322inline void require_callable(
const Handler& handler, std::string_view label) {
323 if (callable_is_empty(handler)) {
324 throw std::invalid_argument(std::string(label) +
325 " handler must not be empty");
329inline protocol::ToolResult value_to_tool_result(protocol::ToolResult result) {
333inline protocol::ToolResult value_to_tool_result(std::string text) {
334 protocol::ToolResult result;
335 protocol::ContentBlock block;
337 block.
text = std::move(text);
338 result.content.push_back(std::move(block));
342inline protocol::ToolResult value_to_tool_result(
const char* text) {
343 return value_to_tool_result(std::string(text ==
nullptr ?
"" : text));
347inline protocol::ToolResult value_to_tool_result(T&& value) {
348 protocol::ToolResult result;
350 value_to_tool_structured_content(std::forward<T>(value));
351 protocol::ContentBlock block;
353 block.text = result.structured_content->dump();
354 result.content.push_back(std::move(block));
358inline protocol::PromptsGetResult value_to_prompt_result(
359 protocol::PromptsGetResult result) {
363inline protocol::PromptsGetResult value_to_prompt_result(std::string text) {
364 protocol::PromptsGetResult result;
365 protocol::ContentBlock block;
367 block.text = std::move(text);
368 protocol::PromptMessage message;
369 message.role =
"assistant";
370 message.content = std::move(block);
371 result.messages.push_back(std::move(message));
375inline protocol::PromptsGetResult value_to_prompt_result(
376 protocol::PromptMessage message) {
377 protocol::PromptsGetResult result;
378 result.
messages.push_back(std::move(message));
382inline protocol::PromptsGetResult value_to_prompt_result(
383 std::vector<protocol::PromptMessage> messages) {
384 protocol::PromptsGetResult result;
385 result.
messages = std::move(messages);
389inline protocol::ResourcesReadResult value_to_resource_read_result(
390 protocol::ResourcesReadResult result, std::string_view) {
394inline protocol::ResourcesReadResult value_to_resource_read_result(
395 protocol::ResourceContents contents, std::string_view) {
396 protocol::ResourcesReadResult result;
397 result.
contents.push_back(std::move(contents));
401inline protocol::ResourcesReadResult value_to_resource_read_result(
402 std::vector<protocol::ResourceContents> contents, std::string_view) {
403 protocol::ResourcesReadResult result;
404 result.
contents = std::move(contents);
408inline protocol::ResourcesReadResult value_to_resource_read_result(
409 std::string text, std::string_view uri) {
410 protocol::ResourcesReadResult result;
411 protocol::ResourceContents contents;
412 contents.uri = std::string(uri);
413 contents.mime_type =
"text/plain";
414 contents.text = std::move(text);
415 result.contents.push_back(std::move(contents));
419inline protocol::Json value_to_complete_result_json(protocol::Json json) {
423inline protocol::Json value_to_complete_result_json(
424 protocol::CompleteResult result) {
425 return protocol::complete_result_to_json(result);
428inline protocol::Json value_to_complete_result_json(
429 protocol::CompletionResult result) {
430 protocol::CompleteResult envelope;
431 envelope.completion = std::move(result);
432 return protocol::complete_result_to_json(envelope);
435inline protocol::Json value_to_complete_result_json(
436 std::vector<std::string> values) {
437 protocol::CompletionResult completion;
438 completion.values = std::move(values);
439 return value_to_complete_result_json(std::move(completion));
442inline protocol::Json value_to_complete_result_json(std::string value) {
443 return value_to_complete_result_json(
444 std::vector<std::string>{std::move(value)});
447inline protocol::Json value_to_complete_result_json(
const char* value) {
448 return value_to_complete_result_json(
449 std::string(value ==
nullptr ?
"" : value));
453inline core::Result<protocol::Json> completion_response_to_json(T&& value) {
454 using Value = std::decay_t<T>;
455 if constexpr (is_result<Value>::value) {
459 return completion_response_to_json(std::move(*value));
461 return value_to_complete_result_json(std::forward<T>(value));
466inline Arg argument_from_json(
const protocol::Json& arguments,
467 std::string_view fallback_name = {}) {
468 using Decayed = std::decay_t<Arg>;
469 if constexpr (std::is_same_v<Decayed, protocol::Json>) {
471 }
else if constexpr (protocol::has_reflect_v<Decayed>) {
472 protocol::Json effective = arguments;
473 if (!fallback_name.empty() && arguments.is_object() &&
474 arguments.contains(std::string(fallback_name))) {
475 effective = arguments.at(std::string(fallback_name));
477 auto result = protocol::reflect_from_json<Decayed>(effective);
479 throw std::invalid_argument(result.error().message);
481 return std::move(*result);
483 if (!fallback_name.empty() && arguments.is_object() &&
484 arguments.contains(std::string(fallback_name))) {
485 return arguments.at(std::string(fallback_name)).template get<Arg>();
487 if (arguments.is_object() && arguments.size() == 1) {
488 return arguments.begin().value().template get<Arg>();
490 return arguments.template get<Arg>();
494template <
class Result>
495inline void apply_default_output_schema(protocol::ToolDefinition& definition) {
496 if constexpr (!std::is_same_v<std::decay_t<Result>, protocol::ToolResult> &&
497 !std::is_same_v<std::decay_t<Result>, std::string> &&
498 !std::is_same_v<std::decay_t<Result>,
const char*> &&
499 !std::is_same_v<std::decay_t<Result>,
char*>) {
500 if (definition.output_schema.empty()) {
501 definition.output_schema = protocol::tool_output_schema_for<Result>();
502 definition.output_schema_present =
true;
507template <
class Handler,
class Args>
508decltype(
auto) invoke_tool_handler(Handler& handler, Args&& args,
509 const ToolContext& context) {
510 using Arg = std::decay_t<Args>;
511 if constexpr (std::is_invocable_v<Handler&, Arg, const ToolContext&>) {
512 return handler(std::forward<Args>(args), context);
513 }
else if constexpr (std::is_invocable_v<Handler&, const ToolContext&, Arg>) {
514 return handler(context, std::forward<Args>(args));
515 }
else if constexpr (std::is_invocable_v<Handler&, Arg, CancellationToken>) {
516 return handler(std::forward<Args>(args), context.cancellation);
517 }
else if constexpr (std::is_invocable_v<Handler&, CancellationToken, Arg>) {
518 return handler(context.cancellation, std::forward<Args>(args));
519 }
else if constexpr (std::is_invocable_v<Handler&, Arg>) {
520 return handler(std::forward<Args>(args));
521 }
else if constexpr (std::is_invocable_v<Handler&, const ToolContext&>) {
522 return handler(context);
523 }
else if constexpr (std::is_invocable_v<Handler&>) {
526 static_assert(always_false_v<Handler>,
527 "tool handler must accept Args, Args+ToolContext, "
528 "ToolContext+Args, Args+CancellationToken, "
529 "CancellationToken+Args, ToolContext, or no arguments");
533template <
class Handler,
class Args,
class Context>
534decltype(
auto) invoke_typed_context_handler(Handler& handler, Args&& args,
535 const Context& context) {
536 using Arg = std::decay_t<Args>;
537 if constexpr (std::is_invocable_v<Handler&, Arg, const Context&>) {
538 return handler(std::forward<Args>(args), context);
539 }
else if constexpr (std::is_invocable_v<Handler&, const Context&, Arg>) {
540 return handler(context, std::forward<Args>(args));
541 }
else if constexpr (std::is_invocable_v<Handler&, Arg, CancellationToken>) {
542 return handler(std::forward<Args>(args), context.cancellation);
543 }
else if constexpr (std::is_invocable_v<Handler&, CancellationToken, Arg>) {
544 return handler(context.cancellation, std::forward<Args>(args));
545 }
else if constexpr (std::is_invocable_v<Handler&, Arg>) {
546 return handler(std::forward<Args>(args));
547 }
else if constexpr (std::is_invocable_v<Handler&, const Context&>) {
548 return handler(context);
549 }
else if constexpr (std::is_invocable_v<Handler&, CancellationToken>) {
550 return handler(context.cancellation);
551 }
else if constexpr (std::is_invocable_v<Handler&>) {
554 static_assert(always_false_v<Handler>,
555 "typed handler must accept Args, Args+Context, "
556 "Context+Args, Args+CancellationToken, "
557 "CancellationToken+Args, Context, CancellationToken, "
562template <
class Handler>
563decltype(
auto) invoke_prompt_handler(Handler& handler,
564 const PromptContext& context) {
565 using Json = protocol::Json;
566 if constexpr (callable_arguments_match_v<Handler, Json, PromptContext>) {
567 return handler(context.arguments, context);
568 }
else if constexpr (callable_arguments_match_v<Handler, PromptContext,
570 return handler(context, context.arguments);
571 }
else if constexpr (callable_arguments_match_v<Handler, std::string,
573 auto text = argument_from_json<std::string>(context.arguments,
574 std::string_view(
"text"));
575 return handler(std::move(text), context);
576 }
else if constexpr (callable_arguments_match_v<Handler, PromptContext,
578 auto text = argument_from_json<std::string>(context.arguments,
579 std::string_view(
"text"));
580 return handler(context, std::move(text));
581 }
else if constexpr (callable_arguments_match_v<Handler, Json>) {
582 return handler(context.arguments);
583 }
else if constexpr (callable_arguments_match_v<Handler, std::string>) {
584 auto text = argument_from_json<std::string>(context.arguments,
585 std::string_view(
"text"));
586 return handler(std::move(text));
587 }
else if constexpr (callable_arguments_match_v<Handler, PromptContext>) {
588 return handler(context);
589 }
else if constexpr (callable_arguments_match_v<Handler, Json,
591 return handler(context.arguments, context.cancellation);
594 return handler(context.cancellation, context.arguments);
595 }
else if constexpr (callable_arguments_match_v<Handler, std::string,
597 auto text = argument_from_json<std::string>(context.arguments,
598 std::string_view(
"text"));
599 return handler(std::move(text), context.cancellation);
602 auto text = argument_from_json<std::string>(context.arguments,
603 std::string_view(
"text"));
604 return handler(context.cancellation, std::move(text));
605 }
else if constexpr (callable_arguments_match_v<Handler, CancellationToken>) {
606 return handler(context.cancellation);
607 }
else if constexpr (std::is_invocable_v<Handler&,
const Json&,
608 const PromptContext&>) {
609 return handler(context.arguments, context);
610 }
else if constexpr (std::is_invocable_v<Handler&,
const PromptContext&,
612 return handler(context, context.arguments);
613 }
else if constexpr (std::is_invocable_v<Handler&, std::string,
614 const PromptContext&>) {
615 auto text = argument_from_json<std::string>(context.arguments,
616 std::string_view(
"text"));
617 return handler(std::move(text), context);
618 }
else if constexpr (std::is_invocable_v<Handler&,
const PromptContext&,
620 auto text = argument_from_json<std::string>(context.arguments,
621 std::string_view(
"text"));
622 return handler(context, std::move(text));
623 }
else if constexpr (std::is_invocable_v<Handler&, const Json&>) {
624 return handler(context.arguments);
625 }
else if constexpr (std::is_invocable_v<Handler&, std::string>) {
626 auto text = argument_from_json<std::string>(context.arguments,
627 std::string_view(
"text"));
628 return handler(std::move(text));
629 }
else if constexpr (std::is_invocable_v<Handler&, const PromptContext&>) {
630 return handler(context);
631 }
else if constexpr (std::is_invocable_v<Handler&>) {
634 static_assert(always_false_v<Handler>,
635 "prompt handler must accept Json, Json+PromptContext, "
636 "PromptContext+Json, string, string+PromptContext, "
637 "PromptContext+string, PromptContext, Json/string plus "
638 "CancellationToken, CancellationToken, or no arguments");
642template <
class Handler>
643decltype(
auto) invoke_resource_handler(Handler& handler,
644 const ResourceContext& context) {
645 using Json = protocol::Json;
646 if constexpr (callable_arguments_match_v<Handler, Json, ResourceContext>) {
647 return handler(context.params, context);
648 }
else if constexpr (callable_arguments_match_v<Handler, ResourceContext,
650 return handler(context, context.params);
651 }
else if constexpr (callable_arguments_match_v<Handler, std::string,
653 return handler(context.uri, context);
654 }
else if constexpr (callable_arguments_match_v<Handler, ResourceContext,
656 return handler(context, context.uri);
657 }
else if constexpr (callable_arguments_match_v<Handler, Json>) {
658 return handler(context.params);
659 }
else if constexpr (callable_arguments_match_v<Handler, std::string>) {
660 return handler(context.uri);
661 }
else if constexpr (callable_arguments_match_v<Handler, ResourceContext>) {
662 return handler(context);
663 }
else if constexpr (callable_arguments_match_v<Handler, Json,
665 return handler(context.params, context.cancellation);
668 return handler(context.cancellation, context.params);
669 }
else if constexpr (callable_arguments_match_v<Handler, std::string,
671 return handler(context.uri, context.cancellation);
674 return handler(context.cancellation, context.uri);
675 }
else if constexpr (callable_arguments_match_v<Handler, CancellationToken>) {
676 return handler(context.cancellation);
677 }
else if constexpr (std::is_invocable_v<Handler&,
const Json&,
678 const ResourceContext&>) {
679 return handler(context.params, context);
680 }
else if constexpr (std::is_invocable_v<Handler&,
const ResourceContext&,
682 return handler(context, context.params);
683 }
else if constexpr (std::is_invocable_v<Handler&, std::string,
684 const ResourceContext&>) {
685 return handler(context.uri, context);
686 }
else if constexpr (std::is_invocable_v<Handler&,
const ResourceContext&,
688 return handler(context, context.uri);
689 }
else if constexpr (std::is_invocable_v<Handler&, const Json&>) {
690 return handler(context.params);
691 }
else if constexpr (std::is_invocable_v<Handler&, std::string>) {
692 return handler(context.uri);
693 }
else if constexpr (std::is_invocable_v<Handler&, const ResourceContext&>) {
694 return handler(context);
695 }
else if constexpr (std::is_invocable_v<Handler&>) {
698 static_assert(always_false_v<Handler>,
699 "resource handler must accept Json, Json+ResourceContext, "
700 "ResourceContext+Json, string, string+ResourceContext, "
701 "ResourceContext+string, ResourceContext, Json/string plus "
702 "CancellationToken, CancellationToken, or no arguments");
706template <
class Handler>
707decltype(
auto) invoke_json_extension_handler(Handler& handler,
708 const protocol::Json& request,
709 const SessionContext& context,
710 CancellationToken cancellation) {
711 using Json = protocol::Json;
712 if constexpr (std::is_invocable_v<Handler&,
const Json&,
714 return handler(request, context, cancellation);
715 }
else if constexpr (std::is_invocable_v<Handler&,
const Json&,
716 const SessionContext&>) {
717 return handler(request, context);
718 }
else if constexpr (std::is_invocable_v<Handler&,
const SessionContext&,
720 return handler(context, request, cancellation);
721 }
else if constexpr (std::is_invocable_v<Handler&,
const SessionContext&,
723 return handler(context, request);
724 }
else if constexpr (std::is_invocable_v<Handler&,
const Json&,
726 return handler(request, cancellation);
729 return handler(cancellation, request);
730 }
else if constexpr (std::is_invocable_v<Handler&, const Json&>) {
731 return handler(request);
732 }
else if constexpr (std::is_invocable_v<Handler&,
const SessionContext&,
734 return handler(context, cancellation);
736 const SessionContext&>) {
737 return handler(cancellation, context);
738 }
else if constexpr (std::is_invocable_v<Handler&, const SessionContext&>) {
739 return handler(context);
740 }
else if constexpr (std::is_invocable_v<Handler&, CancellationToken>) {
741 return handler(cancellation);
742 }
else if constexpr (std::is_invocable_v<Handler&>) {
745 static_assert(always_false_v<Handler>,
746 "JSON extension handler must accept Json, "
747 "Json+SessionContext, SessionContext+Json, "
748 "Json/SessionContext plus CancellationToken, "
749 "CancellationToken, or no arguments");
753template <
class Handler>
754inline constexpr bool is_typed_completion_handler_v =
755 !callable_arguments_match_v<Handler, protocol::Json, SessionContext> &&
756 !callable_arguments_match_v<Handler, SessionContext, protocol::Json> &&
757 !callable_arguments_match_v<Handler, protocol::Json> &&
758 (callable_arguments_match_v<Handler, protocol::CompleteParams,
759 CompletionContext> ||
760 callable_arguments_match_v<Handler, CompletionContext,
761 protocol::CompleteParams> ||
762 callable_arguments_match_v<Handler, protocol::CompletionArgument,
763 CompletionContext> ||
764 callable_arguments_match_v<Handler, CompletionContext,
765 protocol::CompletionArgument> ||
766 callable_arguments_match_v<Handler, std::string, CompletionContext> ||
767 callable_arguments_match_v<Handler, CompletionContext, std::string> ||
768 callable_arguments_match_v<Handler, protocol::CompleteParams,
771 protocol::CompleteParams> ||
772 callable_arguments_match_v<Handler, protocol::CompletionArgument,
775 protocol::CompletionArgument> ||
776 callable_arguments_match_v<Handler, std::string, CancellationToken> ||
777 callable_arguments_match_v<Handler, CancellationToken, std::string> ||
778 callable_arguments_match_v<Handler, protocol::CompleteParams> ||
779 callable_arguments_match_v<Handler, protocol::CompletionArgument> ||
780 callable_arguments_match_v<Handler, std::string> ||
781 callable_arguments_match_v<Handler, CancellationToken>);
783template <
class Handler>
784decltype(
auto) invoke_completion_handler(Handler& handler,
785 const CompletionContext& context) {
786 if constexpr (std::is_invocable_v<Handler&,
const protocol::CompleteParams&,
787 const CompletionContext&>) {
788 return handler(context.params, context);
789 }
else if constexpr (std::is_invocable_v<Handler&,
const CompletionContext&,
790 const protocol::CompleteParams&>) {
791 return handler(context, context.params);
792 }
else if constexpr (std::is_invocable_v<Handler&,
793 const protocol::CompletionArgument&,
794 const CompletionContext&>) {
795 return handler(context.params.argument, context);
796 }
else if constexpr (std::is_invocable_v<
797 Handler&,
const CompletionContext&,
798 const protocol::CompletionArgument&>) {
799 return handler(context, context.params.argument);
800 }
else if constexpr (std::is_invocable_v<Handler&, std::string,
801 const CompletionContext&>) {
802 return handler(context.params.argument.value, context);
803 }
else if constexpr (std::is_invocable_v<Handler&,
const CompletionContext&,
805 return handler(context, context.params.argument.value);
806 }
else if constexpr (std::is_invocable_v<Handler&,
807 const protocol::CompleteParams&,
809 return handler(context.params, context.cancellation);
811 const protocol::CompleteParams&>) {
812 return handler(context.cancellation, context.params);
813 }
else if constexpr (std::is_invocable_v<Handler&,
814 const protocol::CompletionArgument&,
816 return handler(context.params.argument, context.cancellation);
817 }
else if constexpr (std::is_invocable_v<
819 const protocol::CompletionArgument&>) {
820 return handler(context.cancellation, context.params.argument);
821 }
else if constexpr (std::is_invocable_v<Handler&, std::string,
823 return handler(context.params.argument.value, context.cancellation);
826 return handler(context.cancellation, context.params.argument.value);
827 }
else if constexpr (std::is_invocable_v<Handler&,
828 const protocol::CompleteParams&>) {
829 return handler(context.params);
830 }
else if constexpr (std::is_invocable_v<
831 Handler&,
const protocol::CompletionArgument&>) {
832 return handler(context.params.argument);
833 }
else if constexpr (std::is_invocable_v<Handler&, std::string>) {
834 return handler(context.params.argument.value);
835 }
else if constexpr (std::is_invocable_v<Handler&, CancellationToken>) {
836 return handler(context.cancellation);
838 static_assert(always_false_v<Handler>,
839 "completion handler must accept CompleteParams, "
840 "CompletionArgument, string, or those plus "
841 "CompletionContext or CancellationToken");
Copyable token observed by cancellation-aware SDK operations.
Definition cancellation.hpp:104
Server-side handler invocation contexts.
mcp::CancellationToken CancellationToken
Copyable cooperative cancellation token for server handlers.
Definition context.hpp:22
nlohmann::json Json
JSON value type used by all protocol DTOs.
Definition types.hpp:28
Shared result and error primitives used by the public cxxmcp SDK.
constexpr auto unexpected(E &&value)
Creates an unexpected result value for the active expected backend.
Definition result.hpp:24
Parameters for completion/complete.
Definition completion.hpp:98
Argument value being completed.
Definition completion.hpp:57
std::vector< PromptMessage > messages
Ordered messages produced by the prompt.
Definition prompt.hpp:217
std::vector< ResourceContents > contents
One or more content parts for the requested URI.
Definition resource.hpp:287
Completion request context passed to typed completion handlers.
Definition context.hpp:86
Per-message connection metadata supplied to server handlers.
Definition transport.hpp:42
Definition handler_dispatch.hpp:31
Definition handler_dispatch.hpp:55
Definition handler_dispatch.hpp:70
Definition handler_dispatch.hpp:22