cxxmcp 1.1.6
C++ MCP SDK
Loading...
Searching...
No Matches
authoring.hpp
Go to the documentation of this file.
1// Copyright (c) 2025 [caomengxuan666]
2
3#pragma once
4
7
8#include <cstdint>
9#include <memory>
10#include <stdexcept>
11#include <string>
12#include <type_traits>
13#include <utility>
14
15#include "cxxmcp/config.hpp"
18
19namespace mcp::server {
20
22template <class Args, class Result, class Handler>
24 protocol::ToolDefinition definition;
25 Handler handler;
26};
27
29template <class Args, class Result>
31 public:
32 explicit TypedToolBuilder(std::string name) {
33 definition_ =
34 protocol::tool_definition(std::move(name)).input<Args>().build();
35 detail::apply_default_output_schema<Result>(definition_);
36 }
37
38 TypedToolBuilder& title(std::string value) {
39 definition_.title = std::move(value);
40 return *this;
41 }
42
43 TypedToolBuilder& description(std::string value) {
44 definition_.description = std::move(value);
45 return *this;
46 }
47
48 TypedToolBuilder& input_schema(protocol::Json schema) {
49 definition_.input_schema = std::move(schema);
50 return *this;
51 }
52
53 template <class T>
54 TypedToolBuilder& input() {
55 return input_schema(protocol::schema_for<T>());
56 }
57
58 TypedToolBuilder& output_schema(protocol::Json schema) {
59 definition_.output_schema = std::move(schema);
60 definition_.output_schema_present = true;
61 return *this;
62 }
63
64 template <class T>
65 TypedToolBuilder& output() {
66 return output_schema(protocol::schema_for<T>());
67 }
68
69 TypedToolBuilder& streaming(bool value = true) {
70 definition_.streaming = value;
71 return *this;
72 }
73
74 TypedToolBuilder& icon(protocol::Icon value) {
75 definition_.icons.push_back(std::move(value));
76 return *this;
77 }
78
79 TypedToolBuilder& task_support(protocol::TaskSupport value) {
80 if (!definition_.execution.has_value()) {
81 definition_.execution = protocol::ToolExecution{};
82 }
83 definition_.execution->task_support = value;
84 return *this;
85 }
86
88 definition_.execution = std::move(value);
89 return *this;
90 }
91
92 TypedToolBuilder& annotations(protocol::Json value) {
93 definition_.annotations = std::move(value);
94 return *this;
95 }
96
97 TypedToolBuilder& meta(protocol::Json value) {
98 definition_.meta = std::move(value);
99 return *this;
100 }
101
102 template <class Handler>
103 TypedToolRegistration<Args, Result, Handler> handler(Handler value) {
104 detail::require_callable(value, "tool");
105 detail::require_unambiguous_tool_handler<Handler, Args>();
106 return TypedToolRegistration<Args, Result, Handler>{std::move(definition_),
107 std::move(value)};
108 }
109
110 private:
111 protocol::ToolDefinition definition_;
112};
113
115template <class Args, class Result>
116inline TypedToolBuilder<Args, Result> tool(std::string name) {
117 return TypedToolBuilder<Args, Result>(std::move(name));
118}
119
121template <class Args, class Handler>
123 protocol::Prompt prompt;
124 Handler handler;
125};
126
128template <class Args>
130 public:
131 explicit TypedPromptBuilder(protocol::Prompt prompt)
132 : prompt_(std::move(prompt)) {}
133
134 explicit TypedPromptBuilder(std::string name) {
135 prompt_ = protocol::prompt_definition(std::move(name)).build();
136 }
137
138 TypedPromptBuilder& title(std::string value) {
139 prompt_.title = std::move(value);
140 return *this;
141 }
142
143 TypedPromptBuilder& description(std::string value) {
144 prompt_.description = std::move(value);
145 return *this;
146 }
147
148 TypedPromptBuilder& argument(std::string name, bool required = false,
149 std::string description = {}) {
151 argument.name = std::move(name);
152 argument.required = required;
153 argument.required_present = true;
154 argument.description = std::move(description);
155 prompt_.arguments.push_back(std::move(argument));
156 return *this;
157 }
158
160 prompt_.icons.push_back(std::move(value));
161 return *this;
162 }
163
164 TypedPromptBuilder& annotations(protocol::Json value) {
165 prompt_.annotations = std::move(value);
166 return *this;
167 }
168
170 prompt_.meta = std::move(value);
171 return *this;
172 }
173
174 template <class Handler>
175 TypedPromptRegistration<Args, Handler> handler(Handler value) {
176 detail::require_callable(value, "prompt");
177 detail::require_unambiguous_typed_context_handler<Handler, Args,
178 PromptContext>("prompt");
179 return TypedPromptRegistration<Args, Handler>{std::move(prompt_),
180 std::move(value)};
181 }
182
183 private:
184 protocol::Prompt prompt_;
185};
186
187template <class Args>
188inline TypedPromptBuilder<Args> prompt(std::string name) {
189 return TypedPromptBuilder<Args>(std::move(name));
190}
191
192template <class Args>
193inline TypedPromptBuilder<Args> prompt(protocol::Prompt prompt) {
194 return TypedPromptBuilder<Args>(std::move(prompt));
195}
196
198template <class Args, class Handler>
200 protocol::Resource resource;
201 Handler handler;
202};
203
205template <class Args>
207 public:
209 : resource_(std::move(resource)) {}
210
211 TypedResourceBuilder(std::string uri, std::string name) {
212 resource_ =
213 protocol::resource_definition(std::move(uri), std::move(name)).build();
214 }
215
216 TypedResourceBuilder& title(std::string value) {
217 resource_.title = std::move(value);
218 return *this;
219 }
220
221 TypedResourceBuilder& description(std::string value) {
222 resource_.description = std::move(value);
223 return *this;
224 }
225
226 TypedResourceBuilder& mime_type(std::string value) {
227 resource_.mime_type = std::move(value);
228 return *this;
229 }
230
231 TypedResourceBuilder& size(std::int64_t value) {
232 resource_.size = value;
233 return *this;
234 }
235
237 resource_.icons.push_back(std::move(value));
238 return *this;
239 }
240
241 TypedResourceBuilder& annotations(protocol::Json value) {
242 resource_.annotations = std::move(value);
243 return *this;
244 }
245
247 resource_.meta = std::move(value);
248 return *this;
249 }
250
251 template <class Handler>
252 TypedResourceRegistration<Args, Handler> handler(Handler value) {
253 detail::require_callable(value, "resource");
254 detail::require_unambiguous_typed_context_handler<Handler, Args,
256 "resource");
257 return TypedResourceRegistration<Args, Handler>{std::move(resource_),
258 std::move(value)};
259 }
260
261 private:
262 protocol::Resource resource_;
263};
264
265template <class Args>
266inline TypedResourceBuilder<Args> resource(std::string uri, std::string name) {
267 return TypedResourceBuilder<Args>(std::move(uri), std::move(name));
268}
269
270template <class Args>
271inline TypedResourceBuilder<Args> resource(protocol::Resource resource) {
272 return TypedResourceBuilder<Args>(std::move(resource));
273}
274
275inline protocol::ResourceTemplateBuilder resource_template(
276 std::string uri_template, std::string name) {
277 return protocol::resource_template_definition(std::move(uri_template),
278 std::move(name));
279}
280
285class CXXMCP_DEPRECATED(
286 "App is a compatibility entry point; use ServerPeer::builder() with "
287 "cxxmcp/run.hpp instead") App {
288 public:
290 class Builder {
291 public:
293 Builder& name(std::string value);
294
296 Builder& version(std::string value);
297
299 Builder& instructions(std::string value);
300
302 Builder& stdio();
303
304#if defined(CXXMCP_ENABLE_HTTP)
309 Builder& streamable_http(std::string host, std::uint16_t port,
310 std::string path = "/mcp");
311
316 Builder& legacy_sse(std::string host, std::uint16_t port,
317 std::string path = "/mcp");
318#endif
319
322 Builder& transport(std::unique_ptr<Transport> value);
323
325 Builder& tasks(TaskOperationProcessorOptions options = {});
326
328 Builder& schema_validator(
329 std::shared_ptr<const JsonSchemaValidator> validator);
330
340 template <class Args, class Result, class Handler>
341 Builder& tool(std::string name, Handler handler);
342
344 template <class Args, class Result, class Handler>
345 Builder& tool(protocol::ToolDefinition definition, Handler handler);
346
348 template <class Args, class Result, class Handler>
349 Builder& tool(TypedToolRegistration<Args, Result, Handler> registration);
350
352 Builder& tool(protocol::ToolDefinition definition, ToolHandler handler);
353
361 template <class Args, class Handler>
362 Builder& prompt(std::string name, Handler handler);
363
364 template <class Handler>
365 Builder& prompt(std::string name, Handler handler);
366
368 Builder& prompt(protocol::Prompt prompt, PromptHandler handler);
369
378 template <class Args, class Handler>
379 Builder& resource(std::string name, Handler handler);
380
381 template <class Handler>
382 Builder& resource(std::string name, Handler handler);
383
385 Builder& resource(protocol::Resource resource, ResourceReadHandler handler);
386
394 template <class Handler>
395 Builder& resource_template(std::string name, Handler handler);
396
398 Builder& resource_template(protocol::ResourceTemplate resource_template);
399
401 template <class Handler>
402 Builder& completion(Handler handler);
403
405 template <class Handler>
406 Builder& sampling(Handler handler);
407
409 template <class Handler>
410 Builder& logging(Handler handler);
411
416 template <class Handler>
417 Builder& raw_request(Handler handler);
418
420 core::Result<std::unique_ptr<Server>> build();
421
423 int run();
424
425 private:
426 ServerBuilder builder_;
427 };
428
430 CXXMCP_DEPRECATED("use ServerPeer::builder() instead")
431 static Builder builder();
432};
433
434template <class Args, class Result, class Handler>
435App::Builder& App::Builder::tool(std::string name, Handler handler) {
436 detail::require_callable(handler, "tool");
437 detail::require_unambiguous_tool_handler<Handler, Args>();
438 auto definition =
439 protocol::tool_definition(std::move(name)).input<Args>().build();
440 detail::apply_default_output_schema<Result>(definition);
441 return tool<Args, Result>(std::move(definition), std::move(handler));
442}
443
444template <class Args, class Result, class Handler>
445App::Builder& App::Builder::tool(protocol::ToolDefinition definition,
446 Handler handler) {
447 detail::require_callable(handler, "tool");
448 detail::require_unambiguous_tool_handler<Handler, Args>();
449 if (definition.input_schema.empty()) {
450 definition.input_schema = protocol::schema_for<Args>();
451 }
452 detail::apply_default_output_schema<Result>(definition);
453 return tool(
454 std::move(definition),
455 [handler = std::move(handler)](
456 const ToolContext& context) -> core::Result<protocol::ToolResult> {
457 try {
458 auto args = detail::argument_from_json<Args>(context.arguments);
459 auto handled =
460 detail::invoke_tool_handler(handler, std::move(args), context);
461 if constexpr (detail::is_result<decltype(handled)>::value) {
462 if (!handled) {
463 return mcp::core::unexpected(handled.error());
464 }
465 return detail::value_to_tool_result(*handled);
466 } else {
467 return detail::value_to_tool_result(std::move(handled));
468 }
469 } catch (const std::exception& exception) {
470 return mcp::core::unexpected(core::Error{
471 static_cast<int>(protocol::ErrorCode::InvalidParams),
472 "failed to decode tool arguments",
473 exception.what(),
474 });
475 }
476 });
477}
478
479template <class Args, class Result, class Handler>
480App::Builder& App::Builder::tool(
481 TypedToolRegistration<Args, Result, Handler> registration) {
482 return tool<Args, Result>(std::move(registration.definition),
483 std::move(registration.handler));
484}
485
486template <class Args, class Handler>
487App::Builder& App::Builder::prompt(std::string name, Handler handler) {
488 detail::require_callable(handler, "prompt");
489 detail::require_unambiguous_typed_context_handler<Handler, Args,
490 PromptContext>("prompt");
491 protocol::Prompt prompt;
492 prompt.name = std::move(name);
493 return this->prompt(
494 std::move(prompt),
495 [handler = std::move(handler)](const PromptContext& context)
496 -> core::Result<protocol::PromptsGetResult> {
497 try {
498 auto args = context.arguments.get<Args>();
499 auto handled = detail::invoke_typed_context_handler(
500 handler, std::move(args), context);
501 if constexpr (detail::is_result<decltype(handled)>::value) {
502 if (!handled) {
503 return mcp::core::unexpected(handled.error());
504 }
505 return detail::value_to_prompt_result(*handled);
506 } else {
507 return detail::value_to_prompt_result(std::move(handled));
508 }
509 } catch (const std::exception& exception) {
510 return mcp::core::unexpected(core::Error{
511 static_cast<int>(protocol::ErrorCode::InvalidParams),
512 "failed to decode prompt arguments",
513 exception.what(),
514 });
515 }
516 });
517}
518
519template <class Handler>
520App::Builder& App::Builder::prompt(std::string name, Handler handler) {
521 detail::require_callable(handler, "prompt");
522 detail::require_unambiguous_prompt_handler<Handler>();
523 protocol::Prompt prompt;
524 prompt.name = std::move(name);
525 return this->prompt(
526 std::move(prompt),
527 [handler = std::move(handler)](const PromptContext& context)
528 -> core::Result<protocol::PromptsGetResult> {
529 try {
530 auto handled = detail::invoke_prompt_handler(handler, context);
531 if constexpr (detail::is_result<decltype(handled)>::value) {
532 if (!handled) {
533 return mcp::core::unexpected(handled.error());
534 }
535 return detail::value_to_prompt_result(*handled);
536 } else {
537 return detail::value_to_prompt_result(std::move(handled));
538 }
539 } catch (const std::exception& exception) {
540 return mcp::core::unexpected(core::Error{
541 static_cast<int>(protocol::ErrorCode::InvalidParams),
542 "failed to run prompt handler",
543 exception.what(),
544 });
545 }
546 });
547}
548
549template <class Args, class Handler>
550App::Builder& App::Builder::resource(std::string name, Handler handler) {
551 detail::require_callable(handler, "resource");
552 detail::require_unambiguous_typed_context_handler<Handler, Args,
553 ResourceContext>(
554 "resource");
555 protocol::Resource resource;
556 resource.uri = std::move(name);
557 resource.name = resource.uri;
558 return this->resource(
559 std::move(resource),
560 [handler = std::move(handler)](const ResourceContext& context)
561 -> core::Result<protocol::ResourcesReadResult> {
562 try {
563 auto args = context.params.get<Args>();
564 auto handled = detail::invoke_typed_context_handler(
565 handler, std::move(args), context);
566 if constexpr (detail::is_result<decltype(handled)>::value) {
567 if (!handled) {
568 return mcp::core::unexpected(handled.error());
569 }
570 return detail::value_to_resource_read_result(*handled, context.uri);
571 } else {
572 return detail::value_to_resource_read_result(std::move(handled),
573 context.uri);
574 }
575 } catch (const std::exception& exception) {
576 return mcp::core::unexpected(core::Error{
577 static_cast<int>(protocol::ErrorCode::InvalidParams),
578 "failed to decode resource parameters",
579 exception.what(),
580 });
581 }
582 });
583}
584
585template <class Handler>
586App::Builder& App::Builder::resource(std::string name, Handler handler) {
587 detail::require_callable(handler, "resource");
588 detail::require_unambiguous_resource_handler<Handler>();
589 protocol::Resource resource;
590 resource.uri = std::move(name);
591 resource.name = resource.uri;
592 if constexpr (std::is_invocable_v<Handler>) {
593 using Handled = decltype(handler());
594 if constexpr (std::is_same_v<std::decay_t<Handled>, protocol::Resource>) {
595 resource = handler();
596 }
597 }
598 return this->resource(
599 std::move(resource),
600 [handler = std::move(handler)](const ResourceContext& context)
601 -> core::Result<protocol::ResourcesReadResult> {
602 try {
603 auto handled = detail::invoke_resource_handler(handler, context);
604 if constexpr (std::is_same_v<std::decay_t<decltype(handled)>,
605 protocol::Resource>) {
606 return protocol::ResourcesReadResult{};
607 } else if constexpr (detail::is_result<decltype(handled)>::value) {
608 if (!handled) {
609 return mcp::core::unexpected(handled.error());
610 }
611 return detail::value_to_resource_read_result(*handled, context.uri);
612 } else {
613 return detail::value_to_resource_read_result(std::move(handled),
614 context.uri);
615 }
616 } catch (const std::exception& exception) {
617 return mcp::core::unexpected(core::Error{
618 static_cast<int>(protocol::ErrorCode::InvalidParams),
619 "failed to run resource handler",
620 exception.what(),
621 });
622 }
623 });
624}
625
626template <class Handler>
627App::Builder& App::Builder::resource_template(std::string name,
628 Handler handler) {
629 detail::require_callable(handler, "resource_template");
630 protocol::ResourceTemplate resource_template;
631 if constexpr (std::is_invocable_v<Handler>) {
632 auto handled = handler();
633 if constexpr (detail::is_result<decltype(handled)>::value) {
634 if (!handled) {
635 throw std::runtime_error(handled.error().message);
636 }
637 resource_template = *handled;
638 } else {
639 resource_template = std::move(handled);
640 }
641 } else if constexpr (std::is_invocable_v<Handler, std::string>) {
642 resource_template = handler({});
643 } else {
644 static_assert(
645 std::is_invocable_v<Handler>,
646 "resource_template handler must accept no arguments or string");
647 }
648 if (resource_template.name.empty()) {
649 resource_template.name = name;
650 }
651 if (resource_template.uri_template.empty()) {
652 resource_template.uri_template = std::move(name);
653 }
654 return this->resource_template(std::move(resource_template));
655}
656
657template <class Handler>
658App::Builder& App::Builder::completion(Handler handler) {
659 detail::require_callable(handler, "completion");
660 if constexpr (detail::is_typed_completion_handler_v<Handler>) {
661 detail::require_unambiguous_completion_handler<Handler>();
662 } else {
663 detail::require_unambiguous_json_extension_handler<Handler>();
664 }
665 builder_.on_completion(
666 [handler = std::move(handler)](const protocol::Json& request,
667 const SessionContext& context,
668 CancellationToken cancellation) mutable
669 -> core::Result<protocol::Json> {
670 if constexpr (detail::is_typed_completion_handler_v<Handler>) {
671 const auto params = protocol::complete_params_from_json(request);
672 if (!params) {
673 return mcp::core::unexpected(core::Error{
674 static_cast<int>(protocol::ErrorCode::InvalidParams),
675 params.error().message, params.error().detail, "protocol"});
676 }
677 CompletionContext completion_context;
678 static_cast<SessionContext&>(completion_context) = context;
679 completion_context.params = *params;
680 completion_context.cancellation = cancellation;
681 auto handled =
682 detail::invoke_completion_handler(handler, completion_context);
683 return detail::completion_response_to_json(std::move(handled));
684 } else {
685 auto handled = detail::invoke_json_extension_handler(
686 handler, request, context, cancellation);
687 if constexpr (detail::is_result<decltype(handled)>::value) {
688 return handled;
689 } else {
690 return detail::value_to_json(std::move(handled));
691 }
692 }
693 });
694 return *this;
695}
696
697template <class Handler>
698App::Builder& App::Builder::sampling(Handler handler) {
699 detail::require_callable(handler, "sampling");
700 detail::require_unambiguous_json_extension_handler<Handler>();
701 builder_.on_sampling(
702 [handler = std::move(handler)](const protocol::Json& request,
703 const SessionContext& context,
704 CancellationToken cancellation) mutable
705 -> core::Result<protocol::Json> {
706 auto handled = detail::invoke_json_extension_handler(
707 handler, request, context, cancellation);
708 if constexpr (detail::is_result<decltype(handled)>::value) {
709 return handled;
710 } else {
711 return detail::value_to_json(std::move(handled));
712 }
713 });
714 return *this;
715}
716
717template <class Handler>
718App::Builder& App::Builder::logging(Handler handler) {
719 detail::require_callable(handler, "logging");
720 builder_.on_logging([handler = std::move(handler)](std::string_view level,
721 std::string_view message) {
722 handler(level, message);
723 });
724 return *this;
725}
726
727template <class Handler>
728App::Builder& App::Builder::raw_request(Handler handler) {
729 detail::require_callable(handler, "raw_request");
730 builder_.on_raw_request([handler = std::move(handler)](
731 const protocol::JsonRpcRequest& request,
732 const SessionContext& context)
733 -> std::optional<protocol::JsonRpcResponse> {
734 (void)context;
735 if constexpr (std::is_same_v<std::decay_t<decltype(handler(request))>,
736 std::optional<protocol::JsonRpcResponse>>) {
737 return handler(request);
738 } else if constexpr (std::is_same_v<
739 std::decay_t<decltype(handler(request))>,
740 protocol::JsonRpcResponse>) {
741 return handler(request);
742 } else {
743 handler(request);
744 return std::nullopt;
745 }
746 });
747 return *this;
748}
749
750} // namespace mcp::server
TypedToolBuilder< Args, Result > tool(std::string name)
Starts a typed tool registration builder.
Definition authoring.hpp:116
Fluent builder for resource-template descriptors.
Definition resource.hpp:151
Fluent typed prompt builder for low-boilerplate server authoring.
Definition authoring.hpp:129
Fluent typed resource builder for low-boilerplate server authoring.
Definition authoring.hpp:206
Fluent typed tool builder for low-boilerplate server authoring.
Definition authoring.hpp:30
Public SDK configuration and compatibility markers.
Internal handler dispatch helpers for cxxmcp server authoring APIs.
nlohmann::json Json
JSON value type used by all protocol DTOs.
Definition types.hpp:28
constexpr auto unexpected(E &&value)
Creates an unexpected result value for the active expected backend.
Definition result.hpp:24
High-level server compatibility API, builder, and convenience app API.
Icon descriptor used by tools, resources, resource templates, and prompts.
Definition types.hpp:160
Argument accepted by a prompt template.
Definition prompt.hpp:63
std::string name
Stable argument name used as a key in prompts/get arguments.
Definition prompt.hpp:67
bool required
Whether the caller must provide this argument.
Definition prompt.hpp:71
bool required_present
Whether required was explicitly present on the wire or configured.
Definition prompt.hpp:73
std::string description
Optional human-readable description.
Definition prompt.hpp:69
Prompt descriptor returned by prompts/list.
Definition prompt.hpp:83
std::optional< Json > meta
Optional _meta extension object preserved on the wire.
Definition prompt.hpp:97
std::string description
Optional human-readable description.
Definition prompt.hpp:89
std::vector< Icon > icons
Optional icon descriptors for client presentation.
Definition prompt.hpp:93
std::vector< PromptArgument > arguments
Prompt arguments accepted by this prompt.
Definition prompt.hpp:91
std::string title
Optional human-readable display title.
Definition prompt.hpp:85
Json annotations
Optional annotations for model or client presentation.
Definition prompt.hpp:95
Concrete resource advertised by resources/list.
Definition resource.hpp:28
std::string title
Optional human-readable display title.
Definition resource.hpp:30
std::string mime_type
Optional MIME type for the resource contents.
Definition resource.hpp:38
std::string description
Optional human-readable description.
Definition resource.hpp:36
Json annotations
Optional annotations for model or client presentation.
Definition resource.hpp:44
std::optional< Json > meta
Optional _meta extension object preserved on the wire.
Definition resource.hpp:46
std::optional< std::int64_t > size
Optional size hint in bytes when known.
Definition resource.hpp:40
std::vector< Icon > icons
Optional icon descriptors for client presentation.
Definition resource.hpp:42
Metadata describing a callable MCP tool.
Definition tool.hpp:213
Json input_schema
JSON Schema object describing accepted arguments.
Definition tool.hpp:221
std::optional< ToolExecution > execution
Optional execution configuration including task support mode.
Definition tool.hpp:231
Json output_schema
Optional JSON Schema object describing structured result content.
Definition tool.hpp:223
std::string title
Optional human-readable display title.
Definition tool.hpp:215
Json annotations
Optional raw annotations preserved for forward-compatible round trips.
Definition tool.hpp:235
std::vector< Icon > icons
Optional icon descriptors for client presentation.
Definition tool.hpp:229
bool output_schema_present
Whether output_schema was explicitly present on the wire or configured.
Definition tool.hpp:225
std::string description
Human-readable tool description.
Definition tool.hpp:219
std::optional< Json > meta
Optional _meta extension object preserved on the wire.
Definition tool.hpp:237
bool streaming
Whether the tool may stream partial results outside a single response.
Definition tool.hpp:227
Execution configuration advertised with a tool definition.
Definition tool.hpp:44
Invocation context passed to prompt handlers.
Definition context.hpp:46
Invocation context passed to resource read handlers.
Definition context.hpp:60
Typed prompt registration produced by mcp::server::prompt().
Definition authoring.hpp:122
Typed resource registration produced by mcp::server::resource().
Definition authoring.hpp:199
Typed tool registration produced by mcp::server::tool().
Definition authoring.hpp:23
TaskSupport
Per-tool support mode for task-based invocation.
Definition tool.hpp:34