@mcp-ts/sdk 1.5.0 → 1.5.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 (66) hide show
  1. package/dist/adapters/agui-adapter.d.mts +1 -1
  2. package/dist/adapters/agui-adapter.d.ts +1 -1
  3. package/dist/adapters/agui-adapter.js +43 -9
  4. package/dist/adapters/agui-adapter.js.map +1 -1
  5. package/dist/adapters/agui-adapter.mjs +43 -9
  6. package/dist/adapters/agui-adapter.mjs.map +1 -1
  7. package/dist/adapters/agui-middleware.d.mts +1 -1
  8. package/dist/adapters/agui-middleware.d.ts +1 -1
  9. package/dist/adapters/agui-middleware.js.map +1 -1
  10. package/dist/adapters/agui-middleware.mjs.map +1 -1
  11. package/dist/adapters/ai-adapter.d.mts +1 -1
  12. package/dist/adapters/ai-adapter.d.ts +1 -1
  13. package/dist/adapters/ai-adapter.js +42 -8
  14. package/dist/adapters/ai-adapter.js.map +1 -1
  15. package/dist/adapters/ai-adapter.mjs +42 -8
  16. package/dist/adapters/ai-adapter.mjs.map +1 -1
  17. package/dist/adapters/langchain-adapter.d.mts +1 -1
  18. package/dist/adapters/langchain-adapter.d.ts +1 -1
  19. package/dist/adapters/langchain-adapter.js +42 -8
  20. package/dist/adapters/langchain-adapter.js.map +1 -1
  21. package/dist/adapters/langchain-adapter.mjs +42 -8
  22. package/dist/adapters/langchain-adapter.mjs.map +1 -1
  23. package/dist/client/react.d.mts +91 -2
  24. package/dist/client/react.d.ts +91 -2
  25. package/dist/client/react.js +339 -3
  26. package/dist/client/react.js.map +1 -1
  27. package/dist/client/react.mjs +335 -4
  28. package/dist/client/react.mjs.map +1 -1
  29. package/dist/client/vue.d.mts +10 -0
  30. package/dist/client/vue.d.ts +10 -0
  31. package/dist/client/vue.js +28 -2
  32. package/dist/client/vue.js.map +1 -1
  33. package/dist/client/vue.mjs +28 -2
  34. package/dist/client/vue.mjs.map +1 -1
  35. package/dist/index.d.mts +1 -1
  36. package/dist/index.d.ts +1 -1
  37. package/dist/index.js +170 -37
  38. package/dist/index.js.map +1 -1
  39. package/dist/index.mjs +170 -37
  40. package/dist/index.mjs.map +1 -1
  41. package/dist/server/index.js +55 -11
  42. package/dist/server/index.js.map +1 -1
  43. package/dist/server/index.mjs +55 -11
  44. package/dist/server/index.mjs.map +1 -1
  45. package/dist/shared/index.d.mts +2 -2
  46. package/dist/shared/index.d.ts +2 -2
  47. package/dist/shared/index.js +115 -26
  48. package/dist/shared/index.js.map +1 -1
  49. package/dist/shared/index.mjs +115 -26
  50. package/dist/shared/index.mjs.map +1 -1
  51. package/dist/{tool-router-XnWVxPzv.d.mts → tool-router-DK0RJblO.d.mts} +3 -0
  52. package/dist/{tool-router-Bo8qZbsD.d.ts → tool-router-DsKhRmJm.d.ts} +3 -0
  53. package/package.json +1 -1
  54. package/src/adapters/agui-adapter.ts +7 -7
  55. package/src/adapters/ai-adapter.ts +5 -5
  56. package/src/adapters/langchain-adapter.ts +5 -5
  57. package/src/client/react/index.ts +14 -0
  58. package/src/client/react/oauth-popup.tsx +446 -0
  59. package/src/client/react/use-mcp.ts +84 -3
  60. package/src/client/vue/use-mcp.ts +80 -3
  61. package/src/server/handlers/sse-handler.ts +39 -0
  62. package/src/server/mcp/oauth-client.ts +32 -14
  63. package/src/shared/meta-tools.ts +62 -13
  64. package/src/shared/tool-index.ts +85 -12
  65. package/src/shared/tool-router.ts +8 -7
  66. package/supabase/migrations/20260421010000_add_session_cleanup_cron.sql +32 -0
@@ -4,7 +4,7 @@ import { c as McpConnectionState, M as McpConnectionEvent } from '../events-CK3N
4
4
  export { D as Disposable, a as DisposableStore, E as Emitter, b as Event, d as McpObservabilityEvent } from '../events-CK3N--3g.js';
5
5
  import { v as ToolInfo, k as FinishAuthResult, n as ListToolsRpcResult, L as ListPromptsResult, l as ListResourcesResult } from '../types-CfCoIsWI.js';
6
6
  export { p as McpRpcRequest, q as McpRpcResponse } from '../types-CfCoIsWI.js';
7
- import React$1 from 'react';
7
+ import React$1, { ReactNode, CSSProperties } from 'react';
8
8
  import '@modelcontextprotocol/ext-apps/app-bridge';
9
9
  import '@modelcontextprotocol/sdk/types.js';
10
10
 
@@ -100,6 +100,16 @@ interface McpClient$1 {
100
100
  * Disconnect from an MCP server
101
101
  */
102
102
  disconnect: (sessionId: string) => Promise<void>;
103
+ /**
104
+ * Reconnect to an MCP server (disconnects existing session first)
105
+ */
106
+ reconnect: (params: {
107
+ serverId: string;
108
+ serverName: string;
109
+ serverUrl: string;
110
+ callbackUrl: string;
111
+ transportType?: 'sse' | 'streamable_http';
112
+ }) => Promise<string>;
103
113
  /**
104
114
  * Get connection by session ID
105
115
  */
@@ -170,6 +180,85 @@ interface McpClient$1 {
170
180
  */
171
181
  declare function useMcp(options: UseMcpOptions): McpClient$1;
172
182
 
183
+ interface OAuthPopupConnectionLike {
184
+ sessionId: string;
185
+ state: string;
186
+ error?: string;
187
+ }
188
+ /**
189
+ * Optional helpers for popup-based OAuth UX.
190
+ *
191
+ * These utilities sit on top of the core MCP auth primitives:
192
+ * - `useMcp({ onRedirect })` to decide how auth navigation happens
193
+ * - `finishAuth(sessionId, code)` to complete code exchange
194
+ *
195
+ * Consumers are free to:
196
+ * - use these helpers as-is for a turnkey popup flow
197
+ * - build their own popup UI/message bridge
198
+ * - skip popups entirely and handle auth in a normal callback page
199
+ */
200
+ interface OAuthPopupRedirectOptions {
201
+ width?: number;
202
+ height?: number;
203
+ windowName?: string;
204
+ features?: string[];
205
+ onBlocked?: (url: string) => void;
206
+ }
207
+ interface McpOAuthCallbackContentProps {
208
+ code?: string | null;
209
+ sessionId?: string | null;
210
+ title?: ReactNode;
211
+ initialStatus?: string;
212
+ loadingFallback?: ReactNode;
213
+ rootStyle?: CSSProperties;
214
+ cardStyle?: CSSProperties;
215
+ titleStyle?: CSSProperties;
216
+ messageStyle?: CSSProperties;
217
+ renderContainer?: (content: ReactNode) => ReactNode;
218
+ debugPhase?: 'loading' | 'success' | 'error';
219
+ }
220
+ /**
221
+ * Opens a centered popup window for OAuth.
222
+ *
223
+ * Convenience only: callers can replace this entirely with their own popup,
224
+ * modal, redirect, or router-based navigation strategy.
225
+ */
226
+ declare function openCenteredPopup(url: string, options?: OAuthPopupRedirectOptions): Window | null;
227
+ /**
228
+ * Creates an `onRedirect` handler suitable for `useMcp({ onRedirect })`.
229
+ *
230
+ * This is the simplest popup entry point, but it is intentionally optional.
231
+ * Applications can provide any redirect handler they want, including full-page
232
+ * navigation or a completely custom popup implementation.
233
+ */
234
+ declare function createOAuthPopupRedirectHandler(options?: OAuthPopupRedirectOptions): (url: string) => void;
235
+ /**
236
+ * Handles opener-side popup coordination for OAuth code exchange.
237
+ *
238
+ * Use this when you want popup auth but do not want to reimplement the
239
+ * postMessage wiring between the main app window and the popup callback page.
240
+ *
241
+ * If you are not using a popup flow, you do not need this hook.
242
+ */
243
+ declare function useMcpOAuthPopup<TConnection extends OAuthPopupConnectionLike>(connections: TConnection[], finishAuth: (sessionId: string, code: string) => Promise<unknown>): void;
244
+ /**
245
+ * Default popup callback UI for popup-based OAuth flows.
246
+ *
247
+ * This component reads the OAuth `code` and `state/sessionId`, notifies the
248
+ * opener window, waits for success/failure, and closes the popup on success.
249
+ *
250
+ * It is intentionally optional: apps can replace it with their own callback
251
+ * page UI or skip popup auth entirely and call `finishAuth(sessionId, code)`
252
+ * from any callback route they control.
253
+ */
254
+ declare function McpOAuthCallbackContent({ code, sessionId, title, initialStatus, loadingFallback, rootStyle, cardStyle, titleStyle, messageStyle, renderContainer, debugPhase, }: McpOAuthCallbackContentProps): JSX.Element;
255
+ /**
256
+ * Tiny fallback component for Suspense-wrapped callback pages.
257
+ */
258
+ declare function McpOAuthCallbackFallback({ children, }: {
259
+ children?: ReactNode;
260
+ }): JSX.Element;
261
+
173
262
  /**
174
263
  * Hook to host an MCP App in a React component
175
264
  *
@@ -256,4 +345,4 @@ declare function useMcpApps(mcpClient: McpClient | null): {
256
345
  };
257
346
  declare function getMcpAppMetadata(mcpClient: McpClient | null, toolName: string, input?: Record<string, unknown> | null): McpAppMetadata | undefined;
258
347
 
259
- export { AppHost, type McpAppMetadata, McpAppRenderer, type McpAppRendererHandle, type McpAppRendererProps, type McpClient$1 as McpClient, type McpConnection, McpConnectionEvent, McpConnectionState, SSEClient, ToolInfo, type UseMcpOptions, getMcpAppMetadata, useAppHost, useMcp, useMcpApps };
348
+ export { AppHost, type McpAppMetadata, McpAppRenderer, type McpAppRendererHandle, type McpAppRendererProps, type McpClient$1 as McpClient, type McpConnection, McpConnectionEvent, McpConnectionState, McpOAuthCallbackContent, type McpOAuthCallbackContentProps, McpOAuthCallbackFallback, type OAuthPopupConnectionLike, type OAuthPopupRedirectOptions, SSEClient, ToolInfo, type UseMcpOptions, createOAuthPopupRedirectHandler, getMcpAppMetadata, openCenteredPopup, useAppHost, useMcp, useMcpApps, useMcpOAuthPopup };
@@ -2,8 +2,8 @@
2
2
 
3
3
  var react = require('react');
4
4
  var nanoid = require('nanoid');
5
- var appBridge = require('@modelcontextprotocol/ext-apps/app-bridge');
6
5
  var jsxRuntime = require('react/jsx-runtime');
6
+ var appBridge = require('@modelcontextprotocol/ext-apps/app-bridge');
7
7
 
8
8
  var __defProp = Object.defineProperty;
9
9
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
@@ -315,12 +315,19 @@ function useMcp(options) {
315
315
  const updateConnectionsFromEvent = react.useCallback((event) => {
316
316
  if (!isMountedRef.current) return;
317
317
  const isTransientReconnectState = (state) => state === "INITIALIZING" || state === "VALIDATING" || state === "RECONNECTING" || state === "CONNECTING" || state === "CONNECTED" || state === "DISCOVERING";
318
+ const getVisibleState = (incomingState, existingState, previousState) => {
319
+ if (incomingState === "INITIALIZING" && (existingState === "AUTHENTICATING" || existingState === "AUTHENTICATED" || previousState === "AUTHENTICATING" || previousState === "AUTHENTICATED")) {
320
+ return existingState === "AUTHENTICATED" || previousState === "AUTHENTICATED" ? "AUTHENTICATED" : "AUTHENTICATING";
321
+ }
322
+ return incomingState;
323
+ };
318
324
  setConnections((prev) => {
319
325
  switch (event.type) {
320
326
  case "state_changed": {
321
327
  const existing = prev.find((c) => c.sessionId === event.sessionId);
322
328
  if (existing) {
323
- const nextState = existing.state === "READY" && isTransientReconnectState(event.state) ? existing.state : event.state;
329
+ const normalizedState = getVisibleState(event.state, existing.state, event.previousState);
330
+ const nextState = existing.state === "READY" && isTransientReconnectState(normalizedState) ? existing.state : normalizedState;
324
331
  return prev.map(
325
332
  (c) => c.sessionId === event.sessionId ? {
326
333
  ...c,
@@ -340,7 +347,9 @@ function useMcp(options) {
340
347
  serverId: event.serverId,
341
348
  serverName: event.serverName,
342
349
  serverUrl: event.serverUrl,
343
- state: event.state,
350
+ // New connections do not have prior local state, so we normalize
351
+ // only against the server-reported previous state.
352
+ state: getVisibleState(event.state, void 0, event.previousState),
344
353
  createdAt: event.createdAt ? new Date(event.createdAt) : void 0,
345
354
  tools: []
346
355
  }
@@ -449,6 +458,27 @@ function useMcp(options) {
449
458
  },
450
459
  []
451
460
  );
461
+ const reconnect = react.useCallback(
462
+ async (params) => {
463
+ if (!clientRef.current) {
464
+ throw new Error("SSE client not initialized");
465
+ }
466
+ const existing = connections.find(
467
+ (c) => c.serverId === params.serverId || c.serverUrl === params.serverUrl
468
+ );
469
+ if (existing) {
470
+ await clientRef.current.disconnectFromServer(existing.sessionId);
471
+ if (isMountedRef.current) {
472
+ setConnections(
473
+ (prev) => prev.filter((c) => c.sessionId !== existing.sessionId)
474
+ );
475
+ }
476
+ }
477
+ const result = await clientRef.current.connectToServer(params);
478
+ return result.sessionId;
479
+ },
480
+ [connections]
481
+ );
452
482
  const disconnect = react.useCallback(async (sessionId) => {
453
483
  if (!clientRef.current) {
454
484
  throw new Error("SSE client not initialized");
@@ -550,6 +580,7 @@ function useMcp(options) {
550
580
  status,
551
581
  isInitializing,
552
582
  connect,
583
+ reconnect,
553
584
  disconnect,
554
585
  getConnection,
555
586
  getConnectionByServerId,
@@ -573,6 +604,7 @@ function useMcp(options) {
573
604
  status,
574
605
  isInitializing,
575
606
  connect,
607
+ reconnect,
576
608
  disconnect,
577
609
  getConnection,
578
610
  getConnectionByServerId,
@@ -593,6 +625,305 @@ function useMcp(options) {
593
625
  ]
594
626
  );
595
627
  }
628
+ var AUTH_CODE_MESSAGE = "MCP_AUTH_CODE";
629
+ var AUTH_RESULT_MESSAGE = "MCP_AUTH_RESULT";
630
+ function postPopupResult(popupWindow, result) {
631
+ popupWindow?.postMessage(
632
+ {
633
+ type: AUTH_RESULT_MESSAGE,
634
+ ...result
635
+ },
636
+ window.location.origin
637
+ );
638
+ }
639
+ function openCenteredPopup(url, options = {}) {
640
+ const {
641
+ width = 600,
642
+ height = 700,
643
+ windowName = "mcp-auth-popup",
644
+ features = [],
645
+ onBlocked
646
+ } = options;
647
+ const left = window.screenX + (window.outerWidth - width) / 2;
648
+ const top = window.screenY + (window.outerHeight - height) / 2;
649
+ const featureList = [
650
+ `width=${width}`,
651
+ `height=${height}`,
652
+ `left=${left}`,
653
+ `top=${top}`,
654
+ "resizable=yes",
655
+ "scrollbars=yes",
656
+ "status=yes",
657
+ ...features
658
+ ].join(",");
659
+ const popup = window.open(url, windowName, featureList);
660
+ if (!popup) {
661
+ onBlocked?.(url);
662
+ }
663
+ return popup;
664
+ }
665
+ function createOAuthPopupRedirectHandler(options = {}) {
666
+ return (url) => {
667
+ openCenteredPopup(url, {
668
+ ...options,
669
+ onBlocked: options.onBlocked ?? ((blockedUrl) => {
670
+ window.alert("Popup blocked! Allow popups for this site to complete authentication.");
671
+ window.location.href = blockedUrl;
672
+ })
673
+ });
674
+ };
675
+ }
676
+ function useMcpOAuthPopup(connections, finishAuth) {
677
+ const pendingPopupsRef = react.useRef(/* @__PURE__ */ new Map());
678
+ react.useEffect(() => {
679
+ const handleMessage = async (event) => {
680
+ if (event.origin !== window.location.origin) {
681
+ return;
682
+ }
683
+ if (event.data?.type !== AUTH_CODE_MESSAGE || !event.data.code) {
684
+ return;
685
+ }
686
+ const popupWindow = event.source && "postMessage" in event.source ? event.source : null;
687
+ const targetSessionId = typeof event.data.sessionId === "string" ? event.data.sessionId : "";
688
+ if (!targetSessionId) {
689
+ postPopupResult(popupWindow, {
690
+ success: false,
691
+ error: "Missing OAuth session identifier"
692
+ });
693
+ return;
694
+ }
695
+ const targetSession = connections.find((connection) => connection.sessionId === targetSessionId);
696
+ if (!targetSession) {
697
+ postPopupResult(popupWindow, {
698
+ sessionId: targetSessionId,
699
+ success: false,
700
+ error: "OAuth session not found in the current client state"
701
+ });
702
+ return;
703
+ }
704
+ if (popupWindow) {
705
+ pendingPopupsRef.current.set(targetSession.sessionId, popupWindow);
706
+ }
707
+ try {
708
+ await finishAuth(targetSession.sessionId, event.data.code);
709
+ } catch (error) {
710
+ pendingPopupsRef.current.delete(targetSession.sessionId);
711
+ postPopupResult(popupWindow, {
712
+ sessionId: targetSession.sessionId,
713
+ success: false,
714
+ error: error instanceof Error ? error.message : "Failed to finish auth"
715
+ });
716
+ }
717
+ };
718
+ window.addEventListener("message", handleMessage);
719
+ return () => window.removeEventListener("message", handleMessage);
720
+ }, [connections, finishAuth]);
721
+ react.useEffect(() => {
722
+ for (const connection of connections) {
723
+ const popupWindow = pendingPopupsRef.current.get(connection.sessionId);
724
+ if (!popupWindow) {
725
+ continue;
726
+ }
727
+ if (connection.state === "AUTHENTICATED") {
728
+ postPopupResult(popupWindow, {
729
+ sessionId: connection.sessionId,
730
+ success: true
731
+ });
732
+ pendingPopupsRef.current.delete(connection.sessionId);
733
+ continue;
734
+ }
735
+ if (connection.state === "FAILED") {
736
+ postPopupResult(popupWindow, {
737
+ sessionId: connection.sessionId,
738
+ success: false,
739
+ error: connection.error || "Failed to complete authorization"
740
+ });
741
+ pendingPopupsRef.current.delete(connection.sessionId);
742
+ }
743
+ }
744
+ }, [connections]);
745
+ }
746
+ function McpOAuthCallbackContent({
747
+ code,
748
+ sessionId,
749
+ title = "Verifying Authorization",
750
+ initialStatus = "Completing your authorization...",
751
+ loadingFallback = "Loading...",
752
+ rootStyle,
753
+ cardStyle,
754
+ titleStyle,
755
+ messageStyle,
756
+ renderContainer,
757
+ debugPhase
758
+ }) {
759
+ const [phase, setPhase] = react.useState(debugPhase || "loading");
760
+ const [errorMessage, setErrorMessage] = react.useState("");
761
+ const openerMissing = typeof window !== "undefined" ? !window.opener : false;
762
+ const missingCode = !code;
763
+ const missingSessionId = !sessionId;
764
+ 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;
765
+ react.useEffect(() => {
766
+ if (debugPhase) {
767
+ setPhase(debugPhase);
768
+ if (debugPhase === "error") setErrorMessage("Test error message representing a real failure.");
769
+ return;
770
+ }
771
+ if (blockingError) {
772
+ setPhase("error");
773
+ setErrorMessage(blockingError);
774
+ return;
775
+ }
776
+ let closed = false;
777
+ const handleResult = (event) => {
778
+ if (event.origin !== window.location.origin) {
779
+ return;
780
+ }
781
+ if (event.data?.type !== AUTH_RESULT_MESSAGE) {
782
+ return;
783
+ }
784
+ if (event.data.sessionId !== sessionId) {
785
+ return;
786
+ }
787
+ if (event.data.success) {
788
+ setPhase("success");
789
+ window.removeEventListener("message", handleResult);
790
+ closed = true;
791
+ window.setTimeout(() => window.close(), 1200);
792
+ return;
793
+ }
794
+ const message = typeof event.data.error === "string" && event.data.error.length > 0 ? event.data.error : "Failed to complete authorization.";
795
+ setPhase("error");
796
+ setErrorMessage(message);
797
+ };
798
+ window.addEventListener("message", handleResult);
799
+ try {
800
+ window.opener.postMessage(
801
+ { type: AUTH_CODE_MESSAGE, code, sessionId },
802
+ window.location.origin
803
+ );
804
+ } catch (error) {
805
+ console.error("Failed to communicate with opener:", error);
806
+ window.setTimeout(() => {
807
+ setPhase("error");
808
+ setErrorMessage("Error: Could not communicate with main window.");
809
+ }, 0);
810
+ }
811
+ return () => {
812
+ if (!closed) {
813
+ window.removeEventListener("message", handleResult);
814
+ }
815
+ };
816
+ }, [blockingError, code, sessionId, debugPhase]);
817
+ const loadingBubbles = /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", gap: "8px", justifyContent: "center", height: "12px", alignItems: "center" }, children: [0, 150, 300].map((delay) => /* @__PURE__ */ jsxRuntime.jsx(
818
+ "span",
819
+ {
820
+ style: {
821
+ width: "8px",
822
+ height: "8px",
823
+ borderRadius: "50%",
824
+ backgroundColor: "currentColor",
825
+ opacity: 0.3,
826
+ animation: `mcp-pulse 1.2s ease-in-out infinite`,
827
+ animationDelay: `${delay}ms`
828
+ }
829
+ },
830
+ delay
831
+ )) });
832
+ const content = /* @__PURE__ */ jsxRuntime.jsxs(
833
+ "div",
834
+ {
835
+ style: {
836
+ display: "flex",
837
+ justifyContent: "center",
838
+ alignItems: "center",
839
+ minHeight: "100vh",
840
+ fontFamily: "system-ui, -apple-system, sans-serif",
841
+ flexDirection: "column",
842
+ backgroundColor: "#fafafa",
843
+ color: "#18181b",
844
+ boxSizing: "border-box",
845
+ padding: "1.5rem",
846
+ ...rootStyle
847
+ },
848
+ children: [
849
+ /* @__PURE__ */ jsxRuntime.jsx("style", { children: `
850
+ @keyframes mcp-pulse { 0%, 100% { transform: scale(0.8); opacity: 0.4; } 50% { transform: scale(1.2); opacity: 1; } }
851
+ @keyframes mcp-fade-up { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
852
+ ` }),
853
+ /* @__PURE__ */ jsxRuntime.jsx(
854
+ "div",
855
+ {
856
+ style: {
857
+ backgroundColor: "#fff",
858
+ borderRadius: "20px",
859
+ boxShadow: "0 20px 25px -5px rgba(0, 0, 0, 0.05), 0 8px 10px -6px rgba(0, 0, 0, 0.05)",
860
+ width: "100%",
861
+ maxWidth: "400px",
862
+ overflow: "hidden",
863
+ border: "1px solid #f4f4f5",
864
+ display: "flex",
865
+ flexDirection: "column",
866
+ ...cardStyle
867
+ },
868
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: "3rem 2rem", textAlign: "center", animation: "mcp-fade-up 0.4s ease-out" }, children: [
869
+ phase === "loading" && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "1.5rem", alignItems: "center" }, children: [
870
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", height: "48px", width: "48px", background: "#f8fafc", borderRadius: "12px", border: "1px solid #f1f5f9", color: "#64748b" }, children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" }) }) }),
871
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: [
872
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: { margin: 0, fontSize: "1.125rem", fontWeight: 600, ...titleStyle }, children: title }),
873
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: 0, fontSize: "0.9rem", color: "#71717a", lineHeight: 1.5, ...messageStyle }, children: initialStatus })
874
+ ] }),
875
+ loadingBubbles
876
+ ] }),
877
+ phase === "success" && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "1rem", alignItems: "center" }, children: [
878
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { style: { color: "#10b981" }, width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
879
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10" }),
880
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 12l3 3 5-5" })
881
+ ] }),
882
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: { margin: 0, fontSize: "1.25rem", fontWeight: 600, ...titleStyle }, children: "Connected" }),
883
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: 0, fontSize: "0.9rem", color: "#71717a", lineHeight: 1.5, ...messageStyle }, children: "Authorization complete. This window will close automatically." })
884
+ ] }),
885
+ phase === "error" && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "1rem", alignItems: "center" }, children: [
886
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { style: { color: "#ef4444" }, width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
887
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10" }),
888
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 9l-6 6M9 9l6 6" })
889
+ ] }),
890
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: { margin: 0, fontSize: "1.25rem", fontWeight: 600, ...titleStyle }, children: "Connection Failed" }),
891
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: 0, fontSize: "0.9rem", color: "#ef4444", fontWeight: 500, ...messageStyle }, children: errorMessage }),
892
+ /* @__PURE__ */ jsxRuntime.jsx(
893
+ "button",
894
+ {
895
+ onClick: () => window.close(),
896
+ style: {
897
+ marginTop: "0.5rem",
898
+ padding: "0.625rem 1.25rem",
899
+ border: "none",
900
+ borderRadius: "8px",
901
+ backgroundColor: "#fef2f2",
902
+ color: "#ef4444",
903
+ cursor: "pointer",
904
+ fontWeight: 600,
905
+ fontSize: "0.875rem"
906
+ },
907
+ children: "Close Window"
908
+ }
909
+ )
910
+ ] })
911
+ ] })
912
+ }
913
+ )
914
+ ]
915
+ }
916
+ );
917
+ if (renderContainer) {
918
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: renderContainer(content) });
919
+ }
920
+ return content;
921
+ }
922
+ function McpOAuthCallbackFallback({
923
+ children = "Loading..."
924
+ }) {
925
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: children || "Loading..." });
926
+ }
596
927
 
597
928
  // src/client/core/constants.ts
598
929
  var SANDBOX_PROXY_READY_METHOD = "ui/notifications/sandbox-proxy-ready";
@@ -1373,12 +1704,17 @@ exports.APP_HOST_DEFAULTS = APP_HOST_DEFAULTS;
1373
1704
  exports.AppHost = AppHost;
1374
1705
  exports.DEFAULT_MCP_APP_CSP = DEFAULT_MCP_APP_CSP;
1375
1706
  exports.McpAppRenderer = McpAppRenderer;
1707
+ exports.McpOAuthCallbackContent = McpOAuthCallbackContent;
1708
+ exports.McpOAuthCallbackFallback = McpOAuthCallbackFallback;
1376
1709
  exports.SANDBOX_PROXY_READY_METHOD = SANDBOX_PROXY_READY_METHOD;
1377
1710
  exports.SANDBOX_RESOURCE_READY_METHOD = SANDBOX_RESOURCE_READY_METHOD;
1378
1711
  exports.SSEClient = SSEClient;
1712
+ exports.createOAuthPopupRedirectHandler = createOAuthPopupRedirectHandler;
1379
1713
  exports.getMcpAppMetadata = getMcpAppMetadata;
1714
+ exports.openCenteredPopup = openCenteredPopup;
1380
1715
  exports.useAppHost = useAppHost;
1381
1716
  exports.useMcp = useMcp;
1382
1717
  exports.useMcpApps = useMcpApps;
1718
+ exports.useMcpOAuthPopup = useMcpOAuthPopup;
1383
1719
  //# sourceMappingURL=react.js.map
1384
1720
  //# sourceMappingURL=react.js.map