fix: enumerate conformance client scenarios (#1008)
fixes #1001. Restores explicit dispatch arms for the ten client scenarios orphaned by #991: standard auth flow: - `auth/iss-*` - `auth/offline-access-*` - `auth/metadata-issuer-mismatch` - `auth/authorization-server-migration` plain connect/list client: `json-schema-ref-no-deref` `run_auth_client` now negotiates via `ClientLifecycleMode::Discover` — `auth/authorization-server-migration` tracked in #879
This commit is contained in:
parent
8efc142e51
commit
61b40afdca
1 changed files with 52 additions and 6 deletions
|
|
@ -286,7 +286,17 @@ async fn run_auth_client(server_url: &str, ctx: &ConformanceContext) -> anyhow::
|
||||||
StreamableHttpClientTransportConfig::with_uri(server_url),
|
StreamableHttpClientTransportConfig::with_uri(server_url),
|
||||||
);
|
);
|
||||||
|
|
||||||
let client = BasicClientHandler.serve(transport).await?;
|
// The 2026-07-28 auth mocks require the modern per-request lifecycle
|
||||||
|
// (MCP-Protocol-Version header on every request), so negotiate via the
|
||||||
|
// discover lifecycle rather than the legacy initialize handshake.
|
||||||
|
let client = BasicClientHandler
|
||||||
|
.serve_with_lifecycle(
|
||||||
|
transport,
|
||||||
|
ClientLifecycleMode::Discover {
|
||||||
|
preferred_versions: preferred_protocol_versions(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
tracing::debug!("Connected (authenticated)");
|
tracing::debug!("Connected (authenticated)");
|
||||||
|
|
||||||
let tools = client.list_tools(Default::default()).await?;
|
let tools = client.list_tools(Default::default()).await?;
|
||||||
|
|
@ -899,15 +909,22 @@ fn conformance_protocol_version() -> ProtocolVersion {
|
||||||
.unwrap_or(ProtocolVersion::V_2026_07_28)
|
.unwrap_or(ProtocolVersion::V_2026_07_28)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Runs draft stateless scenarios through the public discover lifecycle and
|
/// Preferred protocol versions for discover-lifecycle negotiation: the
|
||||||
/// Streamable HTTP transport.
|
/// runner-provided version first, then all other known versions newest-first.
|
||||||
async fn run_discover_client(server_url: &str) -> anyhow::Result<()> {
|
fn preferred_protocol_versions() -> Vec<ProtocolVersion> {
|
||||||
let mut preferred_versions = vec![conformance_protocol_version()];
|
let mut preferred_versions = vec![conformance_protocol_version()];
|
||||||
for version in ProtocolVersion::KNOWN_VERSIONS.iter().rev() {
|
for version in ProtocolVersion::KNOWN_VERSIONS.iter().rev() {
|
||||||
if !preferred_versions.contains(version) {
|
if !preferred_versions.contains(version) {
|
||||||
preferred_versions.push(version.clone());
|
preferred_versions.push(version.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
preferred_versions
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Runs draft stateless scenarios through the public discover lifecycle and
|
||||||
|
/// Streamable HTTP transport.
|
||||||
|
async fn run_discover_client(server_url: &str) -> anyhow::Result<()> {
|
||||||
|
let preferred_versions = preferred_protocol_versions();
|
||||||
let transport = StreamableHttpClientTransport::from_uri(server_url);
|
let transport = StreamableHttpClientTransport::from_uri(server_url);
|
||||||
let client = FullClientHandler
|
let client = FullClientHandler
|
||||||
.serve_with_lifecycle(
|
.serve_with_lifecycle(
|
||||||
|
|
@ -968,7 +985,12 @@ async fn main() -> anyhow::Result<()> {
|
||||||
match scenario.as_str() {
|
match scenario.as_str() {
|
||||||
// Non-auth scenarios
|
// Non-auth scenarios
|
||||||
"initialize" => run_basic_client(&server_url).await?,
|
"initialize" => run_basic_client(&server_url).await?,
|
||||||
"json-schema-ref-no-deref" => run_discover_client(&server_url).await?,
|
// SEP-2106: the scenario serves a tool whose schema carries a network
|
||||||
|
// `$ref`; the check passes when the client lists tools without
|
||||||
|
// dereferencing (fetching) that URL. A plain connect → list_tools →
|
||||||
|
// close is sufficient; the scenario's mock server does not implement
|
||||||
|
// the discover lifecycle, so `run_discover_client` hangs against it.
|
||||||
|
"json-schema-ref-no-deref" => run_basic_client(&server_url).await?,
|
||||||
"tools_call" => run_tools_call_client(&server_url, &ctx).await?,
|
"tools_call" => run_tools_call_client(&server_url, &ctx).await?,
|
||||||
"elicitation-sep1034-client-defaults" => {
|
"elicitation-sep1034-client-defaults" => {
|
||||||
run_elicitation_defaults_client(&server_url).await?
|
run_elicitation_defaults_client(&server_url).await?
|
||||||
|
|
@ -994,7 +1016,31 @@ async fn main() -> anyhow::Result<()> {
|
||||||
| "auth/token-endpoint-auth-post"
|
| "auth/token-endpoint-auth-post"
|
||||||
| "auth/token-endpoint-auth-none"
|
| "auth/token-endpoint-auth-none"
|
||||||
| "auth/2025-03-26-oauth-metadata-backcompat"
|
| "auth/2025-03-26-oauth-metadata-backcompat"
|
||||||
| "auth/2025-03-26-oauth-endpoint-fallback" => run_auth_client(&server_url, &ctx).await?,
|
| "auth/2025-03-26-oauth-endpoint-fallback"
|
||||||
|
// Offline access scope handling: positive/negative variants both run
|
||||||
|
// the well-behaved flow; the referee inspects the requested scopes.
|
||||||
|
| "auth/offline-access-scope"
|
||||||
|
| "auth/offline-access-not-supported"
|
||||||
|
// SEP-2468 (RFC 9207 iss / RFC 8414 §3.3 issuer-echo). The client
|
||||||
|
// captures `iss` from the authorization redirect and passes it to the
|
||||||
|
// callback handler; the SDK validates internally. Positive scenarios
|
||||||
|
// proceed to the token endpoint; negative scenarios error out (the
|
||||||
|
// referee sets `allowClientError`).
|
||||||
|
| "auth/iss-supported"
|
||||||
|
| "auth/iss-not-advertised"
|
||||||
|
| "auth/iss-supported-missing"
|
||||||
|
| "auth/iss-wrong-issuer"
|
||||||
|
| "auth/iss-unexpected"
|
||||||
|
| "auth/iss-normalized"
|
||||||
|
| "auth/metadata-issuer-mismatch"
|
||||||
|
| "auth/metadata-issuer-mismatch"
|
||||||
|
// SEP-2352: PRM `authorization_servers` switches between calls; a
|
||||||
|
// compliant client re-registers at the new AS. Known partial failure:
|
||||||
|
// the SDK lacks issuer-stamped credential storage (#879), so the
|
||||||
|
// `sep-2352-reregister-on-as-change` check fails. Left on the standard
|
||||||
|
// flow rather than fixture-orchestrated re-registration so the
|
||||||
|
// conformance result reflects real SDK behavior.
|
||||||
|
| "auth/authorization-server-migration" => run_auth_client(&server_url, &ctx).await?,
|
||||||
|
|
||||||
// Auth - scope step-up
|
// Auth - scope step-up
|
||||||
"auth/scope-step-up" => run_auth_scope_step_up_client(&server_url, &ctx).await?,
|
"auth/scope-step-up" => run_auth_scope_step_up_client(&server_url, &ctx).await?,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue