diff --git a/src/core/mcp/include/sourcemeta/core/mcp_capabilities.h b/src/core/mcp/include/sourcemeta/core/mcp_capabilities.h index 9c317bc8b..2e79054a0 100644 --- a/src/core/mcp/include/sourcemeta/core/mcp_capabilities.h +++ b/src/core/mcp/include/sourcemeta/core/mcp_capabilities.h @@ -168,9 +168,9 @@ struct MCPServerCapabilities { /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/schema#clientcapabilities -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_parse_client_capabilities(const MCPProtocolVersion version, - const sourcemeta::core::JSON &capabilities) +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_parse_client_capabilities(const MCPProtocolVersion version, + const sourcemeta::core::JSON &capabilities) -> MCPClientCapabilities; /// @ingroup mcp @@ -199,9 +199,9 @@ auto mcp_parse_client_capabilities(const MCPProtocolVersion version, /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/schema#clientcapabilities -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_serialize_client_capabilities( - const MCPProtocolVersion version, const MCPClientCapabilities &capabilities) +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_serialize_client_capabilities(const MCPProtocolVersion version, + const MCPClientCapabilities &capabilities) -> sourcemeta::core::JSON; /// @ingroup mcp @@ -226,9 +226,9 @@ auto mcp_serialize_client_capabilities( /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/schema#servercapabilities -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_parse_server_capabilities(MCPProtocolVersion version, - const JSON &capabilities) +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_parse_server_capabilities(MCPProtocolVersion version, + const JSON &capabilities) -> MCPServerCapabilities; /// @ingroup mcp @@ -252,9 +252,9 @@ auto mcp_parse_server_capabilities(MCPProtocolVersion version, /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/schema#servercapabilities -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_serialize_server_capabilities( - MCPProtocolVersion version, const MCPServerCapabilities &capabilities) +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_serialize_server_capabilities(MCPProtocolVersion version, + const MCPServerCapabilities &capabilities) -> JSON; } // namespace sourcemeta::core diff --git a/src/core/mcp/include/sourcemeta/core/mcp_error.h b/src/core/mcp/include/sourcemeta/core/mcp_error.h index f5333f52f..1878f878c 100644 --- a/src/core/mcp/include/sourcemeta/core/mcp_error.h +++ b/src/core/mcp/include/sourcemeta/core/mcp_error.h @@ -109,11 +109,11 @@ enum class MCPErrorContext : std::uint8_t { /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/index#responses -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_error(MCPProtocolVersion version, const JSON *identifier, - std::int64_t code, JSON::StringView message, - std::optional data = std::nullopt, - MCPErrorContext context = MCPErrorContext::Request) -> JSON; +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_make_error(MCPProtocolVersion version, const JSON *identifier, + std::int64_t code, JSON::StringView message, + std::optional data = std::nullopt, + MCPErrorContext context = MCPErrorContext::Request) -> JSON; /// @ingroup mcp /// The legacy MCP error code returned when a requested resource cannot be @@ -196,8 +196,9 @@ constexpr std::int64_t MCP_CODE_UNSUPPORTED_PROTOCOL_VERSION{-32022}; /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/streamable-http#server-validation /// https://modelcontextprotocol.io/specification/2026-07-28/basic/index#_meta -constexpr auto mcp_error_code_to_http_status(const MCPProtocolVersion version, - const std::int64_t code) noexcept +[[nodiscard]] constexpr auto +mcp_error_code_to_http_status(const MCPProtocolVersion version, + const std::int64_t code) noexcept -> std::optional { if (version != MCPProtocolVersion::V_2026_07_28) { return std::nullopt; @@ -247,8 +248,8 @@ constexpr auto mcp_error_code_to_http_status(const MCPProtocolVersion version, /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/index#error-codes -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_error_unsupported_protocol_version( +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_make_error_unsupported_protocol_version( const MCPProtocolVersion version, const sourcemeta::core::JSON *identifier, const JSON::StringView requested, const std::span supported) @@ -282,8 +283,8 @@ auto mcp_make_error_unsupported_protocol_version( /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/index#error-codes -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_error_missing_required_capability( +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_make_error_missing_required_capability( const MCPProtocolVersion version, const sourcemeta::core::JSON *identifier, sourcemeta::core::JSON required_capabilities, const JSON::StringView message) -> sourcemeta::core::JSON; @@ -310,11 +311,9 @@ auto mcp_make_error_missing_required_capability( /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/streamable-http#schema-extension -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_error_header_mismatch(const MCPProtocolVersion version, - const sourcemeta::core::JSON *identifier, - const JSON::StringView message) - -> sourcemeta::core::JSON; +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto mcp_make_error_header_mismatch( + const MCPProtocolVersion version, const sourcemeta::core::JSON *identifier, + const JSON::StringView message) -> sourcemeta::core::JSON; /// @ingroup mcp /// Build a JSON-RPC error response for header mismatch (-32020) with detailed @@ -346,13 +345,10 @@ auto mcp_make_error_header_mismatch(const MCPProtocolVersion version, /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/streamable-http#schema-extension -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_error_header_mismatch(const MCPProtocolVersion version, - const sourcemeta::core::JSON *identifier, - const JSON::StringView header_name, - const JSON::StringView header_value, - const JSON::StringView body_value) - -> sourcemeta::core::JSON; +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto mcp_make_error_header_mismatch( + const MCPProtocolVersion version, const sourcemeta::core::JSON *identifier, + const JSON::StringView header_name, const JSON::StringView header_value, + const JSON::StringView body_value) -> sourcemeta::core::JSON; /// @ingroup mcp /// Build a JSON-RPC error response for header mismatch (-32020) reporting an @@ -379,11 +375,9 @@ auto mcp_make_error_header_mismatch(const MCPProtocolVersion version, /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/streamable-http#schema-extension -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_error_header_mismatch(const MCPProtocolVersion version, - const sourcemeta::core::JSON *identifier, - const JSON::StringView header_name, - const JSON::StringView header_value) +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto mcp_make_error_header_mismatch( + const MCPProtocolVersion version, const sourcemeta::core::JSON *identifier, + const JSON::StringView header_name, const JSON::StringView header_value) -> sourcemeta::core::JSON; /// @ingroup mcp @@ -414,9 +408,9 @@ auto mcp_make_error_header_mismatch(const MCPProtocolVersion version, /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/server/resources#error-handling -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_error_resource_not_found(const MCPProtocolVersion version, - const sourcemeta::core::JSON *identifier) +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_make_error_resource_not_found(const MCPProtocolVersion version, + const sourcemeta::core::JSON *identifier) -> sourcemeta::core::JSON; } // namespace sourcemeta::core diff --git a/src/core/mcp/include/sourcemeta/core/mcp_headers.h b/src/core/mcp/include/sourcemeta/core/mcp_headers.h index a10fdb6db..54993d054 100644 --- a/src/core/mcp/include/sourcemeta/core/mcp_headers.h +++ b/src/core/mcp/include/sourcemeta/core/mcp_headers.h @@ -141,8 +141,8 @@ struct MCPRequestMeta { /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/index#_meta -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_validate_request_meta(const sourcemeta::core::JSON &envelope) +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_validate_request_meta(const sourcemeta::core::JSON &envelope) -> std::pair>; /// @ingroup mcp @@ -166,8 +166,8 @@ auto mcp_validate_request_meta(const sourcemeta::core::JSON &envelope) /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/index#_meta -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_validate_request_parameters(const JSON ¶meters) +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_validate_request_parameters(const JSON ¶meters) -> std::pair>; /// @ingroup mcp @@ -216,8 +216,7 @@ auto mcp_validate_request_parameters(const JSON ¶meters) /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/index#error-codes -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_error_request_meta( +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto mcp_make_error_request_meta( const MCPProtocolVersion version, const sourcemeta::core::JSON *identifier, const MCPRequestMetaStatus status, const JSON::StringView requested, const std::span supported) @@ -242,8 +241,8 @@ auto mcp_make_error_request_meta( /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/streamable-http#standard-request-headers -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_request_name_from_body(const sourcemeta::core::JSON &envelope) +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_request_name_from_body(const sourcemeta::core::JSON &envelope) -> std::optional; /// @ingroup mcp @@ -285,8 +284,7 @@ auto mcp_request_name_from_body(const sourcemeta::core::JSON &envelope) /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/streamable-http#server-validation -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_validate_request_headers( +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto mcp_validate_request_headers( const MCPProtocolVersion version, const std::optional &protocol_version_header, const std::optional &method_header, @@ -316,8 +314,8 @@ auto mcp_validate_request_headers( /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/streamable-http#value-encoding -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_encode_header_value(JSON::StringView value) -> std::string; +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_encode_header_value(JSON::StringView value) -> std::string; /// @ingroup mcp /// Validate a borrowed HTTP header collection. Names are case insensitive. @@ -363,8 +361,7 @@ auto mcp_encode_header_value(JSON::StringView value) -> std::string; /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/streamable-http#server-validation -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_validate_request_headers( +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto mcp_validate_request_headers( MCPProtocolVersion version, std::span> headers, const JSON &envelope, std::span supported_versions) @@ -442,9 +439,9 @@ struct MCPHeaderParameter { /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/streamable-http#schema-extension -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_parameter_headers(std::span parameters, - const JSON &arguments) +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_make_parameter_headers(std::span parameters, + const JSON &arguments) -> std::vector>; /// @ingroup mcp @@ -478,8 +475,7 @@ auto mcp_make_parameter_headers(std::span parameters, /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/streamable-http#server-validation -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_validate_parameter_headers( +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto mcp_validate_parameter_headers( MCPProtocolVersion version, const JSON &identifier, std::span parameters, const JSON &arguments, std::span> headers) diff --git a/src/core/mcp/include/sourcemeta/core/mcp_logging.h b/src/core/mcp/include/sourcemeta/core/mcp_logging.h index 707dc2b63..9c7b5e696 100644 --- a/src/core/mcp/include/sourcemeta/core/mcp_logging.h +++ b/src/core/mcp/include/sourcemeta/core/mcp_logging.h @@ -55,8 +55,8 @@ enum class MCPLogLevel : std::uint8_t { /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/server/utilities/logging -constexpr auto mcp_log_level_string(const MCPLogLevel level) noexcept - -> JSON::StringView { +[[nodiscard]] constexpr auto +mcp_log_level_string(const MCPLogLevel level) noexcept -> JSON::StringView { switch (level) { case MCPLogLevel::Debug: return "debug"; @@ -99,7 +99,8 @@ constexpr auto mcp_log_level_string(const MCPLogLevel level) noexcept /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/server/utilities/logging -constexpr auto mcp_resolve_log_level(const JSON::StringView value) noexcept +[[nodiscard]] constexpr auto +mcp_resolve_log_level(const JSON::StringView value) noexcept -> std::optional { constexpr std::array LEVELS{ {MCPLogLevel::Debug, MCPLogLevel::Info, MCPLogLevel::Notice, @@ -135,9 +136,9 @@ constexpr auto mcp_resolve_log_level(const JSON::StringView value) noexcept /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/server/utilities/logging -constexpr auto mcp_log_level_enabled(const MCPLogLevel level, - const MCPLogLevel threshold) noexcept - -> bool { +[[nodiscard]] constexpr auto +mcp_log_level_enabled(const MCPLogLevel level, + const MCPLogLevel threshold) noexcept -> bool { return level >= threshold; } diff --git a/src/core/mcp/include/sourcemeta/core/mcp_protocol.h b/src/core/mcp/include/sourcemeta/core/mcp_protocol.h index def5acdd9..0b4260cea 100644 --- a/src/core/mcp/include/sourcemeta/core/mcp_protocol.h +++ b/src/core/mcp/include/sourcemeta/core/mcp_protocol.h @@ -384,7 +384,7 @@ constexpr JSON::StringView MCP_METHOD_TASKS_RESULT{"tasks/result"}; /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/versioning -constexpr auto +[[nodiscard]] constexpr auto mcp_protocol_version_string(const MCPProtocolVersion version) noexcept -> JSON::StringView { switch (version) { @@ -421,7 +421,7 @@ mcp_protocol_version_string(const MCPProtocolVersion version) noexcept /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/versioning -constexpr auto +[[nodiscard]] constexpr auto mcp_resolve_protocol_version(const JSON::StringView value) noexcept -> std::optional { if (value == MCP_PROTOCOL_VERSION_2026_07_28) { @@ -458,7 +458,7 @@ mcp_resolve_protocol_version(const JSON::StringView value) noexcept /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/versioning -constexpr auto +[[nodiscard]] constexpr auto mcp_protocol_version_at_least(const MCPProtocolVersion current, const MCPProtocolVersion minimum) noexcept -> bool { @@ -480,7 +480,7 @@ mcp_protocol_version_at_least(const MCPProtocolVersion current, /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/versioning -constexpr auto +[[nodiscard]] constexpr auto mcp_protocol_version_is_valid(const JSON::StringView value) noexcept -> bool { return mcp_resolve_protocol_version(value).has_value(); } @@ -502,7 +502,7 @@ mcp_protocol_version_is_valid(const JSON::StringView value) noexcept -> bool { /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/lifecycle -constexpr auto +[[nodiscard]] constexpr auto mcp_uses_initialization_handshake(const MCPProtocolVersion version) noexcept -> bool { return version != MCPProtocolVersion::V_2026_07_28; @@ -524,8 +524,8 @@ mcp_uses_initialization_handshake(const MCPProtocolVersion version) noexcept /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/lifecycle -constexpr auto mcp_supports_ping(const MCPProtocolVersion version) noexcept - -> bool { +[[nodiscard]] constexpr auto +mcp_supports_ping(const MCPProtocolVersion version) noexcept -> bool { return version != MCPProtocolVersion::V_2026_07_28; } @@ -546,7 +546,7 @@ constexpr auto mcp_supports_ping(const MCPProtocolVersion version) noexcept /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/index#_meta -constexpr auto +[[nodiscard]] constexpr auto mcp_requires_request_meta(const MCPProtocolVersion version) noexcept -> bool { return version == MCPProtocolVersion::V_2026_07_28; } @@ -568,7 +568,7 @@ mcp_requires_request_meta(const MCPProtocolVersion version) noexcept -> bool { /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/schema -constexpr auto +[[nodiscard]] constexpr auto mcp_requires_result_type(const MCPProtocolVersion version) noexcept -> bool { return version == MCPProtocolVersion::V_2026_07_28; } @@ -590,7 +590,7 @@ mcp_requires_result_type(const MCPProtocolVersion version) noexcept -> bool { /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/server/utilities/caching#cacheable-results -constexpr auto +[[nodiscard]] constexpr auto mcp_requires_cacheable_metadata(const MCPProtocolVersion version) noexcept -> bool { return version == MCPProtocolVersion::V_2026_07_28; @@ -613,7 +613,7 @@ mcp_requires_cacheable_metadata(const MCPProtocolVersion version) noexcept /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/server/discover -constexpr auto +[[nodiscard]] constexpr auto mcp_supports_server_discover(const MCPProtocolVersion version) noexcept -> bool { return version == MCPProtocolVersion::V_2026_07_28; @@ -636,7 +636,7 @@ mcp_supports_server_discover(const MCPProtocolVersion version) noexcept /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/patterns/subscriptions -constexpr auto +[[nodiscard]] constexpr auto mcp_supports_subscriptions_listen(const MCPProtocolVersion version) noexcept -> bool { return version == MCPProtocolVersion::V_2026_07_28; @@ -659,8 +659,8 @@ mcp_supports_subscriptions_listen(const MCPProtocolVersion version) noexcept /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/patterns/mrtr -constexpr auto mcp_supports_mrtr(const MCPProtocolVersion version) noexcept - -> bool { +[[nodiscard]] constexpr auto +mcp_supports_mrtr(const MCPProtocolVersion version) noexcept -> bool { return version == MCPProtocolVersion::V_2026_07_28; } @@ -681,7 +681,7 @@ constexpr auto mcp_supports_mrtr(const MCPProtocolVersion version) noexcept /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/streamable-http -constexpr auto +[[nodiscard]] constexpr auto mcp_supports_protocol_sessions(const MCPProtocolVersion version) noexcept -> bool { return version != MCPProtocolVersion::V_2026_07_28; @@ -704,7 +704,7 @@ mcp_supports_protocol_sessions(const MCPProtocolVersion version) noexcept /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/server/tools -constexpr auto +[[nodiscard]] constexpr auto mcp_supports_output_schema(const MCPProtocolVersion version) noexcept -> bool { return mcp_protocol_version_at_least(version, MCPProtocolVersion::V_2025_06_18); @@ -726,7 +726,7 @@ mcp_supports_output_schema(const MCPProtocolVersion version) noexcept -> bool { /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/server/tools -constexpr auto +[[nodiscard]] constexpr auto mcp_supports_structured_content(const MCPProtocolVersion version) noexcept -> bool { return mcp_protocol_version_at_least(version, @@ -749,7 +749,7 @@ mcp_supports_structured_content(const MCPProtocolVersion version) noexcept /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/schema -constexpr auto +[[nodiscard]] constexpr auto mcp_supports_resource_link_content(const MCPProtocolVersion version) noexcept -> bool { return mcp_protocol_version_at_least(version, @@ -772,7 +772,7 @@ mcp_supports_resource_link_content(const MCPProtocolVersion version) noexcept /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/schema -constexpr auto +[[nodiscard]] constexpr auto mcp_supports_implementation_title(const MCPProtocolVersion version) noexcept -> bool { return mcp_protocol_version_at_least(version, @@ -796,7 +796,7 @@ mcp_supports_implementation_title(const MCPProtocolVersion version) noexcept /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/schema -constexpr auto mcp_supports_implementation_description( +[[nodiscard]] constexpr auto mcp_supports_implementation_description( const MCPProtocolVersion version) noexcept -> bool { return mcp_protocol_version_at_least(version, MCPProtocolVersion::V_2025_11_25); @@ -819,7 +819,7 @@ constexpr auto mcp_supports_implementation_description( /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/schema -constexpr auto mcp_supports_implementation_website_url( +[[nodiscard]] constexpr auto mcp_supports_implementation_website_url( const MCPProtocolVersion version) noexcept -> bool { return mcp_protocol_version_at_least(version, MCPProtocolVersion::V_2025_11_25); @@ -841,7 +841,7 @@ constexpr auto mcp_supports_implementation_website_url( /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/streamable-http -constexpr auto +[[nodiscard]] constexpr auto mcp_supports_jsonrpc_batching(const MCPProtocolVersion version) noexcept -> bool { return version == MCPProtocolVersion::V_2025_03_26; @@ -863,9 +863,9 @@ mcp_supports_jsonrpc_batching(const MCPProtocolVersion version) noexcept /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/schema -constexpr auto mcp_is_request_method(const MCPProtocolVersion version, - const JSON::StringView method) noexcept - -> bool { +[[nodiscard]] constexpr auto +mcp_is_request_method(const MCPProtocolVersion version, + const JSON::StringView method) noexcept -> bool { switch (version) { case MCPProtocolVersion::V_2025_03_26: case MCPProtocolVersion::V_2025_06_18: @@ -931,7 +931,7 @@ constexpr auto mcp_is_request_method(const MCPProtocolVersion version, /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/schema -constexpr auto +[[nodiscard]] constexpr auto mcp_is_server_request_method(const MCPProtocolVersion version, const JSON::StringView method) noexcept -> bool { switch (version) { @@ -978,7 +978,7 @@ mcp_is_server_request_method(const MCPProtocolVersion version, /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/schema -constexpr auto +[[nodiscard]] constexpr auto mcp_is_notification_method(const MCPProtocolVersion version, const JSON::StringView method) noexcept -> bool { switch (version) { @@ -1040,7 +1040,7 @@ mcp_is_notification_method(const MCPProtocolVersion version, /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/patterns/mrtr -constexpr auto +[[nodiscard]] constexpr auto mcp_is_input_request_method(const MCPProtocolVersion version, const JSON::StringView method) noexcept -> bool { switch (version) { @@ -1078,9 +1078,9 @@ mcp_is_input_request_method(const MCPProtocolVersion version, /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/schema -constexpr auto mcp_supports_method(const MCPProtocolVersion version, - const JSON::StringView method) noexcept - -> bool { +[[nodiscard]] constexpr auto +mcp_supports_method(const MCPProtocolVersion version, + const JSON::StringView method) noexcept -> bool { switch (version) { case MCPProtocolVersion::V_2025_03_26: return method == MCP_METHOD_COMPLETION_COMPLETE || @@ -1202,8 +1202,8 @@ constexpr auto mcp_supports_method(const MCPProtocolVersion version, /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/patterns/mrtr -constexpr auto mcp_is_mrtr_method(const JSON::StringView method) noexcept - -> bool { +[[nodiscard]] constexpr auto +mcp_is_mrtr_method(const JSON::StringView method) noexcept -> bool { return method == MCP_METHOD_TOOLS_CALL || method == MCP_METHOD_RESOURCES_READ || method == MCP_METHOD_PROMPTS_GET; @@ -1223,8 +1223,8 @@ constexpr auto mcp_is_mrtr_method(const JSON::StringView method) noexcept /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/server/utilities/caching#cacheable-results -constexpr auto mcp_is_cacheable_method(const JSON::StringView method) noexcept - -> bool { +[[nodiscard]] constexpr auto +mcp_is_cacheable_method(const JSON::StringView method) noexcept -> bool { return method == MCP_METHOD_SERVER_DISCOVER || method == MCP_METHOD_TOOLS_LIST || method == MCP_METHOD_PROMPTS_LIST || method == MCP_METHOD_RESOURCES_LIST || @@ -1250,7 +1250,7 @@ constexpr auto mcp_is_cacheable_method(const JSON::StringView method) noexcept /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/schema -constexpr auto +[[nodiscard]] constexpr auto mcp_is_client_notification_method(MCPProtocolVersion version, JSON::StringView method) noexcept -> bool { switch (version) { @@ -1294,7 +1294,7 @@ mcp_is_client_notification_method(MCPProtocolVersion version, /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/schema -constexpr auto +[[nodiscard]] constexpr auto mcp_is_server_notification_method(MCPProtocolVersion version, JSON::StringView method) noexcept -> bool { switch (version) { diff --git a/src/core/mcp/include/sourcemeta/core/mcp_results.h b/src/core/mcp/include/sourcemeta/core/mcp_results.h index 114ceb639..15db1c3f7 100644 --- a/src/core/mcp/include/sourcemeta/core/mcp_results.h +++ b/src/core/mcp/include/sourcemeta/core/mcp_results.h @@ -45,8 +45,8 @@ enum class MCPCacheScope : std::uint8_t { /// assert(sourcemeta::core::mcp_cache_scope_string( /// sourcemeta::core::MCPCacheScope::Private) == "private"); /// ``` -constexpr auto mcp_cache_scope_string(const MCPCacheScope scope) noexcept - -> JSON::StringView { +[[nodiscard]] constexpr auto +mcp_cache_scope_string(const MCPCacheScope scope) noexcept -> JSON::StringView { switch (scope) { case MCPCacheScope::Public: return "public"; @@ -73,7 +73,8 @@ constexpr auto mcp_cache_scope_string(const MCPCacheScope scope) noexcept /// sourcemeta::core::MCPCacheScope::Private); /// assert(!sourcemeta::core::mcp_resolve_cache_scope("shared").has_value()); /// ``` -constexpr auto mcp_resolve_cache_scope(const JSON::StringView scope) noexcept +[[nodiscard]] constexpr auto +mcp_resolve_cache_scope(const JSON::StringView scope) noexcept -> std::optional { if (scope == "public") { return MCPCacheScope::Public; @@ -183,9 +184,9 @@ struct MCPDescriptorPresentation { /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/schema#annotations -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_serialize_resource_annotations( - MCPProtocolVersion version, const MCPResourceAnnotations &annotations) +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_serialize_resource_annotations(MCPProtocolVersion version, + const MCPResourceAnnotations &annotations) -> JSON; /// @ingroup mcp @@ -215,11 +216,10 @@ auto mcp_serialize_resource_annotations( /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/schema#imagecontent -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_image_block(MCPProtocolVersion version, JSON::StringView data, - JSON::StringView mime_type, - const MCPResourceAnnotations &annotations = {}) - -> JSON; +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_make_image_block(MCPProtocolVersion version, JSON::StringView data, + JSON::StringView mime_type, + const MCPResourceAnnotations &annotations = {}) -> JSON; /// @ingroup mcp /// Build a base64 audio block, with the same contracts as the image builder. /// For example: @@ -240,11 +240,10 @@ auto mcp_make_image_block(MCPProtocolVersion version, JSON::StringView data, /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/schema#audiocontent -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_audio_block(MCPProtocolVersion version, JSON::StringView data, - JSON::StringView mime_type, - const MCPResourceAnnotations &annotations = {}) - -> JSON; +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_make_audio_block(MCPProtocolVersion version, JSON::StringView data, + JSON::StringView mime_type, + const MCPResourceAnnotations &annotations = {}) -> JSON; /// @ingroup mcp /// Embed a checked text/blob resource-content entry in a content block. For /// example: @@ -269,9 +268,9 @@ auto mcp_make_audio_block(MCPProtocolVersion version, JSON::StringView data, /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/schema#embeddedresource -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_embedded_resource(MCPProtocolVersion version, JSON resource, - const MCPResourceAnnotations &annotations = {}) +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_make_embedded_resource(MCPProtocolVersion version, JSON resource, + const MCPResourceAnnotations &annotations = {}) -> JSON; /// @ingroup mcp /// Build a blob resource-content entry. The caller supplies base64-encoded @@ -292,10 +291,9 @@ auto mcp_make_embedded_resource(MCPProtocolVersion version, JSON resource, /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/schema#blobresourcecontents -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_resource_blob_content(JSON::StringView uri, - JSON::StringView mime_type, - JSON::StringView blob) -> JSON; +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_make_resource_blob_content(JSON::StringView uri, JSON::StringView mime_type, + JSON::StringView blob) -> JSON; /// @ingroup mcp /// Build an MCP `text` content block carrying the given text payload. For /// example: @@ -313,8 +311,8 @@ auto mcp_make_resource_blob_content(JSON::StringView uri, /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/schema#textcontent -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_text_block(const JSON::StringView text) -> sourcemeta::core::JSON; +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_make_text_block(const JSON::StringView text) -> sourcemeta::core::JSON; /// @ingroup mcp /// Build an MCP content block referencing a resource by URI. This block type @@ -339,13 +337,10 @@ auto mcp_make_text_block(const JSON::StringView text) -> sourcemeta::core::JSON; /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/schema#resourcelink -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_resource_link(const MCPProtocolVersion version, - const JSON::StringView uri, - const JSON::StringView name, - const JSON::StringView mime_type = {}, - const JSON::StringView description = {}) - -> sourcemeta::core::JSON; +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto mcp_make_resource_link( + const MCPProtocolVersion version, const JSON::StringView uri, + const JSON::StringView name, const JSON::StringView mime_type = {}, + const JSON::StringView description = {}) -> sourcemeta::core::JSON; /// @ingroup mcp /// Decorate a successful MCP result object with version-appropriate envelope @@ -373,8 +368,7 @@ auto mcp_make_resource_link(const MCPProtocolVersion version, /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/schema#result -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_decorate_result( +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto mcp_decorate_result( const MCPProtocolVersion version, sourcemeta::core::JSON result, const std::optional &server_info = std::nullopt) -> sourcemeta::core::JSON; @@ -403,11 +397,9 @@ auto mcp_decorate_result( /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/server/utilities/caching#cacheable-results -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_decorate_cacheable_result(const MCPProtocolVersion version, - sourcemeta::core::JSON result, - const MCPCachePolicy &cache_policy, - const JSON::StringView method) +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto mcp_decorate_cacheable_result( + const MCPProtocolVersion version, sourcemeta::core::JSON result, + const MCPCachePolicy &cache_policy, const JSON::StringView method) -> sourcemeta::core::JSON; /// @ingroup mcp @@ -439,8 +431,7 @@ auto mcp_decorate_cacheable_result(const MCPProtocolVersion version, /// https://modelcontextprotocol.io/specification/2026-07-28/schema#emptyresult /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/schema#jsonrpcresultresponse -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_empty_response( +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto mcp_make_empty_response( const MCPProtocolVersion version, const sourcemeta::core::JSON &identifier, const std::optional &server_info = std::nullopt) -> sourcemeta::core::JSON; @@ -474,8 +465,7 @@ auto mcp_make_empty_response( /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/server/tools -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_tool_success( +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto mcp_make_tool_success( const MCPProtocolVersion version, const sourcemeta::core::JSON &identifier, sourcemeta::core::JSON result, const std::optional &server_info = std::nullopt) @@ -511,8 +501,7 @@ auto mcp_make_tool_success( /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/server/tools -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_tool_success( +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto mcp_make_tool_success( const MCPProtocolVersion version, const sourcemeta::core::JSON &identifier, sourcemeta::core::JSON structured, sourcemeta::core::JSON content_blocks, const std::optional &server_info = std::nullopt) @@ -543,8 +532,7 @@ auto mcp_make_tool_success( /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/server/tools#error-handling -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_tool_error( +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto mcp_make_tool_error( const MCPProtocolVersion version, const sourcemeta::core::JSON &identifier, const JSON::StringView message, const std::optional &server_info = std::nullopt) @@ -571,15 +559,14 @@ auto mcp_make_tool_error( /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/schema#resource -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_resource(const MCPProtocolVersion version, - const JSON::StringView uri, const JSON::StringView name, - const JSON::StringView mime_type, - const JSON::StringView description = {}, - const std::optional size = std::nullopt, - const std::optional priority = std::nullopt, - const MCPDescriptorPresentation &presentation = {}, - const MCPResourceAnnotations &annotations = {}) +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_make_resource(const MCPProtocolVersion version, const JSON::StringView uri, + const JSON::StringView name, const JSON::StringView mime_type, + const JSON::StringView description = {}, + const std::optional size = std::nullopt, + const std::optional priority = std::nullopt, + const MCPDescriptorPresentation &presentation = {}, + const MCPResourceAnnotations &annotations = {}) -> sourcemeta::core::JSON; /// @ingroup mcp @@ -601,11 +588,9 @@ auto mcp_make_resource(const MCPProtocolVersion version, /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/schema#textresourcecontents -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_resource_text_content(const JSON::StringView uri, - const JSON::StringView mime_type, - const JSON::StringView text) - -> sourcemeta::core::JSON; +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto mcp_make_resource_text_content( + const JSON::StringView uri, const JSON::StringView mime_type, + const JSON::StringView text) -> sourcemeta::core::JSON; /// @ingroup mcp /// Wrap a pre-built array of content entries into the MCP `resources/read` @@ -635,11 +620,9 @@ auto mcp_make_resource_text_content(const JSON::StringView uri, /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/server/resources -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_resources_read_result(const MCPProtocolVersion version, - sourcemeta::core::JSON contents, - const MCPCachePolicy &cache_policy) - -> sourcemeta::core::JSON; +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto mcp_make_resources_read_result( + const MCPProtocolVersion version, sourcemeta::core::JSON contents, + const MCPCachePolicy &cache_policy) -> sourcemeta::core::JSON; /// @ingroup mcp /// Build a single entry for an MCP `resources/templates/list` response. For @@ -663,8 +646,7 @@ auto mcp_make_resources_read_result(const MCPProtocolVersion version, /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/schema#resourcetemplate -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_resource_template( +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto mcp_make_resource_template( const MCPProtocolVersion version, const JSON::StringView uri_template, const JSON::StringView name, const JSON::StringView description, const JSON::StringView mime_type, @@ -702,8 +684,7 @@ auto mcp_make_resource_template( /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/schema#tool -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_tool_descriptor( +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto mcp_make_tool_descriptor( const MCPProtocolVersion version, const JSON::StringView name, const JSON::StringView description, sourcemeta::core::JSON input_schema, std::optional output_schema = std::nullopt, @@ -735,8 +716,7 @@ auto mcp_make_tool_descriptor( /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/server/utilities/caching#cacheable-results -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_tools_list_result( +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto mcp_make_tools_list_result( const MCPProtocolVersion version, sourcemeta::core::JSON tools, const std::optional next_cursor, const MCPCachePolicy &cache_policy) -> sourcemeta::core::JSON; @@ -771,8 +751,7 @@ auto mcp_make_tools_list_result( /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/server/utilities/caching#cacheable-results -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_resources_list_result( +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto mcp_make_resources_list_result( const MCPProtocolVersion version, sourcemeta::core::JSON resources, const std::optional next_cursor, const MCPCachePolicy &cache_policy) -> sourcemeta::core::JSON; @@ -801,8 +780,8 @@ auto mcp_make_resources_list_result( /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/server/utilities/caching#cacheable-results -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_resource_templates_list_result( +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_make_resource_templates_list_result( const MCPProtocolVersion version, sourcemeta::core::JSON resource_templates, const std::optional next_cursor, const MCPCachePolicy &cache_policy) -> sourcemeta::core::JSON; @@ -833,8 +812,7 @@ auto mcp_make_resource_templates_list_result( /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/server/utilities/caching#cacheable-results -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_prompts_list_result( +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto mcp_make_prompts_list_result( const MCPProtocolVersion version, sourcemeta::core::JSON prompts, const std::optional next_cursor, const MCPCachePolicy &cache_policy) -> sourcemeta::core::JSON; @@ -869,9 +847,9 @@ auto mcp_make_prompts_list_result( /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/server/prompts -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_prompts_get_result(MCPProtocolVersion version, - JSON::StringView description, JSON messages) +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_make_prompts_get_result(MCPProtocolVersion version, + JSON::StringView description, JSON messages) -> JSON; /// @ingroup mcp @@ -893,10 +871,10 @@ auto mcp_make_prompts_get_result(MCPProtocolVersion version, /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/schema#completeresult -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_completion_result(MCPProtocolVersion version, JSON values, - std::optional total, - std::optional has_more) -> JSON; +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_make_completion_result(MCPProtocolVersion version, JSON values, + std::optional total, + std::optional has_more) -> JSON; /// @ingroup mcp /// Serialize a complete MCP response for one of the six cacheable operations. @@ -1005,8 +983,7 @@ auto mcp_write_result( /// /// @see /// https://modelcontextprotocol.io/specification/2025-11-25/basic/lifecycle#initialization -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_initialize_response( +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto mcp_make_initialize_response( const sourcemeta::core::JSON &request, const MCPServerCapabilities &capabilities, const MCPImplementation &server, const std::span supported_versions, @@ -1045,8 +1022,7 @@ auto mcp_make_initialize_response( /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/schema#discoverresult -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_server_discover_response( +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto mcp_make_server_discover_response( const MCPProtocolVersion version, const sourcemeta::core::JSON &identifier, const MCPServerCapabilities &capabilities, const MCPImplementation &server, const std::span supported_versions, @@ -1098,8 +1074,7 @@ auto mcp_make_server_discover_response( /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/patterns/mrtr#supported-requests -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_input_required_response( +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto mcp_make_input_required_response( const MCPProtocolVersion version, const JSON::StringView method, const sourcemeta::core::JSON &identifier, std::optional input_requests, @@ -1136,9 +1111,9 @@ auto mcp_make_input_required_response( /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/patterns/mrtr -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_request_input_responses(MCPProtocolVersion version, - const sourcemeta::core::JSON &envelope) +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_request_input_responses(MCPProtocolVersion version, + const sourcemeta::core::JSON &envelope) -> const sourcemeta::core::JSON *; /// @ingroup mcp @@ -1162,9 +1137,9 @@ auto mcp_request_input_responses(MCPProtocolVersion version, /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/patterns/mrtr -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_request_state(MCPProtocolVersion version, - const sourcemeta::core::JSON &envelope) +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_request_state(MCPProtocolVersion version, + const sourcemeta::core::JSON &envelope) -> std::optional; /// @ingroup mcp @@ -1215,9 +1190,9 @@ struct MCPSubscriptionFilter { /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/patterns/subscriptions -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_parse_subscription_filter(MCPProtocolVersion version, - const JSON ¶meters) +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_parse_subscription_filter(MCPProtocolVersion version, + const JSON ¶meters) -> std::optional; /// @ingroup mcp @@ -1242,9 +1217,9 @@ auto mcp_parse_subscription_filter(MCPProtocolVersion version, /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/patterns/subscriptions -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_intersect_subscription_filters(const MCPSubscriptionFilter &requested, - const MCPSubscriptionFilter &supported) +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_intersect_subscription_filters(const MCPSubscriptionFilter &requested, + const MCPSubscriptionFilter &supported) -> MCPSubscriptionFilter; /// @ingroup mcp @@ -1269,8 +1244,8 @@ auto mcp_intersect_subscription_filters(const MCPSubscriptionFilter &requested, /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/index#result-responses -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_result_type(const JSON &result) -> std::optional; +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_result_type(const JSON &result) -> std::optional; /// @ingroup mcp /// Recognize base and explicitly negotiated extension result types. The @@ -1299,8 +1274,7 @@ auto mcp_result_type(const JSON &result) -> std::optional; /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/index#result-responses -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_resolve_result_type( +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto mcp_resolve_result_type( MCPProtocolVersion version, const JSON &result, std::span supported_extension_types = {}) -> std::optional; @@ -1344,10 +1318,9 @@ auto mcp_resolve_result_type( /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/patterns/mrtr#client-requirements-basic-workflow -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_validate_continuation(MCPProtocolVersion version, - const JSON ¶meters, - const JSON &input_requests) -> bool; +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_validate_continuation(MCPProtocolVersion version, const JSON ¶meters, + const JSON &input_requests) -> bool; /// @ingroup mcp /// Check continuation fields and the state token, where the expected state @@ -1382,11 +1355,10 @@ auto mcp_validate_continuation(MCPProtocolVersion version, /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/patterns/mrtr -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_validate_continuation(MCPProtocolVersion version, - const JSON ¶meters, - const JSON &input_requests, - std::optional expected_state) +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_validate_continuation(MCPProtocolVersion version, const JSON ¶meters, + const JSON &input_requests, + std::optional expected_state) -> bool; /// @ingroup mcp @@ -1419,13 +1391,12 @@ auto mcp_validate_continuation(MCPProtocolVersion version, /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/patterns/subscriptions -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_notification(MCPProtocolVersion version, bool from_server, - JSON::StringView method, JSON parameters, - std::optional subscription_id, - const MCPSubscriptionFilter *acknowledged = nullptr, - const MCPRequestMeta *request_context = nullptr) - -> JSON; +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_make_notification(MCPProtocolVersion version, bool from_server, + JSON::StringView method, JSON parameters, + std::optional subscription_id, + const MCPSubscriptionFilter *acknowledged = nullptr, + const MCPRequestMeta *request_context = nullptr) -> JSON; /// @ingroup mcp /// Build an acknowledgement notification for `subscriptions/listen` with a @@ -1454,8 +1425,8 @@ auto mcp_make_notification(MCPProtocolVersion version, bool from_server, /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/patterns/subscriptions -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_subscription_acknowledged_notification( +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_make_subscription_acknowledged_notification( const MCPProtocolVersion version, const sourcemeta::core::JSON &subscription_id, const MCPSubscriptionFilter &requested, @@ -1486,8 +1457,8 @@ auto mcp_make_subscription_acknowledged_notification( /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/patterns/subscriptions -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_subscription_acknowledged_notification( +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_make_subscription_acknowledged_notification( const MCPProtocolVersion version, const JSON::StringView subscription_id, const MCPSubscriptionFilter &requested, const MCPSubscriptionFilter &supported) -> sourcemeta::core::JSON; @@ -1508,8 +1479,8 @@ auto mcp_make_subscription_acknowledged_notification( /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/patterns/subscriptions -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_make_subscription_close_response( +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_make_subscription_close_response( const MCPProtocolVersion version, const sourcemeta::core::JSON &identifier, const std::optional &server_info = std::nullopt) -> sourcemeta::core::JSON; @@ -1537,9 +1508,9 @@ auto mcp_make_subscription_close_response( /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/basic/patterns/subscriptions -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_request_subscription_id(MCPProtocolVersion version, - const sourcemeta::core::JSON &envelope) +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_request_subscription_id(MCPProtocolVersion version, + const sourcemeta::core::JSON &envelope) -> const sourcemeta::core::JSON *; /// @ingroup mcp @@ -1564,8 +1535,8 @@ auto mcp_request_subscription_id(MCPProtocolVersion version, /// /// @see /// https://modelcontextprotocol.io/specification/2026-07-28/server/tools -SOURCEMETA_CORE_MCP_EXPORT -auto mcp_tool_call_arguments(const sourcemeta::core::JSON &envelope) +[[nodiscard]] SOURCEMETA_CORE_MCP_EXPORT auto +mcp_tool_call_arguments(const sourcemeta::core::JSON &envelope) -> const sourcemeta::core::JSON *; } // namespace sourcemeta::core diff --git a/src/core/mcp/validation.h b/src/core/mcp/validation.h index 53accb05a..1c2436691 100644 --- a/src/core/mcp/validation.h +++ b/src/core/mcp/validation.h @@ -165,12 +165,6 @@ inline auto icon_size(const JSON::StringView value) -> bool { }); } -inline auto strings(const JSON &value) -> bool { - return value.is_array() && - std::all_of(value.as_array().begin(), value.as_array().end(), - [](const auto &item) { return item.is_string(); }); -} - inline auto annotations(const JSON &value, const bool received = false) -> bool { const auto *item{ @@ -194,11 +188,12 @@ inline auto annotations(const JSON &value, const bool received = false) if (const auto *audience{ field(*item, "audience", sourcemeta::core::MCP_HASH_AUDIENCE)}; audience != nullptr) { - if (!strings(*audience)) { + if (!audience->is_array_of_strings()) { return false; } for (const auto &role : audience->as_array()) { - if (role.to_string() != "user" && role.to_string() != "assistant") { + const auto &role_name{role.to_string()}; + if (role_name != "user" && role_name != "assistant") { return false; } } @@ -228,7 +223,7 @@ inline auto icons(const JSON &value, const bool received = false) -> bool { if (const auto *sizes{ field(item, "sizes", sourcemeta::core::MCP_HASH_SIZES)}; sizes != nullptr) { - if (!strings(*sizes)) { + if (!sizes->is_array_of_strings()) { return false; } @@ -240,10 +235,14 @@ inline auto icons(const JSON &value, const bool received = false) -> bool { } if (const auto *theme{ field(item, "theme", sourcemeta::core::MCP_HASH_THEME)}; - (theme != nullptr) && - (!theme->is_string() || - (theme->to_string() != "light" && theme->to_string() != "dark"))) { - return false; + theme != nullptr) { + if (!theme->is_string()) { + return false; + } + const auto &theme_name{theme->to_string()}; + if (theme_name != "light" && theme_name != "dark") { + return false; + } } } return true; @@ -361,7 +360,7 @@ inline auto sampling_block(const JSON &value, const bool received = false) value)) { return false; } - const auto name{type->to_string()}; + const auto &name{type->to_string()}; if (name == "text" || name == "image" || name == "audio") { return sourcemeta::core::internal::valid_content( MCPProtocolVersion::V_2026_07_28, value, received); @@ -402,7 +401,7 @@ inline auto sampling_message_block(const JSON &block, const bool tools, if (!sampling_block(block)) { return false; } - const auto type{ + const auto &type{ block.at("type", sourcemeta::core::MCP_HASH_TYPE).to_string()}; if (type == "tool_result") { return tools && answering && role == "user" && @@ -484,7 +483,7 @@ inline auto sampling_options(const JSON ¶ms) -> bool { } if (const auto *stop{field(params, "stopSequences", sourcemeta::core::MCP_HASH_STOP_SEQUENCES)}; - (stop != nullptr) && !strings(*stop)) { + (stop != nullptr) && !stop->is_array_of_strings()) { return false; } if (const auto *choice{ @@ -914,7 +913,7 @@ inline auto valid_resource(const MCPProtocolVersion version, const JSON &value, validation::field(value, "size", sourcemeta::core::MCP_HASH_SIZE)}; return validation::base(value, received) && validation::annotations(value, received) && - ((size == nullptr) || (size->is_integral() && *size >= JSON{0})); + ((size == nullptr) || (size->is_integral() && size->is_positive())); } inline auto valid_content(const MCPProtocolVersion version, const JSON &value, @@ -928,7 +927,7 @@ inline auto valid_content(const MCPProtocolVersion version, const JSON &value, if ((type == nullptr) || !type->is_string()) { return false; } - const auto name{type->to_string()}; + const auto &name{type->to_string()}; if (name == "text") { return validation::string_field(value, "text", sourcemeta::core::MCP_HASH_TEXT, true); @@ -1002,7 +1001,7 @@ inline auto valid_input_requests(const JSON &value, !valid_meta(MCPProtocolVersion::V_2026_07_28, *params))) { return false; } - const auto name{method->to_string()}; + const auto &name{method->to_string()}; if (name == MCP_METHOD_ROOTS_LIST) { if (!capabilities.roots) { return false; @@ -1147,7 +1146,7 @@ inline auto valid_input_response(const JSON::StringView method, } for (const auto &entry : content->as_object()) { if (!entry.second.is_string() && !entry.second.is_number() && - !entry.second.is_boolean() && !validation::strings(entry.second)) { + !entry.second.is_boolean() && !entry.second.is_array_of_strings()) { return false; } } diff --git a/test/mcp/mcp_error_test.cc b/test/mcp/mcp_error_test.cc index 0b22b8151..1858930eb 100644 --- a/test/mcp/mcp_error_test.cc +++ b/test/mcp/mcp_error_test.cc @@ -1144,8 +1144,8 @@ TEST(error_code_to_http_status_unmapped_code) { TEST(mcp_error_is_catchable_as_an_invalid_argument) { try { - sourcemeta::core::mcp_make_resource_link( - sourcemeta::core::MCPProtocolVersion::V_2025_03_26, "file:///a", "a"); + static_cast(sourcemeta::core::mcp_make_resource_link( + sourcemeta::core::MCPProtocolVersion::V_2025_03_26, "file:///a", "a")); FAIL(); } catch (const std::invalid_argument &error) { EXPECT_STREQ(error.what(), diff --git a/test/mcp/mcp_helpers.h b/test/mcp/mcp_helpers.h index 690d70f6f..142809a82 100644 --- a/test/mcp/mcp_helpers.h +++ b/test/mcp/mcp_helpers.h @@ -11,7 +11,7 @@ // expectation is re-raised so that it is not mistaken for a rejection #define EXPECT_MCP_REJECTS(expression, expected_message) \ try { \ - expression; \ + static_cast(expression); \ FAIL(); \ } catch (const ::sourcemeta::core::MCPError &sourcemeta_test_error) { \ EXPECT_STREQ(sourcemeta_test_error.what(), expected_message); \