@@ -36,6 +36,60 @@ TEST(request_meta_validation_valid_minimum) {
3636 EXPECT_EQ (meta->progress_token , nullptr );
3737}
3838
39+ // Integer-valued numbers are integers regardless of their JSON representation
40+ // https://json-schema.org/understanding-json-schema/reference/numeric#integer
41+ TEST (request_meta_validation_accepts_integral_real_identifier) {
42+ const auto envelope{sourcemeta::core::parse_json (R"JSON( {
43+ "jsonrpc": "2.0", "id": 42.0, "method": "tools/list",
44+ "params": { "_meta": {
45+ "io.modelcontextprotocol/protocolVersion": "2026-07-28",
46+ "io.modelcontextprotocol/clientCapabilities": {}
47+ } }
48+ })JSON" )};
49+ EXPECT_TRUE (envelope.at (" id" ).is_real ());
50+ EXPECT_EQ (sourcemeta::core::mcp_validate_request_meta (envelope).first ,
51+ sourcemeta::core::MCPRequestMetaStatus::Valid);
52+ }
53+
54+ TEST (request_meta_validation_accepts_integral_exponent_identifier) {
55+ const auto envelope{sourcemeta::core::parse_json (R"JSON( {
56+ "jsonrpc": "2.0", "id": 4.2e1, "method": "tools/list",
57+ "params": { "_meta": {
58+ "io.modelcontextprotocol/protocolVersion": "2026-07-28",
59+ "io.modelcontextprotocol/clientCapabilities": {}
60+ } }
61+ })JSON" )};
62+ EXPECT_EQ (envelope.at (" id" ), sourcemeta::core::JSON {42 });
63+ EXPECT_EQ (sourcemeta::core::mcp_validate_request_meta (envelope).first ,
64+ sourcemeta::core::MCPRequestMetaStatus::Valid);
65+ }
66+
67+ TEST (request_meta_validation_accepts_integral_decimal_identifier) {
68+ const auto envelope{sourcemeta::core::parse_json (R"JSON( {
69+ "jsonrpc": "2.0", "id": 18446744073709551617, "method": "tools/list",
70+ "params": { "_meta": {
71+ "io.modelcontextprotocol/protocolVersion": "2026-07-28",
72+ "io.modelcontextprotocol/clientCapabilities": {}
73+ } }
74+ })JSON" )};
75+ EXPECT_TRUE (envelope.at (" id" ).is_decimal ());
76+ EXPECT_EQ (sourcemeta::core::mcp_validate_request_meta (envelope).first ,
77+ sourcemeta::core::MCPRequestMetaStatus::Valid);
78+ }
79+
80+ TEST (request_meta_validation_rejects_fractional_decimal_identifier) {
81+ const auto envelope{sourcemeta::core::parse_json (R"JSON( {
82+ "jsonrpc": "2.0", "id": 42.00000000000000000001, "method": "tools/list",
83+ "params": { "_meta": {
84+ "io.modelcontextprotocol/protocolVersion": "2026-07-28",
85+ "io.modelcontextprotocol/clientCapabilities": {}
86+ } }
87+ })JSON" )};
88+ EXPECT_TRUE (envelope.at (" id" ).is_decimal ());
89+ EXPECT_EQ (sourcemeta::core::mcp_validate_request_meta (envelope).first ,
90+ sourcemeta::core::MCPRequestMetaStatus::InvalidEnvelope);
91+ }
92+
3993TEST (request_meta_validation_valid_with_client_info) {
4094 const auto envelope{sourcemeta::core::parse_json (R"JSON( {
4195 "jsonrpc": "2.0",
@@ -1763,6 +1817,36 @@ TEST(request_client_info_rejects_icon_src_number) {
17631817 .second .has_value ());
17641818}
17651819
1820+ TEST (request_metadata_accepts_integral_real_progress_token) {
1821+ const auto parameters{sourcemeta::core::parse_json (R"JSON( {
1822+ "_meta": {
1823+ "io.modelcontextprotocol/protocolVersion": "2026-07-28",
1824+ "io.modelcontextprotocol/clientCapabilities": {},
1825+ "progressToken": 7.0
1826+ }
1827+ })JSON" )};
1828+ const auto [status, meta]{
1829+ sourcemeta::core::mcp_validate_request_parameters (parameters)};
1830+ EXPECT_EQ (status, sourcemeta::core::MCPRequestMetaStatus::Valid);
1831+ EXPECT_TRUE (meta.has_value ());
1832+ EXPECT_EQ (meta->progress_token , ¶meters.at (" _meta" ).at (" progressToken" ));
1833+ }
1834+
1835+ TEST (request_metadata_accepts_integral_decimal_progress_token) {
1836+ const auto parameters{sourcemeta::core::parse_json (R"JSON( {
1837+ "_meta": {
1838+ "io.modelcontextprotocol/protocolVersion": "2026-07-28",
1839+ "io.modelcontextprotocol/clientCapabilities": {},
1840+ "progressToken": 18446744073709551617
1841+ }
1842+ })JSON" )};
1843+ const auto [status, meta]{
1844+ sourcemeta::core::mcp_validate_request_parameters (parameters)};
1845+ EXPECT_EQ (status, sourcemeta::core::MCPRequestMetaStatus::Valid);
1846+ EXPECT_TRUE (meta.has_value ());
1847+ EXPECT_EQ (meta->progress_token , ¶meters.at (" _meta" ).at (" progressToken" ));
1848+ }
1849+
17661850TEST (request_metadata_rejects_fractional_progress_token) {
17671851 auto value{sourcemeta::core::parse_json (R"JSON( {
17681852 "_meta": {
0 commit comments