@introspection-ai/recipes 0.19.2 → 0.20.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 (116) hide show
  1. package/dist/agents.d.ts +17 -1
  2. package/dist/agents.d.ts.map +1 -1
  3. package/dist/agents.js +15 -1
  4. package/dist/agents.js.map +1 -1
  5. package/dist/child-agent.d.ts +3 -1
  6. package/dist/child-agent.d.ts.map +1 -1
  7. package/dist/child-agent.js +1 -0
  8. package/dist/child-agent.js.map +1 -1
  9. package/dist/mcp-chunks/{auth-command-3K7V3VCW.js → auth-command-IQ4J332A.js} +26 -38
  10. package/dist/mcp-chunks/call-arguments-MCCBPJMY.js +15 -0
  11. package/dist/mcp-chunks/{call-command-OFPHPFM5.js → call-command-WPQ3MDOE.js} +74 -40
  12. package/dist/mcp-chunks/{chunk-LNSUME65.js → chunk-24FKKIXI.js} +29 -13
  13. package/dist/mcp-chunks/{chunk-HTZ2URXW.js → chunk-2CTVPSHF.js} +3 -3
  14. package/dist/mcp-chunks/{chunk-NCXEJ35U.js → chunk-3FB4ZJ4Z.js} +4 -4
  15. package/dist/mcp-chunks/{chunk-P3RN22HQ.js → chunk-3MIFROM7.js} +3 -2
  16. package/dist/mcp-chunks/{chunk-GFYTST6N.js → chunk-54UGGTOX.js} +1 -1
  17. package/dist/mcp-chunks/{chunk-L4VKBFYI.js → chunk-5HQYKAE7.js} +101 -16
  18. package/dist/mcp-chunks/{chunk-E6RVTWJY.js → chunk-5YBCGQA7.js} +1 -1
  19. package/dist/mcp-chunks/{chunk-6D6KPSXN.js → chunk-AJPFOQLF.js} +1 -1
  20. package/dist/mcp-chunks/{chunk-C2PQFLWS.js → chunk-B4XFULJ6.js} +15 -6
  21. package/dist/mcp-chunks/{chunk-HAO6PL7Z.js → chunk-DIIFWDZ7.js} +7 -7
  22. package/dist/mcp-chunks/{chunk-55JIHDU3.js → chunk-EEYUPDRX.js} +1 -1
  23. package/dist/mcp-chunks/{chunk-7A63PAGP.js → chunk-ETYYCEQF.js} +21 -5
  24. package/dist/mcp-chunks/{chunk-E6T37ED6.js → chunk-FNQV2ONG.js} +2 -2
  25. package/dist/mcp-chunks/{chunk-2JHHONW4.js → chunk-FW5QVG6V.js} +1 -1
  26. package/dist/mcp-chunks/{chunk-YCYSQA5V.js → chunk-FZ7K5EGL.js} +5 -5
  27. package/dist/mcp-chunks/{chunk-KSMY7PXI.js → chunk-G5C4WVDQ.js} +1 -1
  28. package/dist/mcp-chunks/{chunk-XRGLP3Z2.js → chunk-GPCLDF6U.js} +1 -1
  29. package/dist/mcp-chunks/{chunk-KSGYBW3F.js → chunk-GQHTGV5E.js} +72 -22
  30. package/dist/mcp-chunks/{chunk-64EP2BVO.js → chunk-HULRE4D2.js} +1 -1
  31. package/dist/mcp-chunks/{chunk-UENXT3NE.js → chunk-ILSK6AWI.js} +1 -1
  32. package/dist/mcp-chunks/{chunk-RBVYCKCD.js → chunk-ILULMM2E.js} +2 -2
  33. package/dist/mcp-chunks/{chunk-NZOIX6XW.js → chunk-ITJWLDF5.js} +2 -2
  34. package/dist/mcp-chunks/{chunk-XUF6KARU.js → chunk-IUFDFNNP.js} +1 -1
  35. package/dist/mcp-chunks/chunk-JJG2OEHI.js +12 -0
  36. package/dist/mcp-chunks/{chunk-YPJ5EHXR.js → chunk-K56RW4HB.js} +4 -4
  37. package/dist/mcp-chunks/{chunk-H7F5RZXS.js → chunk-KJ3CMHWS.js} +2 -1
  38. package/dist/mcp-chunks/{chunk-WXBPMFSN.js → chunk-LI4L4FOV.js} +91 -34
  39. package/dist/mcp-chunks/{chunk-ETWN4IIA.js → chunk-LYZRCACV.js} +6 -6
  40. package/dist/mcp-chunks/{chunk-ZBFZ5UFE.js → chunk-MDVNQ4HM.js} +3 -1
  41. package/dist/mcp-chunks/{chunk-3IZQW4H4.js → chunk-MNAVFYYV.js} +212 -18
  42. package/dist/mcp-chunks/{chunk-7DH57OKF.js → chunk-MWD5PZ4G.js} +2 -2
  43. package/dist/mcp-chunks/{chunk-YSPT6F7K.js → chunk-N2HVJU7X.js} +1 -1
  44. package/dist/mcp-chunks/{chunk-WWO5WGH5.js → chunk-NACLB5YH.js} +5 -5
  45. package/dist/mcp-chunks/{chunk-QJACOI2W.js → chunk-NMF5S5DC.js} +4 -2
  46. package/dist/mcp-chunks/{chunk-54EWGONA.js → chunk-NPU7EMGE.js} +10 -6
  47. package/dist/mcp-chunks/{chunk-SFREPU3D.js → chunk-NSZY5WLR.js} +1 -1
  48. package/dist/mcp-chunks/{chunk-7RDLPFIO.js → chunk-QK6LUI5Q.js} +2 -2
  49. package/dist/mcp-chunks/{chunk-XTL4MHFH.js → chunk-QONTHFPO.js} +11 -7
  50. package/dist/mcp-chunks/{chunk-YTKRAHO6.js → chunk-RDOD354S.js} +4 -4
  51. package/dist/mcp-chunks/{chunk-2MEHGB7D.js → chunk-RXSZ2W6Y.js} +1 -1
  52. package/dist/mcp-chunks/{chunk-UHOKCTZT.js → chunk-RYAUNXFA.js} +1 -1
  53. package/dist/mcp-chunks/{chunk-GIF7LOYU.js → chunk-SCD2NAX5.js} +2 -2
  54. package/dist/mcp-chunks/{chunk-F3LL4EBL.js → chunk-SHZVDY6Z.js} +1 -1
  55. package/dist/mcp-chunks/{chunk-CNDY7WB4.js → chunk-TAVMVGD5.js} +2 -2
  56. package/dist/mcp-chunks/{chunk-JAKI24KR.js → chunk-U23EY5DN.js} +1 -1
  57. package/dist/mcp-chunks/{chunk-SB2UUURE.js → chunk-UAIJZBGL.js} +10 -10
  58. package/dist/mcp-chunks/{chunk-PKOJCYNA.js → chunk-UDG3RHKX.js} +2 -2
  59. package/dist/mcp-chunks/{chunk-CA5WFJZA.js → chunk-VC6SKXTI.js} +1 -1
  60. package/dist/mcp-chunks/chunk-VJ2TSA5R.js +818 -0
  61. package/dist/mcp-chunks/{chunk-FWP4RACK.js → chunk-VREKED5H.js} +2 -2
  62. package/dist/mcp-chunks/{chunk-2FSDGCHW.js → chunk-WKUCIR2F.js} +374 -527
  63. package/dist/mcp-chunks/chunk-XRRT3SZM.js +1931 -0
  64. package/dist/mcp-chunks/{chunk-GSZOK5TS.js → chunk-YDJ7E2PH.js} +3 -3
  65. package/dist/mcp-chunks/{chunk-LICH4Q7A.js → chunk-ZI44YPFF.js} +4 -4
  66. package/dist/mcp-chunks/{chunk-DEUU7WSN.js → chunk-ZNKNF2BV.js} +2 -2
  67. package/dist/mcp-chunks/{chunk-DXPHJFSA.js → chunk-ZSKQI4TS.js} +4 -4
  68. package/dist/mcp-chunks/{cli-E4P6SZLQ.js → cli-Z7KV4PCE.js} +70 -69
  69. package/dist/mcp-chunks/client-B3FMQNGF.js +21 -0
  70. package/dist/mcp-chunks/{config-command-MWF3RHPQ.js → config-command-XXCDOB3M.js} +27 -27
  71. package/dist/mcp-chunks/daemon-command-BAREANTC.js +35 -0
  72. package/dist/mcp-chunks/{dist-ZIPUENTM.js → dist-V4UB7RTR.js} +547 -402
  73. package/dist/mcp-chunks/{emit-ts-command-GOVJJ64A.js → emit-ts-command-FEHTMXXB.js} +16 -16
  74. package/dist/mcp-chunks/{generate-cli-runner-L5OQIMEY.js → generate-cli-runner-OA6XL77R.js} +49 -42
  75. package/dist/mcp-chunks/{inspect-cli-command-7OMMREPE.js → inspect-cli-command-UQKKE5VO.js} +9 -9
  76. package/dist/mcp-chunks/{launch-BWXPLPB7.js → launch-KMPDJOUH.js} +1 -1
  77. package/dist/mcp-chunks/{lifecycle-B5UC65PT.js → lifecycle-R3IP22MJ.js} +1 -1
  78. package/dist/mcp-chunks/{list-command-ZO4HVFQK.js → list-command-7ENYKBF6.js} +31 -31
  79. package/dist/mcp-chunks/{output-utils-M3TJ2N4M.js → output-utils-N75TOWBX.js} +3 -3
  80. package/dist/mcp-chunks/{prompt-CH6TK0bC-C7OTKGRD.js → prompt-CH6TK0bC-NSBYYJZH.js} +1 -1
  81. package/dist/mcp-chunks/{record-command-VD3HUQIC.js → record-command-XHPCL7IG.js} +5 -5
  82. package/dist/mcp-chunks/{replay-command-AX6IN7YD.js → replay-command-CB56L3ZA.js} +6 -6
  83. package/dist/mcp-chunks/{resource-command-JEZ2DW2G.js → resource-command-STEBHVT7.js} +9 -9
  84. package/dist/mcp-chunks/{result-utils-3YHYGS45.js → result-utils-UONY2KNY.js} +3 -3
  85. package/dist/mcp-chunks/runtime-Z45IVD24.js +39 -0
  86. package/dist/mcp-chunks/{runtime-wrapper-UREU7GC3.js → runtime-wrapper-SYYAQVO6.js} +6 -6
  87. package/dist/mcp-chunks/{serve-command-M47YZ6JN.js → serve-command-VYSFRZFE.js} +35 -27
  88. package/dist/mcp-chunks/{timeouts-THZRYP4B.js → timeouts-T3JP3MUF.js} +5 -3
  89. package/dist/mcp-chunks/{vault-command-53P7MLCB.js → vault-command-AJ3X7GDI.js} +58 -12
  90. package/dist/mcp-chunks/{webapi-PHEQZQKH.js → webapi-BLTNWSB2.js} +68 -60
  91. package/dist/mcp-daemon.js +30 -28
  92. package/dist/mcp-run-worker.js +30 -28
  93. package/dist/mcp.d.ts.map +1 -1
  94. package/dist/mcp.js +2 -1
  95. package/dist/mcp.js.map +1 -1
  96. package/dist/pi-extension.d.ts +3 -0
  97. package/dist/pi-extension.d.ts.map +1 -1
  98. package/dist/pi-extension.js +27 -0
  99. package/dist/pi-extension.js.map +1 -1
  100. package/dist/run-controller.d.ts +3 -1
  101. package/dist/run-controller.d.ts.map +1 -1
  102. package/dist/run-controller.js +10 -0
  103. package/dist/run-controller.js.map +1 -1
  104. package/dist/session.d.ts +3 -1
  105. package/dist/session.d.ts.map +1 -1
  106. package/dist/session.js +4 -1
  107. package/dist/session.js.map +1 -1
  108. package/docs/host-api.md +12 -0
  109. package/docs/pi-extension.md +10 -0
  110. package/package.json +11 -11
  111. package/vendor/introspection-recipe-check/win32-x64/introspection-recipe-check.exe +0 -0
  112. package/dist/mcp-chunks/call-arguments-TX3F2TEE.js +0 -15
  113. package/dist/mcp-chunks/chunk-SRZZQ6TL.js +0 -266
  114. package/dist/mcp-chunks/client-2EJC4PLL.js +0 -18
  115. package/dist/mcp-chunks/daemon-command-6CJ26MKI.js +0 -33
  116. package/dist/mcp-chunks/runtime-HSYVOME7.js +0 -37
@@ -12,31 +12,35 @@ import {
12
12
  sameOAuthTokenGeneration,
13
13
  sameOAuthTokenValue,
14
14
  saveVaultEntry,
15
+ vaultCredentialKeys,
15
16
  withHiddenOAuthClientGeneration,
16
17
  withHiddenOAuthTokenGeneration,
17
18
  withOAuthClientGeneration,
18
19
  withOAuthTokenGeneration
19
- } from "./chunk-C2PQFLWS.js";
20
+ } from "./chunk-B4XFULJ6.js";
20
21
  import {
21
22
  checkResourceAllowed,
22
23
  discoverOAuthServerInfo,
23
24
  refreshAuthorization,
24
25
  resourceUrlFromServerUrl
25
- } from "./chunk-YPJ5EHXR.js";
26
+ } from "./chunk-K56RW4HB.js";
26
27
  import {
28
+ canonicalizeFilePath,
29
+ isFileLockTimeoutError,
27
30
  readJsonFile,
28
31
  withFileLock,
29
32
  writeJsonFile,
30
33
  writeTextFileAtomic
31
- } from "./chunk-7A63PAGP.js";
34
+ } from "./chunk-ETYYCEQF.js";
32
35
  import {
33
- legacyMcporterDir
34
- } from "./chunk-FWP4RACK.js";
36
+ legacyMcporterDir,
37
+ mcporterDir
38
+ } from "./chunk-VREKED5H.js";
35
39
 
36
- // node_modules/.pnpm/mcporter@0.13.0/node_modules/mcporter/dist/oauth-persistence.js
40
+ // node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/oauth-persistence.js
37
41
  import fs2 from "node:fs/promises";
38
42
 
39
- // node_modules/.pnpm/mcporter@0.13.0/node_modules/mcporter/dist/oauth-persistence-stores.js
43
+ // node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/oauth-persistence-stores.js
40
44
  import fs from "node:fs/promises";
41
45
  import os from "node:os";
42
46
  import path from "node:path";
@@ -441,6 +445,10 @@ var CompositePersistence = class {
441
445
  this.recoveryTokenSource = result.source;
442
446
  return result.value;
443
447
  }
448
+ async readTokensPerStore() {
449
+ const perStore = await Promise.all(this.stores.map((store) => store.readTokens()));
450
+ return perStore.filter((tokens) => tokens !== void 0);
451
+ }
444
452
  async saveTokens(tokens) {
445
453
  const stored = prepareStoredTokens(tokens);
446
454
  await Promise.all(this.stores.map((store) => store.saveTokens(stored)));
@@ -598,10 +606,10 @@ async function clearLegacyOAuthArtifacts(definition, logger, scope) {
598
606
  }));
599
607
  }
600
608
 
601
- // node_modules/.pnpm/mcporter@0.13.0/node_modules/mcporter/dist/oauth-token-refresh.js
609
+ // node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/oauth-token-refresh.js
602
610
  import { Buffer } from "node:buffer";
603
611
 
604
- // node_modules/.pnpm/mcporter@0.13.0/node_modules/mcporter/dist/oauth-client-info.js
612
+ // node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/oauth-client-info.js
605
613
  function buildStaticClientInformation(definition, options = {}) {
606
614
  if (!definition.oauthClientId) {
607
615
  return void 0;
@@ -627,10 +635,121 @@ function resolveOAuthClientSecret(definition, options = {}) {
627
635
  return definition.oauthClientSecret;
628
636
  }
629
637
 
630
- // node_modules/.pnpm/mcporter@0.13.0/node_modules/mcporter/dist/oauth-token-refresh.js
638
+ // node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/oauth-refresh-lock.js
639
+ import { AsyncLocalStorage } from "node:async_hooks";
640
+ import crypto from "node:crypto";
641
+ import path2 from "node:path";
642
+ var REFRESH_LOCK_DIR = "refresh-locks";
643
+ var LOCK_LABEL_MAX = 40;
644
+ var IDENTITY_HASH_LENGTH = 16;
645
+ var TIMEOUT_OVERRIDE_ENV = "MCPORTER_TEST_REFRESH_LOCK_TIMEOUT_MS";
646
+ var heldLockPaths = new AsyncLocalStorage();
647
+ function refreshLockDir() {
648
+ return path2.join(mcporterDir("data"), REFRESH_LOCK_DIR);
649
+ }
650
+ async function refreshLockPaths(definition) {
651
+ const paths = [];
652
+ if (definition.tokenCacheDir) {
653
+ const tokenPath = await canonicalizeFilePath(path2.join(definition.tokenCacheDir, "tokens.json"));
654
+ paths.push(lockPathFor(path2.basename(path2.dirname(tokenPath)), `dir:${tokenPath}`));
655
+ }
656
+ for (const vaultKey of await vaultCredentialKeys(definition)) {
657
+ paths.push(lockPathFor(vaultKey.split("|")[0] ?? "", `vault:${vaultKey}`));
658
+ }
659
+ return [...new Set(paths)].toSorted();
660
+ }
661
+ async function withRefreshLock(definition, task, options = {}) {
662
+ const lockPaths = await refreshLockPaths(definition);
663
+ return await acquireAll(lockPaths, task, resolveTimeoutMs(options.timeoutMs));
664
+ }
665
+ async function acquireAll(lockPaths, task, timeoutMs) {
666
+ const held = heldLockPaths.getStore();
667
+ const pending = held ? lockPaths.filter((lockPath) => !held.has(lockPath)) : lockPaths;
668
+ if (pending.length === 0) {
669
+ return await task();
670
+ }
671
+ const nextHeld = /* @__PURE__ */ new Set([...held ?? [], ...pending]);
672
+ return await heldLockPaths.run(nextHeld, async () => {
673
+ let run = task;
674
+ for (const lockPath of pending.toReversed()) {
675
+ const inner = run;
676
+ run = async () => await withFileLock(lockPath, inner, timeoutMs === void 0 ? {} : { timeoutMs });
677
+ }
678
+ return await run();
679
+ });
680
+ }
681
+ function resolveTimeoutMs(explicit) {
682
+ if (explicit !== void 0) {
683
+ return explicit;
684
+ }
685
+ const raw = process.env[TIMEOUT_OVERRIDE_ENV];
686
+ if (raw === void 0 || raw.trim().length === 0) {
687
+ return void 0;
688
+ }
689
+ const parsed = Number(raw);
690
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : void 0;
691
+ }
692
+ function lockPathFor(label, identity) {
693
+ const digest = crypto.createHash("sha256").update(identity).digest("hex").slice(0, IDENTITY_HASH_LENGTH);
694
+ const safeLabel = filenameSafeLabel(label);
695
+ return path2.join(refreshLockDir(), safeLabel.length > 0 ? `${safeLabel}-${digest}` : digest);
696
+ }
697
+ function filenameSafeLabel(value) {
698
+ return value.replace(/[^A-Za-z0-9._-]+/g, "_").replace(/^[._-]+/, "").slice(0, LOCK_LABEL_MAX);
699
+ }
700
+
701
+ // node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/oauth-token-refresh.js
631
702
  var TOKEN_EXPIRY_SKEW_SECONDS = 60;
703
+ var TOKEN_REQUEST_TIMEOUT_MS = 1e4;
632
704
  var OAuthIssuerMismatchError = class extends Error {
633
705
  };
706
+ function decideUnderRefreshLock(original, latest, skewSeconds) {
707
+ if (!latest || typeof latest.access_token !== "string" || latest.access_token.trim().length === 0) {
708
+ return { kind: "gone" };
709
+ }
710
+ const adopted = cachedTokensChanged(original, latest);
711
+ if (!shouldRefreshCachedToken(latest, skewSeconds)) {
712
+ return { kind: "use", accessToken: latest.access_token, adopted };
713
+ }
714
+ if (typeof latest.refresh_token !== "string" || latest.refresh_token.trim().length === 0) {
715
+ return adopted ? { kind: "use", accessToken: latest.access_token, adopted } : { kind: "unrefreshable", accessToken: latest.access_token };
716
+ }
717
+ return { kind: "redeem", tokens: latest, refreshToken: latest.refresh_token };
718
+ }
719
+ async function reconcilePersistedTokens(definition, persistence, logger) {
720
+ const perStore = await persistence.readTokensPerStore?.();
721
+ if (!perStore || perStore.length <= 1) {
722
+ return await persistence.readTokens();
723
+ }
724
+ const candidates = perStore.filter((candidate) => typeof candidate.access_token === "string" && candidate.access_token.trim().length > 0);
725
+ const distinctRefreshTokens = new Set(candidates.map((candidate) => typeof candidate.refresh_token === "string" ? candidate.refresh_token : ""));
726
+ if (candidates.length <= 1 || distinctRefreshTokens.size <= 1) {
727
+ return await persistence.readTokens();
728
+ }
729
+ let selected = candidates[0];
730
+ for (const candidate of candidates.slice(1)) {
731
+ if (selected === void 0 || outranksForRedemption(candidate, selected)) {
732
+ selected = candidate;
733
+ }
734
+ }
735
+ logger?.debug?.(`Persisted OAuth stores for '${definition.name}' hold different refresh tokens; redeeming the newest.`);
736
+ return selected;
737
+ }
738
+ function outranksForRedemption(candidate, incumbent) {
739
+ const candidateDue = shouldRefreshCachedToken(candidate);
740
+ if (candidateDue !== shouldRefreshCachedToken(incumbent)) {
741
+ return !candidateDue;
742
+ }
743
+ const candidateExpiry = tokenExpirySeconds(candidate) ?? Number.NEGATIVE_INFINITY;
744
+ const incumbentExpiry = tokenExpirySeconds(incumbent) ?? Number.NEGATIVE_INFINITY;
745
+ return candidateExpiry > incumbentExpiry;
746
+ }
747
+ async function accessTokenAfterLockTimeout(definition, persistence, tokenKind, logger) {
748
+ const latest = await persistence.readTokens();
749
+ const accessToken = typeof latest?.access_token === "string" && latest.access_token.trim().length > 0 ? latest.access_token : void 0;
750
+ logger?.debug?.(`Timed out waiting for the ${tokenKind} refresh lock for '${definition.name}'; ${accessToken ? "returning the persisted access token, which may already be expired." : "no persisted access token remains."}`);
751
+ return accessToken;
752
+ }
634
753
  function tokenExpirySeconds(tokens) {
635
754
  const stored = tokens;
636
755
  for (const candidate of [stored.expires_at, stored.expiresAt]) {
@@ -646,6 +765,9 @@ function cachedTokensChanged(original, current) {
646
765
  }
647
766
  return !sameOAuthTokenGeneration(current, original);
648
767
  }
768
+ function oauthAccessTokenNeedsRefresh(tokens) {
769
+ return shouldRefreshCachedToken(tokens);
770
+ }
649
771
  function shouldRefreshCachedToken(tokens, skewSeconds = TOKEN_EXPIRY_SKEW_SECONDS) {
650
772
  const expiresAt = tokenExpirySeconds(tokens);
651
773
  if (expiresAt !== void 0) {
@@ -698,9 +820,11 @@ function oauthErrorCode(error) {
698
820
  if (!error || typeof error !== "object") {
699
821
  return void 0;
700
822
  }
701
- const { errorCode, name } = error;
702
- if (typeof errorCode === "string" && errorCode.length > 0) {
703
- return errorCode.toLowerCase();
823
+ const { errorCode, code, name } = error;
824
+ for (const candidate of [errorCode, code]) {
825
+ if (typeof candidate === "string" && candidate.length > 0) {
826
+ return candidate.toLowerCase();
827
+ }
704
828
  }
705
829
  if (typeof name === "string") {
706
830
  const normalized = name.toLowerCase();
@@ -730,6 +854,35 @@ async function readCachedAccessTokenWithPersistence(definition, persistence, log
730
854
  if (typeof tokens.refresh_token !== "string" || tokens.refresh_token.trim().length === 0) {
731
855
  return tokens.access_token;
732
856
  }
857
+ if (definition.command.kind !== "http") {
858
+ return tokens.access_token;
859
+ }
860
+ try {
861
+ return await withRefreshLock(definition, async () => await refreshCachedOAuthTokenUnderLock(definition, persistence, tokens, logger));
862
+ } catch (error) {
863
+ if (isFileLockTimeoutError(error)) {
864
+ return await accessTokenAfterLockTimeout(definition, persistence, "OAuth", logger);
865
+ }
866
+ throw error;
867
+ }
868
+ }
869
+ async function refreshCachedOAuthTokenUnderLock(definition, persistence, original, logger) {
870
+ const latest = await reconcilePersistedTokens(definition, persistence, logger);
871
+ const decision = decideUnderRefreshLock(original, latest, TOKEN_EXPIRY_SKEW_SECONDS);
872
+ if (decision.kind === "gone") {
873
+ logger?.debug?.(`Cached OAuth token for '${definition.name}' was cleared before its refresh could run.`);
874
+ return void 0;
875
+ }
876
+ if (decision.kind === "unrefreshable") {
877
+ return decision.accessToken;
878
+ }
879
+ if (decision.kind === "use") {
880
+ if (decision.adopted) {
881
+ logger?.debug?.(`Adopted the OAuth access token another refresh persisted first for '${definition.name}'.`);
882
+ }
883
+ return decision.accessToken;
884
+ }
885
+ const tokens = decision.tokens;
733
886
  let persistedClientInformation;
734
887
  try {
735
888
  const staticClientInformation = buildStaticClientInformation(definition);
@@ -742,13 +895,14 @@ async function readCachedAccessTokenWithPersistence(definition, persistence, log
742
895
  if (definition.command.kind !== "http") {
743
896
  return tokens.access_token;
744
897
  }
745
- const serverInfo = await discoverOAuthServerInfo(definition.command.url);
898
+ const serverInfo = await discoverOAuthServerInfo(definition.command.url, { fetchFn: boundedRefreshFetch });
746
899
  await assertRefreshIssuerBinding(definition, persistence, tokens, clientInformation, serverInfo.authorizationServerUrl);
747
900
  const resource = resourceForRefresh(definition.command.url, serverInfo.resourceMetadata);
748
901
  const refreshed = await refreshAuthorization(serverInfo.authorizationServerUrl, {
749
902
  metadata: serverInfo.authorizationServerMetadata,
750
903
  clientInformation,
751
- refreshToken: tokens.refresh_token,
904
+ refreshToken: decision.refreshToken,
905
+ fetchFn: boundedRefreshFetch,
752
906
  ...resource ? { resource } : {}
753
907
  });
754
908
  await persistence.saveTokens({ ...refreshed, issuer: serverInfo.authorizationServerUrl });
@@ -766,6 +920,12 @@ async function readCachedAccessTokenWithPersistence(definition, persistence, log
766
920
  return tokens.access_token;
767
921
  }
768
922
  }
923
+ function boundedRefreshFetch(input, init) {
924
+ return withRefreshRequestTimeout(fetch)(input, init);
925
+ }
926
+ function withRefreshRequestTimeout(fetchFn) {
927
+ return async (input, init) => await fetchFn(input, { ...init, signal: init?.signal ?? AbortSignal.timeout(TOKEN_REQUEST_TIMEOUT_MS) });
928
+ }
769
929
  async function recoverFromUnrecoverableRefresh(definition, persistence, tokens, unrecoverableCode, tokenKind, logger, rejectedClientInformation) {
770
930
  const clientToClear = unrecoverableCode === "invalid_grant" ? void 0 : rejectedClientInformation;
771
931
  await persistence.clearRejectedCredentials(tokens, clientToClear);
@@ -791,7 +951,36 @@ async function readExplicitRefreshableBearerToken(definition, persistence, token
791
951
  throw new Error(`Cached bearer token for '${definition.name}' is expired, but no refresh_token is available.`);
792
952
  }
793
953
  try {
794
- const refreshed = await refreshBearerToken(definition, tokens.refresh_token);
954
+ return await withRefreshLock(definition, async () => await refreshBearerTokenUnderLock(definition, persistence, tokens, skewSeconds, logger));
955
+ } catch (error) {
956
+ if (!isFileLockTimeoutError(error)) {
957
+ throw error;
958
+ }
959
+ const persisted = await accessTokenAfterLockTimeout(definition, persistence, "bearer", logger);
960
+ if (persisted) {
961
+ return persisted;
962
+ }
963
+ throw new Error(`Failed to refresh cached bearer token for '${definition.name}': timed out waiting for the refresh lock.`, { cause: error });
964
+ }
965
+ }
966
+ async function refreshBearerTokenUnderLock(definition, persistence, original, skewSeconds, logger) {
967
+ const latest = await reconcilePersistedTokens(definition, persistence, logger);
968
+ const decision = decideUnderRefreshLock(original, latest, skewSeconds);
969
+ if (decision.kind === "gone") {
970
+ throw new Error(`Cached bearer token for '${definition.name}' was cleared before its refresh could run.`);
971
+ }
972
+ if (decision.kind === "unrefreshable") {
973
+ throw new Error(`Cached bearer token for '${definition.name}' is expired, but no refresh_token is available.`);
974
+ }
975
+ if (decision.kind === "use") {
976
+ if (decision.adopted) {
977
+ logger?.debug?.(`Adopted the bearer access token another refresh persisted first for '${definition.name}'.`);
978
+ }
979
+ return decision.accessToken;
980
+ }
981
+ const tokens = decision.tokens;
982
+ try {
983
+ const refreshed = await refreshBearerToken(definition, decision.refreshToken);
795
984
  await persistence.saveTokens(refreshed);
796
985
  logger?.debug?.(`Refreshed bearer access token for '${definition.name}' (non-interactive).`);
797
986
  return refreshed.access_token;
@@ -840,7 +1029,7 @@ async function refreshBearerToken(definition, refreshToken) {
840
1029
  }
841
1030
  headers.authorization = `Basic ${Buffer.from(`${formEncodeCredential(clientId)}:${formEncodeCredential(clientSecret)}`).toString("base64")}`;
842
1031
  }
843
- const response = await fetch(refresh.tokenEndpoint, {
1032
+ const response = await boundedRefreshFetch(refresh.tokenEndpoint, {
844
1033
  method: "POST",
845
1034
  headers,
846
1035
  body
@@ -904,7 +1093,7 @@ function readClientSecret(definition, refreshClientSecretEnv) {
904
1093
  return resolveOAuthClientSecret(definition, { rejectBlank: true });
905
1094
  }
906
1095
 
907
- // node_modules/.pnpm/mcporter@0.13.0/node_modules/mcporter/dist/oauth-persistence.js
1096
+ // node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/oauth-persistence.js
908
1097
  async function buildOAuthPersistence(definition, logger) {
909
1098
  return await createOAuthPersistenceStores(definition, logger);
910
1099
  }
@@ -923,6 +1112,11 @@ async function readCachedAccessToken(definition, logger) {
923
1112
 
924
1113
  export {
925
1114
  buildStaticClientInformation,
1115
+ withRefreshLock,
1116
+ reconcilePersistedTokens,
1117
+ oauthAccessTokenNeedsRefresh,
1118
+ readCachedAccessTokenWithPersistence,
1119
+ withRefreshRequestTimeout,
926
1120
  buildOAuthPersistence,
927
1121
  clearOAuthCaches,
928
1122
  readCachedAccessToken
@@ -1,9 +1,9 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
2
  import {
3
3
  analyzeConnectionError
4
- } from "./chunk-DEUU7WSN.js";
4
+ } from "./chunk-ZNKNF2BV.js";
5
5
 
6
- // node_modules/.pnpm/mcporter@0.13.0/node_modules/mcporter/dist/runtime-oauth-support.js
6
+ // node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/runtime-oauth-support.js
7
7
  function maybeEnableOAuth(definition, logger) {
8
8
  if (definition.auth === "oauth" || definition.auth === "refreshable_bearer") {
9
9
  return void 0;
@@ -1,6 +1,6 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
2
 
3
- // node_modules/.pnpm/mcporter@0.13.0/node_modules/mcporter/dist/daemon/launch.js
3
+ // node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/daemon/launch.js
4
4
  import { spawn } from "node:child_process";
5
5
  import path from "node:path";
6
6
  function launchDaemonDetached(options, launch = spawn) {
@@ -1,20 +1,20 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
2
  import {
3
3
  __configInternals
4
- } from "./chunk-L4VKBFYI.js";
4
+ } from "./chunk-5HQYKAE7.js";
5
5
  import {
6
6
  withFileLock,
7
7
  writeTextFileAtomic
8
- } from "./chunk-7A63PAGP.js";
8
+ } from "./chunk-ETYYCEQF.js";
9
9
  import {
10
10
  expandHome
11
- } from "./chunk-HAO6PL7Z.js";
11
+ } from "./chunk-DIIFWDZ7.js";
12
12
  import {
13
13
  canonicalKeepAliveName,
14
14
  resolveLifecycle
15
- } from "./chunk-6D6KPSXN.js";
15
+ } from "./chunk-AJPFOQLF.js";
16
16
 
17
- // node_modules/.pnpm/mcporter@0.13.0/node_modules/mcporter/dist/cli/adhoc-server.js
17
+ // node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/cli/adhoc-server.js
18
18
  import fs from "node:fs/promises";
19
19
  import path from "node:path";
20
20
  var TEMP_SOURCE = { kind: "local", path: "<adhoc>" };
@@ -1,12 +1,13 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
2
  import {
3
3
  raceWithTimeout
4
- } from "./chunk-ETWN4IIA.js";
4
+ } from "./chunk-LYZRCACV.js";
5
5
 
6
- // node_modules/.pnpm/mcporter@0.13.0/node_modules/mcporter/dist/cli/timeouts.js
6
+ // node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/cli/timeouts.js
7
7
  var DEFAULT_LIST_TIMEOUT_MS = 3e4;
8
8
  var DEFAULT_CALL_TIMEOUT_MS = 6e4;
9
9
  var POSITIVE_INTEGER_PATTERN = /^[1-9]\d*$/;
10
+ var STDOUT_FLUSH_TIMEOUT_MS = 2e3;
10
11
  function parsePositiveInteger(raw) {
11
12
  if (!raw || !POSITIVE_INTEGER_PATTERN.test(raw)) {
12
13
  return void 0;
@@ -49,6 +50,7 @@ function consumeTimeoutFlag(args, index, options) {
49
50
  }
50
51
 
51
52
  export {
53
+ STDOUT_FLUSH_TIMEOUT_MS,
52
54
  parsePositiveInteger,
53
55
  parseTimeout,
54
56
  LIST_TIMEOUT_MS,
@@ -2,15 +2,15 @@ import { createRequire as __createRequire } from "node:module"; const require =
2
2
  import {
3
3
  buildFallbackLiteral,
4
4
  pickExampleLiteral
5
- } from "./chunk-P3RN22HQ.js";
5
+ } from "./chunk-3MIFROM7.js";
6
6
  import {
7
7
  cyanText,
8
8
  dimText,
9
9
  extraDimText,
10
10
  yellowText
11
- } from "./chunk-XUF6KARU.js";
11
+ } from "./chunk-IUFDFNNP.js";
12
12
 
13
- // node_modules/.pnpm/mcporter@0.13.0/node_modules/mcporter/dist/cli/list-signature.js
13
+ // node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/cli/list-signature.js
14
14
  function formatFunctionSignature(name, options, outputSchema, formatOptions) {
15
15
  const colorize = formatOptions?.colorize !== false;
16
16
  const keyword = colorize ? extraDimText("function") : "function";
@@ -136,7 +136,8 @@ function inferSchemaDisplayType(descriptor) {
136
136
  function formatTypeAnnotation(option, colorize) {
137
137
  let baseType;
138
138
  if (option.enumValues && option.enumValues.length > 0) {
139
- baseType = option.enumValues.map((value) => JSON.stringify(value)).join(" | ");
139
+ const union = option.enumValues.map((value) => JSON.stringify(value)).join(" | ");
140
+ baseType = option.type === "array" ? formatEnumArrayType(union, option.enumValues.length) : union;
140
141
  } else {
141
142
  switch (option.type) {
142
143
  case "number":
@@ -174,6 +175,9 @@ function formatTypeAnnotation(option, colorize) {
174
175
  }
175
176
  return base;
176
177
  }
178
+ function formatEnumArrayType(union, memberCount) {
179
+ return memberCount > 1 ? `(${union})[]` : `${union}[]`;
180
+ }
177
181
  function formatArrayItemType(type) {
178
182
  switch (type) {
179
183
  case "string":
@@ -189,7 +193,7 @@ function formatArrayItemType(type) {
189
193
  }
190
194
  }
191
195
 
192
- // node_modules/.pnpm/mcporter@0.13.0/node_modules/mcporter/dist/cli/list-doc-comments.js
196
+ // node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/cli/list-doc-comments.js
193
197
  var DEFAULT_WRAP_WIDTH = 100;
194
198
  function buildDocComment(description, options, opts) {
195
199
  const colorize = opts?.colorize !== false;
@@ -300,7 +304,7 @@ function wrapCommentText(text, width = DEFAULT_WRAP_WIDTH) {
300
304
  return lines;
301
305
  }
302
306
 
303
- // node_modules/.pnpm/mcporter@0.13.0/node_modules/mcporter/dist/cli/list-detail-helpers.js
307
+ // node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/cli/list-detail-helpers.js
304
308
  var DEFAULT_MIN_VISIBLE_PARAMS = 5;
305
309
  function selectDisplayOptions(options, requiredOnly, minVisible = DEFAULT_MIN_VISIBLE_PARAMS) {
306
310
  if (!requiredOnly || options.length <= minVisible) {
@@ -1,6 +1,6 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
2
 
3
- // node_modules/.pnpm/mcporter@0.13.0/node_modules/mcporter/dist/version.js
3
+ // node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/version.js
4
4
  import { createRequire } from "node:module";
5
5
  var MCPORTER_VERSION = (() => {
6
6
  try {
@@ -2,9 +2,9 @@ import { createRequire as __createRequire } from "node:module"; const require =
2
2
  import {
3
3
  logInfo,
4
4
  logWarn
5
- } from "./chunk-RBVYCKCD.js";
5
+ } from "./chunk-ILULMM2E.js";
6
6
 
7
- // node_modules/.pnpm/mcporter@0.13.0/node_modules/mcporter/dist/cli/runtime-debug.js
7
+ // node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/cli/runtime-debug.js
8
8
  var DEBUG_HANG = process.env.MCPORTER_DEBUG_HANG === "1";
9
9
  function describeHandle(handle) {
10
10
  if (!handle || typeof handle !== "object" && typeof handle !== "function") {
@@ -1,18 +1,19 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
2
  import {
3
3
  isUnauthorizedError
4
- } from "./chunk-7DH57OKF.js";
4
+ } from "./chunk-MWD5PZ4G.js";
5
5
  import {
6
6
  ProtocolErrorCode
7
- } from "./chunk-YPJ5EHXR.js";
7
+ } from "./chunk-K56RW4HB.js";
8
8
  import {
9
+ DAEMON_OAUTH_FLOW_ERROR_CODE,
9
10
  DAEMON_OPERATION_TIMEOUT_CODE
10
- } from "./chunk-ZBFZ5UFE.js";
11
+ } from "./chunk-MDVNQ4HM.js";
11
12
  import {
12
13
  isKeepAliveServer
13
- } from "./chunk-6D6KPSXN.js";
14
+ } from "./chunk-AJPFOQLF.js";
14
15
 
15
- // node_modules/.pnpm/mcporter@0.13.0/node_modules/mcporter/dist/daemon/runtime-wrapper.js
16
+ // node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/daemon/runtime-wrapper.js
16
17
  function createKeepAliveRuntime(base, options) {
17
18
  if (!options.daemonClient || options.keepAliveServers.size === 0) {
18
19
  return base;
@@ -152,8 +153,11 @@ function shouldRestartDaemonServer(error) {
152
153
  if (!error) {
153
154
  return false;
154
155
  }
155
- if (typeof error === "object" && error.code === DAEMON_OPERATION_TIMEOUT_CODE) {
156
- return false;
156
+ if (typeof error === "object") {
157
+ const code2 = error.code;
158
+ if (code2 === DAEMON_OPERATION_TIMEOUT_CODE || code2 === DAEMON_OAUTH_FLOW_ERROR_CODE) {
159
+ return false;
160
+ }
157
161
  }
158
162
  if (isUnauthorizedError(error)) {
159
163
  return false;
@@ -1,15 +1,15 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
2
  import {
3
3
  buildRecordCommandEnv
4
- } from "./chunk-E6RVTWJY.js";
4
+ } from "./chunk-5YBCGQA7.js";
5
5
  import {
6
6
  PRIVATE_RECORDING_FILE_MODE,
7
7
  ensurePrivateRecordingDir,
8
8
  resolveRecordingConfigPath,
9
9
  resolveRecordingPath
10
- } from "./chunk-E6T37ED6.js";
10
+ } from "./chunk-FNQV2ONG.js";
11
11
 
12
- // node_modules/.pnpm/mcporter@0.13.0/node_modules/mcporter/dist/cli/record-replay-command.js
12
+ // node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/cli/record-replay-command.js
13
13
  import { spawn } from "node:child_process";
14
14
  import fs from "node:fs/promises";
15
15
  async function writeRecordReplayConfig(parsed, mode) {
@@ -63,7 +63,7 @@ function buildRecordReplayInstructionEnv(mode, sessionName, server) {
63
63
  };
64
64
  }
65
65
 
66
- // node_modules/.pnpm/mcporter@0.13.0/node_modules/mcporter/dist/cli/record-command.js
66
+ // node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/cli/record-command.js
67
67
  async function handleRecordCli(args) {
68
68
  const parsed = parseRecordArgs(args);
69
69
  const recordPath = resolveRecordingPath(parsed.sessionName);
@@ -1,6 +1,6 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
2
 
3
- // node_modules/.pnpm/mcporter@0.13.0/node_modules/mcporter/dist/sdk-stdio-logging.js
3
+ // node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/sdk-stdio-logging.js
4
4
  var STDIO_LOGS_FORCED = process.env.MCPORTER_STDIO_LOGS === "1";
5
5
  var STDIO_TRACE_ENABLED = process.env.MCPORTER_STDIO_TRACE === "1";
6
6
  var stdioLogMode = STDIO_LOGS_FORCED ? "always" : "auto";
@@ -1,6 +1,6 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
2
 
3
- // node_modules/.pnpm/mcporter@0.13.0/node_modules/mcporter/dist/stable-json.js
3
+ // node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/stable-json.js
4
4
  function stableJsonStringify(value, space) {
5
5
  const json = JSON.stringify(sortJsonValue(value), void 0, space);
6
6
  if (json === void 0) {
@@ -1,9 +1,9 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
2
  import {
3
3
  normalizeHttpUrl
4
- } from "./chunk-UENXT3NE.js";
4
+ } from "./chunk-ILSK6AWI.js";
5
5
 
6
- // node_modules/.pnpm/mcporter@0.13.0/node_modules/mcporter/dist/cli/server-lookup.js
6
+ // node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/cli/server-lookup.js
7
7
  function findServerByHttpUrl(definitions, urlString) {
8
8
  const normalizedTarget = normalizeHttpUrl(urlString);
9
9
  if (!normalizedTarget) {
@@ -1,6 +1,6 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
2
 
3
- // node_modules/.pnpm/mcporter@0.13.0/node_modules/mcporter/dist/cli/output-format.js
3
+ // node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/cli/output-format.js
4
4
  function consumeOutputFormat(args, options = {}) {
5
5
  const allowed = options.allowed ?? ["auto", "text", "markdown", "json", "raw"];
6
6
  const defaultFormat = options.defaultFormat ?? "auto";
@@ -1,9 +1,9 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
2
  import {
3
3
  logWarn
4
- } from "./chunk-RBVYCKCD.js";
4
+ } from "./chunk-ILULMM2E.js";
5
5
 
6
- // node_modules/.pnpm/mcporter@0.13.0/node_modules/mcporter/dist/cli/output-utils.js
6
+ // node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/cli/output-utils.js
7
7
  import fs from "node:fs";
8
8
  import path from "node:path";
9
9
  import { inspect } from "node:util";
@@ -1,6 +1,6 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
2
 
3
- // node_modules/.pnpm/mcporter@0.13.0/node_modules/mcporter/dist/cli/identifier-helpers.js
3
+ // node_modules/.pnpm/mcporter@0.13.6/node_modules/mcporter/dist/cli/identifier-helpers.js
4
4
  var AUTO_THRESHOLD_RATIO = 0.3;
5
5
  var AUTO_THRESHOLD_MIN = 2;
6
6
  function chooseClosestIdentifier(input, candidates) {