deadbyte-mcp 0.15.16 → 0.15.18

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 (110) hide show
  1. package/MANIFEST.SHA256 +99 -96
  2. package/PROVENANCE.json +1 -1
  3. package/README.txt +6 -6
  4. package/RELEASE.json +1 -1
  5. package/SBOM.cdx.json +7 -33
  6. package/TEST-MATRIX.json +10 -25
  7. package/node_modules/@modelcontextprotocol/client/dist/{index-CHhhk6PQ.d.cts → index-BCtJi0p5.d.mts} +38 -6
  8. package/node_modules/@modelcontextprotocol/client/dist/index-BCtJi0p5.d.mts.map +1 -0
  9. package/node_modules/@modelcontextprotocol/client/dist/{index-D4xIIEF6.d.mts → index-CEk3qkZM.d.cts} +41 -3
  10. package/node_modules/@modelcontextprotocol/client/dist/index-CEk3qkZM.d.cts.map +1 -0
  11. package/node_modules/@modelcontextprotocol/client/dist/index.cjs +375 -60
  12. package/node_modules/@modelcontextprotocol/client/dist/index.cjs.map +1 -1
  13. package/node_modules/@modelcontextprotocol/client/dist/index.d.cts +227 -11
  14. package/node_modules/@modelcontextprotocol/client/dist/index.d.cts.map +1 -1
  15. package/node_modules/@modelcontextprotocol/client/dist/index.d.mts +227 -11
  16. package/node_modules/@modelcontextprotocol/client/dist/index.d.mts.map +1 -1
  17. package/node_modules/@modelcontextprotocol/client/dist/index.mjs +369 -61
  18. package/node_modules/@modelcontextprotocol/client/dist/index.mjs.map +1 -1
  19. package/node_modules/@modelcontextprotocol/client/dist/shimsWorkerd.cjs +1 -1
  20. package/node_modules/@modelcontextprotocol/client/dist/shimsWorkerd.mjs +1 -1
  21. package/node_modules/@modelcontextprotocol/client/dist/{src-NAgB4Mp8.cjs → src-D0qEN74R.cjs} +111 -38
  22. package/node_modules/@modelcontextprotocol/client/dist/src-D0qEN74R.cjs.map +1 -0
  23. package/node_modules/@modelcontextprotocol/client/dist/{src-D_zzAWoS.mjs → src-DDAAhLnO.mjs} +106 -33
  24. package/node_modules/@modelcontextprotocol/client/dist/src-DDAAhLnO.mjs.map +1 -0
  25. package/node_modules/@modelcontextprotocol/client/dist/stdio.cjs +8 -2
  26. package/node_modules/@modelcontextprotocol/client/dist/stdio.cjs.map +1 -1
  27. package/node_modules/@modelcontextprotocol/client/dist/stdio.d.cts +1 -1
  28. package/node_modules/@modelcontextprotocol/client/dist/stdio.d.cts.map +1 -1
  29. package/node_modules/@modelcontextprotocol/client/dist/stdio.d.mts +1 -1
  30. package/node_modules/@modelcontextprotocol/client/dist/stdio.d.mts.map +1 -1
  31. package/node_modules/@modelcontextprotocol/client/dist/stdio.mjs +8 -2
  32. package/node_modules/@modelcontextprotocol/client/dist/stdio.mjs.map +1 -1
  33. package/node_modules/@modelcontextprotocol/client/package.json +4 -4
  34. package/node_modules/@modelcontextprotocol/core/dist/{auth-BWdKR39I.d.mts → auth--n_Yzytt.d.cts} +6 -1
  35. package/node_modules/@modelcontextprotocol/core/dist/{auth-BWdKR39I.d.mts.map → auth--n_Yzytt.d.cts.map} +1 -1
  36. package/node_modules/@modelcontextprotocol/core/dist/{auth-CfDMXiII.cjs → auth-4-zilcqg.cjs} +3 -2
  37. package/node_modules/@modelcontextprotocol/core/dist/{auth-CfDMXiII.cjs.map → auth-4-zilcqg.cjs.map} +1 -1
  38. package/node_modules/@modelcontextprotocol/core/dist/{auth-CUe6YdwF.mjs → auth-CGP0BDVq.mjs} +3 -2
  39. package/node_modules/@modelcontextprotocol/core/dist/{auth-CUe6YdwF.mjs.map → auth-CGP0BDVq.mjs.map} +1 -1
  40. package/node_modules/@modelcontextprotocol/core/dist/{auth-hYtaIUZm.d.cts → auth-YUQV3RRv.d.mts} +6 -1
  41. package/node_modules/@modelcontextprotocol/core/dist/{auth-hYtaIUZm.d.cts.map → auth-YUQV3RRv.d.mts.map} +1 -1
  42. package/node_modules/@modelcontextprotocol/core/dist/index.cjs +1 -1
  43. package/node_modules/@modelcontextprotocol/core/dist/index.d.cts +1 -1
  44. package/node_modules/@modelcontextprotocol/core/dist/index.d.mts +1 -1
  45. package/node_modules/@modelcontextprotocol/core/dist/index.mjs +1 -1
  46. package/node_modules/@modelcontextprotocol/core/dist/internal.cjs +1 -1
  47. package/node_modules/@modelcontextprotocol/core/dist/internal.d.cts +1 -1
  48. package/node_modules/@modelcontextprotocol/core/dist/internal.d.mts +1 -1
  49. package/node_modules/@modelcontextprotocol/core/dist/internal.mjs +1 -1
  50. package/node_modules/@modelcontextprotocol/core/package.json +1 -1
  51. package/node_modules/@modelcontextprotocol/server/dist/{createMcpHandler-dBHMsxwf.d.cts → createMcpHandler-BLVe3qmU.d.cts} +110 -7
  52. package/node_modules/@modelcontextprotocol/server/dist/createMcpHandler-BLVe3qmU.d.cts.map +1 -0
  53. package/node_modules/@modelcontextprotocol/server/dist/{createMcpHandler-CLhGwQTn.d.mts → createMcpHandler-Bt6U_Fqb.d.mts} +110 -7
  54. package/node_modules/@modelcontextprotocol/server/dist/createMcpHandler-Bt6U_Fqb.d.mts.map +1 -0
  55. package/node_modules/@modelcontextprotocol/server/dist/index.cjs +144 -248
  56. package/node_modules/@modelcontextprotocol/server/dist/index.cjs.map +1 -1
  57. package/node_modules/@modelcontextprotocol/server/dist/index.d.cts +38 -3
  58. package/node_modules/@modelcontextprotocol/server/dist/index.d.cts.map +1 -1
  59. package/node_modules/@modelcontextprotocol/server/dist/index.d.mts +38 -3
  60. package/node_modules/@modelcontextprotocol/server/dist/index.d.mts.map +1 -1
  61. package/node_modules/@modelcontextprotocol/server/dist/index.mjs +136 -243
  62. package/node_modules/@modelcontextprotocol/server/dist/index.mjs.map +1 -1
  63. package/node_modules/@modelcontextprotocol/server/dist/{mcp-D7GmuPnv.cjs → mcp-DUcCQSTW.cjs} +426 -21
  64. package/node_modules/@modelcontextprotocol/server/dist/mcp-DUcCQSTW.cjs.map +1 -0
  65. package/node_modules/@modelcontextprotocol/server/dist/{mcp-DXXb3Vv3.mjs → mcp-Dw2OlZ1f.mjs} +367 -22
  66. package/node_modules/@modelcontextprotocol/server/dist/mcp-Dw2OlZ1f.mjs.map +1 -0
  67. package/node_modules/@modelcontextprotocol/server/dist/shimsWorkerd.cjs +1 -1
  68. package/node_modules/@modelcontextprotocol/server/dist/shimsWorkerd.mjs +1 -1
  69. package/node_modules/@modelcontextprotocol/server/dist/{src-STyD_Vvf.cjs → src-CgFsfg3E.cjs} +114 -36
  70. package/node_modules/@modelcontextprotocol/server/dist/src-CgFsfg3E.cjs.map +1 -0
  71. package/node_modules/@modelcontextprotocol/server/dist/{src-CX2iR2pK.mjs → src-D-y6h4N7.mjs} +114 -36
  72. package/node_modules/@modelcontextprotocol/server/dist/src-D-y6h4N7.mjs.map +1 -0
  73. package/node_modules/@modelcontextprotocol/server/dist/stdio.cjs +30 -3
  74. package/node_modules/@modelcontextprotocol/server/dist/stdio.cjs.map +1 -1
  75. package/node_modules/@modelcontextprotocol/server/dist/stdio.d.cts +9 -1
  76. package/node_modules/@modelcontextprotocol/server/dist/stdio.d.cts.map +1 -1
  77. package/node_modules/@modelcontextprotocol/server/dist/stdio.d.mts +9 -1
  78. package/node_modules/@modelcontextprotocol/server/dist/stdio.d.mts.map +1 -1
  79. package/node_modules/@modelcontextprotocol/server/dist/stdio.mjs +30 -3
  80. package/node_modules/@modelcontextprotocol/server/dist/stdio.mjs.map +1 -1
  81. package/node_modules/@modelcontextprotocol/server/package.json +3 -3
  82. package/package.json +91 -93
  83. package/scripts/commander-hardening-gate-r47.mjs +1 -0
  84. package/scripts/full-regression-r47.mjs +1 -1
  85. package/scripts/init-host-policy.ps1 +2 -1
  86. package/src/coding-plane.mjs +24 -0
  87. package/src/commander-core-bridge.mjs +26 -30
  88. package/src/commander-extended-bridge-r47.mjs +17 -0
  89. package/src/commander-extended-runtime.mjs +2 -1
  90. package/src/commander-wire-adapter-r47.mjs +341 -0
  91. package/src/machine-fs.mjs +6 -6
  92. package/src/mcp-server.mjs +13 -87
  93. package/src/tunnel-stdio-compat.mjs +3 -3
  94. package/src/version.mjs +1 -1
  95. package/test/commander-core-bridge-r47.test.mjs +1 -1
  96. package/test/commander-protocol-r47.test.mjs +17 -2
  97. package/test/commander-wire-contract-r47.test.mjs +143 -0
  98. package/test/machine-fs-runtime.test.mjs +19 -1
  99. package/test/r47-release-contract.test.mjs +3 -3
  100. package/node_modules/@modelcontextprotocol/client/dist/index-CHhhk6PQ.d.cts.map +0 -1
  101. package/node_modules/@modelcontextprotocol/client/dist/index-D4xIIEF6.d.mts.map +0 -1
  102. package/node_modules/@modelcontextprotocol/client/dist/src-D_zzAWoS.mjs.map +0 -1
  103. package/node_modules/@modelcontextprotocol/client/dist/src-NAgB4Mp8.cjs.map +0 -1
  104. package/node_modules/@modelcontextprotocol/server/dist/createMcpHandler-CLhGwQTn.d.mts.map +0 -1
  105. package/node_modules/@modelcontextprotocol/server/dist/createMcpHandler-dBHMsxwf.d.cts.map +0 -1
  106. package/node_modules/@modelcontextprotocol/server/dist/mcp-D7GmuPnv.cjs.map +0 -1
  107. package/node_modules/@modelcontextprotocol/server/dist/mcp-DXXb3Vv3.mjs.map +0 -1
  108. package/node_modules/@modelcontextprotocol/server/dist/src-CX2iR2pK.mjs.map +0 -1
  109. package/node_modules/@modelcontextprotocol/server/dist/src-STyD_Vvf.cjs.map +0 -1
  110. package/node_modules/which/CHANGELOG.md +0 -166
@@ -1,4 +1,4 @@
1
- import { $ as legacyProtocolVersions, A as isInitializeRequest, At as SdkErrorCode, B as DiscoverResultSchema, C as HEADER_MISMATCH_ERROR_CODE, Ct as OAuthClientInformationFullSchema, D as assertCompleteRequestPrompt, Dt as OAuthTokensSchema, E as scanXMcpHeaderDeclarations, Et as OAuthProtectedResourceMetadataSchema, F as isJSONRPCRequest, Ft as stampErrorBrands, G as MissingRequiredClientCapabilityError, H as ListChangedOptionsBaseSchema, I as isJSONRPCResponse, J as UnsupportedProtocolVersionError, K as ProtocolError, L as isJSONRPCResultResponse, M as isInputRequiredResult, Mt as OAuthError, N as isJSONRPCErrorResponse, Nt as OAuthErrorCode, O as assertCompleteRequestResourceTemplate, Ot as OpenIdProviderDiscoveryMetadataSchema, P as isJSONRPCNotification, Pt as brandedHasInstance, Q as isModernProtocolVersion, R as isTaskAugmentedRequestParams, S as parseSchema, St as IdJagTokenExchangeResponseSchema, T as encodeMcpParamValue, Tt as OAuthMetadataSchema, U as MODERN_WIRE_REVISION, V as JSONRPCMessageSchema, W as codecForVersion, X as ProtocolErrorCode, Y as UrlElicitationRequiredError, Z as SUPPORTED_MODERN_PROTOCOL_VERSIONS, _ as mergeCapabilities, _t as SUPPORTED_PROTOCOL_VERSIONS, a as createFetchWithInit, at as INTERNAL_ERROR, b as resolveInputRequiredDriverConfig, bt as checkResourceAllowed, c as STDIO_DEFAULT_MAX_BUFFER_SIZE, ct as JSONRPC_VERSION, d as getDisplayName, dt as METHOD_NOT_FOUND, et as modernProtocolVersions, f as isJsonContentType, ft as PARSE_ERROR, g as Protocol, gt as SUBSCRIPTION_ID_META_KEY, h as DEFAULT_REQUEST_TIMEOUT_MSEC, ht as SERVER_INFO_META_KEY, i as UriTemplate, it as DEFAULT_NEGOTIATED_PROTOCOL_VERSION, j as isInitializedNotification, jt as SdkHttpError, k as isCallToolResult, kt as SdkError, l as deserializeMessage, lt as LATEST_PROTOCOL_VERSION, m as runInputRequiredFlow, mt as RELATED_TASK_META_KEY, n as preloadSchemas, nt as CLIENT_CAPABILITIES_META_KEY, o as normalizeHeaders, ot as INVALID_PARAMS, p as mediaTypeEssence, pt as PROTOCOL_VERSION_META_KEY, q as ResourceNotFoundError, r as InMemoryTransport, rt as CLIENT_INFO_META_KEY, s as ReadBuffer, st as INVALID_REQUEST, t as fromJsonSchema$1, tt as BAGGAGE_META_KEY, u as serializeMessage, ut as LOG_LEVEL_META_KEY, v as isSpecType, vt as TRACEPARENT_META_KEY, w as buildMcpParamHeaders, wt as OAuthErrorResponseSchema, x as withInputRequired, xt as resourceUrlFromServerUrl, y as specTypeSchemas, yt as TRACESTATE_META_KEY, z as parseJSONRPCMessage } from "./src-D_zzAWoS.mjs";
1
+ import { $ as legacyProtocolVersions, A as isInitializeRequest, At as SdkErrorCode, B as DiscoverResultSchema, C as mcpNameSource, Ct as OAuthClientInformationFullSchema, D as assertCompleteRequestPrompt, Dt as OAuthTokensSchema, E as scanXMcpHeaderDeclarations, Et as OAuthProtectedResourceMetadataSchema, F as isJSONRPCRequest, Ft as stampErrorBrands, G as MissingRequiredClientCapabilityError, H as ListChangedOptionsBaseSchema, I as isJSONRPCResponse, J as UnsupportedProtocolVersionError, K as ProtocolError, L as isJSONRPCResultResponse, M as isInputRequiredResult, Mt as OAuthError, N as isJSONRPCErrorResponse, Nt as OAuthErrorCode, O as assertCompleteRequestResourceTemplate, Ot as OpenIdProviderDiscoveryMetadataSchema, P as isJSONRPCNotification, Pt as brandedHasInstance, Q as isModernProtocolVersion, R as isTaskAugmentedRequestParams, S as HEADER_MISMATCH_ERROR_CODE, St as IdJagTokenExchangeResponseSchema, T as encodeMcpParamValue, Tt as OAuthMetadataSchema, U as MODERN_WIRE_REVISION, V as JSONRPCMessageSchema, W as codecForVersion, X as ProtocolErrorCode, Y as UrlElicitationRequiredError, Z as SUPPORTED_MODERN_PROTOCOL_VERSIONS, _ as isSpecType, _t as SUPPORTED_PROTOCOL_VERSIONS, a as createFetchWithInit, at as INTERNAL_ERROR, b as withInputRequired, bt as checkResourceAllowed, c as deserializeMessage, ct as JSONRPC_VERSION, d as isJsonContentType, dt as METHOD_NOT_FOUND, et as modernProtocolVersions, f as mediaTypeEssence, ft as PARSE_ERROR, g as mergeCapabilities, gt as SUBSCRIPTION_ID_META_KEY, h as Protocol, ht as SERVER_INFO_META_KEY, i as UriTemplate, it as DEFAULT_NEGOTIATED_PROTOCOL_VERSION, j as isInitializedNotification, jt as SdkHttpError, k as isCallToolResult, kt as SdkError, l as serializeMessage, lt as LATEST_PROTOCOL_VERSION, m as DEFAULT_REQUEST_TIMEOUT_MSEC, mt as RELATED_TASK_META_KEY, n as preloadSchemas, nt as CLIENT_CAPABILITIES_META_KEY, o as ReadBuffer, ot as INVALID_PARAMS, p as runInputRequiredFlow, pt as PROTOCOL_VERSION_META_KEY, q as ResourceNotFoundError, r as InMemoryTransport, rt as CLIENT_INFO_META_KEY, s as STDIO_DEFAULT_MAX_BUFFER_SIZE, st as INVALID_REQUEST, t as fromJsonSchema$1, tt as BAGGAGE_META_KEY, u as getDisplayName, ut as LOG_LEVEL_META_KEY, v as specTypeSchemas, vt as TRACEPARENT_META_KEY, w as buildMcpParamHeaders, wt as OAuthErrorResponseSchema, x as parseSchema, xt as resourceUrlFromServerUrl, y as resolveInputRequiredDriverConfig, yt as TRACESTATE_META_KEY, z as parseJSONRPCMessage } from "./src-DDAAhLnO.mjs";
2
2
  import { CORS_IS_POSSIBLE, DefaultJsonSchemaValidator } from "@modelcontextprotocol/client/_shims";
3
3
  import pkceChallenge from "pkce-challenge";
4
4
  import { EventSource } from "eventsource";
@@ -266,6 +266,12 @@ async function handleOAuthUnauthorized(provider, ctx, extraAuthOptions) {
266
266
  * not in scope. Providers that key storage on `ctx.issuer` MUST treat `ctx === undefined`
267
267
  * as "return the most-recently-saved token set" (the only consumer is the resource server
268
268
  * the token was minted for); providers that round-trip a single blob need no change.
269
+ *
270
+ * SEP-1932 (DPoP) note: DPoP request-signing is deliberately *not* done here. When the provider
271
+ * implements {@linkcode OAuthClientProvider.dpop | dpop()}, the transports wrap their
272
+ * resource-server `fetch` with {@linkcode withDpopFromProvider}, which upgrades the `Bearer` header
273
+ * this adapter produces to `DPoP` + proof for DPoP-bound tokens and handles nonce challenges — at
274
+ * the one layer that sees the real method, URL and response of every request.
269
275
  */
270
276
  function adaptOAuthProvider(provider, extraAuthOptions) {
271
277
  return {
@@ -602,6 +608,17 @@ async function parseErrorResponse(input) {
602
608
  }
603
609
  }
604
610
  /**
611
+ * Recovering from a recoverable OAuth error discards stored credentials and silently starts a
612
+ * fresh authorization. On a headless client whose `redirectToAuthorization()` is a no-op that
613
+ * recovery is indistinguishable from nothing happening at all, so name the cause. The most
614
+ * common case is `invalid_grant` — an expired, revoked, or rotation-reuse-detected refresh
615
+ * token. See issue #2034.
616
+ */
617
+ function warnCredentialInvalidation(provider, error, invalidated) {
618
+ const action = provider.invalidateCredentials === void 0 ? `retrying authorization without discarding the stored ${invalidated} (provider implements no invalidateCredentials())` : `invalidating the stored ${invalidated} and retrying authorization`;
619
+ console.warn(`[mcp-sdk] OAuth ${JSON.stringify(error.code)} — ${action}. Cause: ${JSON.stringify(error.message)}`);
620
+ }
621
+ /**
605
622
  * Orchestrates the full auth flow with a server.
606
623
  *
607
624
  * This can be used as a single entry point for all authorization functionality,
@@ -613,10 +630,12 @@ async function auth(provider, options) {
613
630
  } catch (error) {
614
631
  if (error instanceof OAuthError) {
615
632
  if (error.code === OAuthErrorCode.InvalidClient || error.code === OAuthErrorCode.UnauthorizedClient) {
633
+ warnCredentialInvalidation(provider, error, "client credentials and tokens");
616
634
  await provider.invalidateCredentials?.("client");
617
635
  await provider.invalidateCredentials?.("tokens");
618
636
  return await authInternal(provider, options);
619
- } else if (error.code === OAuthErrorCode.InvalidGrant) {
637
+ } else if (error.code === OAuthErrorCode.InvalidGrant || error.code === OAuthErrorCode.InvalidDpopProof) {
638
+ warnCredentialInvalidation(provider, error, "tokens");
620
639
  await provider.invalidateCredentials?.("tokens");
621
640
  return await authInternal(provider, options);
622
641
  }
@@ -687,8 +706,9 @@ async function authInternal(provider, { serverUrl, authorizationCode, iss, scope
687
706
  } else if (!issuersMatch(recordedIssuer, issuer)) throw new AuthorizationServerMismatchError(recordedIssuer, issuer);
688
707
  }
689
708
  if (freshDiscoveryState) await provider.saveDiscoveryState?.(freshDiscoveryState);
690
- const resource = await selectResourceURL(serverUrl, provider, resourceMetadata);
691
- if (resource) await provider.saveResourceUrl?.(String(resource));
709
+ const selectedResource = await selectResourceURL(serverUrl, provider, resourceMetadata);
710
+ const resource = selectedResource && resourceMetadata && !provider.validateResourceURL ? resourceMetadata.resource : selectedResource;
711
+ if (resource) await provider.saveResourceUrl?.(resourceIndicatorToString(resource));
692
712
  const resolvedScope = determineScope({
693
713
  requestedScope: scope,
694
714
  resourceMetadata,
@@ -759,23 +779,30 @@ async function authInternal(provider, { serverUrl, authorizationCode, iss, scope
759
779
  };
760
780
  await provider.saveTokens(tokens, infoCtx);
761
781
  }
762
- if (tokens?.refresh_token && !forceReauthorization) try {
763
- const newTokens = await refreshAuthorization(authorizationServerUrl, {
764
- metadata,
765
- clientInformation,
766
- refreshToken: tokens.refresh_token,
767
- resource,
768
- addClientAuthentication: provider.addClientAuthentication,
769
- fetchFn
770
- });
771
- await provider.saveTokens({
772
- ...newTokens,
773
- issuer
774
- }, infoCtx);
775
- return "AUTHORIZED";
776
- } catch (error) {
777
- if (error instanceof InsecureTokenEndpointError) throw error;
778
- if (!(error instanceof OAuthError) || error.code === OAuthErrorCode.ServerError) {} else throw error;
782
+ if (tokens?.refresh_token && !forceReauthorization) {
783
+ let newTokens;
784
+ try {
785
+ newTokens = await refreshAuthorization(authorizationServerUrl, {
786
+ metadata,
787
+ clientInformation,
788
+ refreshToken: tokens.refresh_token,
789
+ resource,
790
+ addClientAuthentication: provider.addClientAuthentication,
791
+ dpop: await provider.dpop?.(),
792
+ fetchFn
793
+ });
794
+ } catch (error) {
795
+ if (error instanceof InsecureTokenEndpointError) throw error;
796
+ if (!(error instanceof OAuthError) || error.code === OAuthErrorCode.ServerError) console.warn(`[mcp-sdk] Could not refresh OAuth tokens; falling back to a new authorization request. Cause: ${JSON.stringify(error instanceof Error ? error.message : String(error))}`);
797
+ else throw error;
798
+ }
799
+ if (newTokens) {
800
+ await provider.saveTokens({
801
+ ...newTokens,
802
+ issuer
803
+ }, infoCtx);
804
+ return "AUTHORIZED";
805
+ }
779
806
  }
780
807
  const state = provider.state ? await provider.state() : void 0;
781
808
  const { authorizationUrl, codeVerifier } = await startAuthorization(authorizationServerUrl, {
@@ -819,6 +846,17 @@ function isHttpsUrl(value) {
819
846
  return false;
820
847
  }
821
848
  }
849
+ /**
850
+ * Selects the RFC 8707 resource indicator for an MCP server: the provider's
851
+ * {@linkcode OAuthClientProvider.validateResourceURL | validateResourceURL} result when
852
+ * implemented, otherwise the protected resource metadata's `resource` (checked against the
853
+ * server URL with `checkResourceAllowed`), or `undefined` when there is no metadata.
854
+ *
855
+ * The result is a parsed `URL`, so a pathless indicator such as `https://example.com` has
856
+ * the `href` `https://example.com/`. {@linkcode auth} therefore sends the metadata string
857
+ * verbatim instead of this URL's `href` (#1968); callers that emit the `resource`
858
+ * parameter themselves should do the same.
859
+ */
822
860
  async function selectResourceURL(serverUrl, provider, resourceMetadata) {
823
861
  const defaultResource = resourceUrlFromServerUrl(serverUrl);
824
862
  if (provider.validateResourceURL) return await provider.validateResourceURL(defaultResource, resourceMetadata?.resource);
@@ -829,15 +867,22 @@ async function selectResourceURL(serverUrl, provider, resourceMetadata) {
829
867
  })) throw new Error(`Protected resource ${resourceMetadata.resource} does not match expected ${defaultResource} (or origin)`);
830
868
  return new URL(resourceMetadata.resource);
831
869
  }
870
+ /** Auth-scheme challenge tokens {@linkcode extractWWWAuthenticateParams} recognizes. */
871
+ const RECOGNIZED_CHALLENGE_SCHEMES = new Set(["bearer", "dpop"]);
832
872
  /**
833
873
  * Extract `resource_metadata`, `scope`, `error`, and `error_description` from a
834
874
  * `WWW-Authenticate` header.
875
+ *
876
+ * Recognizes both the `Bearer` scheme (RFC 6750) and the `DPoP` scheme (RFC 9449 §7.1,
877
+ * SEP-1932) — a DPoP-protected resource's challenge carries the same parameters under `DPoP`
878
+ * instead of `Bearer`, and this must still surface `resource_metadata`/`scope` from it for
879
+ * discovery and SEP-2350 step-up to work against such a resource.
835
880
  */
836
881
  function extractWWWAuthenticateParams(res) {
837
882
  const authenticateHeader = res.headers.get("WWW-Authenticate");
838
883
  if (!authenticateHeader) return {};
839
884
  const [type, scheme] = authenticateHeader.split(" ");
840
- if (type?.toLowerCase() !== "bearer" || !scheme) return {};
885
+ if (!type || !RECOGNIZED_CHALLENGE_SCHEMES.has(type.toLowerCase()) || !scheme) return {};
841
886
  const resourceMetadataMatch = extractFieldFromWwwAuth(res, "resource_metadata") || void 0;
842
887
  let resourceMetadataUrl;
843
888
  if (resourceMetadataMatch) try {
@@ -1135,6 +1180,9 @@ async function discoverOAuthServerInfo(serverUrl, opts) {
1135
1180
  resourceMetadata
1136
1181
  };
1137
1182
  }
1183
+ function resourceIndicatorToString(resource) {
1184
+ return typeof resource === "string" ? resource : resource.href;
1185
+ }
1138
1186
  /**
1139
1187
  * Begins the authorization flow with the given server, by generating a PKCE challenge and constructing the authorization URL.
1140
1188
  */
@@ -1156,7 +1204,7 @@ async function startAuthorization(authorizationServerUrl, { metadata, clientInfo
1156
1204
  if (state) authorizationUrl.searchParams.set("state", state);
1157
1205
  if (scope) authorizationUrl.searchParams.set("scope", scope);
1158
1206
  if (scope?.split(" ").includes("offline_access")) authorizationUrl.searchParams.append("prompt", "consent");
1159
- if (resource) authorizationUrl.searchParams.set("resource", resource.href);
1207
+ if (resource) authorizationUrl.searchParams.set("resource", resourceIndicatorToString(resource));
1160
1208
  return {
1161
1209
  authorizationUrl,
1162
1210
  codeVerifier
@@ -1185,20 +1233,35 @@ function prepareAuthorizationCodeRequest(authorizationCode, codeVerifier, redire
1185
1233
  * Internal helper to execute a token request with the given parameters.
1186
1234
  * Used by {@linkcode exchangeAuthorization}, {@linkcode refreshAuthorization}, and {@linkcode fetchToken}.
1187
1235
  */
1188
- async function executeTokenRequest(authorizationServerUrl, { metadata, tokenRequestParams, clientInformation, addClientAuthentication, resource, fetchFn }) {
1236
+ async function executeTokenRequest(authorizationServerUrl, { metadata, tokenRequestParams, clientInformation, addClientAuthentication, resource, dpop, fetchFn }) {
1189
1237
  const tokenUrl = assertSecureTokenEndpoint(metadata?.token_endpoint ?? new URL("/token", authorizationServerUrl));
1190
1238
  const headers = new Headers({
1191
1239
  "Content-Type": "application/x-www-form-urlencoded",
1192
1240
  Accept: "application/json"
1193
1241
  });
1194
- if (resource) tokenRequestParams.set("resource", resource.href);
1195
- if (addClientAuthentication) await addClientAuthentication(headers, tokenRequestParams, tokenUrl, metadata);
1196
- else if (clientInformation) applyClientAuthentication(selectClientAuthMethod(clientInformation, metadata?.token_endpoint_auth_methods_supported ?? []), clientInformation, headers, tokenRequestParams);
1197
- const response = await (fetchFn ?? fetch)(tokenUrl, {
1198
- method: "POST",
1199
- headers,
1200
- body: tokenRequestParams
1201
- });
1242
+ if (resource) tokenRequestParams.set("resource", resourceIndicatorToString(resource));
1243
+ if (!addClientAuthentication && clientInformation) applyClientAuthentication(selectClientAuthMethod(clientInformation, metadata?.token_endpoint_auth_methods_supported ?? []), clientInformation, headers, tokenRequestParams);
1244
+ const requestOnce = async () => {
1245
+ const requestHeaders = new Headers(headers);
1246
+ if (addClientAuthentication) await addClientAuthentication(requestHeaders, tokenRequestParams, tokenUrl, metadata);
1247
+ if (dpop) requestHeaders.set("DPoP", await dpop.buildProof({
1248
+ htm: "POST",
1249
+ htu: tokenUrl
1250
+ }));
1251
+ return (fetchFn ?? fetch)(tokenUrl, {
1252
+ method: "POST",
1253
+ headers: requestHeaders,
1254
+ body: tokenRequestParams
1255
+ });
1256
+ };
1257
+ let response = await requestOnce();
1258
+ if (dpop && response.status === 400) {
1259
+ if ((await response.clone().json().catch(() => {}))?.error === OAuthErrorCode.UseDpopNonce) {
1260
+ dpop.observeNonce(response, tokenUrl);
1261
+ response = await requestOnce();
1262
+ }
1263
+ }
1264
+ dpop?.observeNonce(response, tokenUrl);
1202
1265
  if (!response.ok) throw await parseErrorResponse(response);
1203
1266
  const json = await response.json();
1204
1267
  try {
@@ -1220,7 +1283,7 @@ async function executeTokenRequest(authorizationServerUrl, { metadata, tokenRequ
1220
1283
  * @returns Promise resolving to OAuth tokens
1221
1284
  * @throws {Error} When token exchange fails or authentication is invalid
1222
1285
  */
1223
- async function exchangeAuthorization(authorizationServerUrl, { metadata, clientInformation, authorizationCode, iss, codeVerifier, redirectUri, resource, addClientAuthentication, fetchFn }) {
1286
+ async function exchangeAuthorization(authorizationServerUrl, { metadata, clientInformation, authorizationCode, iss, codeVerifier, redirectUri, resource, addClientAuthentication, dpop, fetchFn }) {
1224
1287
  validateAuthorizationResponseIssuer({
1225
1288
  iss,
1226
1289
  expectedIssuer: metadata?.issuer,
@@ -1232,6 +1295,7 @@ async function exchangeAuthorization(authorizationServerUrl, { metadata, clientI
1232
1295
  clientInformation,
1233
1296
  addClientAuthentication,
1234
1297
  resource,
1298
+ dpop,
1235
1299
  fetchFn
1236
1300
  });
1237
1301
  }
@@ -1247,7 +1311,7 @@ async function exchangeAuthorization(authorizationServerUrl, { metadata, clientI
1247
1311
  * @returns Promise resolving to OAuth tokens (preserves original `refresh_token` if not replaced)
1248
1312
  * @throws {Error} When token refresh fails or authentication is invalid
1249
1313
  */
1250
- async function refreshAuthorization(authorizationServerUrl, { metadata, clientInformation, refreshToken, resource, addClientAuthentication, fetchFn }) {
1314
+ async function refreshAuthorization(authorizationServerUrl, { metadata, clientInformation, refreshToken, resource, addClientAuthentication, dpop, fetchFn }) {
1251
1315
  return {
1252
1316
  refresh_token: refreshToken,
1253
1317
  ...await executeTokenRequest(authorizationServerUrl, {
@@ -1259,6 +1323,7 @@ async function refreshAuthorization(authorizationServerUrl, { metadata, clientIn
1259
1323
  clientInformation,
1260
1324
  addClientAuthentication,
1261
1325
  resource,
1326
+ dpop,
1262
1327
  fetchFn
1263
1328
  })
1264
1329
  };
@@ -1311,6 +1376,7 @@ async function fetchToken(provider, authorizationServerUrl, { metadata, resource
1311
1376
  clientInformation: clientInformation ?? void 0,
1312
1377
  addClientAuthentication: provider.addClientAuthentication,
1313
1378
  resource,
1379
+ dpop: await provider.dpop?.(),
1314
1380
  fetchFn
1315
1381
  });
1316
1382
  }
@@ -2397,7 +2463,7 @@ function classifyNetworkError(error, context) {
2397
2463
  if (context.environment === "browser" && isOpaqueFetchTypeError(error)) return { kind: "legacy" };
2398
2464
  return {
2399
2465
  kind: "error",
2400
- error: new SdkError(SdkErrorCode.EraNegotiationFailed, `Version negotiation probe failed: ${describeError(error)}`, { cause: error })
2466
+ error: new SdkError(SdkErrorCode.EraNegotiationFailed, `Version negotiation probe failed: ${describeError(error)}`, { cause: error }, { cause: error })
2401
2467
  };
2402
2468
  }
2403
2469
  function isOpaqueFetchTypeError(error) {
@@ -4428,6 +4494,160 @@ async function exchangeJwtAuthGrant(options) {
4428
4494
  return parseResult.data;
4429
4495
  }
4430
4496
 
4497
+ //#endregion
4498
+ //#region src/client/dpop.ts
4499
+ /** Asymmetric JWS algorithms usable for a DPoP proof (RFC 9449 §11.6 forbids symmetric algs and `none`). */
4500
+ const DPOP_SUPPORTED_ALGS = [
4501
+ "ES256",
4502
+ "ES384",
4503
+ "ES512",
4504
+ "RS256",
4505
+ "RS384",
4506
+ "RS512",
4507
+ "PS256",
4508
+ "PS384",
4509
+ "PS512",
4510
+ "EdDSA"
4511
+ ];
4512
+ const DEFAULT_DPOP_ALG = "ES256";
4513
+ const DPOP_TYP = "dpop+jwt";
4514
+ async function importJose() {
4515
+ if (globalThis.crypto === void 0) throw new TypeError("crypto is not available, please ensure you have Web Crypto API support for older Node.js versions (see https://github.com/modelcontextprotocol/typescript-sdk#nodejs-web-crypto-globalthiscrypto-compatibility)");
4516
+ return import("jose");
4517
+ }
4518
+ /** Generate an asymmetric DPoP signing key pair. Non-extractable by default (RFC 9449 §11). */
4519
+ async function generateDpopKeyPair(options = {}) {
4520
+ const alg = options.alg ?? DEFAULT_DPOP_ALG;
4521
+ const jose = await importJose();
4522
+ const { publicKey, privateKey } = await jose.generateKeyPair(alg, { extractable: options.extractable ?? false });
4523
+ const publicJwk = await jose.exportJWK(publicKey);
4524
+ return {
4525
+ privateKey,
4526
+ publicKey,
4527
+ publicJwk,
4528
+ thumbprint: await jose.calculateJwkThumbprint(publicJwk, "sha256"),
4529
+ alg
4530
+ };
4531
+ }
4532
+ /**
4533
+ * Compute the `ath` claim for a DPoP proof presented alongside an access token: the
4534
+ * base64url-encoded SHA-256 digest of the ASCII access-token value (RFC 9449 §4.1).
4535
+ *
4536
+ * Uses Web Crypto (`crypto.subtle`) rather than a Node-only hashing API so this stays usable
4537
+ * in browser and edge runtimes.
4538
+ */
4539
+ async function accessTokenHash(accessToken) {
4540
+ if (globalThis.crypto?.subtle === void 0) throw new TypeError("crypto.subtle is not available, please ensure you have Web Crypto API support for older Node.js versions (see https://github.com/modelcontextprotocol/typescript-sdk#nodejs-web-crypto-globalthiscrypto-compatibility)");
4541
+ const digest = await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(accessToken));
4542
+ return base64UrlEncode(new Uint8Array(digest));
4543
+ }
4544
+ function base64UrlEncode(bytes) {
4545
+ let binary = "";
4546
+ for (const byte of bytes) binary += String.fromCodePoint(byte);
4547
+ return btoa(binary).replaceAll("+", "-").replaceAll("/", "_").replaceAll("=", "");
4548
+ }
4549
+ /** Strip the query and fragment from a URL, per RFC 9449 §4.2 (`htu` MUST NOT contain either). */
4550
+ function stripQueryAndFragment(url) {
4551
+ const u = new URL(url.toString());
4552
+ return `${u.origin}${u.pathname}`;
4553
+ }
4554
+ /** A fresh, cryptographically random `jti` (RFC 9449 §4.2 — MUST be unique per proof). */
4555
+ function randomJti() {
4556
+ const bytes = new Uint8Array(16);
4557
+ globalThis.crypto.getRandomValues(bytes);
4558
+ return base64UrlEncode(bytes);
4559
+ }
4560
+ /**
4561
+ * A DPoP signing identity plus the small amount of state RFC 9449 requires across requests:
4562
+ * the key pair and, per origin, the most recently server-supplied nonce (RFC 9449 §8/§9).
4563
+ *
4564
+ * One `DpopSession` is meant to live for the lifetime of a single OAuth client registration —
4565
+ * the token endpoint and the resource server are different origins and get independent nonce
4566
+ * slots, so a nonce challenge from one never leaks into proofs sent to the other.
4567
+ */
4568
+ var DpopSession = class DpopSession {
4569
+ nonces = /* @__PURE__ */ new Map();
4570
+ constructor(keyPair) {
4571
+ this.keyPair = keyPair;
4572
+ }
4573
+ /** Create a session with a fresh key pair, or reuse a caller-supplied one. */
4574
+ static async create(options = {}) {
4575
+ return new DpopSession(options.keyPair ?? await generateDpopKeyPair({ alg: options.alg }));
4576
+ }
4577
+ /** RFC 7638 JWK SHA-256 thumbprint of the signing key — matches the token's `cnf.jkt` once bound. */
4578
+ get thumbprint() {
4579
+ return this.keyPair.thumbprint;
4580
+ }
4581
+ /** The JWS algorithm this session signs proofs with. */
4582
+ get alg() {
4583
+ return this.keyPair.alg;
4584
+ }
4585
+ /** The public JWK embedded in every proof's `jwk` header parameter. */
4586
+ get publicJwk() {
4587
+ return this.keyPair.publicJwk;
4588
+ }
4589
+ /** The remembered nonce for `url`'s origin, if the server has issued one (RFC 9449 §8/§9). */
4590
+ nonceFor(url) {
4591
+ return this.nonces.get(new URL(url.toString()).origin);
4592
+ }
4593
+ /** Record a server-supplied nonce for `url`'s origin (newest-wins, RFC 9449 §8.2). */
4594
+ rememberNonce(url, nonce) {
4595
+ this.nonces.set(new URL(url.toString()).origin, nonce);
4596
+ }
4597
+ /**
4598
+ * Capture a `DPoP-Nonce` response header, if present, for `url`'s origin. RFC 9449 §8.2 says a
4599
+ * fresh nonce may ride on *any* response (success or failure), so call this unconditionally
4600
+ * after every request, not only on a `use_dpop_nonce` challenge.
4601
+ */
4602
+ observeNonce(response, url) {
4603
+ const nonce = response.headers.get("dpop-nonce");
4604
+ if (nonce) this.rememberNonce(url, nonce);
4605
+ }
4606
+ /**
4607
+ * Build a fresh DPoP proof JWT. Always mints a new `jti` — proofs are never cached or reused,
4608
+ * since RFC 9449 §4.3 step 9 requires each to be presented at most once.
4609
+ */
4610
+ async buildProof(request) {
4611
+ const jose = await importJose();
4612
+ const htu = stripQueryAndFragment(request.htu);
4613
+ const nonce = request.nonce ?? this.nonceFor(request.htu);
4614
+ const payload = {
4615
+ jti: randomJti(),
4616
+ htm: request.htm.toUpperCase(),
4617
+ htu,
4618
+ iat: Math.floor(Date.now() / 1e3)
4619
+ };
4620
+ if (request.accessToken !== void 0) payload.ath = await accessTokenHash(request.accessToken);
4621
+ if (nonce !== void 0) payload.nonce = nonce;
4622
+ return new jose.SignJWT(payload).setProtectedHeader({
4623
+ alg: this.keyPair.alg,
4624
+ typ: DPOP_TYP,
4625
+ jwk: this.keyPair.publicJwk
4626
+ }).sign(this.keyPair.privateKey);
4627
+ }
4628
+ };
4629
+ /**
4630
+ * Whether `wwwAuthenticate` advertises a `DPoP` auth-scheme challenge (matched at the start of the
4631
+ * header or after a comma, per RFC 9110 §11.6.1 — a server may list several schemes together, e.g.
4632
+ * `Bearer …, DPoP …`).
4633
+ */
4634
+ function hasDpopChallenge(wwwAuthenticate) {
4635
+ return /(?:^|,)\s*dpop(?:\s|$|,)/i.test(wwwAuthenticate);
4636
+ }
4637
+ /**
4638
+ * Whether `response` is a resource-server `use_dpop_nonce` challenge (RFC 9449 §9): a `401` whose
4639
+ * `WWW-Authenticate` header carries a `DPoP` challenge with `error="use_dpop_nonce"`.
4640
+ *
4641
+ * A conformant retry re-signs the proof with the nonce {@linkcode DpopSession.observeNonce} just
4642
+ * captured — never resend the original proof: RFC 9449 §4.2 requires a unique `jti` per proof, and
4643
+ * replaying one across the challenge/retry boundary is itself a violation.
4644
+ */
4645
+ function isDpopNonceChallenge(response) {
4646
+ if (response.status !== 401) return false;
4647
+ const wwwAuthenticate = response.headers.get("www-authenticate") ?? "";
4648
+ return hasDpopChallenge(wwwAuthenticate) && /use_dpop_nonce/i.test(wwwAuthenticate);
4649
+ }
4650
+
4431
4651
  //#endregion
4432
4652
  //#region src/client/middleware.ts
4433
4653
  /**
@@ -4438,6 +4658,10 @@ async function exchangeJwtAuthGrant(options) {
4438
4658
  * - Handle 401 responses by attempting re-authentication
4439
4659
  * - Retry the original request after successful auth
4440
4660
  * - Handle OAuth errors appropriately ({@linkcode index.OAuthErrorCode.InvalidClient | OAuthErrorCode.InvalidClient}, etc.)
4661
+ * - When {@linkcode OAuthClientProvider.dpop | provider.dpop()} is implemented, present DPoP-bound
4662
+ * tokens with the `DPoP` scheme plus a per-request proof (RFC 9449 / SEP-1932) by composing
4663
+ * {@linkcode withDpopFromProvider} underneath — so a `use_dpop_nonce` challenge is retried
4664
+ * inline on every attempt, independently of the single re-authentication retry here
4441
4665
  *
4442
4666
  * The `baseUrl` parameter is optional and defaults to using the domain from the request URL.
4443
4667
  * However, you should explicitly provide `baseUrl` when:
@@ -4456,7 +4680,8 @@ async function exchangeJwtAuthGrant(options) {
4456
4680
  * @param baseUrl - Base URL for OAuth server discovery (defaults to request URL domain)
4457
4681
  * @returns A fetch middleware function
4458
4682
  */
4459
- const withOAuth = (provider, baseUrl) => (next) => {
4683
+ const withOAuth = (provider, baseUrl) => (baseNext) => {
4684
+ const next = provider.dpop ? withDpopFromProvider(provider)(baseNext) : baseNext;
4460
4685
  return async (input, init) => {
4461
4686
  const makeRequest = async () => {
4462
4687
  const headers = new Headers(init?.headers);
@@ -4474,7 +4699,7 @@ const withOAuth = (provider, baseUrl) => (next) => {
4474
4699
  serverUrl: baseUrl || (typeof input === "string" ? new URL(input).origin : input.origin),
4475
4700
  resourceMetadataUrl,
4476
4701
  scope,
4477
- fetchFn: next
4702
+ fetchFn: baseNext
4478
4703
  });
4479
4704
  if (result === "REDIRECT") throw new UnauthorizedError("Authentication requires user authorization - redirect initiated");
4480
4705
  if (result !== "AUTHORIZED") throw new UnauthorizedError(`Authentication failed with result: ${result}`);
@@ -4488,6 +4713,90 @@ const withOAuth = (provider, baseUrl) => (next) => {
4488
4713
  };
4489
4714
  };
4490
4715
  /**
4716
+ * Creates a fetch wrapper that presents an access token using the `DPoP` Authorization scheme
4717
+ * (RFC 9449 / SEP-1932) instead of `Bearer`: every request carries `Authorization: DPoP <token>`
4718
+ * plus a fresh `DPoP` proof bound to that request's method and URL, a resource-server
4719
+ * `use_dpop_nonce` challenge (RFC 9449 §9) is retried once, inline, with the server-supplied nonce,
4720
+ * and a `DPoP-Nonce` delivered on any response is remembered for the next proof (RFC 9449 §8.2).
4721
+ *
4722
+ * Because it wraps `fetch` itself, the proof is always bound to the request actually sent and every
4723
+ * response is observed — which is why the MCP transports apply this wrapper internally (via
4724
+ * {@linkcode withDpopFromProvider}) when their `authProvider` implements
4725
+ * {@linkcode OAuthClientProvider.dpop | dpop()}, rather than threading request context through
4726
+ * {@linkcode AuthProvider}.
4727
+ *
4728
+ * Use this directly when you already manage the access token yourself (a non-OAuth token source,
4729
+ * or credentials obtained out-of-band) and only need DPoP's request-signing behavior — e.g.
4730
+ * `fetch: withDpop(session, getToken)(fetch)` alongside a minimal `authProvider: { token }`.
4731
+ *
4732
+ * @param session - The DPoP signing session (key pair + nonce state), or a function resolving to
4733
+ * it. Reuse the same session across requests to the same server so its nonce state persists.
4734
+ * When the function resolves to `undefined` the request passes through unchanged.
4735
+ * @param getToken - Returns the current access token, or `undefined` if none is available (the
4736
+ * request passes through unchanged — any `Authorization` header already on it is left as is).
4737
+ * @returns A fetch middleware function
4738
+ */
4739
+ const withDpop = (session, getToken) => (next) => {
4740
+ const resolveSession = typeof session === "function" ? session : () => session;
4741
+ return async (input, init) => {
4742
+ const method = (init?.method ?? "GET").toUpperCase();
4743
+ const url = new URL(input.toString());
4744
+ const activeSession = await resolveSession();
4745
+ if (!activeSession) return next(input, init);
4746
+ const makeRequest = async () => {
4747
+ const accessToken = await getToken();
4748
+ if (!accessToken) return next(input, init);
4749
+ const headers = new Headers(init?.headers);
4750
+ const proof = await activeSession.buildProof({
4751
+ htm: method,
4752
+ htu: url,
4753
+ accessToken
4754
+ });
4755
+ headers.set("Authorization", `DPoP ${accessToken}`);
4756
+ headers.set("DPoP", proof);
4757
+ return next(input, {
4758
+ ...init,
4759
+ headers
4760
+ });
4761
+ };
4762
+ let response = await makeRequest();
4763
+ if (isDpopNonceChallenge(response) && response.headers.has("dpop-nonce")) {
4764
+ activeSession.observeNonce(response, url);
4765
+ await response.text?.().catch(() => {});
4766
+ response = await makeRequest();
4767
+ }
4768
+ activeSession.observeNonce(response, url);
4769
+ return response;
4770
+ };
4771
+ };
4772
+ /**
4773
+ * {@linkcode withDpop} driven by an {@linkcode OAuthClientProvider}: the session comes from
4774
+ * {@linkcode OAuthClientProvider.dpop | provider.dpop()} and the token from
4775
+ * {@linkcode OAuthClientProvider.tokens | provider.tokens()} — presented with the DPoP scheme only
4776
+ * when the AS actually issued `token_type: "DPoP"` (RFC 9449 §7.1); a Bearer token passes through
4777
+ * untouched.
4778
+ *
4779
+ * This is what the MCP transports and {@linkcode withOAuth} compose internally when the provider
4780
+ * implements `dpop()`. Use it directly only when building your own fetch pipeline around an
4781
+ * `OAuthClientProvider` (e.g. a custom re-authorization middleware) — place it *innermost*, below
4782
+ * whatever sets `Authorization: Bearer` and handles 401 re-authentication.
4783
+ */
4784
+ const withDpopFromProvider = (provider) => withDpop(async () => {
4785
+ try {
4786
+ return await provider.dpop?.();
4787
+ } catch (error) {
4788
+ throw markAuthSeamEscape(error);
4789
+ }
4790
+ }, async () => {
4791
+ let tokens;
4792
+ try {
4793
+ tokens = await provider.tokens();
4794
+ } catch (error) {
4795
+ throw markAuthSeamEscape(error);
4796
+ }
4797
+ return tokens?.token_type?.toLowerCase() === "dpop" ? tokens.access_token : void 0;
4798
+ });
4799
+ /**
4491
4800
  * Creates a fetch middleware that logs HTTP requests and responses.
4492
4801
  *
4493
4802
  * When called without arguments `withLogging()`, it uses the default logger that:
@@ -4685,6 +4994,7 @@ var SSEClientTransport = class {
4685
4994
  _skipIssuerMetadataValidation;
4686
4995
  _fetch;
4687
4996
  _fetchWithInit;
4997
+ _dpop;
4688
4998
  _protocolVersion;
4689
4999
  onclose;
4690
5000
  onerror;
@@ -4696,32 +5006,33 @@ var SSEClientTransport = class {
4696
5006
  this._eventSourceInit = opts?.eventSourceInit;
4697
5007
  this._requestInit = opts?.requestInit;
4698
5008
  this._skipIssuerMetadataValidation = opts?.skipIssuerMetadataValidation;
5009
+ this._fetch = opts?.fetch;
4699
5010
  if (isOAuthClientProvider(opts?.authProvider)) {
4700
5011
  this._oauthProvider = opts.authProvider;
4701
5012
  this._authProvider = adaptOAuthProvider(opts.authProvider, { skipIssuerMetadataValidation: opts.skipIssuerMetadataValidation });
5013
+ if (opts.authProvider.dpop) {
5014
+ this._dpop = withDpopFromProvider(opts.authProvider);
5015
+ this._fetch = this._dpop(opts.fetch ?? fetch);
5016
+ }
4702
5017
  } else this._authProvider = opts?.authProvider;
4703
- this._fetch = opts?.fetch;
4704
5018
  this._fetchWithInit = createFetchWithInit(opts?.fetch, opts?.requestInit);
4705
5019
  }
4706
5020
  _last401Response;
4707
5021
  async _commonHeaders() {
4708
- const headers = {};
5022
+ const headers = new Headers(this._requestInit?.headers || void 0);
4709
5023
  let token;
4710
5024
  try {
4711
5025
  token = await this._authProvider?.token();
4712
5026
  } catch (error) {
4713
5027
  throw markAuthSeamEscape(error);
4714
5028
  }
4715
- if (token) headers["Authorization"] = `Bearer ${token}`;
4716
- if (this._protocolVersion) headers["mcp-protocol-version"] = this._protocolVersion;
4717
- const extraHeaders = normalizeHeaders(this._requestInit?.headers);
4718
- return new Headers({
4719
- ...headers,
4720
- ...extraHeaders
4721
- });
5029
+ if (token) headers.set("Authorization", `Bearer ${token}`);
5030
+ if (this._protocolVersion) headers.set("mcp-protocol-version", this._protocolVersion);
5031
+ return headers;
4722
5032
  }
4723
5033
  _startOrAuth() {
4724
- const fetchImpl = this?._eventSourceInit?.fetch ?? this._fetch ?? fetch;
5034
+ const eventSourceFetch = this._eventSourceInit?.fetch;
5035
+ const fetchImpl = eventSourceFetch ? this._dpop?.(eventSourceFetch) ?? eventSourceFetch : this._fetch ?? fetch;
4725
5036
  return new Promise((resolve, reject) => {
4726
5037
  this._eventSource = new EventSource(this._url.href, {
4727
5038
  ...this._eventSourceInit,
@@ -4899,6 +5210,7 @@ const DEFAULT_STREAMABLE_HTTP_RECONNECTION_OPTIONS = {
4899
5210
  */
4900
5211
  const RESERVED_REQUEST_HEADER_NAMES = new Set([
4901
5212
  "authorization",
5213
+ "dpop",
4902
5214
  "content-type",
4903
5215
  "mcp-protocol-version",
4904
5216
  "mcp-method",
@@ -4974,11 +5286,12 @@ var StreamableHTTPClientTransport = class {
4974
5286
  this._scope = void 0;
4975
5287
  this._requestInit = opts?.requestInit;
4976
5288
  this._skipIssuerMetadataValidation = opts?.skipIssuerMetadataValidation;
5289
+ this._fetch = opts?.fetch;
4977
5290
  if (isOAuthClientProvider(opts?.authProvider)) {
4978
5291
  this._oauthProvider = opts.authProvider;
4979
5292
  this._authProvider = adaptOAuthProvider(opts.authProvider, { skipIssuerMetadataValidation: opts.skipIssuerMetadataValidation });
5293
+ if (opts.authProvider.dpop) this._fetch = withDpopFromProvider(opts.authProvider)(opts.fetch ?? fetch);
4980
5294
  } else this._authProvider = opts?.authProvider;
4981
- this._fetch = opts?.fetch;
4982
5295
  this._fetchWithInit = createFetchWithInit(opts?.fetch, opts?.requestInit);
4983
5296
  this._sessionId = opts?.sessionId;
4984
5297
  this._protocolVersion = opts?.protocolVersion;
@@ -5032,21 +5345,17 @@ var StreamableHTTPClientTransport = class {
5032
5345
  });
5033
5346
  }
5034
5347
  async _commonHeaders() {
5035
- const headers = {};
5348
+ const headers = new Headers(this._requestInit?.headers || void 0);
5036
5349
  let token;
5037
5350
  try {
5038
5351
  token = await this._authProvider?.token();
5039
5352
  } catch (error) {
5040
5353
  throw markAuthSeamEscape(error);
5041
5354
  }
5042
- if (token) headers["Authorization"] = `Bearer ${token}`;
5043
- if (this._sessionId) headers["mcp-session-id"] = this._sessionId;
5044
- if (this._protocolVersion) headers["mcp-protocol-version"] = this._protocolVersion;
5045
- const extraHeaders = normalizeHeaders(this._requestInit?.headers);
5046
- return new Headers({
5047
- ...headers,
5048
- ...extraHeaders
5049
- });
5355
+ if (token) headers.set("Authorization", `Bearer ${token}`);
5356
+ if (this._sessionId) headers.set("mcp-session-id", this._sessionId);
5357
+ if (this._protocolVersion) headers.set("mcp-protocol-version", this._protocolVersion);
5358
+ return headers;
5050
5359
  }
5051
5360
  /**
5052
5361
  * Body-derived per-request headers: when an outgoing request carries a
@@ -5062,9 +5371,8 @@ var StreamableHTTPClientTransport = class {
5062
5371
  if (typeof envelopeVersion !== "string") return;
5063
5372
  headers.set("mcp-protocol-version", envelopeVersion);
5064
5373
  headers.set("mcp-method", message.method);
5065
- const params = message.params;
5066
- const nameHeader = message.method === "resources/read" ? typeof params?.uri === "string" ? params.uri : void 0 : typeof params?.name === "string" ? params.name : void 0;
5067
- if (nameHeader !== void 0) headers.set("mcp-name", encodeMcpParamValue(nameHeader));
5374
+ const source = mcpNameSource(message.method, message.params);
5375
+ if (source?.value !== void 0) headers.set("mcp-name", encodeMcpParamValue(source.value));
5068
5376
  }
5069
5377
  /**
5070
5378
  * `true` when the outbound message is a single request carrying a
@@ -5477,5 +5785,5 @@ function fromJsonSchema(schema, validator) {
5477
5785
  }
5478
5786
 
5479
5787
  //#endregion
5480
- export { AuthorizationServerMismatchError, BAGGAGE_META_KEY, CLIENT_CAPABILITIES_META_KEY, CLIENT_INFO_META_KEY, Client, ClientCredentialsProvider, CrossAppAccessProvider, DEFAULT_NEGOTIATED_PROTOCOL_VERSION, DEFAULT_REQUEST_TIMEOUT_MSEC, INTERNAL_ERROR, INVALID_PARAMS, INVALID_REQUEST, InMemoryResponseCacheStore, InMemoryTransport, InsecureTokenEndpointError, InsufficientScopeError, IssuerMismatchError, JSONRPC_VERSION, LATEST_PROTOCOL_VERSION, LOG_LEVEL_META_KEY, MAX_CACHE_TTL_MS, METHOD_NOT_FOUND, MissingRequiredClientCapabilityError, OAuthClientFlowError, OAuthError, OAuthErrorCode, PARSE_ERROR, PROTOCOL_VERSION_META_KEY, PrivateKeyJwtProvider, Protocol, ProtocolError, ProtocolErrorCode, RELATED_TASK_META_KEY, ReadBuffer, RegistrationRejectedError, ResourceNotFoundError, SERVER_INFO_META_KEY, SSEClientTransport, STDIO_DEFAULT_MAX_BUFFER_SIZE, SUBSCRIPTION_ID_META_KEY, SUPPORTED_PROTOCOL_VERSIONS, SdkError, SdkErrorCode, SdkHttpError, SseError, StaticPrivateKeyJwtProvider, StreamableHTTPClientTransport, TRACEPARENT_META_KEY, TRACESTATE_META_KEY, UnauthorizedError, UnsupportedProtocolVersionError, UriTemplate, UrlElicitationRequiredError, applyMiddlewares, assertCompleteRequestPrompt, assertCompleteRequestResourceTemplate, assertSecureTokenEndpoint, auth, buildDiscoveryUrls, checkResourceAllowed, computeScopeUnion, createFetchWithInit, createMiddleware, createPrivateKeyJwtAuth, deserializeMessage, discoverAndRequestJwtAuthGrant, discoverAuthorizationServerMetadata, discoverOAuthMetadata, discoverOAuthProtectedResourceMetadata, discoverOAuthServerInfo, exchangeAuthorization, exchangeJwtAuthGrant, extractResourceMetadataUrl, extractWWWAuthenticateParams, fetchToken, fromJsonSchema, getDisplayName, getSupportedElicitationModes, isCallToolResult, isHttpsUrl, isInitializeRequest, isInitializedNotification, isInputRequiredResult, isJSONRPCErrorResponse, isJSONRPCNotification, isJSONRPCRequest, isJSONRPCResponse, isJSONRPCResultResponse, isJsonContentType, isSpecType, isStrictScopeSuperset, isTaskAugmentedRequestParams, mergeCapabilities, parseErrorResponse, parseJSONRPCMessage, preloadSchemas, prepareAuthorizationCodeRequest, refreshAuthorization, registerClient, requestJwtAuthorizationGrant, resolveClientMetadata, resourceUrlFromServerUrl, selectClientAuthMethod, selectResourceURL, serializeMessage, specTypeSchemas, startAuthorization, validateAuthorizationResponseIssuer, validateClientMetadataUrl, withInputRequired, withLogging, withOAuth };
5788
+ export { AuthorizationServerMismatchError, BAGGAGE_META_KEY, CLIENT_CAPABILITIES_META_KEY, CLIENT_INFO_META_KEY, Client, ClientCredentialsProvider, CrossAppAccessProvider, DEFAULT_NEGOTIATED_PROTOCOL_VERSION, DEFAULT_REQUEST_TIMEOUT_MSEC, DPOP_SUPPORTED_ALGS, DpopSession, INTERNAL_ERROR, INVALID_PARAMS, INVALID_REQUEST, InMemoryResponseCacheStore, InMemoryTransport, InsecureTokenEndpointError, InsufficientScopeError, IssuerMismatchError, JSONRPC_VERSION, LATEST_PROTOCOL_VERSION, LOG_LEVEL_META_KEY, MAX_CACHE_TTL_MS, METHOD_NOT_FOUND, MissingRequiredClientCapabilityError, OAuthClientFlowError, OAuthError, OAuthErrorCode, PARSE_ERROR, PROTOCOL_VERSION_META_KEY, PrivateKeyJwtProvider, Protocol, ProtocolError, ProtocolErrorCode, RELATED_TASK_META_KEY, ReadBuffer, RegistrationRejectedError, ResourceNotFoundError, SERVER_INFO_META_KEY, SSEClientTransport, STDIO_DEFAULT_MAX_BUFFER_SIZE, SUBSCRIPTION_ID_META_KEY, SUPPORTED_PROTOCOL_VERSIONS, SdkError, SdkErrorCode, SdkHttpError, SseError, StaticPrivateKeyJwtProvider, StreamableHTTPClientTransport, TRACEPARENT_META_KEY, TRACESTATE_META_KEY, UnauthorizedError, UnsupportedProtocolVersionError, UriTemplate, UrlElicitationRequiredError, accessTokenHash, applyMiddlewares, assertCompleteRequestPrompt, assertCompleteRequestResourceTemplate, assertSecureTokenEndpoint, auth, buildDiscoveryUrls, checkResourceAllowed, computeScopeUnion, createFetchWithInit, createMiddleware, createPrivateKeyJwtAuth, deserializeMessage, discoverAndRequestJwtAuthGrant, discoverAuthorizationServerMetadata, discoverOAuthMetadata, discoverOAuthProtectedResourceMetadata, discoverOAuthServerInfo, exchangeAuthorization, exchangeJwtAuthGrant, extractResourceMetadataUrl, extractWWWAuthenticateParams, fetchToken, fromJsonSchema, generateDpopKeyPair, getDisplayName, getSupportedElicitationModes, isCallToolResult, isDpopNonceChallenge, isHttpsUrl, isInitializeRequest, isInitializedNotification, isInputRequiredResult, isJSONRPCErrorResponse, isJSONRPCNotification, isJSONRPCRequest, isJSONRPCResponse, isJSONRPCResultResponse, isJsonContentType, isSpecType, isStrictScopeSuperset, isTaskAugmentedRequestParams, mergeCapabilities, parseErrorResponse, parseJSONRPCMessage, preloadSchemas, prepareAuthorizationCodeRequest, refreshAuthorization, registerClient, requestJwtAuthorizationGrant, resolveClientMetadata, resourceUrlFromServerUrl, selectClientAuthMethod, selectResourceURL, serializeMessage, specTypeSchemas, startAuthorization, validateAuthorizationResponseIssuer, validateClientMetadataUrl, withDpop, withDpopFromProvider, withInputRequired, withLogging, withOAuth };
5481
5789
  //# sourceMappingURL=index.mjs.map