@@ -286,7 +286,17 @@ async fn run_auth_client(server_url: &str, ctx: &ConformanceContext) -> anyhow::
286286 StreamableHttpClientTransportConfig :: with_uri ( server_url) ,
287287 ) ;
288288
289- let client = BasicClientHandler . serve ( transport) . await ?;
289+ // The 2026-07-28 auth mocks require the modern per-request lifecycle
290+ // (MCP-Protocol-Version header on every request), so negotiate via the
291+ // discover lifecycle rather than the legacy initialize handshake.
292+ let client = BasicClientHandler
293+ . serve_with_lifecycle (
294+ transport,
295+ ClientLifecycleMode :: Discover {
296+ preferred_versions : preferred_protocol_versions ( ) ,
297+ } ,
298+ )
299+ . await ?;
290300 tracing:: debug!( "Connected (authenticated)" ) ;
291301
292302 let tools = client. list_tools ( Default :: default ( ) ) . await ?;
@@ -899,15 +909,22 @@ fn conformance_protocol_version() -> ProtocolVersion {
899909 . unwrap_or ( ProtocolVersion :: V_2026_07_28 )
900910}
901911
902- /// Runs draft stateless scenarios through the public discover lifecycle and
903- /// Streamable HTTP transport .
904- async fn run_discover_client ( server_url : & str ) -> anyhow :: Result < ( ) > {
912+ /// Preferred protocol versions for discover- lifecycle negotiation: the
913+ /// runner-provided version first, then all other known versions newest-first .
914+ fn preferred_protocol_versions ( ) -> Vec < ProtocolVersion > {
905915 let mut preferred_versions = vec ! [ conformance_protocol_version( ) ] ;
906916 for version in ProtocolVersion :: KNOWN_VERSIONS . iter ( ) . rev ( ) {
907917 if !preferred_versions. contains ( version) {
908918 preferred_versions. push ( version. clone ( ) ) ;
909919 }
910920 }
921+ preferred_versions
922+ }
923+
924+ /// Runs draft stateless scenarios through the public discover lifecycle and
925+ /// Streamable HTTP transport.
926+ async fn run_discover_client ( server_url : & str ) -> anyhow:: Result < ( ) > {
927+ let preferred_versions = preferred_protocol_versions ( ) ;
911928 let transport = StreamableHttpClientTransport :: from_uri ( server_url) ;
912929 let client = FullClientHandler
913930 . serve_with_lifecycle (
@@ -968,7 +985,12 @@ async fn main() -> anyhow::Result<()> {
968985 match scenario. as_str ( ) {
969986 // Non-auth scenarios
970987 "initialize" => run_basic_client ( & server_url) . await ?,
971- "json-schema-ref-no-deref" => run_discover_client ( & server_url) . await ?,
988+ // SEP-2106: the scenario serves a tool whose schema carries a network
989+ // `$ref`; the check passes when the client lists tools without
990+ // dereferencing (fetching) that URL. A plain connect → list_tools →
991+ // close is sufficient; the scenario's mock server does not implement
992+ // the discover lifecycle, so `run_discover_client` hangs against it.
993+ "json-schema-ref-no-deref" => run_basic_client ( & server_url) . await ?,
972994 "tools_call" => run_tools_call_client ( & server_url, & ctx) . await ?,
973995 "elicitation-sep1034-client-defaults" => {
974996 run_elicitation_defaults_client ( & server_url) . await ?
@@ -994,7 +1016,31 @@ async fn main() -> anyhow::Result<()> {
9941016 | "auth/token-endpoint-auth-post"
9951017 | "auth/token-endpoint-auth-none"
9961018 | "auth/2025-03-26-oauth-metadata-backcompat"
997- | "auth/2025-03-26-oauth-endpoint-fallback" => run_auth_client ( & server_url, & ctx) . await ?,
1019+ | "auth/2025-03-26-oauth-endpoint-fallback"
1020+ // Offline access scope handling: positive/negative variants both run
1021+ // the well-behaved flow; the referee inspects the requested scopes.
1022+ | "auth/offline-access-scope"
1023+ | "auth/offline-access-not-supported"
1024+ // SEP-2468 (RFC 9207 iss / RFC 8414 §3.3 issuer-echo). The client
1025+ // captures `iss` from the authorization redirect and passes it to the
1026+ // callback handler; the SDK validates internally. Positive scenarios
1027+ // proceed to the token endpoint; negative scenarios error out (the
1028+ // referee sets `allowClientError`).
1029+ | "auth/iss-supported"
1030+ | "auth/iss-not-advertised"
1031+ | "auth/iss-supported-missing"
1032+ | "auth/iss-wrong-issuer"
1033+ | "auth/iss-unexpected"
1034+ | "auth/iss-normalized"
1035+ | "auth/metadata-issuer-mismatch"
1036+ | "auth/metadata-issuer-mismatch"
1037+ // SEP-2352: PRM `authorization_servers` switches between calls; a
1038+ // compliant client re-registers at the new AS. Known partial failure:
1039+ // the SDK lacks issuer-stamped credential storage (#879), so the
1040+ // `sep-2352-reregister-on-as-change` check fails. Left on the standard
1041+ // flow rather than fixture-orchestrated re-registration so the
1042+ // conformance result reflects real SDK behavior.
1043+ | "auth/authorization-server-migration" => run_auth_client ( & server_url, & ctx) . await ?,
9981044
9991045 // Auth - scope step-up
10001046 "auth/scope-step-up" => run_auth_scope_step_up_client ( & server_url, & ctx) . await ?,
0 commit comments