19namespace mcp::server {
22template <
class Args,
class Result,
class Handler>
29template <
class Args,
class Result>
34 protocol::tool_definition(std::move(name)).input<Args>().build();
35 detail::apply_default_output_schema<Result>(definition_);
39 definition_.
title = std::move(value);
55 return input_schema(protocol::schema_for<T>());
66 return output_schema(protocol::schema_for<T>());
75 definition_.
icons.push_back(std::move(value));
83 definition_.
execution->task_support = value;
98 definition_.
meta = std::move(value);
102 template <
class Handler>
104 detail::require_callable(value,
"tool");
105 detail::require_unambiguous_tool_handler<Handler, Args>();
115template <
class Args,
class Result>
121template <
class Args,
class Handler>
132 : prompt_(std::move(prompt)) {}
135 prompt_ = protocol::prompt_definition(std::move(name)).build();
139 prompt_.
title = std::move(value);
149 std::string description = {}) {
151 argument.
name = std::move(name);
155 prompt_.
arguments.push_back(std::move(argument));
160 prompt_.
icons.push_back(std::move(value));
170 prompt_.
meta = std::move(value);
174 template <
class Handler>
176 detail::require_callable(value,
"prompt");
177 detail::require_unambiguous_typed_context_handler<Handler, Args,
194 return TypedPromptBuilder<Args>(std::move(prompt));
198template <
class Args,
class Handler>
209 : resource_(std::move(resource)) {}
213 protocol::resource_definition(std::move(uri), std::move(name)).build();
217 resource_.
title = std::move(value);
232 resource_.
size = value;
237 resource_.
icons.push_back(std::move(value));
247 resource_.
meta = std::move(value);
251 template <
class Handler>
253 detail::require_callable(value,
"resource");
254 detail::require_unambiguous_typed_context_handler<Handler, Args,
272 return TypedResourceBuilder<Args>(std::move(resource));
276 std::string uri_template, std::string name) {
277 return protocol::resource_template_definition(std::move(uri_template),
285class CXXMCP_DEPRECATED(
286 "App is a compatibility entry point; use ServerPeer::builder() with "
287 "cxxmcp/run.hpp instead") App {
293 Builder& name(std::string value);
296 Builder& version(std::string value);
299 Builder& instructions(std::string value);
304#if defined(CXXMCP_ENABLE_HTTP)
309 Builder& streamable_http(std::string host, std::uint16_t port,
310 std::string path =
"/mcp");
316 Builder& legacy_sse(std::string host, std::uint16_t port,
317 std::string path =
"/mcp");
322 Builder& transport(std::unique_ptr<Transport> value);
325 Builder& tasks(TaskOperationProcessorOptions options = {});
328 Builder& schema_validator(
329 std::shared_ptr<const JsonSchemaValidator> validator);
340 template <
class Args,
class Result,
class Handler>
341 Builder& tool(std::string name, Handler handler);
344 template <
class Args,
class Result,
class Handler>
345 Builder& tool(protocol::ToolDefinition definition, Handler handler);
348 template <
class Args,
class Result,
class Handler>
349 Builder& tool(TypedToolRegistration<Args, Result, Handler> registration);
352 Builder& tool(protocol::ToolDefinition definition, ToolHandler handler);
361 template <
class Args,
class Handler>
362 Builder& prompt(std::string name, Handler handler);
364 template <
class Handler>
365 Builder& prompt(std::string name, Handler handler);
368 Builder& prompt(protocol::Prompt prompt, PromptHandler handler);
378 template <
class Args,
class Handler>
379 Builder& resource(std::string name, Handler handler);
381 template <
class Handler>
382 Builder& resource(std::string name, Handler handler);
385 Builder& resource(protocol::Resource resource, ResourceReadHandler handler);
394 template <
class Handler>
395 Builder& resource_template(std::string name, Handler handler);
398 Builder& resource_template(protocol::ResourceTemplate resource_template);
401 template <
class Handler>
402 Builder& completion(Handler handler);
405 template <
class Handler>
406 Builder& sampling(Handler handler);
409 template <
class Handler>
410 Builder& logging(Handler handler);
416 template <
class Handler>
417 Builder& raw_request(Handler handler);
420 core::Result<std::unique_ptr<Server>> build();
426 ServerBuilder builder_;
430 CXXMCP_DEPRECATED(
"use ServerPeer::builder() instead")
431 static Builder builder();
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>();
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));
444template <
class Args,
class Result,
class Handler>
445App::Builder& App::Builder::tool(protocol::ToolDefinition definition,
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>();
452 detail::apply_default_output_schema<Result>(definition);
454 std::move(definition),
455 [handler = std::move(handler)](
456 const ToolContext& context) -> core::Result<protocol::ToolResult> {
458 auto args = detail::argument_from_json<Args>(context.arguments);
460 detail::invoke_tool_handler(handler, std::move(args), context);
461 if constexpr (detail::is_result<
decltype(handled)>::value) {
465 return detail::value_to_tool_result(*handled);
467 return detail::value_to_tool_result(std::move(handled));
469 }
catch (
const std::exception& exception) {
471 static_cast<int>(protocol::ErrorCode::InvalidParams),
472 "failed to decode tool arguments",
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));
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);
495 [handler = std::move(handler)](
const PromptContext& context)
496 -> core::Result<protocol::PromptsGetResult> {
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) {
505 return detail::value_to_prompt_result(*handled);
507 return detail::value_to_prompt_result(std::move(handled));
509 }
catch (
const std::exception& exception) {
511 static_cast<int>(protocol::ErrorCode::InvalidParams),
512 "failed to decode prompt arguments",
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);
527 [handler = std::move(handler)](
const PromptContext& context)
528 -> core::Result<protocol::PromptsGetResult> {
530 auto handled = detail::invoke_prompt_handler(handler, context);
531 if constexpr (detail::is_result<
decltype(handled)>::value) {
535 return detail::value_to_prompt_result(*handled);
537 return detail::value_to_prompt_result(std::move(handled));
539 }
catch (
const std::exception& exception) {
541 static_cast<int>(protocol::ErrorCode::InvalidParams),
542 "failed to run prompt handler",
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,
555 protocol::Resource resource;
556 resource.uri = std::move(name);
557 resource.name = resource.uri;
558 return this->resource(
560 [handler = std::move(handler)](
const ResourceContext& context)
561 -> core::Result<protocol::ResourcesReadResult> {
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) {
570 return detail::value_to_resource_read_result(*handled, context.uri);
572 return detail::value_to_resource_read_result(std::move(handled),
575 }
catch (
const std::exception& exception) {
577 static_cast<int>(protocol::ErrorCode::InvalidParams),
578 "failed to decode resource parameters",
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();
598 return this->resource(
600 [handler = std::move(handler)](
const ResourceContext& context)
601 -> core::Result<protocol::ResourcesReadResult> {
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) {
611 return detail::value_to_resource_read_result(*handled, context.uri);
613 return detail::value_to_resource_read_result(std::move(handled),
616 }
catch (
const std::exception& exception) {
618 static_cast<int>(protocol::ErrorCode::InvalidParams),
619 "failed to run resource handler",
626template <
class Handler>
627App::Builder& App::Builder::resource_template(std::string name,
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) {
635 throw std::runtime_error(handled.error().message);
637 resource_template = *handled;
639 resource_template = std::move(handled);
641 }
else if constexpr (std::is_invocable_v<Handler, std::string>) {
642 resource_template = handler({});
645 std::is_invocable_v<Handler>,
646 "resource_template handler must accept no arguments or string");
648 if (resource_template.name.empty()) {
649 resource_template.name = name;
651 if (resource_template.uri_template.empty()) {
652 resource_template.uri_template = std::move(name);
654 return this->resource_template(std::move(resource_template));
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>();
663 detail::require_unambiguous_json_extension_handler<Handler>();
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);
674 static_cast<int>(protocol::ErrorCode::InvalidParams),
675 params.error().message, params.error().detail,
"protocol"});
677 CompletionContext completion_context;
678 static_cast<SessionContext&
>(completion_context) = context;
679 completion_context.params = *params;
680 completion_context.cancellation = cancellation;
682 detail::invoke_completion_handler(handler, completion_context);
683 return detail::completion_response_to_json(std::move(handled));
685 auto handled = detail::invoke_json_extension_handler(
686 handler, request, context, cancellation);
687 if constexpr (detail::is_result<
decltype(handled)>::value) {
690 return detail::value_to_json(std::move(handled));
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) {
711 return detail::value_to_json(std::move(handled));
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);
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> {
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);
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
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
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