@@ -87,6 +87,30 @@ describe("McpClientOAuthDynamicRegistration", () => {
8787 expect ( Object . isFrozen ( result . client . authentication ) ) . toBe ( true ) ;
8888 } ) ;
8989
90+ it ( "accepts an SDK-compatible 2xx response with only required echoed metadata" , async ( ) => {
91+ const registration = new McpClientOAuthDynamicRegistration ( {
92+ fetch : async ( ) =>
93+ jsonResponse (
94+ {
95+ client_id : "minimally-registered-public-client" ,
96+ client_secret : "optional-non-confidential-secret" ,
97+ redirect_uris : [ REDIRECT_URI ] ,
98+ } ,
99+ 200 ,
100+ ) ,
101+ endpointPolicy : allowEndpoint ,
102+ } ) ;
103+
104+ await expect ( registerDefault ( registration ) ) . resolves . toEqual ( {
105+ issuer : ISSUER_URL ,
106+ client : {
107+ clientId : "minimally-registered-public-client" ,
108+ authentication : { method : "none" } ,
109+ } ,
110+ clientSecret : "optional-non-confidential-secret" ,
111+ } ) ;
112+ } ) ;
113+
90114 it . each ( [
91115 { name : "claimed HTTPS" , redirectUri : "https://native.example.test/oauth/callback" } ,
92116 { name : "loopback HTTP" , redirectUri : "http://127.0.0.1:9876/oauth/callback" } ,
@@ -252,10 +276,6 @@ describe("McpClientOAuthDynamicRegistration", () => {
252276 } ) ;
253277
254278 it . each ( [
255- {
256- name : "non-201 successful status" ,
257- response : ( ) => jsonResponse ( registrationResponse ( ) , 200 ) ,
258- } ,
259279 {
260280 name : "declared oversized body" ,
261281 response : ( ) =>
@@ -290,13 +310,12 @@ describe("McpClientOAuthDynamicRegistration", () => {
290310 response : ( ) => jsonResponse ( registrationResponse ( { client_secret : "x" . repeat ( 8_193 ) } ) , 201 ) ,
291311 } ,
292312 {
293- name : "client secret without an expiry " ,
313+ name : "redirect URI substitution " ,
294314 response : ( ) =>
295- jsonResponse ( registrationResponse ( { client_secret_expires_at : undefined } ) , 201 ) ,
296- } ,
297- {
298- name : "client secret expiry without a secret" ,
299- response : ( ) => jsonResponse ( registrationResponse ( { client_secret : undefined } ) , 201 ) ,
315+ jsonResponse (
316+ registrationResponse ( { redirect_uris : [ "https://evil.example.test/callback" ] } ) ,
317+ 201 ,
318+ ) ,
300319 } ,
301320 {
302321 name : "confidential authentication substitution" ,
@@ -310,6 +329,14 @@ describe("McpClientOAuthDynamicRegistration", () => {
310329 name : "application type substitution" ,
311330 response : ( ) => jsonResponse ( registrationResponse ( { application_type : "native" } ) , 201 ) ,
312331 } ,
332+ {
333+ name : "authorization-code response type removal" ,
334+ response : ( ) => jsonResponse ( registrationResponse ( { response_types : [ "token" ] } ) , 201 ) ,
335+ } ,
336+ {
337+ name : "authorization-code grant removal" ,
338+ response : ( ) => jsonResponse ( registrationResponse ( { grant_types : [ "refresh_token" ] } ) , 201 ) ,
339+ } ,
313340 {
314341 name : "non-NQCHAR registered scope" ,
315342 response : ( ) => jsonResponse ( registrationResponse ( { scope : 'tools"read' } ) , 201 ) ,
0 commit comments