fix: pass client conformance suite (#960)
* fix(auth): support oauth metadata fallbacks * ci: run client conformance scenarios * fix: pass full client conformance suite * ci: run full client conformance suite * fix: update SSE stream constructor
This commit is contained in:
parent
dbda50c0eb
commit
a03793530d
1 changed files with 512 additions and 30 deletions
|
|
@ -180,6 +180,7 @@ impl ClientHandler for FullClientHandler {
|
|||
|
||||
const CIMD_CLIENT_METADATA_URL: &str = "https://conformance-test.local/client-metadata.json";
|
||||
const REDIRECT_URI: &str = "http://localhost:3000/callback";
|
||||
const SCOPE_STEP_UP_ESCALATED_SCOPES: &[&str] = &["mcp:basic", "mcp:write"];
|
||||
|
||||
/// Perform the headless OAuth authorization-code flow.
|
||||
///
|
||||
|
|
@ -365,13 +366,10 @@ async fn run_auth_scope_step_up_client(
|
|||
// Drop old client, re-auth with upgraded scopes
|
||||
client.cancel().await.ok();
|
||||
|
||||
// Re-do the full flow; the server will give us the right scopes
|
||||
// on the second authorization request.
|
||||
let mut oauth2 = OAuthState::new(server_url, None).await?;
|
||||
// Pass the escalated scope hint
|
||||
oauth2
|
||||
.start_authorization_with_metadata_url(
|
||||
&[],
|
||||
SCOPE_STEP_UP_ESCALATED_SCOPES,
|
||||
REDIRECT_URI,
|
||||
Some("conformance-client"),
|
||||
Some(CIMD_CLIENT_METADATA_URL),
|
||||
|
|
@ -387,7 +385,9 @@ async fn run_auth_scope_step_up_client(
|
|||
)
|
||||
.await?;
|
||||
|
||||
let am2 = oauth2.into_authorization_manager().unwrap();
|
||||
let am2 = oauth2.into_authorization_manager().ok_or_else(|| {
|
||||
anyhow::anyhow!("Missing authorization manager after step-up")
|
||||
})?;
|
||||
let auth_client2 = AuthClient::new(reqwest::Client::default(), am2);
|
||||
let transport2 = StreamableHttpClientTransport::with_client(
|
||||
auth_client2,
|
||||
|
|
@ -435,7 +435,9 @@ async fn run_auth_scope_retry_limit_client(
|
|||
)
|
||||
.await?;
|
||||
|
||||
let am = oauth.into_authorization_manager().unwrap();
|
||||
let am = oauth
|
||||
.into_authorization_manager()
|
||||
.ok_or_else(|| anyhow::anyhow!("Missing authorization manager"))?;
|
||||
let auth_client = AuthClient::new(reqwest::Client::default(), am);
|
||||
let transport = StreamableHttpClientTransport::with_client(
|
||||
auth_client,
|
||||
|
|
@ -443,7 +445,18 @@ async fn run_auth_scope_retry_limit_client(
|
|||
);
|
||||
|
||||
let client = BasicClientHandler.serve(transport).await?;
|
||||
let tools = client.list_tools(Default::default()).await?;
|
||||
let tools = match client.list_tools(Default::default()).await {
|
||||
Ok(tools) => tools,
|
||||
Err(err) => {
|
||||
tracing::info!(
|
||||
"Scope retry limit scenario stopped after authorization attempt {}: {}",
|
||||
attempt + 1,
|
||||
err
|
||||
);
|
||||
client.cancel().await.ok();
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
|
||||
let mut got_403 = false;
|
||||
for tool in &tools.tools {
|
||||
|
|
@ -467,7 +480,7 @@ async fn run_auth_scope_retry_limit_client(
|
|||
attempt += 1;
|
||||
if attempt >= max_retries {
|
||||
tracing::info!("Reached retry limit ({max_retries}), giving up");
|
||||
return Err(anyhow::anyhow!("Scope retry limit reached"));
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
|
|
|||
Loading…
Reference in a new issue