@@ -957,10 +957,12 @@ async def echo(ctx: Ctx, params: RequestParams) -> dict[str, Any]:
957957 born_ready = Connection .from_envelope (LATEST_MODERN_VERSION , None , None )
958958 async with connected_runner (server , initialized = False , connection = born_ready ) as (client , _ ):
959959 result = await client .send_raw_request ("myorg/echo" , None )
960- # Custom-method results served at a modern version carry the serverInfo
961- # `_meta` stamp like any other result (spec 2026-07-28, #3002).
960+ # Custom-method results served at a modern version carry the required
961+ # `resultType` discriminator and the serverInfo `_meta` stamp like any
962+ # other result (spec 2026-07-28, #3002).
962963 assert result == {
963964 "echoed" : True ,
965+ "resultType" : "complete" ,
964966 "_meta" : {SERVER_INFO_META_KEY : {"name" : "test-server" , "version" : "0.0.1" }},
965967 }
966968
@@ -1039,7 +1041,7 @@ async def custom(ctx: Ctx, params: RequestParams) -> dict[str, Any]:
10391041 born_ready = Connection .from_envelope (LATEST_MODERN_VERSION , None , None )
10401042 async with connected_runner (server , initialized = False , connection = born_ready ) as (client , _ ):
10411043 result = await client .send_raw_request ("myorg/odd-meta" , None )
1042- assert result == {"_meta" : "not-a-mapping" }
1044+ assert result == {"_meta" : "not-a-mapping" , "resultType" : "complete" }
10431045
10441046
10451047@pytest .mark .anyio
@@ -1103,6 +1105,40 @@ async def custom(ctx: Ctx, params: CallToolRequestParams) -> dict[str, Any]:
11031105 assert exc .value .error .message == "Handler returned an invalid result"
11041106
11051107
1108+ @pytest .mark .anyio
1109+ async def test_a_handshake_era_custom_result_gains_no_discriminator (server : SrvT ):
1110+ """The `resultType` fill is modern-only: handshake-era results keep the
1111+ handler's exact shape (the field does not exist pre-2026)."""
1112+
1113+ async def echo (ctx : Ctx , params : RequestParams ) -> dict [str , Any ]:
1114+ return {"echoed" : True }
1115+
1116+ server .add_request_handler ("myorg/echo" , RequestParams , echo )
1117+ async with connected_runner (server ) as (client , _ ):
1118+ result = await client .send_raw_request ("myorg/echo" , None )
1119+ assert result == {"echoed" : True }
1120+
1121+
1122+ @pytest .mark .anyio
1123+ async def test_an_explicit_null_result_type_is_filled_on_the_modern_path (server : SrvT ):
1124+ """A handler-authored `"resultType": null` reads as absent (null is not a
1125+ valid discriminator) and is filled, mirroring the null posture of the
1126+ identity stamp."""
1127+
1128+ async def custom (ctx : Ctx , params : RequestParams ) -> dict [str , Any ]:
1129+ return {"echoed" : True , "resultType" : None }
1130+
1131+ server .add_request_handler ("myorg/echo" , RequestParams , custom )
1132+ born_ready = Connection .from_envelope (LATEST_MODERN_VERSION , None , None )
1133+ async with connected_runner (server , initialized = False , connection = born_ready ) as (client , _ ):
1134+ result = await client .send_raw_request ("myorg/echo" , None )
1135+ assert result == {
1136+ "echoed" : True ,
1137+ "resultType" : "complete" ,
1138+ "_meta" : {SERVER_INFO_META_KEY : {"name" : "test-server" , "version" : "0.0.1" }},
1139+ }
1140+
1141+
11061142@pytest .mark .anyio
11071143async def test_a_claimed_extension_result_type_bypasses_the_sieve_and_is_stamped (server : SrvT ):
11081144 """SDK-defined: a spec-method result carrying an extension `resultType` is a
@@ -1125,10 +1161,11 @@ async def custom(ctx: Ctx, params: CallToolRequestParams) -> dict[str, Any]:
11251161
11261162
11271163@pytest .mark .anyio
1128- async def test_an_empty_result_on_the_modern_path_carries_only_the_stamp (server : SrvT ):
1129- """Spec-mandated (2026-07-28, #3002): serverInfo is stamped into every
1130- result, including empty ones — a result that dumps as `{}` goes on the
1131- modern wire as just the identity `_meta`."""
1164+ async def test_an_empty_result_on_the_modern_path_carries_the_discriminator_and_stamp (server : SrvT ):
1165+ """Spec-mandated (2026-07-28): `resultType` is required on every result a
1166+ modern server sends (the absent-means-complete bridge is for clients of
1167+ older servers only), and serverInfo is stamped into every result too - so
1168+ a result that dumps as `{}` goes on the modern wire with both."""
11321169
11331170 async def custom (ctx : Ctx , params : RequestParams ) -> EmptyResult :
11341171 return EmptyResult ()
@@ -1137,7 +1174,10 @@ async def custom(ctx: Ctx, params: RequestParams) -> EmptyResult:
11371174 born_ready = Connection .from_envelope (LATEST_MODERN_VERSION , None , None )
11381175 async with connected_runner (server , initialized = False , connection = born_ready ) as (client , _ ):
11391176 result = await client .send_raw_request ("myorg/empty" , None )
1140- assert result == {"_meta" : {SERVER_INFO_META_KEY : {"name" : "test-server" , "version" : "0.0.1" }}}
1177+ assert result == {
1178+ "resultType" : "complete" ,
1179+ "_meta" : {SERVER_INFO_META_KEY : {"name" : "test-server" , "version" : "0.0.1" }},
1180+ }
11411181
11421182
11431183@pytest .mark .anyio
@@ -1879,7 +1919,11 @@ async def greet(ctx: Ctx, params: RequestParams | None) -> dict[str, Any]:
18791919 params ["_meta" ][CLIENT_INFO_META_KEY ] = "not-an-object"
18801920 async with dual_era_client (greeter ) as (client , _ ):
18811921 result = await client .send_raw_request ("custom/greet" , params )
1882- assert result == {"ok" : True , "_meta" : {SERVER_INFO_META_KEY : {"name" : "greeter-server" , "version" : "0.0.1" }}}
1922+ assert result == {
1923+ "ok" : True ,
1924+ "resultType" : "complete" ,
1925+ "_meta" : {SERVER_INFO_META_KEY : {"name" : "greeter-server" , "version" : "0.0.1" }},
1926+ }
18831927 assert seen == [None ]
18841928
18851929
0 commit comments