@mcp-z/client 2.2.3 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/README.md +12 -1
  2. package/dist/cjs/auth/capability-discovery.d.cts +3 -1
  3. package/dist/cjs/auth/capability-discovery.d.ts +3 -1
  4. package/dist/cjs/auth/capability-discovery.js +46 -32
  5. package/dist/cjs/auth/capability-discovery.js.map +1 -1
  6. package/dist/cjs/auth/discovery-fetch.d.cts +2 -0
  7. package/dist/cjs/auth/discovery-fetch.d.ts +2 -0
  8. package/dist/cjs/auth/discovery-fetch.js +85 -31
  9. package/dist/cjs/auth/discovery-fetch.js.map +1 -1
  10. package/dist/cjs/auth/interactive-oauth-flow.d.cts +1 -1
  11. package/dist/cjs/auth/interactive-oauth-flow.d.ts +1 -1
  12. package/dist/cjs/auth/interactive-oauth-flow.js +13 -6
  13. package/dist/cjs/auth/interactive-oauth-flow.js.map +1 -1
  14. package/dist/cjs/auth/oauth-callback-listener.d.cts +1 -1
  15. package/dist/cjs/auth/oauth-callback-listener.d.ts +1 -1
  16. package/dist/cjs/auth/oauth-callback-listener.js +40 -4
  17. package/dist/cjs/auth/oauth-callback-listener.js.map +1 -1
  18. package/dist/cjs/auth/rfc9728-discovery.d.cts +7 -2
  19. package/dist/cjs/auth/rfc9728-discovery.d.ts +7 -2
  20. package/dist/cjs/auth/rfc9728-discovery.js +120 -88
  21. package/dist/cjs/auth/rfc9728-discovery.js.map +1 -1
  22. package/dist/cjs/auth/types.d.cts +4 -0
  23. package/dist/cjs/auth/types.d.ts +4 -0
  24. package/dist/cjs/auth/types.js.map +1 -1
  25. package/dist/cjs/connection/connect-client.d.cts +9 -1
  26. package/dist/cjs/connection/connect-client.d.ts +9 -1
  27. package/dist/cjs/connection/connect-client.js +282 -75
  28. package/dist/cjs/connection/connect-client.js.map +1 -1
  29. package/dist/cjs/connection/existing-process-transport.d.cts +18 -18
  30. package/dist/cjs/connection/existing-process-transport.d.ts +18 -18
  31. package/dist/cjs/connection/existing-process-transport.js +187 -82
  32. package/dist/cjs/connection/existing-process-transport.js.map +1 -1
  33. package/dist/cjs/connection/wait-for-http-ready.d.cts +1 -1
  34. package/dist/cjs/connection/wait-for-http-ready.d.ts +1 -1
  35. package/dist/cjs/connection/wait-for-http-ready.js +30 -5
  36. package/dist/cjs/connection/wait-for-http-ready.js.map +1 -1
  37. package/dist/cjs/dcr/dcr-authenticator.d.cts +1 -1
  38. package/dist/cjs/dcr/dcr-authenticator.d.ts +1 -1
  39. package/dist/cjs/dcr/dcr-authenticator.js +29 -18
  40. package/dist/cjs/dcr/dcr-authenticator.js.map +1 -1
  41. package/dist/cjs/dcr/dynamic-client-registrar.js +2 -1
  42. package/dist/cjs/dcr/dynamic-client-registrar.js.map +1 -1
  43. package/dist/cjs/index.d.cts +1 -1
  44. package/dist/cjs/index.d.ts +1 -1
  45. package/dist/cjs/index.js.map +1 -1
  46. package/dist/cjs/spawn/owned-process-tree.d.cts +12 -0
  47. package/dist/cjs/spawn/owned-process-tree.d.ts +12 -0
  48. package/dist/cjs/spawn/owned-process-tree.js +93 -0
  49. package/dist/cjs/spawn/owned-process-tree.js.map +1 -0
  50. package/dist/cjs/spawn/spawn-server.d.cts +8 -32
  51. package/dist/cjs/spawn/spawn-server.d.ts +8 -32
  52. package/dist/cjs/spawn/spawn-server.js +406 -97
  53. package/dist/cjs/spawn/spawn-server.js.map +1 -1
  54. package/dist/cjs/spawn/spawn-servers.d.cts +18 -8
  55. package/dist/cjs/spawn/spawn-servers.d.ts +18 -8
  56. package/dist/cjs/spawn/spawn-servers.js +342 -113
  57. package/dist/cjs/spawn/spawn-servers.js.map +1 -1
  58. package/dist/cjs/types.d.cts +1 -1
  59. package/dist/cjs/types.d.ts +1 -1
  60. package/dist/cjs/types.js.map +1 -1
  61. package/dist/cjs/utils/path-utils.js +7 -4
  62. package/dist/cjs/utils/path-utils.js.map +1 -1
  63. package/dist/esm/auth/capability-discovery.d.ts +3 -1
  64. package/dist/esm/auth/capability-discovery.js +21 -11
  65. package/dist/esm/auth/capability-discovery.js.map +1 -1
  66. package/dist/esm/auth/discovery-fetch.d.ts +2 -0
  67. package/dist/esm/auth/discovery-fetch.js +64 -23
  68. package/dist/esm/auth/discovery-fetch.js.map +1 -1
  69. package/dist/esm/auth/interactive-oauth-flow.d.ts +1 -1
  70. package/dist/esm/auth/interactive-oauth-flow.js +13 -6
  71. package/dist/esm/auth/interactive-oauth-flow.js.map +1 -1
  72. package/dist/esm/auth/oauth-callback-listener.d.ts +1 -1
  73. package/dist/esm/auth/oauth-callback-listener.js +34 -4
  74. package/dist/esm/auth/oauth-callback-listener.js.map +1 -1
  75. package/dist/esm/auth/rfc9728-discovery.d.ts +7 -2
  76. package/dist/esm/auth/rfc9728-discovery.js +40 -16
  77. package/dist/esm/auth/rfc9728-discovery.js.map +1 -1
  78. package/dist/esm/auth/types.d.ts +4 -0
  79. package/dist/esm/auth/types.js.map +1 -1
  80. package/dist/esm/connection/connect-client.d.ts +9 -1
  81. package/dist/esm/connection/connect-client.js +97 -35
  82. package/dist/esm/connection/connect-client.js.map +1 -1
  83. package/dist/esm/connection/existing-process-transport.d.ts +18 -18
  84. package/dist/esm/connection/existing-process-transport.js +132 -70
  85. package/dist/esm/connection/existing-process-transport.js.map +1 -1
  86. package/dist/esm/connection/wait-for-http-ready.d.ts +1 -1
  87. package/dist/esm/connection/wait-for-http-ready.js +19 -4
  88. package/dist/esm/connection/wait-for-http-ready.js.map +1 -1
  89. package/dist/esm/dcr/dcr-authenticator.d.ts +1 -1
  90. package/dist/esm/dcr/dcr-authenticator.js +26 -15
  91. package/dist/esm/dcr/dcr-authenticator.js.map +1 -1
  92. package/dist/esm/dcr/dynamic-client-registrar.js +2 -1
  93. package/dist/esm/dcr/dynamic-client-registrar.js.map +1 -1
  94. package/dist/esm/index.d.ts +1 -1
  95. package/dist/esm/index.js.map +1 -1
  96. package/dist/esm/spawn/owned-process-tree.d.ts +12 -0
  97. package/dist/esm/spawn/owned-process-tree.js +39 -0
  98. package/dist/esm/spawn/owned-process-tree.js.map +1 -0
  99. package/dist/esm/spawn/spawn-server.d.ts +8 -32
  100. package/dist/esm/spawn/spawn-server.js +228 -99
  101. package/dist/esm/spawn/spawn-server.js.map +1 -1
  102. package/dist/esm/spawn/spawn-servers.d.ts +18 -8
  103. package/dist/esm/spawn/spawn-servers.js +180 -55
  104. package/dist/esm/spawn/spawn-servers.js.map +1 -1
  105. package/dist/esm/types.d.ts +1 -1
  106. package/dist/esm/types.js.map +1 -1
  107. package/dist/esm/utils/path-utils.js +7 -4
  108. package/dist/esm/utils/path-utils.js.map +1 -1
  109. package/package.json +8 -3
  110. package/schemas/servers.d.ts +24 -0
  111. package/schemas/servers.schema.json +31 -0
@@ -164,27 +164,33 @@ function _ts_generator(thisArg, body) {
164
164
  return '';
165
165
  }
166
166
  }
167
- function discoverProtectedResourceMetadata(resourceUrl) {
168
- return _async_to_generator(function() {
169
- var normalizedResourceUrl, allowLoopback, headerMetadata, localWellKnownUrl, response, unused, origin, path, rootUrl, response1, metadata, rootMetadata, subPathUrl, subPathResponse, unused1, unused2, subPathUrl1, response2, unused3, _error;
167
+ function discoverProtectedResourceMetadata(_0) {
168
+ return _async_to_generator(function(resourceUrl) {
169
+ var options, signal, normalizedResourceUrl, allowLoopback, headerMetadata, localWellKnownUrl, response, unused, origin, path, rootUrl, response1, metadata, rootMetadata, subPathUrl, subPathResponse, unused1, unused2, subPathUrl1, response2, unused3, _error;
170
+ var _arguments = arguments;
170
171
  return _ts_generator(this, function(_state) {
171
172
  switch(_state.label){
172
173
  case 0:
174
+ options = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {};
175
+ signal = options.signal;
176
+ _state.label = 1;
177
+ case 1:
173
178
  _state.trys.push([
174
- 0,
175
- 26,
179
+ 1,
180
+ 27,
176
181
  ,
177
- 27
182
+ 28
178
183
  ]);
184
+ (0, _discoveryfetchts.throwIfAborted)(signal);
179
185
  normalizedResourceUrl = (0, _urlutilsts.normalizeUrl)(resourceUrl);
180
186
  // resourceUrl is the server the caller configured (never remote-supplied);
181
187
  // its loopback-ness is the trust signal every fetch below relies on.
182
188
  allowLoopback = (0, _discoveryfetchts.isLoopbackUrl)(normalizedResourceUrl);
183
189
  return [
184
190
  4,
185
- discoverProtectedResourceMetadataFromHeader(normalizedResourceUrl, allowLoopback)
191
+ discoverProtectedResourceMetadataFromHeader(normalizedResourceUrl, allowLoopback, signal)
186
192
  ];
187
- case 1:
193
+ case 2:
188
194
  headerMetadata = _state.sent();
189
195
  if (headerMetadata) return [
190
196
  2,
@@ -192,13 +198,13 @@ function discoverProtectedResourceMetadata(resourceUrl) {
192
198
  ];
193
199
  // Strategy 0: Try path-local well-known (supports path-prefixed deployments like /outlook)
194
200
  localWellKnownUrl = (0, _urlutilsts.joinWellKnown)(normalizedResourceUrl, '/.well-known/oauth-protected-resource');
195
- _state.label = 2;
196
- case 2:
201
+ _state.label = 3;
202
+ case 3:
197
203
  _state.trys.push([
198
- 2,
199
- 6,
204
+ 3,
205
+ 7,
200
206
  ,
201
- 7
207
+ 8
202
208
  ]);
203
209
  return [
204
210
  4,
@@ -207,49 +213,51 @@ function discoverProtectedResourceMetadata(resourceUrl) {
207
213
  headers: {
208
214
  Accept: 'application/json',
209
215
  Connection: 'close'
210
- }
216
+ },
217
+ signal: signal
211
218
  }, 'protected resource metadata (path-local)', {
212
219
  allowLoopback: allowLoopback
213
220
  })
214
221
  ];
215
- case 3:
222
+ case 4:
216
223
  response = _state.sent();
217
224
  if (!response.ok) return [
218
225
  3,
219
- 5
226
+ 6
220
227
  ];
221
228
  return [
222
229
  4,
223
230
  (0, _discoveryfetchts.readDiscoveryJson)(response, 'protected resource metadata (path-local)')
224
231
  ];
225
- case 4:
232
+ case 5:
226
233
  return [
227
234
  2,
228
235
  _state.sent()
229
236
  ];
230
- case 5:
237
+ case 6:
231
238
  return [
232
239
  3,
233
- 7
240
+ 8
234
241
  ];
235
- case 6:
242
+ case 7:
236
243
  unused = _state.sent();
244
+ (0, _discoveryfetchts.throwIfAborted)(signal);
237
245
  return [
238
246
  3,
239
- 7
247
+ 8
240
248
  ];
241
- case 7:
249
+ case 8:
242
250
  origin = getOrigin(normalizedResourceUrl);
243
251
  path = getPath(normalizedResourceUrl);
244
252
  // Strategy 1: Try root location (REQUIRED by RFC 9728)
245
253
  rootUrl = "".concat(origin, "/.well-known/oauth-protected-resource");
246
- _state.label = 8;
247
- case 8:
254
+ _state.label = 9;
255
+ case 9:
248
256
  _state.trys.push([
249
- 8,
250
- 18,
257
+ 9,
258
+ 19,
251
259
  ,
252
- 19
260
+ 20
253
261
  ]);
254
262
  return [
255
263
  4,
@@ -258,22 +266,23 @@ function discoverProtectedResourceMetadata(resourceUrl) {
258
266
  headers: {
259
267
  Accept: 'application/json',
260
268
  Connection: 'close'
261
- }
269
+ },
270
+ signal: signal
262
271
  }, 'protected resource metadata (root)', {
263
272
  allowLoopback: allowLoopback
264
273
  })
265
274
  ];
266
- case 9:
275
+ case 10:
267
276
  response1 = _state.sent();
268
277
  if (!response1.ok) return [
269
278
  3,
270
- 17
279
+ 18
271
280
  ];
272
281
  return [
273
282
  4,
274
283
  (0, _discoveryfetchts.readDiscoveryJson)(response1, 'protected resource metadata (root)')
275
284
  ];
276
- case 10:
285
+ case 11:
277
286
  metadata = _state.sent();
278
287
  // Check if the discovered resource matches what we're looking for
279
288
  if (metadata.resource === normalizedResourceUrl) {
@@ -292,20 +301,20 @@ function discoverProtectedResourceMetadata(resourceUrl) {
292
301
  }
293
302
  if (!normalizedResourceUrl.startsWith(metadata.resource)) return [
294
303
  3,
295
- 17
304
+ 18
296
305
  ];
297
306
  // Still try sub-path location to see if there's more specific metadata
298
307
  // But save root metadata as fallback
299
308
  rootMetadata = metadata;
300
309
  // Try sub-path location for more specific metadata
301
310
  subPathUrl = "".concat(origin, "/.well-known/oauth-protected-resource").concat(path);
302
- _state.label = 11;
303
- case 11:
311
+ _state.label = 12;
312
+ case 12:
304
313
  _state.trys.push([
305
- 11,
306
- 15,
314
+ 12,
315
+ 16,
307
316
  ,
308
- 16
317
+ 17
309
318
  ]);
310
319
  return [
311
320
  4,
@@ -314,67 +323,70 @@ function discoverProtectedResourceMetadata(resourceUrl) {
314
323
  headers: {
315
324
  Accept: 'application/json',
316
325
  Connection: 'close'
317
- }
326
+ },
327
+ signal: signal
318
328
  }, 'protected resource metadata (sub-path)', {
319
329
  allowLoopback: allowLoopback
320
330
  })
321
331
  ];
322
- case 12:
332
+ case 13:
323
333
  subPathResponse = _state.sent();
324
334
  if (!subPathResponse.ok) return [
325
335
  3,
326
- 14
336
+ 15
327
337
  ];
328
338
  return [
329
339
  4,
330
340
  (0, _discoveryfetchts.readDiscoveryJson)(subPathResponse, 'protected resource metadata (sub-path)')
331
341
  ];
332
- case 13:
342
+ case 14:
333
343
  return [
334
344
  2,
335
345
  _state.sent()
336
346
  ];
337
- case 14:
347
+ case 15:
338
348
  return [
339
349
  3,
340
- 16
350
+ 17
341
351
  ];
342
- case 15:
352
+ case 16:
343
353
  unused1 = _state.sent();
354
+ (0, _discoveryfetchts.throwIfAborted)(signal);
344
355
  return [
345
356
  3,
346
- 16
357
+ 17
347
358
  ];
348
- case 16:
359
+ case 17:
349
360
  // Return root metadata as it applies to this resource
350
361
  return [
351
362
  2,
352
363
  rootMetadata
353
364
  ];
354
- case 17:
365
+ case 18:
355
366
  return [
356
367
  3,
357
- 19
368
+ 20
358
369
  ];
359
- case 18:
370
+ case 19:
360
371
  unused2 = _state.sent();
372
+ (0, _discoveryfetchts.throwIfAborted)(signal);
361
373
  return [
362
374
  3,
363
- 19
375
+ 20
364
376
  ];
365
- case 19:
377
+ case 20:
366
378
  if (!path) return [
367
379
  3,
368
- 25
380
+ 26
369
381
  ];
370
382
  subPathUrl1 = "".concat(origin, "/.well-known/oauth-protected-resource").concat(path);
371
- _state.label = 20;
372
- case 20:
383
+ _state.label = 21;
384
+ case 21:
373
385
  _state.trys.push([
374
- 20,
375
- 24,
386
+ 21,
387
+ 25,
376
388
  ,
377
- 25
389
+ 26
378
390
  ]);
379
391
  return [
380
392
  4,
@@ -383,59 +395,62 @@ function discoverProtectedResourceMetadata(resourceUrl) {
383
395
  headers: {
384
396
  Accept: 'application/json',
385
397
  Connection: 'close'
386
- }
398
+ },
399
+ signal: signal
387
400
  }, 'protected resource metadata (sub-path)', {
388
401
  allowLoopback: allowLoopback
389
402
  })
390
403
  ];
391
- case 21:
404
+ case 22:
392
405
  response2 = _state.sent();
393
406
  if (!response2.ok) return [
394
407
  3,
395
- 23
408
+ 24
396
409
  ];
397
410
  return [
398
411
  4,
399
412
  (0, _discoveryfetchts.readDiscoveryJson)(response2, 'protected resource metadata (sub-path)')
400
413
  ];
401
- case 22:
414
+ case 23:
402
415
  return [
403
416
  2,
404
417
  _state.sent()
405
418
  ];
406
- case 23:
419
+ case 24:
407
420
  return [
408
421
  3,
409
- 25
422
+ 26
410
423
  ];
411
- case 24:
424
+ case 25:
412
425
  unused3 = _state.sent();
426
+ (0, _discoveryfetchts.throwIfAborted)(signal);
413
427
  return [
414
428
  3,
415
- 25
429
+ 26
416
430
  ];
417
- case 25:
431
+ case 26:
418
432
  // Neither location found or resource didn't match
419
433
  return [
420
434
  2,
421
435
  null
422
436
  ];
423
- case 26:
437
+ case 27:
424
438
  _error = _state.sent();
439
+ (0, _discoveryfetchts.throwIfAborted)(signal);
425
440
  // Network error, invalid URL, or other failure
426
441
  return [
427
442
  2,
428
443
  null
429
444
  ];
430
- case 27:
445
+ case 28:
431
446
  return [
432
447
  2
433
448
  ];
434
449
  }
435
450
  });
436
- })();
451
+ }).apply(this, arguments);
437
452
  }
438
- function discoverProtectedResourceMetadataFromHeader(resourceUrl, allowLoopback) {
453
+ function discoverProtectedResourceMetadataFromHeader(resourceUrl, allowLoopback, signal) {
439
454
  return _async_to_generator(function() {
440
455
  var response, header, postResponse, match, metadataUrl, metadataResponse, _error;
441
456
  return _ts_generator(this, function(_state) {
@@ -447,6 +462,7 @@ function discoverProtectedResourceMetadataFromHeader(resourceUrl, allowLoopback)
447
462
  ,
448
463
  7
449
464
  ]);
465
+ (0, _discoveryfetchts.throwIfAborted)(signal);
450
466
  return [
451
467
  4,
452
468
  fetch(resourceUrl, {
@@ -454,7 +470,8 @@ function discoverProtectedResourceMetadataFromHeader(resourceUrl, allowLoopback)
454
470
  headers: {
455
471
  Accept: 'application/json',
456
472
  Connection: 'close'
457
- }
473
+ },
474
+ signal: signal
458
475
  })
459
476
  ];
460
477
  case 1:
@@ -473,7 +490,8 @@ function discoverProtectedResourceMetadataFromHeader(resourceUrl, allowLoopback)
473
490
  Connection: 'close',
474
491
  'Content-Type': 'application/json'
475
492
  },
476
- body: '{}'
493
+ body: '{}',
494
+ signal: signal
477
495
  })
478
496
  ];
479
497
  case 2:
@@ -500,7 +518,8 @@ function discoverProtectedResourceMetadataFromHeader(resourceUrl, allowLoopback)
500
518
  headers: {
501
519
  Accept: 'application/json',
502
520
  Connection: 'close'
503
- }
521
+ },
522
+ signal: signal
504
523
  }, 'resource_metadata URL', {
505
524
  allowLoopback: allowLoopback
506
525
  })
@@ -524,6 +543,7 @@ function discoverProtectedResourceMetadataFromHeader(resourceUrl, allowLoopback)
524
543
  ];
525
544
  case 6:
526
545
  _error = _state.sent();
546
+ (0, _discoveryfetchts.throwIfAborted)(signal);
527
547
  return [
528
548
  2,
529
549
  null
@@ -538,13 +558,13 @@ function discoverProtectedResourceMetadataFromHeader(resourceUrl, allowLoopback)
538
558
  }
539
559
  function discoverAuthorizationServerMetadata(_0) {
540
560
  return _async_to_generator(function(authServerUrl) {
541
- var options, _options_allowLoopback, allowLoopback, normalizedAuthServerUrl, localWellKnownUrl, localResponse, origin, wellKnownUrl, response, _error;
561
+ var options, _options_allowLoopback, allowLoopback, signal, normalizedAuthServerUrl, localWellKnownUrl, localResponse, origin, wellKnownUrl, response, _error;
542
562
  var _arguments = arguments;
543
563
  return _ts_generator(this, function(_state) {
544
564
  switch(_state.label){
545
565
  case 0:
546
566
  options = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {};
547
- _options_allowLoopback = options.allowLoopback, allowLoopback = _options_allowLoopback === void 0 ? false : _options_allowLoopback;
567
+ _options_allowLoopback = options.allowLoopback, allowLoopback = _options_allowLoopback === void 0 ? false : _options_allowLoopback, signal = options.signal;
548
568
  _state.label = 1;
549
569
  case 1:
550
570
  _state.trys.push([
@@ -553,6 +573,7 @@ function discoverAuthorizationServerMetadata(_0) {
553
573
  ,
554
574
  8
555
575
  ]);
576
+ (0, _discoveryfetchts.throwIfAborted)(signal);
556
577
  normalizedAuthServerUrl = (0, _urlutilsts.normalizeUrl)(authServerUrl);
557
578
  localWellKnownUrl = (0, _urlutilsts.joinWellKnown)(normalizedAuthServerUrl, '/.well-known/oauth-authorization-server');
558
579
  return [
@@ -562,7 +583,8 @@ function discoverAuthorizationServerMetadata(_0) {
562
583
  headers: {
563
584
  Accept: 'application/json',
564
585
  Connection: 'close'
565
- }
586
+ },
587
+ signal: signal
566
588
  }, 'authorization server metadata (path-local)', {
567
589
  allowLoopback: allowLoopback
568
590
  })
@@ -592,7 +614,8 @@ function discoverAuthorizationServerMetadata(_0) {
592
614
  headers: {
593
615
  Accept: 'application/json',
594
616
  Connection: 'close'
595
- }
617
+ },
618
+ signal: signal
596
619
  }, 'authorization server metadata', {
597
620
  allowLoopback: allowLoopback
598
621
  })
@@ -616,6 +639,7 @@ function discoverAuthorizationServerMetadata(_0) {
616
639
  ];
617
640
  case 7:
618
641
  _error = _state.sent();
642
+ (0, _discoveryfetchts.throwIfAborted)(signal);
619
643
  return [
620
644
  2,
621
645
  null
@@ -628,18 +652,24 @@ function discoverAuthorizationServerMetadata(_0) {
628
652
  });
629
653
  }).apply(this, arguments);
630
654
  }
631
- function discoverAuthorizationServerIssuer(resourceUrl) {
632
- return _async_to_generator(function() {
633
- var _match_, response, header, match, _error;
655
+ function discoverAuthorizationServerIssuer(_0) {
656
+ return _async_to_generator(function(resourceUrl) {
657
+ var options, signal, _match_, response, header, match, _error;
658
+ var _arguments = arguments;
634
659
  return _ts_generator(this, function(_state) {
635
660
  switch(_state.label){
636
661
  case 0:
662
+ options = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : {};
663
+ signal = options.signal;
664
+ _state.label = 1;
665
+ case 1:
637
666
  _state.trys.push([
638
- 0,
639
- 2,
667
+ 1,
668
+ 3,
640
669
  ,
641
- 3
670
+ 4
642
671
  ]);
672
+ (0, _discoveryfetchts.throwIfAborted)(signal);
643
673
  return [
644
674
  4,
645
675
  fetch(resourceUrl, {
@@ -647,10 +677,11 @@ function discoverAuthorizationServerIssuer(resourceUrl) {
647
677
  headers: {
648
678
  Accept: 'application/json',
649
679
  Connection: 'close'
650
- }
680
+ },
681
+ signal: signal
651
682
  })
652
683
  ];
653
- case 1:
684
+ case 2:
654
685
  response = _state.sent();
655
686
  header = response.headers.get('www-authenticate');
656
687
  if (!header) return [
@@ -666,18 +697,19 @@ function discoverAuthorizationServerIssuer(resourceUrl) {
666
697
  2,
667
698
  (_match_ = match[1]) !== null && _match_ !== void 0 ? _match_ : null
668
699
  ];
669
- case 2:
700
+ case 3:
670
701
  _error = _state.sent();
702
+ (0, _discoveryfetchts.throwIfAborted)(signal);
671
703
  return [
672
704
  2,
673
705
  null
674
706
  ];
675
- case 3:
707
+ case 4:
676
708
  return [
677
709
  2
678
710
  ];
679
711
  }
680
712
  });
681
- })();
713
+ }).apply(this, arguments);
682
714
  }
683
715
  /* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/client/src/auth/rfc9728-discovery.ts"],"sourcesContent":["/**\n * RFC 9728 Protected Resource Metadata Discovery\n * Probes .well-known/oauth-protected-resource endpoint\n */\n\nimport { joinWellKnown, normalizeUrl } from '../lib/url-utils.ts';\nimport { discoveryFetch, isLoopbackUrl, readDiscoveryJson } from './discovery-fetch.ts';\nimport type { AuthorizationServerMetadata, ProtectedResourceMetadata } from './types.ts';\n\n/** Returns `url`'s origin (protocol + host), or the original string if it doesn't parse. */\nfunction getOrigin(url: string): string {\n try {\n return new URL(url).origin;\n } catch {\n return url;\n }\n}\n\n/** Returns `url`'s pathname, or `''` for the root path or an unparseable URL. */\nfunction getPath(url: string): string {\n try {\n const parsed = new URL(url);\n return parsed.pathname === '/' ? '' : parsed.pathname;\n } catch {\n return '';\n }\n}\n\n/**\n * Discovers RFC 9728 Protected Resource Metadata: the `WWW-Authenticate`\n * header first, then `.well-known/oauth-protected-resource` at the origin root and, for a path-prefixed resource, its sub-path variant.\n *\n * @param resourceUrl - URL of the protected resource (e.g. `https://ai.todoist.net/mcp`).\n * @returns Discovered metadata, or `null` if none is found.\n */\nexport async function discoverProtectedResourceMetadata(resourceUrl: string): Promise<ProtectedResourceMetadata | null> {\n try {\n const normalizedResourceUrl = normalizeUrl(resourceUrl);\n // resourceUrl is the server the caller configured (never remote-supplied);\n // its loopback-ness is the trust signal every fetch below relies on.\n const allowLoopback = isLoopbackUrl(normalizedResourceUrl);\n const headerMetadata = await discoverProtectedResourceMetadataFromHeader(normalizedResourceUrl, allowLoopback);\n if (headerMetadata) return headerMetadata;\n\n // Strategy 0: Try path-local well-known (supports path-prefixed deployments like /outlook)\n const localWellKnownUrl = joinWellKnown(normalizedResourceUrl, '/.well-known/oauth-protected-resource');\n try {\n const response = await discoveryFetch(\n localWellKnownUrl,\n {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n },\n 'protected resource metadata (path-local)',\n { allowLoopback }\n );\n if (response.ok) {\n return await readDiscoveryJson<ProtectedResourceMetadata>(response, 'protected resource metadata (path-local)');\n }\n } catch {\n // Continue to origin-based discovery\n }\n\n const origin = getOrigin(normalizedResourceUrl);\n const path = getPath(normalizedResourceUrl);\n\n // Strategy 1: Try root location (REQUIRED by RFC 9728)\n const rootUrl = `${origin}/.well-known/oauth-protected-resource`;\n\n try {\n const response = await discoveryFetch(\n rootUrl,\n {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n },\n 'protected resource metadata (root)',\n { allowLoopback }\n );\n\n if (response.ok) {\n const metadata = await readDiscoveryJson<ProtectedResourceMetadata>(response, 'protected resource metadata (root)');\n // Check if the discovered resource matches what we're looking for\n if (metadata.resource === normalizedResourceUrl) {\n return metadata;\n }\n // If there's no path component, return root metadata\n // (e.g., looking for http://example.com and found it)\n if (!path) {\n return metadata;\n }\n // If requested URL starts with metadata.resource, the root metadata applies to sub-paths\n // (e.g., looking for http://example.com/api/v1/mcp, found http://example.com)\n if (normalizedResourceUrl.startsWith(metadata.resource)) {\n // Still try sub-path location to see if there's more specific metadata\n // But save root metadata as fallback\n const rootMetadata = metadata;\n\n // Try sub-path location for more specific metadata\n const subPathUrl = `${origin}/.well-known/oauth-protected-resource${path}`;\n try {\n const subPathResponse = await discoveryFetch(\n subPathUrl,\n {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n },\n 'protected resource metadata (sub-path)',\n { allowLoopback }\n );\n if (subPathResponse.ok) {\n return await readDiscoveryJson<ProtectedResourceMetadata>(subPathResponse, 'protected resource metadata (sub-path)');\n }\n } catch {\n // Sub-path failed, use root metadata\n }\n\n // Return root metadata as it applies to this resource\n return rootMetadata;\n }\n // Otherwise, try sub-path location before giving up\n }\n } catch {\n // Continue to sub-path location\n }\n\n // Strategy 2: Try sub-path location (MCP spec extension)\n // Only try if there's a path component\n if (path) {\n const subPathUrl = `${origin}/.well-known/oauth-protected-resource${path}`;\n\n try {\n const response = await discoveryFetch(\n subPathUrl,\n {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n },\n 'protected resource metadata (sub-path)',\n { allowLoopback }\n );\n\n if (response.ok) {\n return await readDiscoveryJson<ProtectedResourceMetadata>(response, 'protected resource metadata (sub-path)');\n }\n } catch {\n // Fall through to return null\n }\n }\n\n // Neither location found or resource didn't match\n return null;\n } catch (_error) {\n // Network error, invalid URL, or other failure\n return null;\n }\n}\n\nasync function discoverProtectedResourceMetadataFromHeader(resourceUrl: string, allowLoopback: boolean): Promise<ProtectedResourceMetadata | null> {\n try {\n const response = await fetch(resourceUrl, {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n });\n\n let header = response.headers.get('www-authenticate');\n if (!header) {\n const postResponse = await fetch(resourceUrl, {\n method: 'POST',\n headers: { Accept: 'application/json', Connection: 'close', 'Content-Type': 'application/json' },\n body: '{}',\n });\n header = postResponse.headers.get('www-authenticate');\n }\n\n if (!header) return null;\n\n const match = header.match(/resource_metadata=\"([^\"]+)\"/i);\n if (!match || !match[1]) return null;\n\n // metadataUrl is remote-server-chosen (the primary SSRF vector here);\n // allowLoopback reflects trust in resourceUrl, not in metadataUrl.\n const metadataUrl = match[1];\n const metadataResponse = await discoveryFetch(\n metadataUrl,\n {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n },\n 'resource_metadata URL',\n { allowLoopback }\n );\n\n if (!metadataResponse.ok) {\n return null;\n }\n\n return await readDiscoveryJson<ProtectedResourceMetadata>(metadataResponse, 'resource_metadata URL');\n } catch (_error) {\n return null;\n }\n}\n\n/**\n * Discovers RFC 8414 Authorization Server Metadata at\n * `.well-known/oauth-authorization-server`, path-local variant first.\n *\n * @param authServerUrl - URL of the authorization server (typically from RFC 9728 discovery).\n * @param options.allowLoopback - Loopback trust grant computed from the server the caller is actually talking to, never from `authServerUrl` itself. Defaults to `false`.\n * @returns Discovered metadata, or `null` if none is found.\n */\nexport async function discoverAuthorizationServerMetadata(authServerUrl: string, options: { allowLoopback?: boolean } = {}): Promise<AuthorizationServerMetadata | null> {\n const { allowLoopback = false } = options;\n try {\n const normalizedAuthServerUrl = normalizeUrl(authServerUrl);\n const localWellKnownUrl = joinWellKnown(normalizedAuthServerUrl, '/.well-known/oauth-authorization-server');\n const localResponse = await discoveryFetch(\n localWellKnownUrl,\n {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n },\n 'authorization server metadata (path-local)',\n { allowLoopback }\n );\n\n if (localResponse.ok) {\n return await readDiscoveryJson<AuthorizationServerMetadata>(localResponse, 'authorization server metadata (path-local)');\n }\n\n const origin = getOrigin(normalizedAuthServerUrl);\n const wellKnownUrl = `${origin}/.well-known/oauth-authorization-server`;\n\n const response = await discoveryFetch(\n wellKnownUrl,\n {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n },\n 'authorization server metadata',\n { allowLoopback }\n );\n\n if (!response.ok) {\n return null;\n }\n\n return await readDiscoveryJson<AuthorizationServerMetadata>(response, 'authorization server metadata');\n } catch (_error) {\n return null;\n }\n}\n\n/**\n * Discover OAuth Authorization Server Issuer from resource response (RFC 9207)\n *\n * @param resourceUrl - URL of the protected resource\n * @returns Issuer URL if present in WWW-Authenticate header, null otherwise\n */\nexport async function discoverAuthorizationServerIssuer(resourceUrl: string): Promise<string | null> {\n try {\n const response = await fetch(resourceUrl, {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n });\n\n const header = response.headers.get('www-authenticate');\n if (!header) return null;\n\n const match = header.match(/(?:authorization_server|issuer)=\"([^\"]+)\"/i);\n if (!match) return null;\n\n return match[1] ?? null;\n } catch (_error) {\n return null;\n }\n}\n"],"names":["discoverAuthorizationServerIssuer","discoverAuthorizationServerMetadata","discoverProtectedResourceMetadata","getOrigin","url","URL","origin","getPath","parsed","pathname","resourceUrl","normalizedResourceUrl","allowLoopback","headerMetadata","localWellKnownUrl","response","path","rootUrl","metadata","rootMetadata","subPathUrl","subPathResponse","_error","normalizeUrl","isLoopbackUrl","discoverProtectedResourceMetadataFromHeader","joinWellKnown","discoveryFetch","method","headers","Accept","Connection","ok","readDiscoveryJson","resource","startsWith","header","postResponse","match","metadataUrl","metadataResponse","fetch","get","body","authServerUrl","options","normalizedAuthServerUrl","localResponse","wellKnownUrl"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/client/src/auth/rfc9728-discovery.ts"],"sourcesContent":["/**\n * RFC 9728 Protected Resource Metadata Discovery\n * Probes .well-known/oauth-protected-resource endpoint\n */\n\nimport { joinWellKnown, normalizeUrl } from '../lib/url-utils.ts';\nimport { discoveryFetch, isLoopbackUrl, readDiscoveryJson, throwIfAborted } from './discovery-fetch.ts';\nimport type { AuthorizationServerMetadata, ProtectedResourceMetadata } from './types.ts';\n\n/** Returns `url`'s origin (protocol + host), or the original string if it doesn't parse. */\nfunction getOrigin(url: string): string {\n try {\n return new URL(url).origin;\n } catch {\n return url;\n }\n}\n\n/** Returns `url`'s pathname, or `''` for the root path or an unparseable URL. */\nfunction getPath(url: string): string {\n try {\n const parsed = new URL(url);\n return parsed.pathname === '/' ? '' : parsed.pathname;\n } catch {\n return '';\n }\n}\n\n/**\n * Discovers RFC 9728 Protected Resource Metadata: the `WWW-Authenticate`\n * header first, then `.well-known/oauth-protected-resource` at the origin root and, for a path-prefixed resource, its sub-path variant.\n *\n * @param resourceUrl - URL of the protected resource (e.g. `https://ai.todoist.net/mcp`).\n * @returns Discovered metadata, or `null` if none is found.\n */\nexport async function discoverProtectedResourceMetadata(resourceUrl: string, options: { signal?: AbortSignal } = {}): Promise<ProtectedResourceMetadata | null> {\n const { signal } = options;\n try {\n throwIfAborted(signal);\n const normalizedResourceUrl = normalizeUrl(resourceUrl);\n // resourceUrl is the server the caller configured (never remote-supplied);\n // its loopback-ness is the trust signal every fetch below relies on.\n const allowLoopback = isLoopbackUrl(normalizedResourceUrl);\n const headerMetadata = await discoverProtectedResourceMetadataFromHeader(normalizedResourceUrl, allowLoopback, signal);\n if (headerMetadata) return headerMetadata;\n\n // Strategy 0: Try path-local well-known (supports path-prefixed deployments like /outlook)\n const localWellKnownUrl = joinWellKnown(normalizedResourceUrl, '/.well-known/oauth-protected-resource');\n try {\n const response = await discoveryFetch(\n localWellKnownUrl,\n {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n signal,\n },\n 'protected resource metadata (path-local)',\n { allowLoopback }\n );\n if (response.ok) {\n return await readDiscoveryJson<ProtectedResourceMetadata>(response, 'protected resource metadata (path-local)');\n }\n } catch {\n throwIfAborted(signal);\n // Continue to origin-based discovery\n }\n\n const origin = getOrigin(normalizedResourceUrl);\n const path = getPath(normalizedResourceUrl);\n\n // Strategy 1: Try root location (REQUIRED by RFC 9728)\n const rootUrl = `${origin}/.well-known/oauth-protected-resource`;\n\n try {\n const response = await discoveryFetch(\n rootUrl,\n {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n signal,\n },\n 'protected resource metadata (root)',\n { allowLoopback }\n );\n\n if (response.ok) {\n const metadata = await readDiscoveryJson<ProtectedResourceMetadata>(response, 'protected resource metadata (root)');\n // Check if the discovered resource matches what we're looking for\n if (metadata.resource === normalizedResourceUrl) {\n return metadata;\n }\n // If there's no path component, return root metadata\n // (e.g., looking for http://example.com and found it)\n if (!path) {\n return metadata;\n }\n // If requested URL starts with metadata.resource, the root metadata applies to sub-paths\n // (e.g., looking for http://example.com/api/v1/mcp, found http://example.com)\n if (normalizedResourceUrl.startsWith(metadata.resource)) {\n // Still try sub-path location to see if there's more specific metadata\n // But save root metadata as fallback\n const rootMetadata = metadata;\n\n // Try sub-path location for more specific metadata\n const subPathUrl = `${origin}/.well-known/oauth-protected-resource${path}`;\n try {\n const subPathResponse = await discoveryFetch(\n subPathUrl,\n {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n signal,\n },\n 'protected resource metadata (sub-path)',\n { allowLoopback }\n );\n if (subPathResponse.ok) {\n return await readDiscoveryJson<ProtectedResourceMetadata>(subPathResponse, 'protected resource metadata (sub-path)');\n }\n } catch {\n throwIfAborted(signal);\n // Sub-path failed, use root metadata\n }\n\n // Return root metadata as it applies to this resource\n return rootMetadata;\n }\n // Otherwise, try sub-path location before giving up\n }\n } catch {\n throwIfAborted(signal);\n // Continue to sub-path location\n }\n\n // Strategy 2: Try sub-path location (MCP spec extension)\n // Only try if there's a path component\n if (path) {\n const subPathUrl = `${origin}/.well-known/oauth-protected-resource${path}`;\n\n try {\n const response = await discoveryFetch(\n subPathUrl,\n {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n signal,\n },\n 'protected resource metadata (sub-path)',\n { allowLoopback }\n );\n\n if (response.ok) {\n return await readDiscoveryJson<ProtectedResourceMetadata>(response, 'protected resource metadata (sub-path)');\n }\n } catch {\n throwIfAborted(signal);\n // Fall through to return null\n }\n }\n\n // Neither location found or resource didn't match\n return null;\n } catch (_error) {\n throwIfAborted(signal);\n // Network error, invalid URL, or other failure\n return null;\n }\n}\n\nasync function discoverProtectedResourceMetadataFromHeader(resourceUrl: string, allowLoopback: boolean, signal?: AbortSignal): Promise<ProtectedResourceMetadata | null> {\n try {\n throwIfAborted(signal);\n const response = await fetch(resourceUrl, {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n signal,\n });\n\n let header = response.headers.get('www-authenticate');\n if (!header) {\n const postResponse = await fetch(resourceUrl, {\n method: 'POST',\n headers: { Accept: 'application/json', Connection: 'close', 'Content-Type': 'application/json' },\n body: '{}',\n signal,\n });\n header = postResponse.headers.get('www-authenticate');\n }\n\n if (!header) return null;\n\n const match = header.match(/resource_metadata=\"([^\"]+)\"/i);\n if (!match || !match[1]) return null;\n\n // metadataUrl is remote-server-chosen (the primary SSRF vector here);\n // allowLoopback reflects trust in resourceUrl, not in metadataUrl.\n const metadataUrl = match[1];\n const metadataResponse = await discoveryFetch(\n metadataUrl,\n {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n signal,\n },\n 'resource_metadata URL',\n { allowLoopback }\n );\n\n if (!metadataResponse.ok) {\n return null;\n }\n\n return await readDiscoveryJson<ProtectedResourceMetadata>(metadataResponse, 'resource_metadata URL');\n } catch (_error) {\n throwIfAborted(signal);\n return null;\n }\n}\n\n/**\n * Discovers RFC 8414 Authorization Server Metadata at\n * `.well-known/oauth-authorization-server`, path-local variant first.\n *\n * @param authServerUrl - URL of the authorization server (typically from RFC 9728 discovery).\n * @param options.allowLoopback - Loopback trust grant computed from the server the caller is actually talking to, never from `authServerUrl` itself. Defaults to `false`.\n * @returns Discovered metadata, or `null` if none is found.\n */\nexport async function discoverAuthorizationServerMetadata(authServerUrl: string, options: { allowLoopback?: boolean; signal?: AbortSignal } = {}): Promise<AuthorizationServerMetadata | null> {\n const { allowLoopback = false, signal } = options;\n try {\n throwIfAborted(signal);\n const normalizedAuthServerUrl = normalizeUrl(authServerUrl);\n const localWellKnownUrl = joinWellKnown(normalizedAuthServerUrl, '/.well-known/oauth-authorization-server');\n const localResponse = await discoveryFetch(\n localWellKnownUrl,\n {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n signal,\n },\n 'authorization server metadata (path-local)',\n { allowLoopback }\n );\n\n if (localResponse.ok) {\n return await readDiscoveryJson<AuthorizationServerMetadata>(localResponse, 'authorization server metadata (path-local)');\n }\n\n const origin = getOrigin(normalizedAuthServerUrl);\n const wellKnownUrl = `${origin}/.well-known/oauth-authorization-server`;\n\n const response = await discoveryFetch(\n wellKnownUrl,\n {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n signal,\n },\n 'authorization server metadata',\n { allowLoopback }\n );\n\n if (!response.ok) {\n return null;\n }\n\n return await readDiscoveryJson<AuthorizationServerMetadata>(response, 'authorization server metadata');\n } catch (_error) {\n throwIfAborted(signal);\n return null;\n }\n}\n\n/**\n * Discover OAuth Authorization Server Issuer from resource response (RFC 9207)\n *\n * @param resourceUrl - URL of the protected resource\n * @returns Issuer URL if present in WWW-Authenticate header, null otherwise\n */\nexport async function discoverAuthorizationServerIssuer(resourceUrl: string, options: { signal?: AbortSignal } = {}): Promise<string | null> {\n const { signal } = options;\n try {\n throwIfAborted(signal);\n const response = await fetch(resourceUrl, {\n method: 'GET',\n headers: { Accept: 'application/json', Connection: 'close' },\n signal,\n });\n\n const header = response.headers.get('www-authenticate');\n if (!header) return null;\n\n const match = header.match(/(?:authorization_server|issuer)=\"([^\"]+)\"/i);\n if (!match) return null;\n\n return match[1] ?? null;\n } catch (_error) {\n throwIfAborted(signal);\n return null;\n }\n}\n"],"names":["discoverAuthorizationServerIssuer","discoverAuthorizationServerMetadata","discoverProtectedResourceMetadata","getOrigin","url","URL","origin","getPath","parsed","pathname","resourceUrl","options","signal","normalizedResourceUrl","allowLoopback","headerMetadata","localWellKnownUrl","response","path","rootUrl","metadata","rootMetadata","subPathUrl","subPathResponse","_error","throwIfAborted","normalizeUrl","isLoopbackUrl","discoverProtectedResourceMetadataFromHeader","joinWellKnown","discoveryFetch","method","headers","Accept","Connection","ok","readDiscoveryJson","resource","startsWith","header","postResponse","match","metadataUrl","metadataResponse","fetch","get","body","authServerUrl","normalizedAuthServerUrl","localResponse","wellKnownUrl"],"mappings":"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"}
@@ -142,11 +142,15 @@ export interface DcrRegistrationOptions {
142
142
  * remote-controlled AS metadata). Defaults to `false`.
143
143
  */
144
144
  allowLoopback?: boolean;
145
+ /** Cancels an in-progress registration request. */
146
+ signal?: AbortSignal;
145
147
  }
146
148
  /**
147
149
  * Options for OAuth authorization flow
148
150
  */
149
151
  export interface OAuthFlowOptions {
152
+ /** Cancels an in-progress authorization and closes its callback listener. */
153
+ signal?: AbortSignal;
150
154
  /** Port for OAuth callback listener (required - use get-port to find available port) */
151
155
  port: number;
152
156
  /** Issuer identifier discovered before the flow starts; the `iss` in the authorization response must match it (RFC 9207) */
@@ -142,11 +142,15 @@ export interface DcrRegistrationOptions {
142
142
  * remote-controlled AS metadata). Defaults to `false`.
143
143
  */
144
144
  allowLoopback?: boolean;
145
+ /** Cancels an in-progress registration request. */
146
+ signal?: AbortSignal;
145
147
  }
146
148
  /**
147
149
  * Options for OAuth authorization flow
148
150
  */
149
151
  export interface OAuthFlowOptions {
152
+ /** Cancels an in-progress authorization and closes its callback listener. */
153
+ signal?: AbortSignal;
150
154
  /** Port for OAuth callback listener (required - use get-port to find available port) */
151
155
  port: number;
152
156
  /** Issuer identifier discovered before the flow starts; the `iss` in the authorization response must match it (RFC 9207) */