20namespace mcp::server {
24template <
class T,
class =
void>
28struct has_tool_title<T, std::void_t<decltype(T::title)>> : std::true_type {};
30template <
class T,
class =
void>
37template <
class T,
class =
void>
42 T, std::void_t<decltype(std::declval<const T&>().definition())>>
45template <
class Tool,
class Text>
46inline std::string static_tool_text(Text value) {
47 if constexpr (std::is_convertible_v<Text, std::string_view>) {
48 return std::string(std::string_view(value));
50 return std::string(value);
57template <
class Args,
class Result,
class Handler>
64template <
class Args,
class Result>
68 definition_ = protocol::tool_definition(std::move(name))
71 detail::apply_default_output_schema<Result>(definition_);
75 : definition_(std::move(definition)) {}
78 definition_.
title = std::move(value);
94 return input_schema(protocol::tool_input_schema_for<T>());
105 return output_schema(protocol::tool_output_schema_for<T>());
114 definition_.
icons.push_back(std::move(value));
119 if (!definition_.
execution.has_value()) {
122 definition_.
execution->task_support = value;
127 definition_.
execution = std::move(value);
137 definition_.
meta = std::move(value);
141 template <
class Handler>
143 detail::require_callable(value,
"tool");
144 detail::require_unambiguous_tool_handler<Handler, Args>();
154template <
class Args,
class Result>
167 using Args =
typename Tool::Args;
168 using Result =
typename Tool::Result;
169 auto definition = [&]() {
171 return value.definition();
174 protocol::tool_definition(detail::static_tool_text<Tool>(Tool::name))
177 built.title = detail::static_tool_text<Tool>(Tool::title);
180 built.description = detail::static_tool_text<Tool>(Tool::description);
185 if (definition.input_schema.empty()) {
186 definition.input_schema = protocol::tool_input_schema_for<Args>();
188 detail::apply_default_output_schema<Result>(definition);
190 return builder.handler(std::move(value));
201template <
class Args,
class Handler>
212 : prompt_(std::move(prompt)) {}
215 prompt_ = protocol::prompt_definition(std::move(name)).build();
219 prompt_.
title = std::move(value);
229 std::string description = {}) {
231 argument.
name = std::move(name);
235 prompt_.
arguments.push_back(std::move(argument));
240 prompt_.
icons.push_back(std::move(value));
250 prompt_.
meta = std::move(value);
254 template <
class Handler>
256 detail::require_callable(value,
"prompt");
257 detail::require_unambiguous_typed_context_handler<Handler, Args,
274 return TypedPromptBuilder<Args>(std::move(prompt));
278template <
class Args,
class Handler>
289 : resource_(std::move(resource)) {}
293 protocol::resource_definition(std::move(uri), std::move(name)).build();
297 resource_.
title = std::move(value);
312 resource_.
size = value;
317 resource_.
icons.push_back(std::move(value));
327 resource_.
meta = std::move(value);
331 template <
class Handler>
333 detail::require_callable(value,
"resource");
334 detail::require_unambiguous_typed_context_handler<Handler, Args,
352 return TypedResourceBuilder<Args>(std::move(resource));
355inline protocol::ResourceTemplateBuilder resource_template(
356 std::string uri_template, std::string name) {
357 return protocol::resource_template_definition(std::move(uri_template),
382#if defined(CXXMCP_ENABLE_HTTP)
387 Builder& streamable_http(std::string host, std::uint16_t port,
388 std::string path =
"/mcp");
394 Builder& legacy_sse(std::string host, std::uint16_t port,
395 std::string path =
"/mcp");
407 std::shared_ptr<const JsonSchemaValidator> validator);
418 template <
class Args,
class Result,
class Handler>
422 template <
class Args,
class Result,
class Handler>
426 template <
class Args,
class Result,
class Handler>
439 template <
class Args,
class Handler>
442 template <
class Handler>
456 template <
class Args,
class Handler>
459 template <
class Handler>
472 template <
class Handler>
479 template <
class Handler>
483 template <
class Handler>
487 template <
class Handler>
494 template <
class Handler>
512template <class Args, class Result, class Handler>
514 detail::require_callable(handler,
"tool");
515 detail::require_unambiguous_tool_handler<Handler, Args>();
516 auto definition = protocol::tool_definition(std::move(name))
517 .input_schema(protocol::tool_input_schema_for<Args>())
519 detail::apply_default_output_schema<Result>(definition);
520 return tool<Args, Result>(std::move(definition), std::move(handler));
523template <
class Args,
class Result,
class Handler>
526 detail::require_callable(handler,
"tool");
527 detail::require_unambiguous_tool_handler<Handler, Args>();
529 definition.
input_schema = protocol::tool_input_schema_for<Args>();
531 detail::apply_default_output_schema<Result>(definition);
533 std::move(definition),
534 [handler = std::move(handler)](
537 auto args = detail::argument_from_json<Args>(context.arguments);
539 detail::invoke_tool_handler(handler, std::move(args), context);
540 if constexpr (detail::is_result<
decltype(handled)>::value) {
542 return mcp::core::unexpected(handled.error());
544 return detail::value_to_tool_result(*handled);
546 return detail::value_to_tool_result(std::move(handled));
548 }
catch (
const std::exception& exception) {
550 static_cast<int>(protocol::ErrorCode::InvalidParams),
551 "failed to decode tool arguments",
558template <
class Args,
class Result,
class Handler>
560 TypedToolRegistration<Args, Result, Handler> registration) {
561 return tool<Args, Result>(std::move(registration.definition),
562 std::move(registration.handler));
565template <
class Args,
class Handler>
567 detail::require_callable(handler,
"prompt");
568 detail::require_unambiguous_typed_context_handler<Handler, Args,
569 PromptContext>(
"prompt");
570 protocol::Prompt prompt;
571 prompt.name = std::move(name);
574 [handler = std::move(handler)](
const PromptContext& context)
575 -> core::Result<protocol::PromptsGetResult> {
577 auto args = context.arguments.get<Args>();
578 auto handled = detail::invoke_typed_context_handler(
579 handler, std::move(args), context);
580 if constexpr (detail::is_result<
decltype(handled)>::value) {
584 return detail::value_to_prompt_result(*handled);
586 return detail::value_to_prompt_result(std::move(handled));
588 }
catch (
const std::exception& exception) {
590 static_cast<int>(protocol::ErrorCode::InvalidParams),
591 "failed to decode prompt arguments",
598template <
class Handler>
600 detail::require_callable(handler,
"prompt");
601 detail::require_unambiguous_prompt_handler<Handler>();
602 protocol::Prompt prompt;
603 prompt.name = std::move(name);
606 [handler = std::move(handler)](
const PromptContext& context)
607 -> core::Result<protocol::PromptsGetResult> {
609 auto handled = detail::invoke_prompt_handler(handler, context);
610 if constexpr (detail::is_result<
decltype(handled)>::value) {
614 return detail::value_to_prompt_result(*handled);
616 return detail::value_to_prompt_result(std::move(handled));
618 }
catch (
const std::exception& exception) {
620 static_cast<int>(protocol::ErrorCode::InvalidParams),
621 "failed to run prompt handler",
628template <
class Args,
class Handler>
630 detail::require_callable(handler,
"resource");
631 detail::require_unambiguous_typed_context_handler<Handler, Args,
634 protocol::Resource resource;
635 resource.uri = std::move(name);
636 resource.name = resource.uri;
637 return this->resource(
639 [handler = std::move(handler)](
const ResourceContext& context)
640 -> core::Result<protocol::ResourcesReadResult> {
642 auto args = context.params.get<Args>();
643 auto handled = detail::invoke_typed_context_handler(
644 handler, std::move(args), context);
645 if constexpr (detail::is_result<
decltype(handled)>::value) {
649 return detail::value_to_resource_read_result(*handled, context.uri);
651 return detail::value_to_resource_read_result(std::move(handled),
654 }
catch (
const std::exception& exception) {
656 static_cast<int>(protocol::ErrorCode::InvalidParams),
657 "failed to decode resource parameters",
664template <
class Handler>
666 detail::require_callable(handler,
"resource");
667 detail::require_unambiguous_resource_handler<Handler>();
668 protocol::Resource resource;
669 resource.uri = std::move(name);
670 resource.name = resource.uri;
671 if constexpr (std::is_invocable_v<Handler>) {
672 using Handled =
decltype(handler());
673 if constexpr (std::is_same_v<std::decay_t<Handled>, protocol::Resource>) {
674 resource = handler();
677 return this->resource(
679 [handler = std::move(handler)](
const ResourceContext& context)
680 -> core::Result<protocol::ResourcesReadResult> {
682 auto handled = detail::invoke_resource_handler(handler, context);
683 if constexpr (std::is_same_v<std::decay_t<
decltype(handled)>,
684 protocol::Resource>) {
685 return protocol::ResourcesReadResult{};
686 }
else if constexpr (detail::is_result<
decltype(handled)>::value) {
690 return detail::value_to_resource_read_result(*handled, context.uri);
692 return detail::value_to_resource_read_result(std::move(handled),
695 }
catch (
const std::exception& exception) {
697 static_cast<int>(protocol::ErrorCode::InvalidParams),
698 "failed to run resource handler",
705template <
class Handler>
708 detail::require_callable(handler,
"resource_template");
709 protocol::ResourceTemplate resource_template;
710 if constexpr (std::is_invocable_v<Handler>) {
711 auto handled = handler();
712 if constexpr (detail::is_result<
decltype(handled)>::value) {
714 throw std::runtime_error(handled.error().message);
716 resource_template = *handled;
718 resource_template = std::move(handled);
720 }
else if constexpr (std::is_invocable_v<Handler, std::string>) {
721 resource_template = handler({});
724 std::is_invocable_v<Handler>,
725 "resource_template handler must accept no arguments or string");
727 if (resource_template.name.empty()) {
728 resource_template.name = name;
730 if (resource_template.uri_template.empty()) {
731 resource_template.uri_template = std::move(name);
733 return this->resource_template(std::move(resource_template));
736template <
class Handler>
738 detail::require_callable(handler,
"completion");
739 if constexpr (detail::is_typed_completion_handler_v<Handler>) {
740 detail::require_unambiguous_completion_handler<Handler>();
742 detail::require_unambiguous_json_extension_handler<Handler>();
744 builder_.on_completion(
745 [handler = std::move(handler)](
const protocol::Json& request,
746 const SessionContext& context,
747 CancellationToken cancellation)
mutable
748 -> core::Result<protocol::Json> {
749 if constexpr (detail::is_typed_completion_handler_v<Handler>) {
750 const auto params = protocol::complete_params_from_json(request);
753 static_cast<int>(protocol::ErrorCode::InvalidParams),
754 params.error().message, params.error().detail,
"protocol"});
756 CompletionContext completion_context;
757 static_cast<SessionContext&
>(completion_context) = context;
758 completion_context.params = *params;
759 completion_context.cancellation = cancellation;
761 detail::invoke_completion_handler(handler, completion_context);
762 return detail::completion_response_to_json(std::move(handled));
764 auto handled = detail::invoke_json_extension_handler(
765 handler, request, context, cancellation);
766 if constexpr (detail::is_result<
decltype(handled)>::value) {
769 return detail::value_to_json(std::move(handled));
776template <
class Handler>
778 detail::require_callable(handler,
"sampling");
779 detail::require_unambiguous_json_extension_handler<Handler>();
780 builder_.on_sampling(
781 [handler = std::move(handler)](
const protocol::Json& request,
782 const SessionContext& context,
783 CancellationToken cancellation)
mutable
784 -> core::Result<protocol::Json> {
785 auto handled = detail::invoke_json_extension_handler(
786 handler, request, context, cancellation);
787 if constexpr (detail::is_result<
decltype(handled)>::value) {
790 return detail::value_to_json(std::move(handled));
796template <
class Handler>
798 detail::require_callable(handler,
"logging");
799 builder_.on_logging([handler = std::move(handler)](std::string_view level,
800 std::string_view message) {
801 handler(level, message);
806template <
class Handler>
808 detail::require_callable(handler,
"raw_request");
809 builder_.on_raw_request([handler = std::move(handler)](
810 const protocol::JsonRpcRequest& request,
811 const SessionContext& context)
812 -> std::optional<protocol::JsonRpcResponse> {
814 if constexpr (std::is_same_v<std::decay_t<
decltype(handler(request))>,
815 std::optional<protocol::JsonRpcResponse>>) {
816 return handler(request);
817 }
else if constexpr (std::is_same_v<
818 std::decay_t<
decltype(handler(request))>,
819 protocol::JsonRpcResponse>) {
820 return handler(request);
TypedToolBuilder< Args, Result > tool(std::string name)
Starts a typed tool registration builder.
Definition authoring.hpp:155
Higher-level server builder with callable adapters.
Definition authoring.hpp:368
Builder & tool(std::string name, Handler handler)
Registers a tool using a typed argument adapter.
Builder & transport(std::unique_ptr< Transport > value)
Adds a caller-supplied transport.
Builder & tasks(TaskOperationProcessorOptions options={})
Enables server-side task processing for task-aware tools.
Builder & raw_request(Handler handler)
Registers a raw request hook adapter.
Builder & instructions(std::string value)
Sets the advertised server instructions.
Builder & completion(Handler handler)
Registers a completion request handler adapter.
Builder & resource_template(protocol::ResourceTemplate resource_template)
Registers a fully described resource template.
core::Result< std::unique_ptr< Server > > build()
Builds the configured server.
Builder & schema_validator(std::shared_ptr< const JsonSchemaValidator > validator)
Installs an optional JSON Schema validator.
Builder & sampling(Handler handler)
Registers a sampling request handler adapter.
Builder & tool(protocol::ToolDefinition definition, Handler handler)
Registers a typed callable using an explicit tool definition.
Builder & tool(TypedToolRegistration< Args, Result, Handler > registration)
Registers a typed tool registration built by mcp::server::tool().
int run()
Builds, starts, and runs the configured server application.
Builder & stdio()
Adds a stdio server transport.
Builder & prompt(std::string name, Handler handler)
Registers a prompt using a callable adapter.
Builder & resource_template(std::string name, Handler handler)
Registers a resource template using a callable adapter.
Builder & logging(Handler handler)
Registers a logging notification handler adapter.
Builder & prompt(protocol::Prompt prompt, PromptHandler handler)
Registers a fully described prompt and low-level handler.
Builder & resource(protocol::Resource resource, ResourceReadHandler handler)
Registers a fully described resource and low-level read handler.
Builder & tool(protocol::ToolDefinition definition, ToolHandler handler)
Registers a fully described tool and low-level handler.
Builder & resource(std::string name, Handler handler)
Registers a resource using a callable adapter.
Builder & version(std::string value)
Sets the advertised server version.
Builder & name(std::string value)
Sets the advertised server name.
Convenience entry point for compact server applications.
Definition authoring.hpp:365
static Builder builder()
Creates a new convenience server builder.
Fluent builder for constructing a configured Server.
Definition server.hpp:571
Fluent typed prompt builder for low-boilerplate server authoring.
Definition authoring.hpp:209
Fluent typed resource builder for low-boilerplate server authoring.
Definition authoring.hpp:286
Public SDK configuration and compatibility markers.
#define CXXMCP_COMPAT_DEPRECATED(message)
Marks compatibility-only APIs as deprecated when explicitly enabled.
Definition config.hpp:39
Internal handler dispatch helpers for cxxmcp server authoring APIs.
std::function< core::Result< protocol::ToolResult >(const ToolContext &)> ToolHandler
Application callback that executes a tool.
Definition handler_types.hpp:21
std::function< core::Result< protocol::ResourcesReadResult >(const ResourceContext &)> ResourceReadHandler
Application callback that reads a resource.
Definition handler_types.hpp:32
std::function< core::Result< protocol::PromptsGetResult >(const PromptContext &)> PromptHandler
Application callback that renders a prompt.
Definition handler_types.hpp:26
nlohmann::json Json
JSON value type used by all protocol DTOs.
Definition types.hpp:28
tl::expected< T, Error > Result
Alias for the SDK result type.
Definition result.hpp:64
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
URI template advertised by resources/templates/list.
Definition resource.hpp:127
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
Invocation context passed to prompt handlers.
Definition context.hpp:56
Invocation context passed to resource read handlers.
Definition context.hpp:70
Options for the SDK server task processor.
Definition task_manager.hpp:35
Typed prompt registration produced by mcp::server::prompt().
Definition authoring.hpp:202
Typed resource registration produced by mcp::server::resource().
Definition authoring.hpp:279