@mcp-ts/sdk 1.6.0 → 1.6.2

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 (45) hide show
  1. package/dist/adapters/agui-adapter.d.mts +2 -2
  2. package/dist/adapters/agui-adapter.d.ts +2 -2
  3. package/dist/adapters/agui-middleware.d.mts +2 -2
  4. package/dist/adapters/agui-middleware.d.ts +2 -2
  5. package/dist/adapters/ai-adapter.d.mts +2 -2
  6. package/dist/adapters/ai-adapter.d.ts +2 -2
  7. package/dist/adapters/langchain-adapter.d.mts +2 -2
  8. package/dist/adapters/langchain-adapter.d.ts +2 -2
  9. package/dist/client/index.d.mts +2 -2
  10. package/dist/client/index.d.ts +2 -2
  11. package/dist/client/react.d.mts +4 -4
  12. package/dist/client/react.d.ts +4 -4
  13. package/dist/client/react.js +96 -44
  14. package/dist/client/react.js.map +1 -1
  15. package/dist/client/react.mjs +96 -44
  16. package/dist/client/react.mjs.map +1 -1
  17. package/dist/client/vue.d.mts +4 -4
  18. package/dist/client/vue.d.ts +4 -4
  19. package/dist/{index-GfC_eNEv.d.ts → index-DhA-OEAe.d.ts} +1 -1
  20. package/dist/{index-DcYfpY3H.d.mts → index-bFL4ZF2N.d.mts} +1 -1
  21. package/dist/index.d.mts +3 -3
  22. package/dist/index.d.ts +3 -3
  23. package/dist/index.js +12 -2
  24. package/dist/index.js.map +1 -1
  25. package/dist/index.mjs +12 -2
  26. package/dist/index.mjs.map +1 -1
  27. package/dist/server/index.d.mts +2 -2
  28. package/dist/server/index.d.ts +2 -2
  29. package/dist/server/index.js +12 -2
  30. package/dist/server/index.js.map +1 -1
  31. package/dist/server/index.mjs +12 -2
  32. package/dist/server/index.mjs.map +1 -1
  33. package/dist/shared/index.d.mts +4 -4
  34. package/dist/shared/index.d.ts +4 -4
  35. package/dist/shared/index.js.map +1 -1
  36. package/dist/shared/index.mjs.map +1 -1
  37. package/dist/{tool-router-_O2tIwf7.d.mts → tool-router-BVaV1udm.d.mts} +1 -1
  38. package/dist/{tool-router-Bn9R0KWr.d.ts → tool-router-Dh2804tM.d.ts} +1 -1
  39. package/dist/{types-CfCoIsWI.d.mts → types-rIuN1CQi.d.mts} +1 -0
  40. package/dist/{types-CfCoIsWI.d.ts → types-rIuN1CQi.d.ts} +1 -0
  41. package/package.json +1 -1
  42. package/src/client/react/oauth-popup.tsx +111 -51
  43. package/src/server/handlers/sse-handler.ts +12 -0
  44. package/src/server/mcp/oauth-client.ts +6 -2
  45. package/src/shared/types.ts +1 -0
@@ -625,14 +625,31 @@ function useMcp(options) {
625
625
  }
626
626
  var AUTH_CODE_MESSAGE = "MCP_AUTH_CODE";
627
627
  var AUTH_RESULT_MESSAGE = "MCP_AUTH_RESULT";
628
+ var AUTH_CHANNEL_NAME = "mcp-auth-channel";
629
+ function createAuthBroadcastChannel() {
630
+ if (typeof BroadcastChannel === "undefined") {
631
+ return null;
632
+ }
633
+ try {
634
+ return new BroadcastChannel(AUTH_CHANNEL_NAME);
635
+ } catch {
636
+ return null;
637
+ }
638
+ }
628
639
  function postPopupResult(popupWindow, result) {
629
- popupWindow?.postMessage(
630
- {
631
- type: AUTH_RESULT_MESSAGE,
632
- ...result
633
- },
634
- window.location.origin
635
- );
640
+ const payload = {
641
+ type: AUTH_RESULT_MESSAGE,
642
+ ...result
643
+ };
644
+ try {
645
+ popupWindow?.postMessage(payload, window.location.origin);
646
+ } catch {
647
+ }
648
+ const channel = createAuthBroadcastChannel();
649
+ if (channel) {
650
+ channel.postMessage(payload);
651
+ channel.close();
652
+ }
636
653
  }
637
654
  function openCenteredPopup(url, options = {}) {
638
655
  const {
@@ -673,60 +690,87 @@ function createOAuthPopupRedirectHandler(options = {}) {
673
690
  }
674
691
  function useMcpOAuthPopup(connections, finishAuth) {
675
692
  const pendingPopupsRef = useRef(/* @__PURE__ */ new Map());
693
+ const processingCodesRef = useRef(/* @__PURE__ */ new Set());
676
694
  useEffect(() => {
677
695
  const handleMessage = async (event) => {
678
- if (event.origin !== window.location.origin) {
696
+ if (event.origin && event.origin !== window.location.origin) {
679
697
  return;
680
698
  }
681
- if (event.data?.type !== AUTH_CODE_MESSAGE || !event.data.code) {
699
+ const code = typeof event.data?.code === "string" ? event.data.code : "";
700
+ if (event.data?.type !== AUTH_CODE_MESSAGE || !code) {
682
701
  return;
683
702
  }
684
703
  const popupWindow = event.source && "postMessage" in event.source ? event.source : null;
685
704
  const targetSessionId = typeof event.data.sessionId === "string" ? event.data.sessionId : "";
705
+ if (popupWindow && targetSessionId) {
706
+ pendingPopupsRef.current.set(targetSessionId, popupWindow);
707
+ }
686
708
  if (!targetSessionId) {
687
- postPopupResult(popupWindow, {
688
- success: false,
689
- error: "Missing OAuth session identifier"
690
- });
709
+ if (popupWindow) {
710
+ postPopupResult(popupWindow, {
711
+ success: false,
712
+ error: "Missing OAuth session identifier"
713
+ });
714
+ }
691
715
  return;
692
716
  }
693
717
  const targetSession = connections.find((connection) => connection.sessionId === targetSessionId);
694
718
  if (!targetSession) {
695
- postPopupResult(popupWindow, {
696
- sessionId: targetSessionId,
697
- success: false,
698
- error: "OAuth session not found in the current client state"
699
- });
719
+ if (popupWindow) {
720
+ postPopupResult(popupWindow, {
721
+ sessionId: targetSessionId,
722
+ success: false,
723
+ error: "OAuth session not found in the current client state"
724
+ });
725
+ }
700
726
  return;
701
727
  }
702
- if (popupWindow) {
703
- pendingPopupsRef.current.set(targetSession.sessionId, popupWindow);
728
+ const codeKey = `${targetSession.sessionId}:${code}`;
729
+ if (processingCodesRef.current.has(codeKey)) {
730
+ return;
704
731
  }
732
+ processingCodesRef.current.add(codeKey);
705
733
  try {
706
- await finishAuth(targetSession.sessionId, event.data.code);
734
+ await finishAuth(targetSession.sessionId, code);
707
735
  } catch (error) {
736
+ processingCodesRef.current.delete(codeKey);
708
737
  pendingPopupsRef.current.delete(targetSession.sessionId);
709
- postPopupResult(popupWindow, {
710
- sessionId: targetSession.sessionId,
711
- success: false,
712
- error: error instanceof Error ? error.message : "Failed to finish auth"
713
- });
738
+ if (popupWindow) {
739
+ postPopupResult(popupWindow, {
740
+ sessionId: targetSession.sessionId,
741
+ success: false,
742
+ error: error instanceof Error ? error.message : "Failed to finish auth"
743
+ });
744
+ }
745
+ }
746
+ };
747
+ const channel = createAuthBroadcastChannel();
748
+ const handleChannelMessage = (event) => {
749
+ if (event.data?.type === AUTH_CODE_MESSAGE) {
750
+ void handleMessage(event);
714
751
  }
715
752
  };
716
753
  window.addEventListener("message", handleMessage);
717
- return () => window.removeEventListener("message", handleMessage);
754
+ channel?.addEventListener("message", handleChannelMessage);
755
+ return () => {
756
+ window.removeEventListener("message", handleMessage);
757
+ channel?.removeEventListener("message", handleChannelMessage);
758
+ channel?.close();
759
+ };
718
760
  }, [connections, finishAuth]);
719
761
  useEffect(() => {
720
762
  for (const connection of connections) {
721
- const popupWindow = pendingPopupsRef.current.get(connection.sessionId);
722
- if (!popupWindow) {
723
- continue;
724
- }
725
- if (connection.state === "AUTHENTICATED") {
763
+ const popupWindow = pendingPopupsRef.current.get(connection.sessionId) || null;
764
+ if (connection.state === "AUTHENTICATED" || connection.state === "READY" || connection.state === "CONNECTED") {
726
765
  postPopupResult(popupWindow, {
727
766
  sessionId: connection.sessionId,
728
767
  success: true
729
768
  });
769
+ for (const codeKey of processingCodesRef.current) {
770
+ if (codeKey.startsWith(`${connection.sessionId}:`)) {
771
+ processingCodesRef.current.delete(codeKey);
772
+ }
773
+ }
730
774
  pendingPopupsRef.current.delete(connection.sessionId);
731
775
  continue;
732
776
  }
@@ -736,6 +780,11 @@ function useMcpOAuthPopup(connections, finishAuth) {
736
780
  success: false,
737
781
  error: connection.error || "Failed to complete authorization"
738
782
  });
783
+ for (const codeKey of processingCodesRef.current) {
784
+ if (codeKey.startsWith(`${connection.sessionId}:`)) {
785
+ processingCodesRef.current.delete(codeKey);
786
+ }
787
+ }
739
788
  pendingPopupsRef.current.delete(connection.sessionId);
740
789
  }
741
790
  }
@@ -756,10 +805,9 @@ function McpOAuthCallbackContent({
756
805
  }) {
757
806
  const [phase, setPhase] = useState(debugPhase || "loading");
758
807
  const [errorMessage, setErrorMessage] = useState("");
759
- const openerMissing = typeof window !== "undefined" ? !window.opener : false;
760
808
  const missingCode = !code;
761
809
  const missingSessionId = !sessionId;
762
- const blockingError = openerMissing ? "Error: No opener window found. This window should be opened from the app." : missingCode ? "Error: No authorization code received." : missingSessionId ? "Error: No OAuth state received." : null;
810
+ const blockingError = missingCode ? "Error: No authorization code received." : missingSessionId ? "Error: No OAuth state received." : null;
763
811
  useEffect(() => {
764
812
  if (debugPhase) {
765
813
  setPhase(debugPhase);
@@ -772,8 +820,9 @@ function McpOAuthCallbackContent({
772
820
  return;
773
821
  }
774
822
  let closed = false;
823
+ const channel = createAuthBroadcastChannel();
775
824
  const handleResult = (event) => {
776
- if (event.origin !== window.location.origin) {
825
+ if (event.origin && event.origin !== window.location.origin) {
777
826
  return;
778
827
  }
779
828
  if (event.data?.type !== AUTH_RESULT_MESSAGE) {
@@ -785,6 +834,7 @@ function McpOAuthCallbackContent({
785
834
  if (event.data.success) {
786
835
  setPhase("success");
787
836
  window.removeEventListener("message", handleResult);
837
+ channel?.close();
788
838
  closed = true;
789
839
  window.setTimeout(() => window.close(), 1200);
790
840
  return;
@@ -794,21 +844,23 @@ function McpOAuthCallbackContent({
794
844
  setErrorMessage(message);
795
845
  };
796
846
  window.addEventListener("message", handleResult);
797
- try {
798
- window.opener.postMessage(
799
- { type: AUTH_CODE_MESSAGE, code, sessionId },
800
- window.location.origin
801
- );
802
- } catch (error) {
803
- console.error("Failed to communicate with opener:", error);
804
- window.setTimeout(() => {
847
+ channel?.addEventListener("message", handleResult);
848
+ const payload = { type: AUTH_CODE_MESSAGE, code, sessionId };
849
+ if (window.opener) {
850
+ try {
851
+ window.opener.postMessage(payload, window.location.origin);
852
+ } catch {
805
853
  setPhase("error");
806
854
  setErrorMessage("Error: Could not communicate with main window.");
807
- }, 0);
855
+ }
856
+ }
857
+ if (channel) {
858
+ channel.postMessage(payload);
808
859
  }
809
860
  return () => {
810
861
  if (!closed) {
811
862
  window.removeEventListener("message", handleResult);
863
+ channel?.close();
812
864
  }
813
865
  };
814
866
  }, [blockingError, code, sessionId, debugPhase]);