@mcp-ts/sdk 1.3.0 → 1.3.1
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.
package/dist/client/react.d.mts
CHANGED
|
@@ -184,10 +184,9 @@ declare function useAppHost(client: SSEClient, iframeRef: React.RefObject<HTMLIF
|
|
|
184
184
|
};
|
|
185
185
|
|
|
186
186
|
/**
|
|
187
|
-
*
|
|
187
|
+
* MCP Apps Hook
|
|
188
188
|
*
|
|
189
|
-
*
|
|
190
|
-
* We return a stable McpAppRenderer component and separate metadata lookup.
|
|
189
|
+
* Provides utilities for rendering interactive UI components from MCP servers.
|
|
191
190
|
*/
|
|
192
191
|
|
|
193
192
|
interface McpClient {
|
|
@@ -219,6 +218,8 @@ interface McpAppRendererProps {
|
|
|
219
218
|
result?: unknown;
|
|
220
219
|
status: 'executing' | 'inProgress' | 'complete' | 'idle';
|
|
221
220
|
sseClient?: SSEClient | null;
|
|
221
|
+
/** Custom CSS class for the container */
|
|
222
|
+
className?: string;
|
|
222
223
|
}
|
|
223
224
|
/**
|
|
224
225
|
* Simple hook to get MCP app metadata
|
package/dist/client/react.d.ts
CHANGED
|
@@ -184,10 +184,9 @@ declare function useAppHost(client: SSEClient, iframeRef: React.RefObject<HTMLIF
|
|
|
184
184
|
};
|
|
185
185
|
|
|
186
186
|
/**
|
|
187
|
-
*
|
|
187
|
+
* MCP Apps Hook
|
|
188
188
|
*
|
|
189
|
-
*
|
|
190
|
-
* We return a stable McpAppRenderer component and separate metadata lookup.
|
|
189
|
+
* Provides utilities for rendering interactive UI components from MCP servers.
|
|
191
190
|
*/
|
|
192
191
|
|
|
193
192
|
interface McpClient {
|
|
@@ -219,6 +218,8 @@ interface McpAppRendererProps {
|
|
|
219
218
|
result?: unknown;
|
|
220
219
|
status: 'executing' | 'inProgress' | 'complete' | 'idle';
|
|
221
220
|
sseClient?: SSEClient | null;
|
|
221
|
+
/** Custom CSS class for the container */
|
|
222
|
+
className?: string;
|
|
222
223
|
}
|
|
223
224
|
/**
|
|
224
225
|
* Simple hook to get MCP app metadata
|
package/dist/client/react.js
CHANGED
|
@@ -934,7 +934,8 @@ var McpAppRenderer = react.memo(function McpAppRenderer2({
|
|
|
934
934
|
input,
|
|
935
935
|
result,
|
|
936
936
|
status,
|
|
937
|
-
sseClient
|
|
937
|
+
sseClient,
|
|
938
|
+
className
|
|
938
939
|
}) {
|
|
939
940
|
const iframeRef = react.useRef(null);
|
|
940
941
|
const { host, error: hostError } = useAppHost(sseClient, iframeRef);
|
|
@@ -976,12 +977,12 @@ var McpAppRenderer = react.memo(function McpAppRenderer2({
|
|
|
976
977
|
}, [status]);
|
|
977
978
|
const displayError = error || hostError;
|
|
978
979
|
if (displayError) {
|
|
979
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className:
|
|
980
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `p-4 bg-red-900/20 border border-red-700 rounded text-red-200 ${className || ""}`, children: [
|
|
980
981
|
"Error: ",
|
|
981
982
|
displayError.message || String(displayError)
|
|
982
983
|
] });
|
|
983
984
|
}
|
|
984
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className:
|
|
985
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `w-full border border-gray-700 rounded overflow-hidden bg-white min-h-96 my-2 relative ${className || ""}`, children: [
|
|
985
986
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
986
987
|
"iframe",
|
|
987
988
|
{
|
package/dist/client/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/client/core/sse-client.ts","../../src/client/react/use-mcp.ts","../../src/client/core/app-host.ts","../../src/client/react/use-app-host.ts","../../src/client/react/use-mcp-apps.tsx"],"names":["nanoid","useRef","useState","useEffect","useCallback","AppBridge","PostMessageTransport","memo","McpAppRenderer","jsxs","jsx"],"mappings":";;;;;;;;;;AAsFA,IAAM,uBAAA,GAA0B,GAAA;AAChC,IAAM,sBAAA,GAAyB,CAAA;AAC/B,IAAM,oBAAA,GAAuB,GAAA;AAStB,IAAM,YAAN,MAAgB;AAAA,EAUrB,YAA6B,OAAA,EAA2B;AAA3B,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAT7B,IAAA,aAAA,CAAA,IAAA,EAAQ,aAAA,EAAkC,IAAA,CAAA;AAC1C,IAAA,aAAA,CAAA,IAAA,EAAQ,iBAAA,sBAAsB,GAAA,EAA4B,CAAA;AAC1D,IAAA,aAAA,CAAA,IAAA,EAAQ,eAAA,sBAAoB,GAAA,EAA8B,CAAA;AAE1D,IAAA,aAAA,CAAA,IAAA,EAAQ,mBAAA,EAAoB,CAAA,CAAA;AAC5B,IAAA,aAAA,CAAA,IAAA,EAAQ,wBAAA,EAAyB,KAAA,CAAA;AACjC,IAAA,aAAA,CAAA,IAAA,EAAQ,mBAAA,EAA0C,IAAA,CAAA;AAClD,IAAA,aAAA,CAAA,IAAA,EAAQ,oBAAA,EAA0C,IAAA,CAAA;AAAA,EAEO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASzD,OAAA,GAAgB;AACd,IAAA,IAAI,KAAK,WAAA,EAAa;AACpB,MAAA;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,sBAAA,GAAyB,KAAA;AAC9B,IAAA,IAAA,CAAK,OAAA,CAAQ,iBAAiB,YAAY,CAAA;AAC1C,IAAA,IAAA,CAAK,iBAAA,GAAoB,IAAI,OAAA,CAAQ,CAAC,OAAA,KAAY;AAChD,MAAA,IAAA,CAAK,kBAAA,GAAqB,OAAA;AAAA,IAC5B,CAAC,CAAA;AAED,IAAA,MAAM,GAAA,GAAM,KAAK,QAAA,EAAS;AAC1B,IAAA,IAAA,CAAK,WAAA,GAAc,IAAI,WAAA,CAAY,GAAG,CAAA;AACtC,IAAA,IAAA,CAAK,mBAAA,EAAoB;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKA,UAAA,GAAmB;AACjB,IAAA,IAAA,CAAK,sBAAA,GAAyB,IAAA;AAE9B,IAAA,IAAI,KAAK,WAAA,EAAa;AACpB,MAAA,IAAA,CAAK,YAAY,KAAA,EAAM;AACvB,MAAA,IAAA,CAAK,WAAA,GAAc,IAAA;AAAA,IACrB;AAEA,IAAA,IAAA,CAAK,iBAAA,GAAoB,IAAA;AACzB,IAAA,IAAA,CAAK,kBAAA,GAAqB,IAAA;AAC1B,IAAA,IAAA,CAAK,wBAAA,CAAyB,IAAI,KAAA,CAAM,mBAAmB,CAAC,CAAA;AAC5D,IAAA,IAAA,CAAK,OAAA,CAAQ,iBAAiB,cAAc,CAAA;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA,EAKA,WAAA,GAAuB;AACrB,IAAA,OAAO,IAAA,CAAK,WAAA,EAAa,UAAA,KAAe,WAAA,CAAY,IAAA;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,WAAA,GAA0C;AAC9C,IAAA,OAAO,IAAA,CAAK,YAA+B,aAAa,CAAA;AAAA,EAC1D;AAAA,EAEA,MAAM,gBAAgB,MAAA,EAA+C;AACnE,IAAA,OAAO,IAAA,CAAK,WAAA,CAA2B,SAAA,EAAW,MAAM,CAAA;AAAA,EAC1D;AAAA,EAEA,MAAM,qBAAqB,SAAA,EAA8C;AACvE,IAAA,OAAO,IAAA,CAAK,WAAA,CAA8B,YAAA,EAAc,EAAE,WAAW,CAAA;AAAA,EACvE;AAAA,EAEA,MAAM,UAAU,SAAA,EAAgD;AAC9D,IAAA,OAAO,IAAA,CAAK,WAAA,CAAgC,WAAA,EAAa,EAAE,WAAW,CAAA;AAAA,EACxE;AAAA,EAEA,MAAM,QAAA,CACJ,SAAA,EACA,QAAA,EACA,QAAA,EACkB;AAClB,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,WAAA,CAAY,YAAY,EAAE,SAAA,EAAW,QAAA,EAAU,QAAA,EAAU,CAAA;AACnF,IAAA,IAAA,CAAK,oBAAA,CAAqB,MAAA,EAAQ,SAAA,EAAW,QAAQ,CAAA;AACrD,IAAA,OAAO,MAAA;AAAA,EACT;AAAA,EAEA,MAAM,eAAe,SAAA,EAAkD;AACrE,IAAA,OAAO,IAAA,CAAK,WAAA,CAAkC,gBAAA,EAAkB,EAAE,WAAW,CAAA;AAAA,EAC/E;AAAA,EAEA,MAAM,UAAA,CAAW,SAAA,EAAmB,IAAA,EAAyC;AAC3E,IAAA,OAAO,KAAK,WAAA,CAA8B,YAAA,EAAc,EAAE,SAAA,EAAW,MAAM,CAAA;AAAA,EAC7E;AAAA,EAEA,MAAM,YAAY,SAAA,EAA+C;AAC/D,IAAA,OAAO,IAAA,CAAK,WAAA,CAA+B,aAAA,EAAe,EAAE,WAAW,CAAA;AAAA,EACzE;AAAA,EAEA,MAAM,SAAA,CAAU,SAAA,EAAmB,IAAA,EAAc,IAAA,EAAiD;AAChG,IAAA,OAAO,KAAK,WAAA,CAAY,WAAA,EAAa,EAAE,SAAA,EAAW,IAAA,EAAM,MAAM,CAAA;AAAA,EAChE;AAAA,EAEA,MAAM,cAAc,SAAA,EAAiD;AACnE,IAAA,OAAO,IAAA,CAAK,WAAA,CAAiC,eAAA,EAAiB,EAAE,WAAW,CAAA;AAAA,EAC7E;AAAA,EAEA,MAAM,YAAA,CAAa,SAAA,EAAmB,GAAA,EAA+B;AACnE,IAAA,OAAO,KAAK,WAAA,CAAY,cAAA,EAAgB,EAAE,SAAA,EAAW,KAAK,CAAA;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,sBAAA,CAAuB,WAAmB,KAAA,EAAuD;AAC/F,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,MAAA,MAAM,GAAA,GAAM,IAAA,CAAK,oBAAA,CAAqB,IAAI,CAAA;AAC1C,MAAA,IAAI,CAAC,GAAA,EAAK;AAEV,MAAA,IAAI,IAAA,CAAK,aAAA,CAAc,GAAA,CAAI,GAAG,CAAA,EAAG;AAC/B,QAAA,IAAA,CAAK,GAAA,CAAI,CAAA,yBAAA,EAA4B,GAAG,CAAA,CAAE,CAAA;AAC1C,QAAA;AAAA,MACF;AAEA,MAAA,IAAA,CAAK,IAAI,CAAA,iCAAA,EAAoC,IAAA,CAAK,IAAI,CAAA,GAAA,EAAM,GAAG,CAAA,CAAE,CAAA;AACjE,MAAA,MAAM,OAAA,GAAU,IAAA,CAAK,WAAA,CAAY,cAAA,EAAgB,EAAE,SAAA,EAAW,GAAA,EAAK,CAAA,CAChE,KAAA,CAAM,CAAC,GAAA,KAAQ;AACd,QAAA,IAAA,CAAK,IAAI,CAAA,2BAAA,EAA8B,GAAG,KAAK,GAAA,CAAI,OAAO,IAAI,MAAM,CAAA;AACpE,QAAA,IAAA,CAAK,aAAA,CAAc,OAAO,GAAG,CAAA;AAC7B,QAAA,OAAO,IAAA;AAAA,MACT,CAAC,CAAA;AAEH,MAAA,IAAA,CAAK,aAAA,CAAc,GAAA,CAAI,GAAA,EAAK,OAAO,CAAA;AAAA,IACrC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAA,CAAmB,WAAmB,GAAA,EAA+B;AACnE,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,aAAA,CAAc,GAAA,CAAI,GAAG,CAAA;AACzC,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,IAAA,CAAK,GAAA,CAAI,CAAA,wBAAA,EAA2B,GAAG,CAAA,CAAE,CAAA;AACzC,MAAA,OAAO,MAAA;AAAA,IACT;AAEA,IAAA,IAAA,CAAK,GAAA,CAAI,CAAA,+BAAA,EAAkC,GAAG,CAAA,CAAE,CAAA;AAChD,IAAA,MAAM,UAAU,IAAA,CAAK,WAAA,CAAY,gBAAgB,EAAE,SAAA,EAAW,KAAK,CAAA;AACnE,IAAA,IAAA,CAAK,aAAA,CAAc,GAAA,CAAI,GAAA,EAAK,OAAO,CAAA;AACnC,IAAA,OAAO,OAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,qBAAqB,GAAA,EAAsB;AACzC,IAAA,OAAO,IAAA,CAAK,aAAA,CAAc,GAAA,CAAI,GAAG,CAAA;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAA,GAA2B;AACzB,IAAA,IAAA,CAAK,cAAc,KAAA,EAAM;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAc,WAAA,CAAyB,MAAA,EAAsB,MAAA,EAAmC;AAC9F,IAAA,IAAI,KAAK,iBAAA,EAAmB;AAC1B,MAAA,MAAM,IAAA,CAAK,iBAAA;AAAA,IACb;AAEA,IAAA,MAAM,OAAA,GAAyB;AAAA,MAC7B,EAAA,EAAI,CAAA,IAAA,EAAOA,aAAA,CAAO,EAAE,CAAC,CAAA,CAAA;AAAA,MACrB,MAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,IAAA,CAAK,UAAS,EAAG;AAAA,MAC5C,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS,KAAK,YAAA,EAAa;AAAA,MAC3B,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,OAAO;AAAA,KAC7B,CAAA;AAED,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA,MAAM,IAAI,MAAM,CAAA,KAAA,EAAQ,QAAA,CAAS,MAAM,CAAA,EAAA,EAAK,QAAA,CAAS,UAAU,CAAA,CAAE,CAAA;AAAA,IACnE;AAEA,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,IAAA,OAAO,IAAA,CAAK,gBAAA,CAAoB,IAAA,EAAM,OAAA,CAAQ,EAAE,CAAA;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAA,CAAoB,MAAsB,SAAA,EAAmC;AAEnF,IAAA,IAAI,YAAY,IAAA,EAAM;AACpB,MAAA,OAAO,IAAA,CAAK,MAAA;AAAA,IACd;AAGA,IAAA,IAAI,OAAA,IAAW,IAAA,IAAQ,IAAA,CAAK,KAAA,EAAO;AACjC,MAAA,MAAM,IAAI,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,WAAW,mBAAmB,CAAA;AAAA,IAC3D;AAIA,IAAA,IAAI,kBAAkB,IAAA,EAAM;AAC1B,MAAA,OAAO,IAAA,CAAK,mBAAsB,SAAS,CAAA;AAAA,IAC7C;AAEA,IAAA,MAAM,IAAI,MAAM,6BAA6B,CAAA;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAAsB,SAAA,EAA+B;AAC3D,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,OAAA,CAAQ,cAAA,IAAkB,uBAAA;AAEjD,IAAA,OAAO,IAAI,OAAA,CAAW,CAAC,OAAA,EAAS,MAAA,KAAW;AACzC,MAAA,MAAM,SAAA,GAAY,WAAW,MAAM;AACjC,QAAA,IAAA,CAAK,eAAA,CAAgB,OAAO,SAAS,CAAA;AACrC,QAAA,MAAA,CAAO,IAAI,KAAA,CAAM,CAAA,sBAAA,EAAyB,SAAS,IAAI,CAAC,CAAA;AAAA,MAC1D,GAAG,SAAS,CAAA;AAEZ,MAAA,IAAA,CAAK,eAAA,CAAgB,IAAI,SAAA,EAAW;AAAA,QAClC,OAAA;AAAA,QACA,MAAA;AAAA,QACA;AAAA,OACD,CAAA;AAAA,IACH,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAAkB,QAAA,EAAgC;AACxD,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,eAAA,CAAgB,GAAA,CAAI,SAAS,EAAE,CAAA;AACpD,IAAA,IAAI,CAAC,OAAA,EAAS;AAEd,IAAA,YAAA,CAAa,QAAQ,SAAS,CAAA;AAC9B,IAAA,IAAA,CAAK,eAAA,CAAgB,MAAA,CAAO,QAAA,CAAS,EAAE,CAAA;AAEvC,IAAA,IAAI,SAAS,KAAA,EAAO;AAClB,MAAA,OAAA,CAAQ,OAAO,IAAI,KAAA,CAAM,QAAA,CAAS,KAAA,CAAM,OAAO,CAAC,CAAA;AAAA,IAClD,CAAA,MAAO;AACL,MAAA,OAAA,CAAQ,OAAA,CAAQ,SAAS,MAAM,CAAA;AAAA,IACjC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMQ,mBAAA,GAA4B;AAClC,IAAA,IAAI,CAAC,KAAK,WAAA,EAAa;AAEvB,IAAA,IAAA,CAAK,WAAA,CAAY,gBAAA,CAAiB,MAAA,EAAQ,MAAM;AAC9C,MAAA,IAAA,CAAK,IAAI,WAAW,CAAA;AACpB,MAAA,IAAA,CAAK,iBAAA,GAAoB,CAAA;AACzB,MAAA,IAAA,CAAK,OAAA,CAAQ,iBAAiB,WAAW,CAAA;AAAA,IAC3C,CAAC,CAAA;AAED,IAAA,IAAA,CAAK,WAAA,CAAY,gBAAA,CAAiB,WAAA,EAAa,MAAM;AACnD,MAAA,IAAA,CAAK,IAAI,cAAc,CAAA;AACvB,MAAA,IAAA,CAAK,kBAAA,IAAqB;AAC1B,MAAA,IAAA,CAAK,kBAAA,GAAqB,IAAA;AAAA,IAC5B,CAAC,CAAA;AAED,IAAA,IAAA,CAAK,WAAA,CAAY,gBAAA,CAAiB,YAAA,EAAc,CAAC,CAAA,KAAoB;AACnE,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,CAAA,CAAE,IAAI,CAAA;AAC/B,MAAA,IAAA,CAAK,OAAA,CAAQ,oBAAoB,KAAK,CAAA;AAAA,IACxC,CAAC,CAAA;AAED,IAAA,IAAA,CAAK,WAAA,CAAY,gBAAA,CAAiB,eAAA,EAAiB,CAAC,CAAA,KAAoB;AACtE,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,CAAA,CAAE,IAAI,CAAA;AAC/B,MAAA,IAAA,CAAK,OAAA,CAAQ,uBAAuB,KAAK,CAAA;AAAA,IAC3C,CAAC,CAAA;AAED,IAAA,IAAA,CAAK,WAAA,CAAY,gBAAA,CAAiB,cAAA,EAAgB,CAAC,CAAA,KAAoB;AACrE,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,KAAA,CAAM,CAAA,CAAE,IAAI,CAAA;AAClC,MAAA,IAAA,CAAK,kBAAkB,QAAQ,CAAA;AAAA,IACjC,CAAC,CAAA;AAED,IAAA,IAAA,CAAK,WAAA,CAAY,gBAAA,CAAiB,OAAA,EAAS,MAAM;AAC/C,MAAA,IAAA,CAAK,GAAA,CAAI,oBAAoB,OAAO,CAAA;AACpC,MAAA,IAAA,CAAK,OAAA,CAAQ,iBAAiB,OAAO,CAAA;AACrC,MAAA,IAAA,CAAK,gBAAA,EAAiB;AAAA,IACxB,CAAC,CAAA;AAAA,EACH;AAAA,EAEQ,gBAAA,GAAyB;AAC/B,IAAA,IAAI,IAAA,CAAK,sBAAA,IAA0B,IAAA,CAAK,iBAAA,IAAqB,sBAAA,EAAwB;AACnF,MAAA;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,iBAAA,EAAA;AACL,IAAA,MAAM,KAAA,GAAQ,uBAAuB,IAAA,CAAK,iBAAA;AAC1C,IAAA,IAAA,CAAK,GAAA,CAAI,mBAAmB,KAAK,CAAA,YAAA,EAAe,KAAK,iBAAiB,CAAA,CAAA,EAAI,sBAAsB,CAAA,CAAA,CAAG,CAAA;AAEnG,IAAA,UAAA,CAAW,MAAM;AACf,MAAA,IAAA,CAAK,UAAA,EAAW;AAChB,MAAA,IAAA,CAAK,OAAA,EAAQ;AAAA,IACf,GAAG,KAAK,CAAA;AAAA,EACV;AAAA;AAAA;AAAA;AAAA,EAMQ,QAAA,GAAmB;AACzB,IAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,IAAA,CAAK,QAAQ,GAAA,EAAK,UAAA,CAAW,UAAU,MAAM,CAAA;AACjE,IAAA,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,UAAA,EAAY,IAAA,CAAK,QAAQ,QAAQ,CAAA;AACtD,IAAA,IAAI,IAAA,CAAK,QAAQ,SAAA,EAAW;AAC1B,MAAA,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,OAAA,EAAS,IAAA,CAAK,QAAQ,SAAS,CAAA;AAAA,IACtD;AACA,IAAA,OAAO,IAAI,QAAA,EAAS;AAAA,EACtB;AAAA,EAEQ,YAAA,GAA4B;AAClC,IAAA,MAAM,OAAA,GAAuB;AAAA,MAC3B,cAAA,EAAgB;AAAA,KAClB;AACA,IAAA,IAAI,IAAA,CAAK,QAAQ,SAAA,EAAW;AAC1B,MAAA,OAAA,CAAQ,eAAe,CAAA,GAAI,CAAA,OAAA,EAAU,IAAA,CAAK,QAAQ,SAAS,CAAA,CAAA;AAAA,IAC7D;AACA,IAAA,OAAO,OAAA;AAAA,EACT;AAAA,EAEQ,yBAAyB,KAAA,EAAoB;AACnD,IAAA,KAAA,MAAW,GAAG,OAAO,CAAA,IAAK,KAAK,eAAA,EAAiB;AAC9C,MAAA,YAAA,CAAa,QAAQ,SAAS,CAAA;AAC9B,MAAA,OAAA,CAAQ,OAAO,KAAK,CAAA;AAAA,IACtB;AACA,IAAA,IAAA,CAAK,gBAAgB,KAAA,EAAM;AAAA,EAC7B;AAAA,EAEQ,qBAAqB,IAAA,EAA6D;AACxF,IAAA,MAAM,IAAA,GAAQ,KAAK,KAAA,EAAmC,EAAA;AACtD,IAAA,IAAI,CAAC,IAAA,IAAQ,OAAO,IAAA,KAAS,UAAU,OAAO,MAAA;AAG9C,IAAA,IAAI,IAAA,CAAK,cAAc,CAAC,IAAA,CAAK,WAAW,QAAA,CAAS,KAAK,GAAG,OAAO,MAAA;AAGhE,IAAA,OAAO,IAAA,CAAK,eAAe,IAAA,CAAK,GAAA;AAAA,EAClC;AAAA,EAEQ,oBAAA,CAAqB,MAAA,EAAiB,SAAA,EAAmB,QAAA,EAAwB;AACvF,IAAA,MAAM,OAAQ,MAAA,EAAgD,KAAA;AAC9D,IAAA,MAAM,WAAA,GAAc,IAAA,EAAM,EAAA,EAAI,WAAA,IAAgB,OAAe,gBAAgB,CAAA;AAE7E,IAAA,IAAI,WAAA,EAAa;AACf,MAAA,IAAA,CAAK,QAAQ,OAAA,GAAU;AAAA,QACrB,IAAA,EAAM,aAAA;AAAA,QACN,SAAA;AAAA,QACA,WAAA;AAAA,QACA,QAAA;AAAA,QACA,MAAA;AAAA,QACA,SAAA,EAAW,KAAK,GAAA;AAAI,OACrB,CAAA;AAAA,IACH;AAAA,EACF;AAAA,EAEQ,GAAA,CAAI,OAAA,EAAiB,KAAA,GAAmC,MAAA,EAAc;AAC5E,IAAA,IAAI,CAAC,IAAA,CAAK,OAAA,CAAQ,KAAA,IAAS,UAAU,MAAA,EAAQ;AAE7C,IAAA,MAAM,MAAA,GAAS,aAAA;AACf,IAAA,QAAQ,KAAA;AAAO,MACb,KAAK,MAAA;AACH,QAAA,OAAA,CAAQ,IAAA,CAAK,QAAQ,OAAO,CAAA;AAC5B,QAAA;AAAA,MACF,KAAK,OAAA;AACH,QAAA,OAAA,CAAQ,KAAA,CAAM,QAAQ,OAAO,CAAA;AAC7B,QAAA;AAAA,MACF;AACE,QAAA,OAAA,CAAQ,GAAA,CAAI,QAAQ,OAAO,CAAA;AAAA;AAC/B,EACF;AACF;;;ACzSO,SAAS,OAAO,OAAA,EAAmC;AACxD,EAAA,MAAM;AAAA,IACJ,GAAA;AAAA,IACA,QAAA;AAAA,IACA,SAAA;AAAA,IACA,WAAA,GAAc,IAAA;AAAA,IACd,cAAA,GAAiB,IAAA;AAAA,IACjB,iBAAA;AAAA,IACA,KAAA;AAAA,IACA;AAAA,GACF,GAAI,OAAA;AAEJ,EAAA,MAAM,SAAA,GAAYC,aAAyB,IAAI,CAAA;AAC/C,EAAA,MAAM,YAAA,GAAeA,aAAO,IAAI,CAAA;AAEhC,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAIC,cAAA,CAA0B,EAAE,CAAA;AAClE,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAIA,cAAA;AAAA,IAC1B;AAAA,GACF;AACA,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAAIA,eAAS,KAAK,CAAA;AAK1D,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,YAAA,CAAa,OAAA,GAAU,IAAA;AAEvB,IAAA,MAAM,aAAA,GAAkC;AAAA,MACtC,GAAA;AAAA,MACA,QAAA;AAAA,MACA,SAAA;AAAA,MACA,iBAAA,EAAmB,CAAC,KAAA,KAAU;AAE5B,QAAA,0BAAA,CAA2B,KAAK,CAAA;AAGhC,QAAA,iBAAA,GAAoB,KAAK,CAAA;AAAA,MAC3B,CAAA;AAAA,MACA,oBAAA,EAAsB,CAAC,KAAA,KAAU;AAC/B,QAAA,KAAA,GAAQ,KAAA,CAAM,SAAS,MAAA,EAAQ,KAAA,CAAM,WAAW,KAAA,CAAM,cAAA,IAAkB,YAAA,EAAc,KAAA,CAAM,QAAQ,CAAA;AAAA,MACtG,CAAA;AAAA,MACA,cAAA,EAAgB,CAAC,SAAA,KAAc;AAC7B,QAAA,IAAI,aAAa,OAAA,EAAS;AACxB,UAAA,SAAA,CAAU,SAAS,CAAA;AAAA,QACrB;AAAA,MACF,CAAA;AAAA,MACA,gBAAgB,OAAA,CAAQ;AAAA,KAC1B;AAEA,IAAA,MAAM,MAAA,GAAS,IAAI,SAAA,CAAU,aAAa,CAAA;AAC1C,IAAA,SAAA,CAAU,OAAA,GAAU,MAAA;AAEpB,IAAA,IAAI,WAAA,EAAa;AACf,MAAA,MAAA,CAAO,OAAA,EAAQ;AAEf,MAAA,IAAI,cAAA,EAAgB;AAClB,QAAA,YAAA,EAAa;AAAA,MACf;AAAA,IACF;AAEA,IAAA,OAAO,MAAM;AACX,MAAA,YAAA,CAAa,OAAA,GAAU,KAAA;AACvB,MAAA,MAAA,CAAO,UAAA,EAAW;AAAA,IACpB,CAAA;AAAA,EACF,GAAG,CAAC,GAAA,EAAK,UAAU,SAAA,EAAW,WAAA,EAAa,cAAc,CAAC,CAAA;AAK1D,EAAA,MAAM,0BAAA,GAA6BC,iBAAA,CAAY,CAAC,KAAA,KAA8B;AAC5E,IAAA,IAAI,CAAC,aAAa,OAAA,EAAS;AAE3B,IAAA,cAAA,CAAe,CAAC,IAAA,KAA0B;AACxC,MAAA,QAAQ,MAAM,IAAA;AAAM,QAClB,KAAK,eAAA,EAAiB;AACpB,UAAA,MAAM,QAAA,GAAW,KAAK,IAAA,CAAK,CAAC,MAAqB,CAAA,CAAE,SAAA,KAAc,MAAM,SAAS,CAAA;AAChF,UAAA,IAAI,QAAA,EAAU;AACZ,YAAA,OAAO,IAAA,CAAK,GAAA;AAAA,cAAI,CAAC,CAAA,KACf,CAAA,CAAE,SAAA,KAAc,KAAA,CAAM,SAAA,GAAY,EAAE,GAAG,CAAA,EAAG,KAAA,EAAO,KAAA,CAAM,KAAA,EAAM,GAAI;AAAA,aACnE;AAAA,UACF,CAAA,MAAO;AACL,YAAA,OAAO;AAAA,cACL,GAAG,IAAA;AAAA,cACH;AAAA,gBACE,WAAW,KAAA,CAAM,SAAA;AAAA,gBACjB,UAAU,KAAA,CAAM,QAAA;AAAA,gBAChB,YAAY,KAAA,CAAM,UAAA;AAAA,gBAClB,OAAO,KAAA,CAAM,KAAA;AAAA,gBACb,OAAO;AAAC;AACV,aACF;AAAA,UACF;AAAA,QACF;AAAA,QAEA,KAAK,kBAAA,EAAoB;AAEvB,UAAA,IAAI,SAAA,CAAU,OAAA,IAAW,KAAA,CAAM,KAAA,EAAO,MAAA,EAAQ;AAC5C,YAAA,SAAA,CAAU,OAAA,CAAQ,sBAAA,CAAuB,KAAA,CAAM,SAAA,EAAW,MAAM,KAAK,CAAA;AAAA,UACvE;AAEA,UAAA,OAAO,IAAA,CAAK,GAAA;AAAA,YAAI,CAAC,CAAA,KACf,CAAA,CAAE,SAAA,KAAc,MAAM,SAAA,GAAY,EAAE,GAAG,CAAA,EAAG,KAAA,EAAO,KAAA,CAAM,KAAA,EAAO,KAAA,EAAO,SAAQ,GAAI;AAAA,WACnF;AAAA,QACF;AAAA,QAEA,KAAK,eAAA,EAAiB;AAEpB,UAAA,IAAI,MAAM,OAAA,EAAS;AACjB,YAAA,KAAA,GAAQ,MAAA,EAAQ,mCAAmC,KAAA,CAAM,OAAO,IAAI,EAAE,OAAA,EAAS,KAAA,CAAM,OAAA,EAAS,CAAA;AAE9F,YAAA,IAAI,UAAA,EAAY;AACd,cAAA,UAAA,CAAW,MAAM,OAAO,CAAA;AAAA,YAC1B,CAAA,MAAA,IAAW,OAAO,MAAA,KAAW,WAAA,EAAa;AACxC,cAAA,MAAA,CAAO,QAAA,CAAS,OAAO,KAAA,CAAM,OAAA;AAAA,YAC/B;AAAA,UACF;AACA,UAAA,OAAO,IAAA,CAAK,GAAA;AAAA,YAAI,CAAC,CAAA,KACf,CAAA,CAAE,SAAA,KAAc,KAAA,CAAM,SAAA,GAAY,EAAE,GAAG,CAAA,EAAG,KAAA,EAAO,gBAAA,EAAiB,GAAI;AAAA,WACxE;AAAA,QACF;AAAA,QAEA,KAAK,OAAA,EAAS;AACZ,UAAA,OAAO,IAAA,CAAK,GAAA;AAAA,YAAI,CAAC,CAAA,KACf,CAAA,CAAE,SAAA,KAAc,MAAM,SAAA,GAAY,EAAE,GAAG,CAAA,EAAG,KAAA,EAAO,QAAA,EAAU,KAAA,EAAO,KAAA,CAAM,OAAM,GAAI;AAAA,WACpF;AAAA,QACF;AAAA,QAEA,KAAK,cAAA,EAAgB;AACnB,UAAA,OAAO,KAAK,MAAA,CAAO,CAAC,MAAqB,CAAA,CAAE,SAAA,KAAc,MAAM,SAAS,CAAA;AAAA,QAC1E;AAAA,QAEA;AACE,UAAA,OAAO,IAAA;AAAA;AACX,IACF,CAAC,CAAA;AAAA,EACH,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA;AAKV,EAAA,MAAM,YAAA,GAAeA,kBAAY,YAAY;AAC3C,IAAA,IAAI,CAAC,UAAU,OAAA,EAAS;AAExB,IAAA,IAAI;AACF,MAAA,iBAAA,CAAkB,IAAI,CAAA;AAEtB,MAAA,MAAM,MAAA,GAAS,MAAM,SAAA,CAAU,OAAA,CAAQ,WAAA,EAAY;AACnD,MAAA,MAAM,QAAA,GAAW,MAAA,CAAO,QAAA,IAAY,EAAC;AAGrC,MAAA,IAAI,aAAa,OAAA,EAAS;AACxB,QAAA,cAAA;AAAA,UACE,QAAA,CAAS,GAAA,CAAI,CAAC,CAAA,MAAoB;AAAA,YAChC,WAAW,CAAA,CAAE,SAAA;AAAA,YACb,QAAA,EAAU,EAAE,QAAA,IAAY,SAAA;AAAA,YACxB,UAAA,EAAY,EAAE,UAAA,IAAc,gBAAA;AAAA,YAC5B,WAAW,CAAA,CAAE,SAAA;AAAA,YACb,WAAW,CAAA,CAAE,SAAA;AAAA,YACb,KAAA,EAAO,YAAA;AAAA,YACP,OAAO;AAAC,WACV,CAAE;AAAA,SACJ;AAAA,MACF;AAGA,MAAA,MAAM,OAAA,CAAQ,GAAA;AAAA,QACZ,QAAA,CAAS,GAAA,CAAI,OAAO,OAAA,KAAyB;AAC3C,UAAA,IAAI,UAAU,OAAA,EAAS;AACrB,YAAA,IAAI;AACF,cAAA,MAAM,SAAA,CAAU,OAAA,CAAQ,cAAA,CAAe,OAAA,CAAQ,SAAS,CAAA;AAAA,YAC1D,SAAS,KAAA,EAAO;AACd,cAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,oCAAA,EAAuC,OAAA,CAAQ,SAAS,KAAK,KAAK,CAAA;AAAA,YAClF;AAAA,UACF;AAAA,QACF,CAAC;AAAA,OACH;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,KAAA,CAAM,qCAAqC,KAAK,CAAA;AACxD,MAAA,KAAA,GAAQ,OAAA,EAAS,yBAAA,EAA2B,EAAE,KAAA,EAAO,CAAA;AAAA,IACvD,CAAA,SAAE;AACA,MAAA,IAAI,aAAa,OAAA,EAAS;AACxB,QAAA,iBAAA,CAAkB,KAAK,CAAA;AAAA,MACzB;AAAA,IACF;AAAA,EACF,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA;AAKV,EAAA,MAAM,OAAA,GAAUA,iBAAA;AAAA,IACd,OAAO,MAAA,KAMgB;AACrB,MAAA,IAAI,CAAC,UAAU,OAAA,EAAS;AACtB,QAAA,MAAM,IAAI,MAAM,4BAA4B,CAAA;AAAA,MAC9C;AAEA,MAAA,MAAM,MAAA,GAAS,MAAM,SAAA,CAAU,OAAA,CAAQ,gBAAgB,MAAM,CAAA;AAC7D,MAAA,OAAO,MAAA,CAAO,SAAA;AAAA,IAChB,CAAA;AAAA,IACA;AAAC,GACH;AAKA,EAAA,MAAM,UAAA,GAAaA,iBAAA,CAAY,OAAO,SAAA,KAAqC;AACzE,IAAA,IAAI,CAAC,UAAU,OAAA,EAAS;AACtB,MAAA,MAAM,IAAI,MAAM,4BAA4B,CAAA;AAAA,IAC9C;AAEA,IAAA,MAAM,SAAA,CAAU,OAAA,CAAQ,oBAAA,CAAqB,SAAS,CAAA;AAGtD,IAAA,IAAI,aAAa,OAAA,EAAS;AACxB,MAAA,cAAA,CAAe,CAAC,SAA0B,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA,KAAqB,CAAA,CAAE,SAAA,KAAc,SAAS,CAAC,CAAA;AAAA,IACxG;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAKL,EAAA,MAAM,OAAA,GAAUA,kBAAY,YAAY;AACtC,IAAA,MAAM,YAAA,EAAa;AAAA,EACrB,CAAA,EAAG,CAAC,YAAY,CAAC,CAAA;AAKjB,EAAA,MAAM,UAAA,GAAaA,kBAAY,MAAM;AACnC,IAAA,SAAA,CAAU,SAAS,OAAA,EAAQ;AAAA,EAC7B,CAAA,EAAG,EAAE,CAAA;AAKL,EAAA,MAAM,aAAA,GAAgBA,kBAAY,MAAM;AACtC,IAAA,SAAA,CAAU,SAAS,UAAA,EAAW;AAAA,EAChC,CAAA,EAAG,EAAE,CAAA;AAKL,EAAA,MAAM,UAAA,GAAaA,iBAAA,CAAY,OAAO,SAAA,EAAmB,IAAA,KAA4C;AACnG,IAAA,IAAI,CAAC,UAAU,OAAA,EAAS;AACtB,MAAA,MAAM,IAAI,MAAM,4BAA4B,CAAA;AAAA,IAC9C;AAEA,IAAA,OAAO,MAAM,SAAA,CAAU,OAAA,CAAQ,UAAA,CAAW,WAAW,IAAI,CAAA;AAAA,EAC3D,CAAA,EAAG,EAAE,CAAA;AAKL,EAAA,MAAM,QAAA,GAAWA,iBAAA;AAAA,IACf,OACE,SAAA,EACA,QAAA,EACA,QAAA,KACqB;AACrB,MAAA,IAAI,CAAC,UAAU,OAAA,EAAS;AACtB,QAAA,MAAM,IAAI,MAAM,4BAA4B,CAAA;AAAA,MAC9C;AAEA,MAAA,OAAO,MAAM,SAAA,CAAU,OAAA,CAAQ,QAAA,CAAS,SAAA,EAAW,UAAU,QAAQ,CAAA;AAAA,IACvE,CAAA;AAAA,IACA;AAAC,GACH;AAKA,EAAA,MAAM,SAAA,GAAYA,iBAAA,CAAY,OAAO,SAAA,KAAmD;AACtF,IAAA,IAAI,CAAC,UAAU,OAAA,EAAS;AACtB,MAAA,MAAM,IAAI,MAAM,4BAA4B,CAAA;AAAA,IAC9C;AAEA,IAAA,OAAO,MAAM,SAAA,CAAU,OAAA,CAAQ,SAAA,CAAU,SAAS,CAAA;AAAA,EACpD,CAAA,EAAG,EAAE,CAAA;AAKL,EAAA,MAAM,WAAA,GAAcA,iBAAA,CAAY,OAAO,SAAA,KAAkD;AACvF,IAAA,IAAI,CAAC,UAAU,OAAA,EAAS;AACtB,MAAA,MAAM,IAAI,MAAM,4BAA4B,CAAA;AAAA,IAC9C;AAEA,IAAA,OAAO,MAAM,SAAA,CAAU,OAAA,CAAQ,WAAA,CAAY,SAAS,CAAA;AAAA,EACtD,CAAA,EAAG,EAAE,CAAA;AAKL,EAAA,MAAM,SAAA,GAAYA,iBAAA;AAAA,IAChB,OAAO,SAAA,EAAmB,IAAA,EAAc,IAAA,KAAoD;AAC1F,MAAA,IAAI,CAAC,UAAU,OAAA,EAAS;AACtB,QAAA,MAAM,IAAI,MAAM,4BAA4B,CAAA;AAAA,MAC9C;AAEA,MAAA,OAAO,MAAM,SAAA,CAAU,OAAA,CAAQ,SAAA,CAAU,SAAA,EAAW,MAAM,IAAI,CAAA;AAAA,IAChE,CAAA;AAAA,IACA;AAAC,GACH;AAKA,EAAA,MAAM,aAAA,GAAgBA,iBAAA,CAAY,OAAO,SAAA,KAAoD;AAC3F,IAAA,IAAI,CAAC,UAAU,OAAA,EAAS;AACtB,MAAA,MAAM,IAAI,MAAM,4BAA4B,CAAA;AAAA,IAC9C;AAEA,IAAA,OAAO,MAAM,SAAA,CAAU,OAAA,CAAQ,aAAA,CAAc,SAAS,CAAA;AAAA,EACxD,CAAA,EAAG,EAAE,CAAA;AAKL,EAAA,MAAM,YAAA,GAAeA,iBAAA,CAAY,OAAO,SAAA,EAAmB,GAAA,KAAkC;AAC3F,IAAA,IAAI,CAAC,UAAU,OAAA,EAAS;AACtB,MAAA,MAAM,IAAI,MAAM,4BAA4B,CAAA;AAAA,IAC9C;AAEA,IAAA,OAAO,MAAM,SAAA,CAAU,OAAA,CAAQ,YAAA,CAAa,WAAW,GAAG,CAAA;AAAA,EAC5D,CAAA,EAAG,EAAE,CAAA;AAGL,EAAA,MAAM,aAAA,GAAgBA,iBAAA;AAAA,IACpB,CAAC,cAAsB,WAAA,CAAY,IAAA,CAAK,CAAC,CAAA,KAAqB,CAAA,CAAE,cAAc,SAAS,CAAA;AAAA,IACvF,CAAC,WAAW;AAAA,GACd;AAEA,EAAA,MAAM,uBAAA,GAA0BA,iBAAA;AAAA,IAC9B,CAAC,aAAqB,WAAA,CAAY,IAAA,CAAK,CAAC,CAAA,KAAqB,CAAA,CAAE,aAAa,QAAQ,CAAA;AAAA,IACpF,CAAC,WAAW;AAAA,GACd;AAEA,EAAA,MAAM,iBAAA,GAAoBA,iBAAA;AAAA,IACxB,CAAC,QAAA,KAAqB;AACpB,MAAA,MAAM,IAAA,GAAO,wBAAwB,QAAQ,CAAA;AAC7C,MAAA,OAAO,MAAM,KAAA,KAAU,WAAA;AAAA,IACzB,CAAA;AAAA,IACA,CAAC,uBAAuB;AAAA,GAC1B;AAEA,EAAA,MAAM,QAAA,GAAWA,iBAAA;AAAA,IACf,CAAC,SAAA,KAAsB;AACrB,MAAA,MAAM,IAAA,GAAO,cAAc,SAAS,CAAA;AACpC,MAAA,OAAO,IAAA,EAAM,SAAS,EAAC;AAAA,IACzB,CAAA;AAAA,IACA,CAAC,aAAa;AAAA,GAChB;AAEA,EAAA,OAAO;AAAA,IACL,WAAA;AAAA,IACA,MAAA;AAAA,IACA,cAAA;AAAA,IACA,OAAA;AAAA,IACA,UAAA;AAAA,IACA,aAAA;AAAA,IACA,uBAAA;AAAA,IACA,iBAAA;AAAA,IACA,QAAA;AAAA,IACA,OAAA;AAAA,IACA,UAAA;AAAA,IACA,aAAA;AAAA,IACA,UAAA;AAAA,IACA,QAAA;AAAA,IACA,SAAA;AAAA,IACA,WAAA;AAAA,IACA,SAAA;AAAA,IACA,aAAA;AAAA,IACA,YAAA;AAAA,IACA,WAAW,SAAA,CAAU;AAAA,GACvB;AACF;AC9gBA,IAAM,SAAA,GAAY,EAAE,IAAA,EAAM,aAAA,EAAe,SAAS,OAAA,EAAQ;AAG1D,IAAM,mBAAA,GAAsB;AAAA,EAC1B,eAAA;AAAA;AAAA,EACA,aAAA;AAAA;AAAA,EACA,mBAAA;AAAA;AAAA,EACA,cAAA;AAAA;AAAA,EACA,cAAA;AAAA;AAAA,EACA;AAAA;AACF,CAAA,CAAE,KAAK,GAAG,CAAA;AAGV,IAAM,eAAA,GAAkB,CAAC,OAAA,EAAS,YAAY,CAAA;AAUvC,IAAM,UAAN,MAAc;AAAA,EASnB,WAAA,CACmB,MAAA,EACA,MAAA,EACjB,OAAA,EACA;AAHiB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAVnB,IAAA,aAAA,CAAA,IAAA,EAAQ,QAAA,CAAA;AACR,IAAA,aAAA,CAAA,IAAA,EAAQ,WAAA,CAAA;AACR,IAAA,aAAA,CAAA,IAAA,EAAQ,eAAA,sBAAoB,GAAA,EAA8C,CAAA;AAC1E,IAAA,aAAA,CAAA,IAAA,EAAQ,OAAA,CAAA;AAGR;AAAA,IAAA,aAAA,CAAA,IAAA,EAAO,cAAA,CAAA;AAOL,IAAA,IAAA,CAAK,KAAA,GAAQ,SAAS,KAAA,IAAS,KAAA;AAC/B,IAAA,IAAA,CAAK,gBAAA,EAAiB;AACtB,IAAA,IAAA,CAAK,MAAA,GAAS,KAAK,gBAAA,EAAiB;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,KAAA,GAAuB;AAG3B,IAAA,IAAA,CAAK,IAAI,+BAA+B,CAAA;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAQ,KAAA,EAAyC;AAC/C,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,MAAA,MAAM,GAAA,GAAM,IAAA,CAAK,oBAAA,CAAqB,IAAI,CAAA;AAC1C,MAAA,IAAI,CAAC,GAAA,IAAO,IAAA,CAAK,aAAA,CAAc,GAAA,CAAI,GAAG,CAAA,EAAG;AAEzC,MAAA,MAAM,OAAA,GAAU,IAAA,CAAK,eAAA,CAAgB,GAAG,CAAA;AACxC,MAAA,IAAA,CAAK,aAAA,CAAc,GAAA,CAAI,GAAA,EAAK,OAAO,CAAA;AAAA,IACrC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,MAAA,CAAO,GAAA,EAAa,SAAA,EAAmC;AAC3D,IAAA,IAAI,SAAA,OAAgB,SAAA,GAAY,SAAA;AAGhC,IAAA,MAAM,kBAAA,GAAqB,KAAK,UAAA,EAAW;AAG3C,IAAA,IAAI,IAAA,CAAK,QAAA,CAAS,GAAG,CAAA,EAAG;AACtB,MAAA,MAAM,IAAA,CAAK,aAAa,GAAG,CAAA;AAAA,IAC7B,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,OAAO,GAAA,GAAM,GAAA;AAAA,IACpB;AAGA,IAAA,MAAM,KAAK,aAAA,EAAc;AAGzB,IAAA,MAAM,KAAK,aAAA,EAAc;AAGzB,IAAA,IAAA,CAAK,IAAI,gCAAgC,CAAA;AACzC,IAAA,MAAM,QAAQ,IAAA,CAAK;AAAA,MACjB,kBAAA;AAAA,MACA,IAAI,OAAA,CAAc,CAAC,OAAA,KAAY,WAAW,MAAM;AAC9C,QAAA,IAAA,CAAK,GAAA,CAAI,8CAA8C,MAAM,CAAA;AAC7D,QAAA,OAAA,EAAQ;AAAA,MACV,CAAA,EAAG,GAAI,CAAC;AAAA,KACT,CAAA;AACD,IAAA,IAAA,CAAK,IAAI,wBAAwB,CAAA;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKQ,UAAA,GAA4B;AAClC,IAAA,OAAO,IAAI,OAAA,CAAc,CAAC,OAAA,KAAY;AACpC,MAAA,MAAM,eAAA,GAAkB,KAAK,MAAA,CAAO,aAAA;AACpC,MAAA,IAAA,CAAK,MAAA,CAAO,aAAA,GAAgB,CAAA,GAAI,IAAA,KAAS;AACvC,QAAA,IAAA,CAAK,IAAI,iBAAiB,CAAA;AAC1B,QAAA,OAAA,EAAQ;AACR,QAAA,IAAA,CAAK,OAAO,aAAA,GAAgB,eAAA;AAC5B,QAAA,eAAA,GAAkB,GAAG,IAAI,CAAA;AAAA,MAC3B,CAAA;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKQ,aAAA,GAA+B;AACrC,IAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,KAAY;AAC9B,MAAA,IAAI,IAAA,CAAK,MAAA,CAAO,eAAA,EAAiB,UAAA,KAAe,UAAA,EAAY;AAC1D,QAAA,OAAA,EAAQ;AACR,QAAA;AAAA,MACF;AACA,MAAA,IAAA,CAAK,MAAA,CAAO,iBAAiB,MAAA,EAAQ,MAAM,SAAQ,EAAG,EAAE,IAAA,EAAM,IAAA,EAAM,CAAA;AAAA,IACtE,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAAc,IAAA,EAAqC;AACjD,IAAA,IAAA,CAAK,IAAI,2BAA2B,CAAA;AACpC,IAAA,IAAA,CAAK,MAAA,CAAO,aAAA,CAAc,EAAE,SAAA,EAAW,MAAM,CAAA;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAe,MAAA,EAAuB;AACpC,IAAA,IAAA,CAAK,IAAI,4BAA4B,CAAA;AACrC,IAAA,IAAA,CAAK,MAAA,CAAO,eAAe,MAAa,CAAA;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,kBAAkB,MAAA,EAAsB;AACtC,IAAA,IAAA,CAAK,IAAI,kCAAkC,CAAA;AAC3C,IAAA,IAAA,CAAK,MAAA,CAAO,iBAAA,CAAkB,EAAE,MAAA,EAAQ,CAAA;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAMQ,gBAAA,GAAyB;AAC/B,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ,KAAA,KAAU,mBAAA,EAAqB;AACrD,MAAA,IAAA,CAAK,MAAA,CAAO,QAAQ,KAAA,GAAQ,mBAAA;AAAA,IAC9B;AAAA,EACF;AAAA,EAEQ,gBAAA,GAA8B;AACpC,IAAA,MAAM,SAAS,IAAIC,mBAAA;AAAA,MACjB,IAAA;AAAA,MACA,SAAA;AAAA,MACA;AAAA,QACE,WAAW,EAAC;AAAA,QACZ,aAAa,EAAC;AAAA,QACd,SAAS,EAAC;AAAA;AAAA,QAEV,kBAAA,EAAoB,EAAE,IAAA,EAAM,EAAC;AAAE,OACjC;AAAA,MACA;AAAA;AAAA,QAEE,WAAA,EAAa;AAAA,UACX,KAAA,EAAO,MAAA;AAAA,UACP,QAAA,EAAU,KAAA;AAAA,UACV,mBAAA,EAAqB,EAAE,SAAA,EAAW,GAAA,EAAK;AAAA,UACvC,WAAA,EAAa,QAAA;AAAA,UACb,qBAAA,EAAuB,CAAC,QAAA,EAAU,YAAY;AAAA;AAChD;AACF,KACF;AAGA,IAAA,MAAA,CAAO,UAAA,GAAa,CAAC,MAAA,KAAW,IAAA,CAAK,eAAe,MAAM,CAAA;AAC1D,IAAA,MAAA,CAAO,UAAA,GAAa,IAAA,CAAK,cAAA,CAAe,IAAA,CAAK,IAAI,CAAA;AACjD,IAAA,MAAA,CAAO,SAAA,GAAY,IAAA,CAAK,aAAA,CAAc,IAAA,CAAK,IAAI,CAAA;AAC/C,IAAA,MAAA,CAAO,gBAAA,GAAmB,CAAC,MAAA,KAAW,IAAA,CAAK,GAAA,CAAI,CAAA,SAAA,EAAY,MAAA,CAAO,KAAK,CAAA,GAAA,EAAM,MAAA,CAAO,IAAI,CAAA,CAAE,CAAA;AAC1F,IAAA,MAAA,CAAO,oBAAA,GAAuB,aAAa,EAAC,CAAA;AAC5C,IAAA,MAAA,CAAO,YAAA,GAAe,OAAO,EAAE,KAAA,EAAO,QAAO,KAAM;AACjD,MAAA,IAAI,WAAW,MAAA,EAAW,IAAA,CAAK,OAAO,KAAA,CAAM,MAAA,GAAS,GAAG,MAAM,CAAA,EAAA,CAAA;AAC9D,MAAA,IAAI,UAAU,MAAA,EAAW,IAAA,CAAK,OAAO,KAAA,CAAM,QAAA,GAAW,OAAO,KAAK,CAAA,SAAA,CAAA;AAClE,MAAA,OAAO,EAAC;AAAA,IACV,CAAA;AACA,IAAA,MAAA,CAAO,oBAAA,GAAuB,OAAO,MAAA,MAAY;AAAA,MAC/C,IAAA,EAAM,MAAA,CAAO,IAAA,KAAS,YAAA,GAAe,YAAA,GAAe;AAAA,KACtD,CAAA;AAEA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA,EAEA,MAAc,aAAA,GAA+B;AAC3C,IAAA,IAAA,CAAK,IAAI,6BAA6B,CAAA;AAEtC,IAAA,MAAM,YAAY,IAAIC,8BAAA;AAAA,MACpB,KAAK,MAAA,CAAO,aAAA;AAAA,MACZ,KAAK,MAAA,CAAO;AAAA,KACd;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ,SAAS,CAAA;AACnC,MAAA,IAAA,CAAK,IAAI,+BAA+B,CAAA;AAAA,IAC1C,SAAS,KAAA,EAAO;AACd,MAAA,IAAA,CAAK,GAAA,CAAI,4BAA4B,OAAO,CAAA;AAC5C,MAAA,MAAM,KAAA;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,eAAe,MAAA,EAAwB;AACnD,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,CAAO,WAAA,EAAY,EAAG;AAC9B,MAAA,MAAM,IAAI,MAAM,qBAAqB,CAAA;AAAA,IACvC;AAEA,IAAA,MAAM,SAAA,GAAY,MAAM,IAAA,CAAK,YAAA,EAAa;AAC1C,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,MAAM,IAAI,MAAM,mBAAmB,CAAA;AAAA,IACrC;AAEA,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,MAAA,CAAO,QAAA;AAAA,MAC/B,SAAA;AAAA,MACA,MAAA,CAAO,IAAA;AAAA,MACP,MAAA,CAAO,aAAa;AAAC,KACvB;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA,EAEA,MAAc,eAAe,MAAA,EAAyD;AACpF,IAAA,MAAA,CAAO,IAAA,CAAK,MAAA,CAAO,GAAA,EAAK,QAAA,EAAU,qBAAqB,CAAA;AACvD,IAAA,OAAO,EAAC;AAAA,EACV;AAAA,EAEA,MAAc,cAAc,MAAA,EAA0D;AACpF,IAAA,IAAA,CAAK,eAAe,MAAM,CAAA;AAC1B,IAAA,OAAO,EAAC;AAAA,EACV;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,aAAa,GAAA,EAA4B;AACrD,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,CAAO,WAAA,EAAY,EAAG;AAC9B,MAAA,MAAM,IAAI,MAAM,0BAA0B,CAAA;AAAA,IAC5C;AAEA,IAAA,MAAM,SAAA,GAAY,MAAM,IAAA,CAAK,YAAA,EAAa;AAC1C,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,MAAM,IAAI,MAAM,mBAAmB,CAAA;AAAA,IACrC;AAGA,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,sBAAA,CAAuB,WAAW,GAAG,CAAA;AACjE,IAAA,IAAI,CAAC,QAAA,EAAU,QAAA,EAAU,MAAA,EAAQ;AAC/B,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,gBAAA,EAAmB,GAAG,CAAA,CAAE,CAAA;AAAA,IAC1C;AAEA,IAAA,MAAM,OAAA,GAAU,QAAA,CAAS,QAAA,CAAS,CAAC,CAAA;AACnC,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,aAAA,CAAc,OAAO,CAAA;AACvC,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,6BAAA,EAAgC,GAAG,CAAA,CAAE,CAAA;AAAA,IACvD;AAGA,IAAA,MAAM,IAAA,GAAO,IAAI,IAAA,CAAK,CAAC,IAAI,CAAA,EAAG,EAAE,IAAA,EAAM,WAAA,EAAa,CAAA;AACnD,IAAA,IAAA,CAAK,MAAA,CAAO,GAAA,GAAM,GAAA,CAAI,eAAA,CAAgB,IAAI,CAAA;AAAA,EAC5C;AAAA,EAEA,MAAc,sBAAA,CAAuB,SAAA,EAAmB,GAAA,EAAwC;AAE9F,IAAA,IAAI,IAAA,CAAK,gBAAe,EAAG;AACzB,MAAA,OAAQ,IAAA,CAAK,MAAA,CAAe,kBAAA,CAAmB,SAAA,EAAW,GAAG,CAAA;AAAA,IAC/D;AAGA,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,aAAA,CAAc,GAAA,CAAI,GAAG,CAAA;AACzC,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,MAAM,SAAS,MAAM,MAAA;AACrB,MAAA,IAAI,QAAQ,OAAO,MAAA;AAAA,IACrB;AAGA,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,YAAA,CAAa,SAAA,EAAW,GAAG,CAAA;AAAA,EAChD;AAAA,EAEA,MAAc,gBAAgB,GAAA,EAA+C;AAC3E,IAAA,IAAI;AACF,MAAA,MAAM,SAAA,GAAY,MAAM,IAAA,CAAK,YAAA,EAAa;AAC1C,MAAA,IAAI,CAAC,WAAW,OAAO,IAAA;AACvB,MAAA,OAAO,MAAM,IAAA,CAAK,MAAA,CAAO,YAAA,CAAa,WAAW,GAAG,CAAA;AAAA,IACtD,SAAS,KAAA,EAAO;AACd,MAAA,IAAA,CAAK,GAAA,CAAI,CAAA,mBAAA,EAAsB,GAAG,CAAA,CAAA,EAAI,MAAM,CAAA;AAC5C,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,YAAA,GAA4C;AACxD,IAAA,IAAI,IAAA,CAAK,SAAA,EAAW,OAAO,IAAA,CAAK,SAAA;AAChC,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,MAAA,CAAO,WAAA,EAAY;AAC7C,IAAA,OAAO,MAAA,CAAO,QAAA,GAAW,CAAC,CAAA,EAAG,SAAA;AAAA,EAC/B;AAAA,EAEQ,SAAS,GAAA,EAAsB;AACrC,IAAA,OAAO,gBAAgB,IAAA,CAAK,CAAA,MAAA,KAAU,GAAA,CAAI,UAAA,CAAW,MAAM,CAAC,CAAA;AAAA,EAC9D;AAAA,EAEQ,cAAA,GAA0B;AAChC,IAAA,OAAO,wBAAwB,IAAA,CAAK,MAAA,IAC7B,OAAQ,IAAA,CAAK,OAAe,kBAAA,KAAuB,UAAA;AAAA,EAC5D;AAAA,EAEQ,qBAAqB,IAAA,EAA+C;AAC1E,IAAA,MAAM,OAAO,IAAA,CAAK,KAAA;AAClB,IAAA,IAAI,CAAC,IAAA,EAAM,EAAA,EAAI,OAAO,MAAA;AACtB,IAAA,OAAO,IAAA,CAAK,EAAA,CAAG,WAAA,IAAe,IAAA,CAAK,EAAA,CAAG,GAAA;AAAA,EACxC;AAAA,EAEQ,cAAc,OAAA,EAA8C;AAClE,IAAA,IAAI,QAAQ,IAAA,EAAM;AAChB,MAAA,OAAO,IAAA,CAAK,QAAQ,IAAI,CAAA;AAAA,IAC1B;AACA,IAAA,OAAO,OAAA,CAAQ,IAAA;AAAA,EACjB;AAAA,EAEQ,GAAA,CAAI,OAAA,EAAiB,KAAA,GAAmC,MAAA,EAAc;AAC5E,IAAA,IAAI,CAAC,IAAA,CAAK,KAAA,IAAS,KAAA,KAAU,MAAA,EAAQ;AAErC,IAAA,MAAM,MAAA,GAAS,WAAA;AACf,IAAA,QAAQ,KAAA;AAAO,MACb,KAAK,MAAA;AACH,QAAA,OAAA,CAAQ,IAAA,CAAK,QAAQ,OAAO,CAAA;AAC5B,QAAA;AAAA,MACF,KAAK,OAAA;AACH,QAAA,OAAA,CAAQ,KAAA,CAAM,QAAQ,OAAO,CAAA;AAC7B,QAAA;AAAA,MACF;AACE,QAAA,OAAA,CAAQ,GAAA,CAAI,QAAQ,OAAO,CAAA;AAAA;AAC/B,EACF;AACF;;;AC/YO,SAAS,UAAA,CACZ,MAAA,EACA,SAAA,EACA,OAAA,EAIF;AACE,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAIJ,eAAyB,IAAI,CAAA;AACrD,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIA,eAAuB,IAAI,CAAA;AACrD,EAAA,MAAM,eAAA,GAAkBD,aAAO,KAAK,CAAA;AAGpC,EAAA,MAAM,YAAA,GAAeA,YAAAA,CAAO,OAAA,EAAS,SAAS,CAAA;AAC9C,EAAAE,gBAAU,MAAM;AACZ,IAAA,YAAA,CAAa,UAAU,OAAA,EAAS,SAAA;AAAA,EACpC,CAAA,EAAG,CAAC,OAAA,EAAS,SAAS,CAAC,CAAA;AAEvB,EAAAA,gBAAU,MAAM;AACZ,IAAA,IAAI,CAAC,MAAA,IAAU,CAAC,SAAA,CAAU,OAAA,IAAW,gBAAgB,OAAA,EAAS;AAG9D,IAAA,eAAA,CAAgB,OAAA,GAAU,IAAA;AAE1B,IAAA,MAAM,WAAW,YAAY;AACzB,MAAA,IAAI;AAEA,QAAA,MAAM,OAAA,GAAU,IAAI,OAAA,CAAQ,MAAA,EAAQ,UAAU,OAAQ,CAAA;AAGtD,QAAA,OAAA,CAAQ,YAAA,GAAe,CAAC,MAAA,KAAW;AAC/B,UAAA,YAAA,CAAa,UAAU,MAAM,CAAA;AAAA,QACjC,CAAA;AAIA,QAAA,OAAA,CAAQ,OAAO,CAAA;AAGf,QAAA,MAAM,QAAQ,KAAA,EAAM;AAAA,MACxB,SAAS,GAAA,EAAK;AACV,QAAA,OAAA,CAAQ,KAAA,CAAM,8CAA8C,GAAG,CAAA;AAC/D,QAAA,QAAA,CAAS,GAAA,YAAe,QAAQ,GAAA,GAAM,IAAI,MAAM,MAAA,CAAO,GAAG,CAAC,CAAC,CAAA;AAAA,MAChE;AAAA,IACJ,CAAA;AAEA,IAAA,QAAA,EAAS;AAET,IAAA,OAAO,MAAM;AACT,MAAA,eAAA,CAAgB,OAAA,GAAU,KAAA;AAC1B,MAAA,OAAA,CAAQ,IAAI,CAAA;AAAA,IAChB,CAAA;AAAA,EACJ,CAAA,EAAG,CAAC,MAAA,EAAQ,SAAS,CAAC,CAAA;AAEtB,EAAA,OAAO,EAAE,MAAM,KAAA,EAAM;AACzB;ACxBA,IAAM,cAAA,GAAiBI,UAAA,CAAK,SAASC,eAAAA,CAAe;AAAA,EAClD,QAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAA,EAAwB;AACtB,EAAA,MAAM,SAAA,GAAYP,aAA0B,IAAI,CAAA;AAChD,EAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAO,WAAU,GAAI,UAAA,CAAW,WAAwB,SAAS,CAAA;AAC/E,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAIC,eAAS,KAAK,CAAA;AAClD,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIA,eAAuB,IAAI,CAAA;AAGrD,EAAA,MAAM,YAAA,GAAeD,aAAO,KAAK,CAAA;AACjC,EAAA,MAAM,aAAA,GAAgBA,aAAO,KAAK,CAAA;AAClC,EAAA,MAAM,YAAA,GAAeA,aAAO,KAAK,CAAA;AACjC,EAAA,MAAM,aAAA,GAAgBA,aAAO,MAAM,CAAA;AACnC,EAAA,MAAM,aAAA,GAAgBA,aAAO,MAAM,CAAA;AAGnC,EAAAE,gBAAU,MAAM;AACd,IAAA,IAAI,CAAC,IAAA,IAAQ,CAAC,SAAS,WAAA,IAAe,CAAC,SAAS,SAAA,EAAW;AAE3D,IAAA,IAAA,CACG,MAAA,CAAO,QAAA,CAAS,WAAA,EAAa,QAAA,CAAS,SAAS,EAC/C,IAAA,CAAK,MAAM,aAAA,CAAc,IAAI,CAAC,CAAA,CAC9B,MAAM,CAAC,GAAA,KAAQ,QAAA,CAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,GAAM,IAAI,KAAA,CAAM,MAAA,CAAO,GAAG,CAAC,CAAC,CAAC,CAAA;AAAA,EACjF,GAAG,CAAC,IAAA,EAAM,SAAS,WAAA,EAAa,QAAA,CAAS,SAAS,CAAC,CAAA;AAGnD,EAAAA,gBAAU,MAAM;AACd,IAAA,IAAI,CAAC,IAAA,IAAQ,CAAC,UAAA,IAAc,CAAC,KAAA,EAAO;AAGpC,IAAA,IAAI,CAAC,YAAA,CAAa,OAAA,IAAW,IAAA,CAAK,SAAA,CAAU,KAAK,CAAA,KAAM,IAAA,CAAK,SAAA,CAAU,YAAA,CAAa,OAAO,CAAA,EAAG;AAC3F,MAAA,YAAA,CAAa,OAAA,GAAU,IAAA;AACvB,MAAA,YAAA,CAAa,OAAA,GAAU,KAAA;AACvB,MAAA,IAAA,CAAK,cAAc,KAAK,CAAA;AAAA,IAC1B;AAAA,EACF,CAAA,EAAG,CAAC,IAAA,EAAM,UAAA,EAAY,KAAK,CAAC,CAAA;AAG5B,EAAAA,gBAAU,MAAM;AACd,IAAA,IAAI,CAAC,IAAA,IAAQ,CAAC,UAAA,IAAc,WAAW,MAAA,EAAW;AAClD,IAAA,IAAI,WAAW,UAAA,EAAY;AAG3B,IAAA,IAAI,CAAC,aAAA,CAAc,OAAA,IAAW,IAAA,CAAK,SAAA,CAAU,MAAM,CAAA,KAAM,IAAA,CAAK,SAAA,CAAU,aAAA,CAAc,OAAO,CAAA,EAAG;AAC9F,MAAA,aAAA,CAAc,OAAA,GAAU,IAAA;AACxB,MAAA,aAAA,CAAc,OAAA,GAAU,MAAA;AACxB,MAAA,MAAM,eAAA,GACJ,OAAO,MAAA,KAAW,QAAA,GACd,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,MAAA,EAAQ,GAAE,GAC5C,MAAA;AACN,MAAA,IAAA,CAAK,eAAe,eAAe,CAAA;AAAA,IACrC;AAAA,EACF,GAAG,CAAC,IAAA,EAAM,UAAA,EAAY,MAAA,EAAQ,MAAM,CAAC,CAAA;AAGrC,EAAAA,gBAAU,MAAM;AACd,IAAA,IAAI,MAAA,KAAW,WAAA,IAAe,aAAA,CAAc,OAAA,KAAY,WAAA,EAAa;AACnE,MAAA,YAAA,CAAa,OAAA,GAAU,KAAA;AACvB,MAAA,aAAA,CAAc,OAAA,GAAU,KAAA;AAAA,IAC1B;AACA,IAAA,aAAA,CAAc,OAAA,GAAU,MAAA;AAAA,EAC1B,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAGX,EAAA,MAAM,eAAe,KAAA,IAAS,SAAA;AAC9B,EAAA,IAAI,YAAA,EAAc;AAChB,IAAA,uBACEM,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,8DAAA,EAA+D,QAAA,EAAA;AAAA,MAAA,SAAA;AAAA,MACpE,YAAA,CAAa,OAAA,IAAW,MAAA,CAAO,YAAY;AAAA,KAAA,EACrD,CAAA;AAAA,EAEJ;AAEA,EAAA,uBACEA,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,uFAAA,EACb,QAAA,EAAA;AAAA,oBAAAC,cAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,GAAA,EAAK,SAAA;AAAA,QACL,OAAA,EAAQ,uFAAA;AAAA,QACR,SAAA,EAAU,wBAAA;AAAA,QACV,KAAA,EAAO,EAAE,MAAA,EAAQ,MAAA,EAAO;AAAA,QACxB,KAAA,EAAM;AAAA;AAAA,KACR;AAAA,IACC,CAAC,UAAA,oBACAA,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,wFACb,QAAA,kBAAAA,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,iFAAA,EAAkF,CAAA,EACnG;AAAA,GAAA,EAEJ,CAAA;AAEJ,CAAC,CAAA;AA0BM,SAAS,WAAW,SAAA,EAA6B;AAKtD,EAAA,MAAM,cAAA,GAAiBN,iBAAAA;AAAA,IACrB,CAAC,QAAA,KAAiD;AAChD,MAAA,IAAI,CAAC,WAAW,OAAO,MAAA;AAEvB,MAAA,MAAM,aAAA,GAAgB,gBAAgB,QAAQ,CAAA;AAE9C,MAAA,KAAA,MAAW,IAAA,IAAQ,UAAU,WAAA,EAAa;AACxC,QAAA,KAAA,MAAW,IAAA,IAAQ,KAAK,KAAA,EAAO;AAC7B,UAAA,MAAM,aAAA,GAAgB,eAAA,CAAgB,IAAA,CAAK,IAAI,CAAA;AAE/C,UAAA,MAAM,WAAA,GACJ,IAAA,CAAK,MAAA,EAAQ,WAAA,IACb,IAAA,CAAK,OAAO,EAAA,EAAI,WAAA,IAChB,IAAA,CAAK,KAAA,GAAQ,gBAAgB,CAAA;AAE/B,UAAA,IAAI,WAAA,IAAe,kBAAkB,aAAA,EAAe;AAClD,YAAA,OAAO;AAAA,cACL,QAAA,EAAU,aAAA;AAAA,cACV,WAAA;AAAA,cACA,WAAW,IAAA,CAAK;AAAA,aAClB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,MAAA,OAAO,MAAA;AAAA,IACT,CAAA;AAAA,IACA,CAAC,SAAS;AAAA,GACZ;AAEA,EAAA,OAAO,EAAE,gBAAgB,cAAA,EAAe;AAC1C;AAKA,SAAS,gBAAgB,QAAA,EAA0B;AAEjD,EAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,KAAA,CAAM,uBAAuB,CAAA;AACpD,EAAA,OAAO,KAAA,GAAQ,CAAC,CAAA,IAAK,QAAA;AACvB","file":"react.js","sourcesContent":["/**\r\n * SSE Client for MCP Connections\r\n *\r\n * Browser-side client that manages real-time communication with the MCP server\r\n * using Server-Sent Events (SSE) for server→client streaming and HTTP POST for\r\n * client→server RPC requests.\r\n *\r\n * Key features:\r\n * - Direct HTTP response for RPC calls (bypasses SSE latency)\r\n * - Resource preloading for instant MCP App UI loading\r\n * - Automatic reconnection with exponential backoff\r\n * - Type-safe RPC methods\r\n */\r\n\r\nimport { nanoid } from 'nanoid';\r\nimport type {\r\n McpConnectionEvent,\r\n McpObservabilityEvent,\r\n McpAppsUIEvent\r\n} from '../../shared/events.js';\r\nimport type {\r\n McpRpcRequest,\r\n McpRpcResponse,\r\n McpRpcMethod,\r\n McpRpcParams,\r\n ConnectParams,\r\n SessionListResult,\r\n ConnectResult,\r\n DisconnectResult,\r\n RestoreSessionResult,\r\n FinishAuthResult,\r\n ListToolsRpcResult,\r\n ListPromptsResult,\r\n ListResourcesResult,\r\n} from '../../shared/types.js';\r\n// ============================================\r\n// Types & Interfaces\r\n// ============================================\r\n\r\nexport interface SSEClientOptions {\r\n /** SSE endpoint URL */\r\n url: string;\r\n\r\n /** User/Client identifier */\r\n identity: string;\r\n\r\n /** Optional auth token for authenticated requests */\r\n authToken?: string;\r\n\r\n /** Callback for MCP connection state changes */\r\n onConnectionEvent?: (event: McpConnectionEvent) => void;\r\n\r\n /** Callback for observability/logging events */\r\n onObservabilityEvent?: (event: McpObservabilityEvent) => void;\r\n\r\n /** Callback for connection status changes */\r\n onStatusChange?: (status: ConnectionStatus) => void;\r\n\r\n /** Callback for MCP App UI events */\r\n onEvent?: (event: McpAppsUIEvent) => void;\r\n\r\n /** Request timeout in milliseconds @default 60000 */\r\n requestTimeout?: number;\r\n\r\n /** Enable debug logging @default false */\r\n debug?: boolean;\r\n}\r\n\r\nexport type ConnectionStatus = 'connecting' | 'connected' | 'disconnected' | 'error';\r\n\r\ninterface PendingRequest {\r\n resolve: (value: unknown) => void;\r\n reject: (error: Error) => void;\r\n timeoutId: ReturnType<typeof setTimeout>;\r\n}\r\n\r\ninterface ToolUiMetadata {\r\n resourceUri?: string;\r\n uri?: string;\r\n visibility?: string[];\r\n}\r\n\r\n// ============================================\r\n// Constants\r\n// ============================================\r\n\r\nconst DEFAULT_REQUEST_TIMEOUT = 60000;\r\nconst MAX_RECONNECT_ATTEMPTS = 5;\r\nconst BASE_RECONNECT_DELAY = 1000;\r\n\r\n// ============================================\r\n// SSEClient Class\r\n// ============================================\r\n\r\n/**\r\n * SSE Client for real-time MCP connection management\r\n */\r\nexport class SSEClient {\r\n private eventSource: EventSource | null = null;\r\n private pendingRequests = new Map<string, PendingRequest>();\r\n private resourceCache = new Map<string, Promise<unknown>>();\r\n\r\n private reconnectAttempts = 0;\r\n private isManuallyDisconnected = false;\r\n private connectionPromise: Promise<void> | null = null;\r\n private connectionResolver: (() => void) | null = null;\r\n\r\n constructor(private readonly options: SSEClientOptions) {}\r\n\r\n // ============================================\r\n // Connection Management\r\n // ============================================\r\n\r\n /**\r\n * Connect to the SSE endpoint\r\n */\r\n connect(): void {\r\n if (this.eventSource) {\r\n return; // Already connected\r\n }\r\n\r\n this.isManuallyDisconnected = false;\r\n this.options.onStatusChange?.('connecting');\r\n this.connectionPromise = new Promise((resolve) => {\r\n this.connectionResolver = resolve;\r\n });\r\n\r\n const url = this.buildUrl();\r\n this.eventSource = new EventSource(url);\r\n this.setupEventListeners();\r\n }\r\n\r\n /**\r\n * Disconnect from the SSE endpoint\r\n */\r\n disconnect(): void {\r\n this.isManuallyDisconnected = true;\r\n\r\n if (this.eventSource) {\r\n this.eventSource.close();\r\n this.eventSource = null;\r\n }\r\n\r\n this.connectionPromise = null;\r\n this.connectionResolver = null;\r\n this.rejectAllPendingRequests(new Error('Connection closed'));\r\n this.options.onStatusChange?.('disconnected');\r\n }\r\n\r\n /**\r\n * Check if connected to the SSE endpoint\r\n */\r\n isConnected(): boolean {\r\n return this.eventSource?.readyState === EventSource.OPEN;\r\n }\r\n\r\n // ============================================\r\n // RPC Methods\r\n // ============================================\r\n\r\n async getSessions(): Promise<SessionListResult> {\r\n return this.sendRequest<SessionListResult>('getSessions');\r\n }\r\n\r\n async connectToServer(params: ConnectParams): Promise<ConnectResult> {\r\n return this.sendRequest<ConnectResult>('connect', params);\r\n }\r\n\r\n async disconnectFromServer(sessionId: string): Promise<DisconnectResult> {\r\n return this.sendRequest<DisconnectResult>('disconnect', { sessionId });\r\n }\r\n\r\n async listTools(sessionId: string): Promise<ListToolsRpcResult> {\r\n return this.sendRequest<ListToolsRpcResult>('listTools', { sessionId });\r\n }\r\n\r\n async callTool(\r\n sessionId: string,\r\n toolName: string,\r\n toolArgs: Record<string, unknown>\r\n ): Promise<unknown> {\r\n const result = await this.sendRequest('callTool', { sessionId, toolName, toolArgs });\r\n this.emitUiEventIfPresent(result, sessionId, toolName);\r\n return result;\r\n }\r\n\r\n async restoreSession(sessionId: string): Promise<RestoreSessionResult> {\r\n return this.sendRequest<RestoreSessionResult>('restoreSession', { sessionId });\r\n }\r\n\r\n async finishAuth(sessionId: string, code: string): Promise<FinishAuthResult> {\r\n return this.sendRequest<FinishAuthResult>('finishAuth', { sessionId, code });\r\n }\r\n\r\n async listPrompts(sessionId: string): Promise<ListPromptsResult> {\r\n return this.sendRequest<ListPromptsResult>('listPrompts', { sessionId });\r\n }\r\n\r\n async getPrompt(sessionId: string, name: string, args?: Record<string, string>): Promise<unknown> {\r\n return this.sendRequest('getPrompt', { sessionId, name, args });\r\n }\r\n\r\n async listResources(sessionId: string): Promise<ListResourcesResult> {\r\n return this.sendRequest<ListResourcesResult>('listResources', { sessionId });\r\n }\r\n\r\n async readResource(sessionId: string, uri: string): Promise<unknown> {\r\n return this.sendRequest('readResource', { sessionId, uri });\r\n }\r\n\r\n // ============================================\r\n // Resource Preloading (for instant UI loading)\r\n // ============================================\r\n\r\n /**\r\n * Preload UI resources for tools that have UI metadata.\r\n * Call this when tools are discovered to enable instant MCP App UI loading.\r\n */\r\n preloadToolUiResources(sessionId: string, tools: Array<{ name: string; _meta?: unknown }>): void {\r\n for (const tool of tools) {\r\n const uri = this.extractUiResourceUri(tool);\r\n if (!uri) continue;\r\n\r\n if (this.resourceCache.has(uri)) {\r\n this.log(`Resource already cached: ${uri}`);\r\n continue;\r\n }\r\n\r\n this.log(`Preloading UI resource for tool \"${tool.name}\": ${uri}`);\r\n const promise = this.sendRequest('readResource', { sessionId, uri })\r\n .catch((err) => {\r\n this.log(`Failed to preload resource ${uri}: ${err.message}`, 'warn');\r\n this.resourceCache.delete(uri);\r\n return null;\r\n });\r\n\r\n this.resourceCache.set(uri, promise);\r\n }\r\n }\r\n\r\n /**\r\n * Get a preloaded resource from cache, or fetch if not cached.\r\n */\r\n getOrFetchResource(sessionId: string, uri: string): Promise<unknown> {\r\n const cached = this.resourceCache.get(uri);\r\n if (cached) {\r\n this.log(`Cache hit for resource: ${uri}`);\r\n return cached;\r\n }\r\n\r\n this.log(`Cache miss, fetching resource: ${uri}`);\r\n const promise = this.sendRequest('readResource', { sessionId, uri });\r\n this.resourceCache.set(uri, promise);\r\n return promise;\r\n }\r\n\r\n /**\r\n * Check if a resource is already cached\r\n */\r\n hasPreloadedResource(uri: string): boolean {\r\n return this.resourceCache.has(uri);\r\n }\r\n\r\n /**\r\n * Clear the resource cache\r\n */\r\n clearResourceCache(): void {\r\n this.resourceCache.clear();\r\n }\r\n\r\n // ============================================\r\n // Private: Request Handling\r\n // ============================================\r\n\r\n /**\r\n * Send an RPC request and return the response directly from HTTP.\r\n * This bypasses SSE latency by returning results in the HTTP response body.\r\n */\r\n private async sendRequest<T = unknown>(method: McpRpcMethod, params?: McpRpcParams): Promise<T> {\r\n if (this.connectionPromise) {\r\n await this.connectionPromise;\r\n }\r\n\r\n const request: McpRpcRequest = {\r\n id: `rpc_${nanoid(10)}`,\r\n method,\r\n params,\r\n };\r\n\r\n const response = await fetch(this.buildUrl(), {\r\n method: 'POST',\r\n headers: this.buildHeaders(),\r\n body: JSON.stringify(request),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\r\n }\r\n\r\n const data = await response.json() as McpRpcResponse;\r\n return this.parseRpcResponse<T>(data, request.id);\r\n }\r\n\r\n /**\r\n * Parse RPC response and handle different response formats\r\n */\r\n private parseRpcResponse<T>(data: McpRpcResponse, requestId: string): T | Promise<T> {\r\n // Fast path: Direct response (new behavior)\r\n if ('result' in data) {\r\n return data.result as T;\r\n }\r\n\r\n // Error response\r\n if ('error' in data && data.error) {\r\n throw new Error(data.error.message || 'Unknown RPC error');\r\n }\r\n\r\n // Legacy path: Acknowledgment only (wait for SSE)\r\n // Kept for backwards compatibility with older servers\r\n if ('acknowledged' in data) {\r\n return this.waitForSseResponse<T>(requestId);\r\n }\r\n\r\n throw new Error('Invalid RPC response format');\r\n }\r\n\r\n /**\r\n * Wait for RPC response via SSE (legacy fallback)\r\n */\r\n private waitForSseResponse<T>(requestId: string): Promise<T> {\r\n const timeoutMs = this.options.requestTimeout ?? DEFAULT_REQUEST_TIMEOUT;\r\n\r\n return new Promise<T>((resolve, reject) => {\r\n const timeoutId = setTimeout(() => {\r\n this.pendingRequests.delete(requestId);\r\n reject(new Error(`Request timeout after ${timeoutMs}ms`));\r\n }, timeoutMs);\r\n\r\n this.pendingRequests.set(requestId, {\r\n resolve: resolve as (value: unknown) => void,\r\n reject,\r\n timeoutId,\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Handle RPC response received via SSE (legacy)\r\n */\r\n private handleRpcResponse(response: McpRpcResponse): void {\r\n const pending = this.pendingRequests.get(response.id);\r\n if (!pending) return;\r\n\r\n clearTimeout(pending.timeoutId);\r\n this.pendingRequests.delete(response.id);\r\n\r\n if (response.error) {\r\n pending.reject(new Error(response.error.message));\r\n } else {\r\n pending.resolve(response.result);\r\n }\r\n }\r\n\r\n // ============================================\r\n // Private: Event Handling\r\n // ============================================\r\n\r\n private setupEventListeners(): void {\r\n if (!this.eventSource) return;\r\n\r\n this.eventSource.addEventListener('open', () => {\r\n this.log('Connected');\r\n this.reconnectAttempts = 0;\r\n this.options.onStatusChange?.('connected');\r\n });\r\n\r\n this.eventSource.addEventListener('connected', () => {\r\n this.log('Server ready');\r\n this.connectionResolver?.();\r\n this.connectionResolver = null;\r\n });\r\n\r\n this.eventSource.addEventListener('connection', (e: MessageEvent) => {\r\n const event = JSON.parse(e.data) as McpConnectionEvent;\r\n this.options.onConnectionEvent?.(event);\r\n });\r\n\r\n this.eventSource.addEventListener('observability', (e: MessageEvent) => {\r\n const event = JSON.parse(e.data) as McpObservabilityEvent;\r\n this.options.onObservabilityEvent?.(event);\r\n });\r\n\r\n this.eventSource.addEventListener('rpc-response', (e: MessageEvent) => {\r\n const response = JSON.parse(e.data) as McpRpcResponse;\r\n this.handleRpcResponse(response);\r\n });\r\n\r\n this.eventSource.addEventListener('error', () => {\r\n this.log('Connection error', 'error');\r\n this.options.onStatusChange?.('error');\r\n this.attemptReconnect();\r\n });\r\n }\r\n\r\n private attemptReconnect(): void {\r\n if (this.isManuallyDisconnected || this.reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {\r\n return;\r\n }\r\n\r\n this.reconnectAttempts++;\r\n const delay = BASE_RECONNECT_DELAY * this.reconnectAttempts;\r\n this.log(`Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts}/${MAX_RECONNECT_ATTEMPTS})`);\r\n\r\n setTimeout(() => {\r\n this.disconnect();\r\n this.connect();\r\n }, delay);\r\n }\r\n\r\n // ============================================\r\n // Private: Utilities\r\n // ============================================\r\n\r\n private buildUrl(): string {\r\n const url = new URL(this.options.url, globalThis.location?.origin);\r\n url.searchParams.set('identity', this.options.identity);\r\n if (this.options.authToken) {\r\n url.searchParams.set('token', this.options.authToken);\r\n }\r\n return url.toString();\r\n }\r\n\r\n private buildHeaders(): HeadersInit {\r\n const headers: HeadersInit = {\r\n 'Content-Type': 'application/json',\r\n };\r\n if (this.options.authToken) {\r\n headers['Authorization'] = `Bearer ${this.options.authToken}`;\r\n }\r\n return headers;\r\n }\r\n\r\n private rejectAllPendingRequests(error: Error): void {\r\n for (const [, pending] of this.pendingRequests) {\r\n clearTimeout(pending.timeoutId);\r\n pending.reject(error);\r\n }\r\n this.pendingRequests.clear();\r\n }\r\n\r\n private extractUiResourceUri(tool: { name: string; _meta?: unknown }): string | undefined {\r\n const meta = (tool._meta as { ui?: ToolUiMetadata })?.ui;\r\n if (!meta || typeof meta !== 'object') return undefined;\r\n\r\n // Check visibility constraint\r\n if (meta.visibility && !meta.visibility.includes('app')) return undefined;\r\n\r\n // Support both 'resourceUri' and 'uri' field names\r\n return meta.resourceUri ?? meta.uri;\r\n }\r\n\r\n private emitUiEventIfPresent(result: unknown, sessionId: string, toolName: string): void {\r\n const meta = (result as { _meta?: { ui?: ToolUiMetadata } })?._meta;\r\n const resourceUri = meta?.ui?.resourceUri ?? (meta as any)?.['ui/resourceUri'];\r\n\r\n if (resourceUri) {\r\n this.options.onEvent?.({\r\n type: 'mcp-apps-ui',\r\n sessionId,\r\n resourceUri,\r\n toolName,\r\n result,\r\n timestamp: Date.now(),\r\n });\r\n }\r\n }\r\n\r\n private log(message: string, level: 'info' | 'warn' | 'error' = 'info'): void {\r\n if (!this.options.debug && level === 'info') return;\r\n\r\n const prefix = '[SSEClient]';\r\n switch (level) {\r\n case 'warn':\r\n console.warn(prefix, message);\r\n break;\r\n case 'error':\r\n console.error(prefix, message);\r\n break;\r\n default:\r\n console.log(prefix, message);\r\n }\r\n }\r\n}\r\n","/**\r\n * useMcp React Hook\r\n * Manages MCP connections with SSE-based real-time updates\r\n * Based on Cloudflare's agents pattern\r\n */\r\n\r\nimport { useEffect, useRef, useState, useCallback } from 'react';\r\nimport { SSEClient, type SSEClientOptions } from '../core/sse-client';\r\nimport type { McpConnectionEvent, McpConnectionState } from '../../shared/events';\r\nimport type {\r\n ToolInfo,\r\n FinishAuthResult,\r\n ListToolsRpcResult,\r\n ListPromptsResult,\r\n ListResourcesResult,\r\n SessionInfo,\r\n} from '../../shared/types';\r\n\r\nexport interface UseMcpOptions {\r\n /**\r\n * SSE endpoint URL\r\n */\r\n url: string;\r\n\r\n /**\r\n * User/Client identifier\r\n */\r\n identity: string;\r\n\r\n /**\r\n * Optional auth token\r\n */\r\n authToken?: string;\r\n\r\n /**\r\n * Auto-connect on mount\r\n * @default true\r\n */\r\n autoConnect?: boolean;\r\n\r\n /**\r\n * Auto-initialize sessions on mount\r\n * @default true\r\n */\r\n autoInitialize?: boolean;\r\n\r\n /**\r\n * Connection event callback\r\n */\r\n onConnectionEvent?: (event: McpConnectionEvent) => void;\r\n\r\n /**\r\n * Debug logging callback\r\n */\r\n onLog?: (level: string, message: string, metadata?: Record<string, unknown>) => void;\r\n /**\r\n * Optional callback to handle OAuth redirects (e.g. for popup flow)\r\n * If provided, this will be called instead of window.location.href assignment\r\n */\r\n onRedirect?: (url: string) => void;\r\n\r\n /**\r\n * Request timeout in milliseconds\r\n * @default 60000\r\n */\r\n requestTimeout?: number;\r\n}\r\n\r\nexport interface McpConnection {\r\n sessionId: string;\r\n serverId: string;\r\n serverName: string;\r\n serverUrl?: string;\r\n transport?: string;\r\n state: McpConnectionState;\r\n tools: ToolInfo[];\r\n error?: string;\r\n connectedAt?: Date;\r\n}\r\n\r\nexport interface McpClient {\r\n /**\r\n * All connections\r\n */\r\n connections: McpConnection[];\r\n\r\n /**\r\n * SSE connection status\r\n */\r\n status: 'connecting' | 'connected' | 'disconnected' | 'error';\r\n\r\n /**\r\n * Whether initializing\r\n */\r\n isInitializing: boolean;\r\n\r\n /**\r\n * Connect to an MCP server\r\n */\r\n connect: (params: {\r\n serverId: string;\r\n serverName: string;\r\n serverUrl: string;\r\n callbackUrl: string;\r\n transportType?: 'sse' | 'streamable_http';\r\n }) => Promise<string>;\r\n\r\n /**\r\n * Disconnect from an MCP server\r\n */\r\n disconnect: (sessionId: string) => Promise<void>;\r\n\r\n /**\r\n * Get connection by session ID\r\n */\r\n getConnection: (sessionId: string) => McpConnection | undefined;\r\n\r\n /**\r\n * Get connection by server ID\r\n */\r\n getConnectionByServerId: (serverId: string) => McpConnection | undefined;\r\n\r\n /**\r\n * Check if server is connected\r\n */\r\n isServerConnected: (serverId: string) => boolean;\r\n\r\n /**\r\n * Get tools for a session\r\n */\r\n getTools: (sessionId: string) => ToolInfo[];\r\n\r\n /**\r\n * Refresh all connections\r\n */\r\n refresh: () => Promise<void>;\r\n\r\n /**\r\n * Manually connect SSE\r\n */\r\n connectSSE: () => void;\r\n\r\n /**\r\n * Manually disconnect SSE\r\n */\r\n disconnectSSE: () => void;\r\n\r\n /**\r\n * Complete OAuth authorization\r\n */\r\n finishAuth: (sessionId: string, code: string) => Promise<FinishAuthResult>;\r\n\r\n /**\r\n * Call a tool from a session\r\n */\r\n callTool: (\r\n sessionId: string,\r\n toolName: string,\r\n toolArgs: Record<string, unknown>\r\n ) => Promise<unknown>;\r\n\r\n /**\r\n * List available tools for a session\r\n */\r\n listTools: (sessionId: string) => Promise<ListToolsRpcResult>;\r\n\r\n /**\r\n * List available prompts for a session\r\n */\r\n listPrompts: (sessionId: string) => Promise<ListPromptsResult>;\r\n\r\n /**\r\n * Get a specific prompt with arguments\r\n */\r\n getPrompt: (sessionId: string, name: string, args?: Record<string, string>) => Promise<unknown>;\r\n\r\n /**\r\n * List available resources for a session\r\n */\r\n listResources: (sessionId: string) => Promise<ListResourcesResult>;\r\n\r\n /**\r\n * Read a specific resource\r\n */\r\n readResource: (sessionId: string, uri: string) => Promise<unknown>;\r\n\r\n /**\r\n * Access the underlying SSEClient instance (for advanced usage like AppHost)\r\n */\r\n sseClient: SSEClient | null;\r\n}\r\n\r\n/**\r\n * React hook for MCP connection management with SSE\r\n */\r\nexport function useMcp(options: UseMcpOptions): McpClient {\r\n const {\r\n url,\r\n identity,\r\n authToken,\r\n autoConnect = true,\r\n autoInitialize = true,\r\n onConnectionEvent,\r\n onLog,\r\n onRedirect,\r\n } = options;\r\n\r\n const clientRef = useRef<SSEClient | null>(null);\r\n const isMountedRef = useRef(true);\r\n\r\n const [connections, setConnections] = useState<McpConnection[]>([]);\r\n const [status, setStatus] = useState<'connecting' | 'connected' | 'disconnected' | 'error'>(\r\n 'disconnected'\r\n );\r\n const [isInitializing, setIsInitializing] = useState(false);\r\n\r\n /**\r\n * Initialize SSE client\r\n */\r\n useEffect(() => {\r\n isMountedRef.current = true;\r\n\r\n const clientOptions: SSEClientOptions = {\r\n url,\r\n identity,\r\n authToken,\r\n onConnectionEvent: (event) => {\r\n // Update local state based on event\r\n updateConnectionsFromEvent(event);\r\n\r\n // Call user callback\r\n onConnectionEvent?.(event);\r\n },\r\n onObservabilityEvent: (event) => {\r\n onLog?.(event.level || 'info', event.message || event.displayMessage || 'No message', event.metadata);\r\n },\r\n onStatusChange: (newStatus) => {\r\n if (isMountedRef.current) {\r\n setStatus(newStatus);\r\n }\r\n },\r\n requestTimeout: options.requestTimeout,\r\n };\r\n\r\n const client = new SSEClient(clientOptions);\r\n clientRef.current = client;\r\n\r\n if (autoConnect) {\r\n client.connect();\r\n\r\n if (autoInitialize) {\r\n loadSessions();\r\n }\r\n }\r\n\r\n return () => {\r\n isMountedRef.current = false;\r\n client.disconnect();\r\n };\r\n }, [url, identity, authToken, autoConnect, autoInitialize]);\r\n\r\n /**\r\n * Update connections based on event\r\n */\r\n const updateConnectionsFromEvent = useCallback((event: McpConnectionEvent) => {\r\n if (!isMountedRef.current) return;\r\n\r\n setConnections((prev: McpConnection[]) => {\r\n switch (event.type) {\r\n case 'state_changed': {\r\n const existing = prev.find((c: McpConnection) => c.sessionId === event.sessionId);\r\n if (existing) {\r\n return prev.map((c: McpConnection) =>\r\n c.sessionId === event.sessionId ? { ...c, state: event.state } : c\r\n );\r\n } else {\r\n return [\r\n ...prev,\r\n {\r\n sessionId: event.sessionId,\r\n serverId: event.serverId,\r\n serverName: event.serverName,\r\n state: event.state,\r\n tools: [],\r\n },\r\n ];\r\n }\r\n }\r\n\r\n case 'tools_discovered': {\r\n // Preload UI resources for instant loading when tools are discovered\r\n if (clientRef.current && event.tools?.length) {\r\n clientRef.current.preloadToolUiResources(event.sessionId, event.tools);\r\n }\r\n\r\n return prev.map((c: McpConnection) =>\r\n c.sessionId === event.sessionId ? { ...c, tools: event.tools, state: 'READY' } : c\r\n );\r\n }\r\n\r\n case 'auth_required': {\r\n // Handle OAuth redirect\r\n if (event.authUrl) {\r\n onLog?.('info', `OAuth required - redirecting to ${event.authUrl}`, { authUrl: event.authUrl });\r\n\r\n if (onRedirect) {\r\n onRedirect(event.authUrl);\r\n } else if (typeof window !== 'undefined') {\r\n window.location.href = event.authUrl;\r\n }\r\n }\r\n return prev.map((c: McpConnection) =>\r\n c.sessionId === event.sessionId ? { ...c, state: 'AUTHENTICATING' } : c\r\n );\r\n }\r\n\r\n case 'error': {\r\n return prev.map((c: McpConnection) =>\r\n c.sessionId === event.sessionId ? { ...c, state: 'FAILED', error: event.error } : c\r\n );\r\n }\r\n\r\n case 'disconnected': {\r\n return prev.filter((c: McpConnection) => c.sessionId !== event.sessionId);\r\n }\r\n\r\n default:\r\n return prev;\r\n }\r\n });\r\n }, [onLog]);\r\n\r\n /**\r\n * Load sessions from server\r\n */\r\n const loadSessions = useCallback(async () => {\r\n if (!clientRef.current) return;\r\n\r\n try {\r\n setIsInitializing(true);\r\n\r\n const result = await clientRef.current.getSessions();\r\n const sessions = result.sessions || [];\r\n\r\n // Initialize connections\r\n if (isMountedRef.current) {\r\n setConnections(\r\n sessions.map((s: SessionInfo) => ({\r\n sessionId: s.sessionId,\r\n serverId: s.serverId ?? 'unknown',\r\n serverName: s.serverName ?? 'Unknown Server',\r\n serverUrl: s.serverUrl,\r\n transport: s.transport,\r\n state: 'VALIDATING' as McpConnectionState,\r\n tools: [],\r\n }))\r\n );\r\n }\r\n\r\n // Validate each session in parallel\r\n await Promise.all(\r\n sessions.map(async (session: SessionInfo) => {\r\n if (clientRef.current) {\r\n try {\r\n await clientRef.current.restoreSession(session.sessionId);\r\n } catch (error) {\r\n console.error(`[useMcp] Failed to validate session ${session.sessionId}:`, error);\r\n }\r\n }\r\n })\r\n );\r\n } catch (error) {\r\n console.error('[useMcp] Failed to load sessions:', error);\r\n onLog?.('error', 'Failed to load sessions', { error });\r\n } finally {\r\n if (isMountedRef.current) {\r\n setIsInitializing(false);\r\n }\r\n }\r\n }, [onLog]);\r\n\r\n /**\r\n * Connect to an MCP server\r\n */\r\n const connect = useCallback(\r\n async (params: {\r\n serverId: string;\r\n serverName: string;\r\n serverUrl: string;\r\n callbackUrl: string;\r\n transportType?: 'sse' | 'streamable_http';\r\n }): Promise<string> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n const result = await clientRef.current.connectToServer(params);\r\n return result.sessionId;\r\n },\r\n []\r\n );\r\n\r\n /**\r\n * Disconnect from an MCP server\r\n */\r\n const disconnect = useCallback(async (sessionId: string): Promise<void> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n await clientRef.current.disconnectFromServer(sessionId);\r\n\r\n // Remove from local state\r\n if (isMountedRef.current) {\r\n setConnections((prev: McpConnection[]) => prev.filter((c: McpConnection) => c.sessionId !== sessionId));\r\n }\r\n }, []);\r\n\r\n /**\r\n * Refresh all connections\r\n */\r\n const refresh = useCallback(async () => {\r\n await loadSessions();\r\n }, [loadSessions]);\r\n\r\n /**\r\n * Manually connect SSE\r\n */\r\n const connectSSE = useCallback(() => {\r\n clientRef.current?.connect();\r\n }, []);\r\n\r\n /**\r\n * Manually disconnect SSE\r\n */\r\n const disconnectSSE = useCallback(() => {\r\n clientRef.current?.disconnect();\r\n }, []);\r\n\r\n /**\r\n * Complete OAuth authorization\r\n */\r\n const finishAuth = useCallback(async (sessionId: string, code: string): Promise<FinishAuthResult> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n return await clientRef.current.finishAuth(sessionId, code);\r\n }, []);\r\n\r\n /**\r\n * Call a tool\r\n */\r\n const callTool = useCallback(\r\n async (\r\n sessionId: string,\r\n toolName: string,\r\n toolArgs: Record<string, unknown>\r\n ): Promise<unknown> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n return await clientRef.current.callTool(sessionId, toolName, toolArgs);\r\n },\r\n []\r\n );\r\n\r\n /**\r\n * List tools (refresh tool list)\r\n */\r\n const listTools = useCallback(async (sessionId: string): Promise<ListToolsRpcResult> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n return await clientRef.current.listTools(sessionId);\r\n }, []);\r\n\r\n /**\r\n * List prompts\r\n */\r\n const listPrompts = useCallback(async (sessionId: string): Promise<ListPromptsResult> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n return await clientRef.current.listPrompts(sessionId);\r\n }, []);\r\n\r\n /**\r\n * Get a specific prompt\r\n */\r\n const getPrompt = useCallback(\r\n async (sessionId: string, name: string, args?: Record<string, string>): Promise<unknown> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n return await clientRef.current.getPrompt(sessionId, name, args);\r\n },\r\n []\r\n );\r\n\r\n /**\r\n * List resources\r\n */\r\n const listResources = useCallback(async (sessionId: string): Promise<ListResourcesResult> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n return await clientRef.current.listResources(sessionId);\r\n }, []);\r\n\r\n /**\r\n * Read a specific resource\r\n */\r\n const readResource = useCallback(async (sessionId: string, uri: string): Promise<unknown> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n return await clientRef.current.readResource(sessionId, uri);\r\n }, []);\r\n\r\n // Utility functions\r\n const getConnection = useCallback(\r\n (sessionId: string) => connections.find((c: McpConnection) => c.sessionId === sessionId),\r\n [connections]\r\n );\r\n\r\n const getConnectionByServerId = useCallback(\r\n (serverId: string) => connections.find((c: McpConnection) => c.serverId === serverId),\r\n [connections]\r\n );\r\n\r\n const isServerConnected = useCallback(\r\n (serverId: string) => {\r\n const conn = getConnectionByServerId(serverId);\r\n return conn?.state === 'CONNECTED';\r\n },\r\n [getConnectionByServerId]\r\n );\r\n\r\n const getTools = useCallback(\r\n (sessionId: string) => {\r\n const conn = getConnection(sessionId);\r\n return conn?.tools || [];\r\n },\r\n [getConnection]\r\n );\r\n\r\n return {\r\n connections,\r\n status,\r\n isInitializing,\r\n connect,\r\n disconnect,\r\n getConnection,\r\n getConnectionByServerId,\r\n isServerConnected,\r\n getTools,\r\n refresh,\r\n connectSSE,\r\n disconnectSSE,\r\n finishAuth,\r\n callTool,\r\n listTools,\r\n listPrompts,\r\n getPrompt,\r\n listResources,\r\n readResource,\r\n sseClient: clientRef.current,\r\n };\r\n}\r\n","/**\r\n * MCP App Host\r\n *\r\n * Bridges the gap between an iframe (MCP App) and the SSEClient (MCP Server).\r\n * Handles secure iframe sandboxing, resource loading, and bi-directional\r\n * communication via the AppBridge protocol.\r\n *\r\n * Key features:\r\n * - Secure iframe sandboxing with minimal permissions\r\n * - Resource preloading for instant MCP App UI loading\r\n * - Cache-aware resource fetching (SSEClient cache → local cache → direct fetch)\r\n * - Support for ui:// and mcp-app:// resource URIs\r\n */\r\n\r\nimport { AppBridge, PostMessageTransport } from '@modelcontextprotocol/ext-apps/app-bridge';\r\nimport type { AppHostClient } from './types';\r\n\r\n// ============================================\r\n// Types & Interfaces\r\n// ============================================\r\n\r\nexport interface AppHostOptions {\r\n /** Enable debug logging @default false */\r\n debug?: boolean;\r\n}\r\n\r\nexport interface AppMessageParams {\r\n role: string;\r\n content: unknown;\r\n}\r\n\r\ninterface ToolCallParams {\r\n name: string;\r\n arguments?: Record<string, unknown>;\r\n}\r\n\r\ninterface ResourceContent {\r\n blob?: string;\r\n text?: string;\r\n}\r\n\r\ninterface ResourceResponse {\r\n contents: ResourceContent[];\r\n}\r\n\r\n// ============================================\r\n// Constants\r\n// ============================================\r\n\r\nconst HOST_INFO = { name: 'mcp-ts-host', version: '1.0.0' };\r\n\r\n/** Sandbox permissions - minimal set required for MCP Apps to function */\r\nconst SANDBOX_PERMISSIONS = [\r\n 'allow-scripts', // Required for app JavaScript execution\r\n 'allow-forms', // Required for form submissions\r\n 'allow-same-origin', // Required for Blob URL correctness\r\n 'allow-modals', // Required for dialogs/alerts\r\n 'allow-popups', // Required for opening links\r\n 'allow-downloads' // Required for file downloads\r\n].join(' ');\r\n\r\n/** Supported MCP App URI schemes */\r\nconst MCP_URI_SCHEMES = ['ui://', 'mcp-app://'] as const;\r\n\r\n// ============================================\r\n// AppHost Class\r\n// ============================================\r\n\r\n/**\r\n * Host for MCP Apps embedded in iframes.\r\n * Manages secure communication between the app and the MCP server.\r\n */\r\nexport class AppHost {\r\n private bridge: AppBridge;\r\n private sessionId?: string;\r\n private resourceCache = new Map<string, Promise<ResourceResponse | null>>();\r\n private debug: boolean;\r\n\r\n /** Callback for app messages (e.g., chat messages from the app) */\r\n public onAppMessage?: (params: AppMessageParams) => void;\r\n\r\n constructor(\r\n private readonly client: AppHostClient,\r\n private readonly iframe: HTMLIFrameElement,\r\n options?: AppHostOptions\r\n ) {\r\n this.debug = options?.debug ?? false;\r\n this.configureSandbox();\r\n this.bridge = this.initializeBridge();\r\n }\r\n\r\n // ============================================\r\n // Public API\r\n // ============================================\r\n\r\n /**\r\n * Start the host. This prepares the bridge handlers but doesn't connect yet.\r\n * The actual connection happens in launch() after HTML is loaded.\r\n * @returns Promise that resolves immediately (bridge connects during launch)\r\n */\r\n async start(): Promise<void> {\r\n // Bridge handlers are already registered in constructor.\r\n // Connection happens in launch() after HTML is loaded.\r\n this.log('Host started, ready to launch');\r\n }\r\n\r\n /**\r\n * Preload UI resources to enable instant app loading.\r\n * Call this when tools are discovered to cache their UI resources.\r\n */\r\n preload(tools: Array<{ _meta?: unknown }>): void {\r\n for (const tool of tools) {\r\n const uri = this.extractUiResourceUri(tool);\r\n if (!uri || this.resourceCache.has(uri)) continue;\r\n\r\n const promise = this.preloadResource(uri);\r\n this.resourceCache.set(uri, promise);\r\n }\r\n }\r\n\r\n /**\r\n * Launch an MCP App from a URL or MCP resource URI.\r\n * Loads the HTML first, then establishes bridge connection.\r\n */\r\n async launch(url: string, sessionId?: string): Promise<void> {\r\n if (sessionId) this.sessionId = sessionId;\r\n\r\n // Set up initialization promise BEFORE connecting\r\n const initializedPromise = this.onAppReady();\r\n\r\n // Load HTML into iframe first\r\n if (this.isMcpUri(url)) {\r\n await this.launchMcpApp(url);\r\n } else {\r\n this.iframe.src = url;\r\n }\r\n\r\n // Wait for iframe to load before connecting bridge\r\n await this.onIframeReady();\r\n\r\n // Connect the bridge (HTML is loaded, contentWindow is ready)\r\n await this.connectBridge();\r\n\r\n // Wait for app to signal it's initialized (with timeout)\r\n this.log('Waiting for app initialization');\r\n await Promise.race([\r\n initializedPromise,\r\n new Promise<void>((resolve) => setTimeout(() => {\r\n this.log('Initialization timeout - continuing anyway', 'warn');\r\n resolve();\r\n }, 3000))\r\n ]);\r\n this.log('App launched and ready');\r\n }\r\n\r\n /**\r\n * Wait for app to signal initialization complete\r\n */\r\n private onAppReady(): Promise<void> {\r\n return new Promise<void>((resolve) => {\r\n const originalHandler = this.bridge.oninitialized;\r\n this.bridge.oninitialized = (...args) => {\r\n this.log('App initialized');\r\n resolve();\r\n this.bridge.oninitialized = originalHandler;\r\n originalHandler?.(...args);\r\n };\r\n });\r\n }\r\n\r\n /**\r\n * Wait for iframe to finish loading\r\n */\r\n private onIframeReady(): Promise<void> {\r\n return new Promise((resolve) => {\r\n if (this.iframe.contentDocument?.readyState === 'complete') {\r\n resolve();\r\n return;\r\n }\r\n this.iframe.addEventListener('load', () => resolve(), { once: true });\r\n });\r\n }\r\n\r\n /**\r\n * Send tool input arguments to the MCP App.\r\n * Call this after launch() when tool input is available.\r\n */\r\n sendToolInput(args: Record<string, unknown>): void {\r\n this.log('Sending tool input to app');\r\n this.bridge.sendToolInput({ arguments: args });\r\n }\r\n\r\n /**\r\n * Send tool result to the MCP App.\r\n * Call this when the tool call completes.\r\n */\r\n sendToolResult(result: unknown): void {\r\n this.log('Sending tool result to app');\r\n this.bridge.sendToolResult(result as any);\r\n }\r\n\r\n /**\r\n * Send tool cancellation to the MCP App.\r\n * Call this when the tool call is cancelled or fails.\r\n */\r\n sendToolCancelled(reason: string): void {\r\n this.log('Sending tool cancellation to app');\r\n this.bridge.sendToolCancelled({ reason });\r\n }\r\n\r\n // ============================================\r\n // Private: Initialization\r\n // ============================================\r\n\r\n private configureSandbox(): void {\r\n if (this.iframe.sandbox.value !== SANDBOX_PERMISSIONS) {\r\n this.iframe.sandbox.value = SANDBOX_PERMISSIONS;\r\n }\r\n }\r\n\r\n private initializeBridge(): AppBridge {\r\n const bridge = new AppBridge(\r\n null,\r\n HOST_INFO,\r\n {\r\n openLinks: {},\r\n serverTools: {},\r\n logging: {},\r\n // Declare support for model context updates\r\n updateModelContext: { text: {} },\r\n },\r\n {\r\n // Initial host context\r\n hostContext: {\r\n theme: 'dark',\r\n platform: 'web',\r\n containerDimensions: { maxHeight: 6000 },\r\n displayMode: 'inline',\r\n availableDisplayModes: ['inline', 'fullscreen'],\r\n },\r\n }\r\n );\r\n\r\n // Register handlers - must be done BEFORE connect()\r\n bridge.oncalltool = (params) => this.handleToolCall(params);\r\n bridge.onopenlink = this.handleOpenLink.bind(this);\r\n bridge.onmessage = this.handleMessage.bind(this);\r\n bridge.onloggingmessage = (params) => this.log(`App log [${params.level}]: ${params.data}`);\r\n bridge.onupdatemodelcontext = async () => ({});\r\n bridge.onsizechange = async ({ width, height }) => {\r\n if (height !== undefined) this.iframe.style.height = `${height}px`;\r\n if (width !== undefined) this.iframe.style.minWidth = `min(${width}px, 100%)`;\r\n return {};\r\n };\r\n bridge.onrequestdisplaymode = async (params) => ({\r\n mode: params.mode === 'fullscreen' ? 'fullscreen' : 'inline'\r\n });\r\n\r\n return bridge;\r\n }\r\n\r\n private async connectBridge(): Promise<void> {\r\n this.log('Connecting bridge to iframe');\r\n\r\n const transport = new PostMessageTransport(\r\n this.iframe.contentWindow!,\r\n this.iframe.contentWindow!\r\n );\r\n\r\n try {\r\n await this.bridge.connect(transport);\r\n this.log('Bridge connected successfully');\r\n } catch (error) {\r\n this.log('Bridge connection failed', 'error');\r\n throw error;\r\n }\r\n }\r\n\r\n // ============================================\r\n // Private: Bridge Event Handlers\r\n // ============================================\r\n\r\n private async handleToolCall(params: ToolCallParams) {\r\n if (!this.client.isConnected()) {\r\n throw new Error('Client disconnected');\r\n }\r\n\r\n const sessionId = await this.getSessionId();\r\n if (!sessionId) {\r\n throw new Error('No active session');\r\n }\r\n\r\n const result = await this.client.callTool(\r\n sessionId,\r\n params.name,\r\n params.arguments ?? {}\r\n );\r\n return result as any;\r\n }\r\n\r\n private async handleOpenLink(params: { url: string }): Promise<Record<string, never>> {\r\n window.open(params.url, '_blank', 'noopener,noreferrer');\r\n return {};\r\n }\r\n\r\n private async handleMessage(params: AppMessageParams): Promise<Record<string, never>> {\r\n this.onAppMessage?.(params);\r\n return {};\r\n }\r\n\r\n // ============================================\r\n // Private: Resource Loading\r\n // ============================================\r\n\r\n private async launchMcpApp(uri: string): Promise<void> {\r\n if (!this.client.isConnected()) {\r\n throw new Error('Client must be connected');\r\n }\r\n\r\n const sessionId = await this.getSessionId();\r\n if (!sessionId) {\r\n throw new Error('No active session');\r\n }\r\n\r\n // Fetch resource using cache hierarchy: SSEClient cache → local cache → direct fetch\r\n const response = await this.fetchResourceWithCache(sessionId, uri);\r\n if (!response?.contents?.length) {\r\n throw new Error(`Empty resource: ${uri}`);\r\n }\r\n\r\n const content = response.contents[0];\r\n const html = this.decodeContent(content);\r\n if (!html) {\r\n throw new Error(`Invalid content in resource: ${uri}`);\r\n }\r\n\r\n // Render via Blob URL for clean isolation\r\n const blob = new Blob([html], { type: 'text/html' });\r\n this.iframe.src = URL.createObjectURL(blob);\r\n }\r\n\r\n private async fetchResourceWithCache(sessionId: string, uri: string): Promise<ResourceResponse> {\r\n // Priority 1: SSEClient's built-in cache (best performance)\r\n if (this.hasClientCache()) {\r\n return (this.client as any).getOrFetchResource(sessionId, uri);\r\n }\r\n\r\n // Priority 2: Local preload cache\r\n const cached = this.resourceCache.get(uri);\r\n if (cached) {\r\n const result = await cached;\r\n if (result) return result;\r\n }\r\n\r\n // Priority 3: Direct fetch\r\n return this.client.readResource(sessionId, uri) as Promise<ResourceResponse>;\r\n }\r\n\r\n private async preloadResource(uri: string): Promise<ResourceResponse | null> {\r\n try {\r\n const sessionId = await this.getSessionId();\r\n if (!sessionId) return null;\r\n return await this.client.readResource(sessionId, uri) as ResourceResponse;\r\n } catch (error) {\r\n this.log(`Preload failed for ${uri}`, 'warn');\r\n return null;\r\n }\r\n }\r\n\r\n // ============================================\r\n // Private: Utilities\r\n // ============================================\r\n\r\n private async getSessionId(): Promise<string | undefined> {\r\n if (this.sessionId) return this.sessionId;\r\n const result = await this.client.getSessions();\r\n return result.sessions?.[0]?.sessionId;\r\n }\r\n\r\n private isMcpUri(url: string): boolean {\r\n return MCP_URI_SCHEMES.some(scheme => url.startsWith(scheme));\r\n }\r\n\r\n private hasClientCache(): boolean {\r\n return 'getOrFetchResource' in this.client &&\r\n typeof (this.client as any).getOrFetchResource === 'function';\r\n }\r\n\r\n private extractUiResourceUri(tool: { _meta?: unknown }): string | undefined {\r\n const meta = tool._meta as { ui?: { resourceUri?: string; uri?: string } } | undefined;\r\n if (!meta?.ui) return undefined;\r\n return meta.ui.resourceUri ?? meta.ui.uri;\r\n }\r\n\r\n private decodeContent(content: ResourceContent): string | undefined {\r\n if (content.blob) {\r\n return atob(content.blob);\r\n }\r\n return content.text;\r\n }\r\n\r\n private log(message: string, level: 'info' | 'warn' | 'error' = 'info'): void {\r\n if (!this.debug && level === 'info') return;\r\n\r\n const prefix = '[AppHost]';\r\n switch (level) {\r\n case 'warn':\r\n console.warn(prefix, message);\r\n break;\r\n case 'error':\r\n console.error(prefix, message);\r\n break;\r\n default:\r\n console.log(prefix, message);\r\n }\r\n }\r\n}\r\n","import { useEffect, useRef, useState, useCallback } from 'react';\r\nimport type { SSEClient } from '../core/sse-client';\r\nimport { AppHost } from '../core/app-host';\r\n\r\n/**\r\n * Hook to host an MCP App in a React component\r\n *\r\n * Optimized for instant loading:\r\n * - Creates AppHost synchronously\r\n * - Starts bridge connection immediately\r\n * - Returns host before connection completes (ready to call launch)\r\n *\r\n * @param client - Connected SSEClient instance\r\n * @param iframeRef - Reference to the iframe element\r\n * @param options - Optional configuration\r\n * @returns Object containing the AppHost instance (or null) and error state\r\n */\r\nexport function useAppHost(\r\n client: SSEClient,\r\n iframeRef: React.RefObject<HTMLIFrameElement>,\r\n options?: {\r\n /** Callback when the App sends a message (e.g. to chat) */\r\n onMessage?: (params: { role: string; content: unknown }) => void;\r\n }\r\n) {\r\n const [host, setHost] = useState<AppHost | null>(null);\r\n const [error, setError] = useState<Error | null>(null);\r\n const initializingRef = useRef(false);\r\n\r\n // Store latest callback in ref to avoid re-initializing AppHost on callback change\r\n const onMessageRef = useRef(options?.onMessage);\r\n useEffect(() => {\r\n onMessageRef.current = options?.onMessage;\r\n }, [options?.onMessage]);\r\n\r\n useEffect(() => {\r\n if (!client || !iframeRef.current || initializingRef.current) return;\r\n\r\n // Prevent double initialization in strict mode\r\n initializingRef.current = true;\r\n\r\n const initHost = async () => {\r\n try {\r\n // Initialize AppHost with security enforcement\r\n const appHost = new AppHost(client, iframeRef.current!);\r\n\r\n // Register message handler\r\n appHost.onAppMessage = (params) => {\r\n onMessageRef.current?.(params);\r\n };\r\n\r\n // Set host immediately so launch can be called\r\n // (launch will wait for bridge if needed)\r\n setHost(appHost);\r\n\r\n // Start bridge connection (this is fast, just sets up PostMessage)\r\n await appHost.start();\r\n } catch (err) {\r\n console.error('[useAppHost] Failed to initialize AppHost:', err);\r\n setError(err instanceof Error ? err : new Error(String(err)));\r\n }\r\n };\r\n\r\n initHost();\r\n\r\n return () => {\r\n initializingRef.current = false;\r\n setHost(null);\r\n };\r\n }, [client, iframeRef]);\r\n\r\n return { host, error };\r\n}\r\n","/**\n * Simplified MCP Apps Hook - Fixed for no flickering\n *\n * The key insight: React component identity must be stable.\n * We return a stable McpAppRenderer component and separate metadata lookup.\n */\n\nimport React, { useState, useEffect, useCallback, useRef, memo } from 'react';\nimport { useAppHost } from './use-app-host.js';\nimport type { SSEClient } from '../core/sse-client.js';\n\nexport interface McpClient {\n connections: Array<{\n sessionId: string;\n tools: Array<{\n name: string;\n mcpApp?: {\n resourceUri: string;\n };\n _meta?: {\n ui?: {\n resourceUri?: string;\n };\n 'ui/resourceUri'?: string;\n };\n }>;\n }>;\n sseClient?: SSEClient | null;\n}\n\nexport interface McpAppMetadata {\n toolName: string;\n resourceUri: string;\n sessionId: string;\n}\n\ninterface McpAppRendererProps {\n metadata: McpAppMetadata;\n input?: Record<string, unknown>;\n result?: unknown;\n status: 'executing' | 'inProgress' | 'complete' | 'idle';\n sseClient?: SSEClient | null;\n}\n\n/**\n * Stable renderer component - memoized to prevent flickering\n * Uses refs to track data changes and send updates to the iframe\n */\nconst McpAppRenderer = memo(function McpAppRenderer({\n metadata,\n input,\n result,\n status,\n sseClient,\n}: McpAppRendererProps) {\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const { host, error: hostError } = useAppHost(sseClient as SSEClient, iframeRef);\n const [isLaunched, setIsLaunched] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n // Track which data has been sent to prevent duplicates\n const sentInputRef = useRef(false);\n const sentResultRef = useRef(false);\n const lastInputRef = useRef(input);\n const lastResultRef = useRef(result);\n const lastStatusRef = useRef(status);\n\n // Launch the app when host is ready\n useEffect(() => {\n if (!host || !metadata.resourceUri || !metadata.sessionId) return;\n\n host\n .launch(metadata.resourceUri, metadata.sessionId)\n .then(() => setIsLaunched(true))\n .catch((err) => setError(err instanceof Error ? err : new Error(String(err))));\n }, [host, metadata.resourceUri, metadata.sessionId]);\n\n // Send tool input when available or when it changes\n useEffect(() => {\n if (!host || !isLaunched || !input) return;\n \n // Send if never sent, or if input changed\n if (!sentInputRef.current || JSON.stringify(input) !== JSON.stringify(lastInputRef.current)) {\n sentInputRef.current = true;\n lastInputRef.current = input;\n host.sendToolInput(input);\n }\n }, [host, isLaunched, input]);\n\n // Send tool result when complete or when it changes\n useEffect(() => {\n if (!host || !isLaunched || result === undefined) return;\n if (status !== 'complete') return;\n\n // Send if never sent, or if result changed\n if (!sentResultRef.current || JSON.stringify(result) !== JSON.stringify(lastResultRef.current)) {\n sentResultRef.current = true;\n lastResultRef.current = result;\n const formattedResult =\n typeof result === 'string'\n ? { content: [{ type: 'text', text: result }] }\n : result;\n host.sendToolResult(formattedResult);\n }\n }, [host, isLaunched, result, status]);\n\n // Reset sent flags when tool status resets to executing (new tool call)\n useEffect(() => {\n if (status === 'executing' && lastStatusRef.current !== 'executing') {\n sentInputRef.current = false;\n sentResultRef.current = false;\n }\n lastStatusRef.current = status;\n }, [status]);\n\n // Display errors\n const displayError = error || hostError;\n if (displayError) {\n return (\n <div className=\"p-4 bg-red-900/20 border border-red-700 rounded text-red-200\">\n Error: {displayError.message || String(displayError)}\n </div>\n );\n }\n\n return (\n <div className=\"w-full border border-gray-700 rounded overflow-hidden bg-white min-h-96 my-2 relative\">\n <iframe\n ref={iframeRef}\n sandbox=\"allow-scripts allow-same-origin allow-forms allow-modals allow-popups allow-downloads\"\n className=\"w-full h-full min-h-96\"\n style={{ height: 'auto' }}\n title=\"MCP App\"\n />\n {!isLaunched && (\n <div className=\"absolute inset-0 bg-gray-900/50 flex items-center justify-center pointer-events-none\">\n <div className=\"w-6 h-6 border-2 border-blue-500 border-t-transparent rounded-full animate-spin\" />\n </div>\n )}\n </div>\n );\n});\n\n/**\n * Simple hook to get MCP app metadata\n *\n * @param mcpClient - The MCP client from useMcp() or context\n * @returns Object with getAppMetadata function and McpAppRenderer component\n *\n * @example\n * ```tsx\n * function ToolRenderer(props) {\n * const { getAppMetadata, McpAppRenderer } = useMcpApps(mcpClient);\n * const metadata = getAppMetadata(props.name);\n *\n * if (!metadata) return null;\n * return (\n * <McpAppRenderer\n * metadata={metadata}\n * input={props.args}\n * result={props.result}\n * status={props.status}\n * />\n * );\n * }\n * ```\n */\nexport function useMcpApps(mcpClient: McpClient | null) {\n /**\n * Get MCP app metadata for a tool name\n * This is fast and can be called on every render\n */\n const getAppMetadata = useCallback(\n (toolName: string): McpAppMetadata | undefined => {\n if (!mcpClient) return undefined;\n\n const extractedName = extractToolName(toolName);\n\n for (const conn of mcpClient.connections) {\n for (const tool of conn.tools) {\n const candidateName = extractToolName(tool.name);\n // Check both locations: direct mcpApp or _meta.ui\n const resourceUri =\n tool.mcpApp?.resourceUri ??\n tool._meta?.ui?.resourceUri ??\n tool._meta?.['ui/resourceUri'];\n\n if (resourceUri && candidateName === extractedName) {\n return {\n toolName: candidateName,\n resourceUri,\n sessionId: conn.sessionId,\n };\n }\n }\n }\n\n return undefined;\n },\n [mcpClient]\n );\n\n return { getAppMetadata, McpAppRenderer };\n}\n\n/**\n * Extract the base tool name, removing any prefixes\n */\nfunction extractToolName(fullName: string): string {\n // Handle patterns like \"tool_abc123_get-time\" -> \"get-time\"\n const match = fullName.match(/(?:tool_[^_]+_)?(.+)$/);\n return match?.[1] || fullName;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/client/core/sse-client.ts","../../src/client/react/use-mcp.ts","../../src/client/core/app-host.ts","../../src/client/react/use-app-host.ts","../../src/client/react/use-mcp-apps.tsx"],"names":["nanoid","useRef","useState","useEffect","useCallback","AppBridge","PostMessageTransport","memo","McpAppRenderer","jsx"],"mappings":"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","file":"react.js","sourcesContent":["/**\r\n * SSE Client for MCP Connections\r\n *\r\n * Browser-side client that manages real-time communication with the MCP server\r\n * using Server-Sent Events (SSE) for server→client streaming and HTTP POST for\r\n * client→server RPC requests.\r\n *\r\n * Key features:\r\n * - Direct HTTP response for RPC calls (bypasses SSE latency)\r\n * - Resource preloading for instant MCP App UI loading\r\n * - Automatic reconnection with exponential backoff\r\n * - Type-safe RPC methods\r\n */\r\n\r\nimport { nanoid } from 'nanoid';\r\nimport type {\r\n McpConnectionEvent,\r\n McpObservabilityEvent,\r\n McpAppsUIEvent\r\n} from '../../shared/events.js';\r\nimport type {\r\n McpRpcRequest,\r\n McpRpcResponse,\r\n McpRpcMethod,\r\n McpRpcParams,\r\n ConnectParams,\r\n SessionListResult,\r\n ConnectResult,\r\n DisconnectResult,\r\n RestoreSessionResult,\r\n FinishAuthResult,\r\n ListToolsRpcResult,\r\n ListPromptsResult,\r\n ListResourcesResult,\r\n} from '../../shared/types.js';\r\n// ============================================\r\n// Types & Interfaces\r\n// ============================================\r\n\r\nexport interface SSEClientOptions {\r\n /** SSE endpoint URL */\r\n url: string;\r\n\r\n /** User/Client identifier */\r\n identity: string;\r\n\r\n /** Optional auth token for authenticated requests */\r\n authToken?: string;\r\n\r\n /** Callback for MCP connection state changes */\r\n onConnectionEvent?: (event: McpConnectionEvent) => void;\r\n\r\n /** Callback for observability/logging events */\r\n onObservabilityEvent?: (event: McpObservabilityEvent) => void;\r\n\r\n /** Callback for connection status changes */\r\n onStatusChange?: (status: ConnectionStatus) => void;\r\n\r\n /** Callback for MCP App UI events */\r\n onEvent?: (event: McpAppsUIEvent) => void;\r\n\r\n /** Request timeout in milliseconds @default 60000 */\r\n requestTimeout?: number;\r\n\r\n /** Enable debug logging @default false */\r\n debug?: boolean;\r\n}\r\n\r\nexport type ConnectionStatus = 'connecting' | 'connected' | 'disconnected' | 'error';\r\n\r\ninterface PendingRequest {\r\n resolve: (value: unknown) => void;\r\n reject: (error: Error) => void;\r\n timeoutId: ReturnType<typeof setTimeout>;\r\n}\r\n\r\ninterface ToolUiMetadata {\r\n resourceUri?: string;\r\n uri?: string;\r\n visibility?: string[];\r\n}\r\n\r\n// ============================================\r\n// Constants\r\n// ============================================\r\n\r\nconst DEFAULT_REQUEST_TIMEOUT = 60000;\r\nconst MAX_RECONNECT_ATTEMPTS = 5;\r\nconst BASE_RECONNECT_DELAY = 1000;\r\n\r\n// ============================================\r\n// SSEClient Class\r\n// ============================================\r\n\r\n/**\r\n * SSE Client for real-time MCP connection management\r\n */\r\nexport class SSEClient {\r\n private eventSource: EventSource | null = null;\r\n private pendingRequests = new Map<string, PendingRequest>();\r\n private resourceCache = new Map<string, Promise<unknown>>();\r\n\r\n private reconnectAttempts = 0;\r\n private isManuallyDisconnected = false;\r\n private connectionPromise: Promise<void> | null = null;\r\n private connectionResolver: (() => void) | null = null;\r\n\r\n constructor(private readonly options: SSEClientOptions) {}\r\n\r\n // ============================================\r\n // Connection Management\r\n // ============================================\r\n\r\n /**\r\n * Connect to the SSE endpoint\r\n */\r\n connect(): void {\r\n if (this.eventSource) {\r\n return; // Already connected\r\n }\r\n\r\n this.isManuallyDisconnected = false;\r\n this.options.onStatusChange?.('connecting');\r\n this.connectionPromise = new Promise((resolve) => {\r\n this.connectionResolver = resolve;\r\n });\r\n\r\n const url = this.buildUrl();\r\n this.eventSource = new EventSource(url);\r\n this.setupEventListeners();\r\n }\r\n\r\n /**\r\n * Disconnect from the SSE endpoint\r\n */\r\n disconnect(): void {\r\n this.isManuallyDisconnected = true;\r\n\r\n if (this.eventSource) {\r\n this.eventSource.close();\r\n this.eventSource = null;\r\n }\r\n\r\n this.connectionPromise = null;\r\n this.connectionResolver = null;\r\n this.rejectAllPendingRequests(new Error('Connection closed'));\r\n this.options.onStatusChange?.('disconnected');\r\n }\r\n\r\n /**\r\n * Check if connected to the SSE endpoint\r\n */\r\n isConnected(): boolean {\r\n return this.eventSource?.readyState === EventSource.OPEN;\r\n }\r\n\r\n // ============================================\r\n // RPC Methods\r\n // ============================================\r\n\r\n async getSessions(): Promise<SessionListResult> {\r\n return this.sendRequest<SessionListResult>('getSessions');\r\n }\r\n\r\n async connectToServer(params: ConnectParams): Promise<ConnectResult> {\r\n return this.sendRequest<ConnectResult>('connect', params);\r\n }\r\n\r\n async disconnectFromServer(sessionId: string): Promise<DisconnectResult> {\r\n return this.sendRequest<DisconnectResult>('disconnect', { sessionId });\r\n }\r\n\r\n async listTools(sessionId: string): Promise<ListToolsRpcResult> {\r\n return this.sendRequest<ListToolsRpcResult>('listTools', { sessionId });\r\n }\r\n\r\n async callTool(\r\n sessionId: string,\r\n toolName: string,\r\n toolArgs: Record<string, unknown>\r\n ): Promise<unknown> {\r\n const result = await this.sendRequest('callTool', { sessionId, toolName, toolArgs });\r\n this.emitUiEventIfPresent(result, sessionId, toolName);\r\n return result;\r\n }\r\n\r\n async restoreSession(sessionId: string): Promise<RestoreSessionResult> {\r\n return this.sendRequest<RestoreSessionResult>('restoreSession', { sessionId });\r\n }\r\n\r\n async finishAuth(sessionId: string, code: string): Promise<FinishAuthResult> {\r\n return this.sendRequest<FinishAuthResult>('finishAuth', { sessionId, code });\r\n }\r\n\r\n async listPrompts(sessionId: string): Promise<ListPromptsResult> {\r\n return this.sendRequest<ListPromptsResult>('listPrompts', { sessionId });\r\n }\r\n\r\n async getPrompt(sessionId: string, name: string, args?: Record<string, string>): Promise<unknown> {\r\n return this.sendRequest('getPrompt', { sessionId, name, args });\r\n }\r\n\r\n async listResources(sessionId: string): Promise<ListResourcesResult> {\r\n return this.sendRequest<ListResourcesResult>('listResources', { sessionId });\r\n }\r\n\r\n async readResource(sessionId: string, uri: string): Promise<unknown> {\r\n return this.sendRequest('readResource', { sessionId, uri });\r\n }\r\n\r\n // ============================================\r\n // Resource Preloading (for instant UI loading)\r\n // ============================================\r\n\r\n /**\r\n * Preload UI resources for tools that have UI metadata.\r\n * Call this when tools are discovered to enable instant MCP App UI loading.\r\n */\r\n preloadToolUiResources(sessionId: string, tools: Array<{ name: string; _meta?: unknown }>): void {\r\n for (const tool of tools) {\r\n const uri = this.extractUiResourceUri(tool);\r\n if (!uri) continue;\r\n\r\n if (this.resourceCache.has(uri)) {\r\n this.log(`Resource already cached: ${uri}`);\r\n continue;\r\n }\r\n\r\n this.log(`Preloading UI resource for tool \"${tool.name}\": ${uri}`);\r\n const promise = this.sendRequest('readResource', { sessionId, uri })\r\n .catch((err) => {\r\n this.log(`Failed to preload resource ${uri}: ${err.message}`, 'warn');\r\n this.resourceCache.delete(uri);\r\n return null;\r\n });\r\n\r\n this.resourceCache.set(uri, promise);\r\n }\r\n }\r\n\r\n /**\r\n * Get a preloaded resource from cache, or fetch if not cached.\r\n */\r\n getOrFetchResource(sessionId: string, uri: string): Promise<unknown> {\r\n const cached = this.resourceCache.get(uri);\r\n if (cached) {\r\n this.log(`Cache hit for resource: ${uri}`);\r\n return cached;\r\n }\r\n\r\n this.log(`Cache miss, fetching resource: ${uri}`);\r\n const promise = this.sendRequest('readResource', { sessionId, uri });\r\n this.resourceCache.set(uri, promise);\r\n return promise;\r\n }\r\n\r\n /**\r\n * Check if a resource is already cached\r\n */\r\n hasPreloadedResource(uri: string): boolean {\r\n return this.resourceCache.has(uri);\r\n }\r\n\r\n /**\r\n * Clear the resource cache\r\n */\r\n clearResourceCache(): void {\r\n this.resourceCache.clear();\r\n }\r\n\r\n // ============================================\r\n // Private: Request Handling\r\n // ============================================\r\n\r\n /**\r\n * Send an RPC request and return the response directly from HTTP.\r\n * This bypasses SSE latency by returning results in the HTTP response body.\r\n */\r\n private async sendRequest<T = unknown>(method: McpRpcMethod, params?: McpRpcParams): Promise<T> {\r\n if (this.connectionPromise) {\r\n await this.connectionPromise;\r\n }\r\n\r\n const request: McpRpcRequest = {\r\n id: `rpc_${nanoid(10)}`,\r\n method,\r\n params,\r\n };\r\n\r\n const response = await fetch(this.buildUrl(), {\r\n method: 'POST',\r\n headers: this.buildHeaders(),\r\n body: JSON.stringify(request),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\r\n }\r\n\r\n const data = await response.json() as McpRpcResponse;\r\n return this.parseRpcResponse<T>(data, request.id);\r\n }\r\n\r\n /**\r\n * Parse RPC response and handle different response formats\r\n */\r\n private parseRpcResponse<T>(data: McpRpcResponse, requestId: string): T | Promise<T> {\r\n // Fast path: Direct response (new behavior)\r\n if ('result' in data) {\r\n return data.result as T;\r\n }\r\n\r\n // Error response\r\n if ('error' in data && data.error) {\r\n throw new Error(data.error.message || 'Unknown RPC error');\r\n }\r\n\r\n // Legacy path: Acknowledgment only (wait for SSE)\r\n // Kept for backwards compatibility with older servers\r\n if ('acknowledged' in data) {\r\n return this.waitForSseResponse<T>(requestId);\r\n }\r\n\r\n throw new Error('Invalid RPC response format');\r\n }\r\n\r\n /**\r\n * Wait for RPC response via SSE (legacy fallback)\r\n */\r\n private waitForSseResponse<T>(requestId: string): Promise<T> {\r\n const timeoutMs = this.options.requestTimeout ?? DEFAULT_REQUEST_TIMEOUT;\r\n\r\n return new Promise<T>((resolve, reject) => {\r\n const timeoutId = setTimeout(() => {\r\n this.pendingRequests.delete(requestId);\r\n reject(new Error(`Request timeout after ${timeoutMs}ms`));\r\n }, timeoutMs);\r\n\r\n this.pendingRequests.set(requestId, {\r\n resolve: resolve as (value: unknown) => void,\r\n reject,\r\n timeoutId,\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Handle RPC response received via SSE (legacy)\r\n */\r\n private handleRpcResponse(response: McpRpcResponse): void {\r\n const pending = this.pendingRequests.get(response.id);\r\n if (!pending) return;\r\n\r\n clearTimeout(pending.timeoutId);\r\n this.pendingRequests.delete(response.id);\r\n\r\n if (response.error) {\r\n pending.reject(new Error(response.error.message));\r\n } else {\r\n pending.resolve(response.result);\r\n }\r\n }\r\n\r\n // ============================================\r\n // Private: Event Handling\r\n // ============================================\r\n\r\n private setupEventListeners(): void {\r\n if (!this.eventSource) return;\r\n\r\n this.eventSource.addEventListener('open', () => {\r\n this.log('Connected');\r\n this.reconnectAttempts = 0;\r\n this.options.onStatusChange?.('connected');\r\n });\r\n\r\n this.eventSource.addEventListener('connected', () => {\r\n this.log('Server ready');\r\n this.connectionResolver?.();\r\n this.connectionResolver = null;\r\n });\r\n\r\n this.eventSource.addEventListener('connection', (e: MessageEvent) => {\r\n const event = JSON.parse(e.data) as McpConnectionEvent;\r\n this.options.onConnectionEvent?.(event);\r\n });\r\n\r\n this.eventSource.addEventListener('observability', (e: MessageEvent) => {\r\n const event = JSON.parse(e.data) as McpObservabilityEvent;\r\n this.options.onObservabilityEvent?.(event);\r\n });\r\n\r\n this.eventSource.addEventListener('rpc-response', (e: MessageEvent) => {\r\n const response = JSON.parse(e.data) as McpRpcResponse;\r\n this.handleRpcResponse(response);\r\n });\r\n\r\n this.eventSource.addEventListener('error', () => {\r\n this.log('Connection error', 'error');\r\n this.options.onStatusChange?.('error');\r\n this.attemptReconnect();\r\n });\r\n }\r\n\r\n private attemptReconnect(): void {\r\n if (this.isManuallyDisconnected || this.reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {\r\n return;\r\n }\r\n\r\n this.reconnectAttempts++;\r\n const delay = BASE_RECONNECT_DELAY * this.reconnectAttempts;\r\n this.log(`Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts}/${MAX_RECONNECT_ATTEMPTS})`);\r\n\r\n setTimeout(() => {\r\n this.disconnect();\r\n this.connect();\r\n }, delay);\r\n }\r\n\r\n // ============================================\r\n // Private: Utilities\r\n // ============================================\r\n\r\n private buildUrl(): string {\r\n const url = new URL(this.options.url, globalThis.location?.origin);\r\n url.searchParams.set('identity', this.options.identity);\r\n if (this.options.authToken) {\r\n url.searchParams.set('token', this.options.authToken);\r\n }\r\n return url.toString();\r\n }\r\n\r\n private buildHeaders(): HeadersInit {\r\n const headers: HeadersInit = {\r\n 'Content-Type': 'application/json',\r\n };\r\n if (this.options.authToken) {\r\n headers['Authorization'] = `Bearer ${this.options.authToken}`;\r\n }\r\n return headers;\r\n }\r\n\r\n private rejectAllPendingRequests(error: Error): void {\r\n for (const [, pending] of this.pendingRequests) {\r\n clearTimeout(pending.timeoutId);\r\n pending.reject(error);\r\n }\r\n this.pendingRequests.clear();\r\n }\r\n\r\n private extractUiResourceUri(tool: { name: string; _meta?: unknown }): string | undefined {\r\n const meta = (tool._meta as { ui?: ToolUiMetadata })?.ui;\r\n if (!meta || typeof meta !== 'object') return undefined;\r\n\r\n // Check visibility constraint\r\n if (meta.visibility && !meta.visibility.includes('app')) return undefined;\r\n\r\n // Support both 'resourceUri' and 'uri' field names\r\n return meta.resourceUri ?? meta.uri;\r\n }\r\n\r\n private emitUiEventIfPresent(result: unknown, sessionId: string, toolName: string): void {\r\n const meta = (result as { _meta?: { ui?: ToolUiMetadata } })?._meta;\r\n const resourceUri = meta?.ui?.resourceUri ?? (meta as any)?.['ui/resourceUri'];\r\n\r\n if (resourceUri) {\r\n this.options.onEvent?.({\r\n type: 'mcp-apps-ui',\r\n sessionId,\r\n resourceUri,\r\n toolName,\r\n result,\r\n timestamp: Date.now(),\r\n });\r\n }\r\n }\r\n\r\n private log(message: string, level: 'info' | 'warn' | 'error' = 'info'): void {\r\n if (!this.options.debug && level === 'info') return;\r\n\r\n const prefix = '[SSEClient]';\r\n switch (level) {\r\n case 'warn':\r\n console.warn(prefix, message);\r\n break;\r\n case 'error':\r\n console.error(prefix, message);\r\n break;\r\n default:\r\n console.log(prefix, message);\r\n }\r\n }\r\n}\r\n","/**\r\n * useMcp React Hook\r\n * Manages MCP connections with SSE-based real-time updates\r\n * Based on Cloudflare's agents pattern\r\n */\r\n\r\nimport { useEffect, useRef, useState, useCallback } from 'react';\r\nimport { SSEClient, type SSEClientOptions } from '../core/sse-client';\r\nimport type { McpConnectionEvent, McpConnectionState } from '../../shared/events';\r\nimport type {\r\n ToolInfo,\r\n FinishAuthResult,\r\n ListToolsRpcResult,\r\n ListPromptsResult,\r\n ListResourcesResult,\r\n SessionInfo,\r\n} from '../../shared/types';\r\n\r\nexport interface UseMcpOptions {\r\n /**\r\n * SSE endpoint URL\r\n */\r\n url: string;\r\n\r\n /**\r\n * User/Client identifier\r\n */\r\n identity: string;\r\n\r\n /**\r\n * Optional auth token\r\n */\r\n authToken?: string;\r\n\r\n /**\r\n * Auto-connect on mount\r\n * @default true\r\n */\r\n autoConnect?: boolean;\r\n\r\n /**\r\n * Auto-initialize sessions on mount\r\n * @default true\r\n */\r\n autoInitialize?: boolean;\r\n\r\n /**\r\n * Connection event callback\r\n */\r\n onConnectionEvent?: (event: McpConnectionEvent) => void;\r\n\r\n /**\r\n * Debug logging callback\r\n */\r\n onLog?: (level: string, message: string, metadata?: Record<string, unknown>) => void;\r\n /**\r\n * Optional callback to handle OAuth redirects (e.g. for popup flow)\r\n * If provided, this will be called instead of window.location.href assignment\r\n */\r\n onRedirect?: (url: string) => void;\r\n\r\n /**\r\n * Request timeout in milliseconds\r\n * @default 60000\r\n */\r\n requestTimeout?: number;\r\n}\r\n\r\nexport interface McpConnection {\r\n sessionId: string;\r\n serverId: string;\r\n serverName: string;\r\n serverUrl?: string;\r\n transport?: string;\r\n state: McpConnectionState;\r\n tools: ToolInfo[];\r\n error?: string;\r\n connectedAt?: Date;\r\n}\r\n\r\nexport interface McpClient {\r\n /**\r\n * All connections\r\n */\r\n connections: McpConnection[];\r\n\r\n /**\r\n * SSE connection status\r\n */\r\n status: 'connecting' | 'connected' | 'disconnected' | 'error';\r\n\r\n /**\r\n * Whether initializing\r\n */\r\n isInitializing: boolean;\r\n\r\n /**\r\n * Connect to an MCP server\r\n */\r\n connect: (params: {\r\n serverId: string;\r\n serverName: string;\r\n serverUrl: string;\r\n callbackUrl: string;\r\n transportType?: 'sse' | 'streamable_http';\r\n }) => Promise<string>;\r\n\r\n /**\r\n * Disconnect from an MCP server\r\n */\r\n disconnect: (sessionId: string) => Promise<void>;\r\n\r\n /**\r\n * Get connection by session ID\r\n */\r\n getConnection: (sessionId: string) => McpConnection | undefined;\r\n\r\n /**\r\n * Get connection by server ID\r\n */\r\n getConnectionByServerId: (serverId: string) => McpConnection | undefined;\r\n\r\n /**\r\n * Check if server is connected\r\n */\r\n isServerConnected: (serverId: string) => boolean;\r\n\r\n /**\r\n * Get tools for a session\r\n */\r\n getTools: (sessionId: string) => ToolInfo[];\r\n\r\n /**\r\n * Refresh all connections\r\n */\r\n refresh: () => Promise<void>;\r\n\r\n /**\r\n * Manually connect SSE\r\n */\r\n connectSSE: () => void;\r\n\r\n /**\r\n * Manually disconnect SSE\r\n */\r\n disconnectSSE: () => void;\r\n\r\n /**\r\n * Complete OAuth authorization\r\n */\r\n finishAuth: (sessionId: string, code: string) => Promise<FinishAuthResult>;\r\n\r\n /**\r\n * Call a tool from a session\r\n */\r\n callTool: (\r\n sessionId: string,\r\n toolName: string,\r\n toolArgs: Record<string, unknown>\r\n ) => Promise<unknown>;\r\n\r\n /**\r\n * List available tools for a session\r\n */\r\n listTools: (sessionId: string) => Promise<ListToolsRpcResult>;\r\n\r\n /**\r\n * List available prompts for a session\r\n */\r\n listPrompts: (sessionId: string) => Promise<ListPromptsResult>;\r\n\r\n /**\r\n * Get a specific prompt with arguments\r\n */\r\n getPrompt: (sessionId: string, name: string, args?: Record<string, string>) => Promise<unknown>;\r\n\r\n /**\r\n * List available resources for a session\r\n */\r\n listResources: (sessionId: string) => Promise<ListResourcesResult>;\r\n\r\n /**\r\n * Read a specific resource\r\n */\r\n readResource: (sessionId: string, uri: string) => Promise<unknown>;\r\n\r\n /**\r\n * Access the underlying SSEClient instance (for advanced usage like AppHost)\r\n */\r\n sseClient: SSEClient | null;\r\n}\r\n\r\n/**\r\n * React hook for MCP connection management with SSE\r\n */\r\nexport function useMcp(options: UseMcpOptions): McpClient {\r\n const {\r\n url,\r\n identity,\r\n authToken,\r\n autoConnect = true,\r\n autoInitialize = true,\r\n onConnectionEvent,\r\n onLog,\r\n onRedirect,\r\n } = options;\r\n\r\n const clientRef = useRef<SSEClient | null>(null);\r\n const isMountedRef = useRef(true);\r\n\r\n const [connections, setConnections] = useState<McpConnection[]>([]);\r\n const [status, setStatus] = useState<'connecting' | 'connected' | 'disconnected' | 'error'>(\r\n 'disconnected'\r\n );\r\n const [isInitializing, setIsInitializing] = useState(false);\r\n\r\n /**\r\n * Initialize SSE client\r\n */\r\n useEffect(() => {\r\n isMountedRef.current = true;\r\n\r\n const clientOptions: SSEClientOptions = {\r\n url,\r\n identity,\r\n authToken,\r\n onConnectionEvent: (event) => {\r\n // Update local state based on event\r\n updateConnectionsFromEvent(event);\r\n\r\n // Call user callback\r\n onConnectionEvent?.(event);\r\n },\r\n onObservabilityEvent: (event) => {\r\n onLog?.(event.level || 'info', event.message || event.displayMessage || 'No message', event.metadata);\r\n },\r\n onStatusChange: (newStatus) => {\r\n if (isMountedRef.current) {\r\n setStatus(newStatus);\r\n }\r\n },\r\n requestTimeout: options.requestTimeout,\r\n };\r\n\r\n const client = new SSEClient(clientOptions);\r\n clientRef.current = client;\r\n\r\n if (autoConnect) {\r\n client.connect();\r\n\r\n if (autoInitialize) {\r\n loadSessions();\r\n }\r\n }\r\n\r\n return () => {\r\n isMountedRef.current = false;\r\n client.disconnect();\r\n };\r\n }, [url, identity, authToken, autoConnect, autoInitialize]);\r\n\r\n /**\r\n * Update connections based on event\r\n */\r\n const updateConnectionsFromEvent = useCallback((event: McpConnectionEvent) => {\r\n if (!isMountedRef.current) return;\r\n\r\n setConnections((prev: McpConnection[]) => {\r\n switch (event.type) {\r\n case 'state_changed': {\r\n const existing = prev.find((c: McpConnection) => c.sessionId === event.sessionId);\r\n if (existing) {\r\n return prev.map((c: McpConnection) =>\r\n c.sessionId === event.sessionId ? { ...c, state: event.state } : c\r\n );\r\n } else {\r\n return [\r\n ...prev,\r\n {\r\n sessionId: event.sessionId,\r\n serverId: event.serverId,\r\n serverName: event.serverName,\r\n state: event.state,\r\n tools: [],\r\n },\r\n ];\r\n }\r\n }\r\n\r\n case 'tools_discovered': {\r\n // Preload UI resources for instant loading when tools are discovered\r\n if (clientRef.current && event.tools?.length) {\r\n clientRef.current.preloadToolUiResources(event.sessionId, event.tools);\r\n }\r\n\r\n return prev.map((c: McpConnection) =>\r\n c.sessionId === event.sessionId ? { ...c, tools: event.tools, state: 'READY' } : c\r\n );\r\n }\r\n\r\n case 'auth_required': {\r\n // Handle OAuth redirect\r\n if (event.authUrl) {\r\n onLog?.('info', `OAuth required - redirecting to ${event.authUrl}`, { authUrl: event.authUrl });\r\n\r\n if (onRedirect) {\r\n onRedirect(event.authUrl);\r\n } else if (typeof window !== 'undefined') {\r\n window.location.href = event.authUrl;\r\n }\r\n }\r\n return prev.map((c: McpConnection) =>\r\n c.sessionId === event.sessionId ? { ...c, state: 'AUTHENTICATING' } : c\r\n );\r\n }\r\n\r\n case 'error': {\r\n return prev.map((c: McpConnection) =>\r\n c.sessionId === event.sessionId ? { ...c, state: 'FAILED', error: event.error } : c\r\n );\r\n }\r\n\r\n case 'disconnected': {\r\n return prev.filter((c: McpConnection) => c.sessionId !== event.sessionId);\r\n }\r\n\r\n default:\r\n return prev;\r\n }\r\n });\r\n }, [onLog]);\r\n\r\n /**\r\n * Load sessions from server\r\n */\r\n const loadSessions = useCallback(async () => {\r\n if (!clientRef.current) return;\r\n\r\n try {\r\n setIsInitializing(true);\r\n\r\n const result = await clientRef.current.getSessions();\r\n const sessions = result.sessions || [];\r\n\r\n // Initialize connections\r\n if (isMountedRef.current) {\r\n setConnections(\r\n sessions.map((s: SessionInfo) => ({\r\n sessionId: s.sessionId,\r\n serverId: s.serverId ?? 'unknown',\r\n serverName: s.serverName ?? 'Unknown Server',\r\n serverUrl: s.serverUrl,\r\n transport: s.transport,\r\n state: 'VALIDATING' as McpConnectionState,\r\n tools: [],\r\n }))\r\n );\r\n }\r\n\r\n // Validate each session in parallel\r\n await Promise.all(\r\n sessions.map(async (session: SessionInfo) => {\r\n if (clientRef.current) {\r\n try {\r\n await clientRef.current.restoreSession(session.sessionId);\r\n } catch (error) {\r\n console.error(`[useMcp] Failed to validate session ${session.sessionId}:`, error);\r\n }\r\n }\r\n })\r\n );\r\n } catch (error) {\r\n console.error('[useMcp] Failed to load sessions:', error);\r\n onLog?.('error', 'Failed to load sessions', { error });\r\n } finally {\r\n if (isMountedRef.current) {\r\n setIsInitializing(false);\r\n }\r\n }\r\n }, [onLog]);\r\n\r\n /**\r\n * Connect to an MCP server\r\n */\r\n const connect = useCallback(\r\n async (params: {\r\n serverId: string;\r\n serverName: string;\r\n serverUrl: string;\r\n callbackUrl: string;\r\n transportType?: 'sse' | 'streamable_http';\r\n }): Promise<string> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n const result = await clientRef.current.connectToServer(params);\r\n return result.sessionId;\r\n },\r\n []\r\n );\r\n\r\n /**\r\n * Disconnect from an MCP server\r\n */\r\n const disconnect = useCallback(async (sessionId: string): Promise<void> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n await clientRef.current.disconnectFromServer(sessionId);\r\n\r\n // Remove from local state\r\n if (isMountedRef.current) {\r\n setConnections((prev: McpConnection[]) => prev.filter((c: McpConnection) => c.sessionId !== sessionId));\r\n }\r\n }, []);\r\n\r\n /**\r\n * Refresh all connections\r\n */\r\n const refresh = useCallback(async () => {\r\n await loadSessions();\r\n }, [loadSessions]);\r\n\r\n /**\r\n * Manually connect SSE\r\n */\r\n const connectSSE = useCallback(() => {\r\n clientRef.current?.connect();\r\n }, []);\r\n\r\n /**\r\n * Manually disconnect SSE\r\n */\r\n const disconnectSSE = useCallback(() => {\r\n clientRef.current?.disconnect();\r\n }, []);\r\n\r\n /**\r\n * Complete OAuth authorization\r\n */\r\n const finishAuth = useCallback(async (sessionId: string, code: string): Promise<FinishAuthResult> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n return await clientRef.current.finishAuth(sessionId, code);\r\n }, []);\r\n\r\n /**\r\n * Call a tool\r\n */\r\n const callTool = useCallback(\r\n async (\r\n sessionId: string,\r\n toolName: string,\r\n toolArgs: Record<string, unknown>\r\n ): Promise<unknown> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n return await clientRef.current.callTool(sessionId, toolName, toolArgs);\r\n },\r\n []\r\n );\r\n\r\n /**\r\n * List tools (refresh tool list)\r\n */\r\n const listTools = useCallback(async (sessionId: string): Promise<ListToolsRpcResult> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n return await clientRef.current.listTools(sessionId);\r\n }, []);\r\n\r\n /**\r\n * List prompts\r\n */\r\n const listPrompts = useCallback(async (sessionId: string): Promise<ListPromptsResult> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n return await clientRef.current.listPrompts(sessionId);\r\n }, []);\r\n\r\n /**\r\n * Get a specific prompt\r\n */\r\n const getPrompt = useCallback(\r\n async (sessionId: string, name: string, args?: Record<string, string>): Promise<unknown> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n return await clientRef.current.getPrompt(sessionId, name, args);\r\n },\r\n []\r\n );\r\n\r\n /**\r\n * List resources\r\n */\r\n const listResources = useCallback(async (sessionId: string): Promise<ListResourcesResult> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n return await clientRef.current.listResources(sessionId);\r\n }, []);\r\n\r\n /**\r\n * Read a specific resource\r\n */\r\n const readResource = useCallback(async (sessionId: string, uri: string): Promise<unknown> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n return await clientRef.current.readResource(sessionId, uri);\r\n }, []);\r\n\r\n // Utility functions\r\n const getConnection = useCallback(\r\n (sessionId: string) => connections.find((c: McpConnection) => c.sessionId === sessionId),\r\n [connections]\r\n );\r\n\r\n const getConnectionByServerId = useCallback(\r\n (serverId: string) => connections.find((c: McpConnection) => c.serverId === serverId),\r\n [connections]\r\n );\r\n\r\n const isServerConnected = useCallback(\r\n (serverId: string) => {\r\n const conn = getConnectionByServerId(serverId);\r\n return conn?.state === 'CONNECTED';\r\n },\r\n [getConnectionByServerId]\r\n );\r\n\r\n const getTools = useCallback(\r\n (sessionId: string) => {\r\n const conn = getConnection(sessionId);\r\n return conn?.tools || [];\r\n },\r\n [getConnection]\r\n );\r\n\r\n return {\r\n connections,\r\n status,\r\n isInitializing,\r\n connect,\r\n disconnect,\r\n getConnection,\r\n getConnectionByServerId,\r\n isServerConnected,\r\n getTools,\r\n refresh,\r\n connectSSE,\r\n disconnectSSE,\r\n finishAuth,\r\n callTool,\r\n listTools,\r\n listPrompts,\r\n getPrompt,\r\n listResources,\r\n readResource,\r\n sseClient: clientRef.current,\r\n };\r\n}\r\n","/**\r\n * MCP App Host\r\n *\r\n * Bridges the gap between an iframe (MCP App) and the SSEClient (MCP Server).\r\n * Handles secure iframe sandboxing, resource loading, and bi-directional\r\n * communication via the AppBridge protocol.\r\n *\r\n * Key features:\r\n * - Secure iframe sandboxing with minimal permissions\r\n * - Resource preloading for instant MCP App UI loading\r\n * - Cache-aware resource fetching (SSEClient cache → local cache → direct fetch)\r\n * - Support for ui:// and mcp-app:// resource URIs\r\n */\r\n\r\nimport { AppBridge, PostMessageTransport } from '@modelcontextprotocol/ext-apps/app-bridge';\r\nimport type { AppHostClient } from './types';\r\n\r\n// ============================================\r\n// Types & Interfaces\r\n// ============================================\r\n\r\nexport interface AppHostOptions {\r\n /** Enable debug logging @default false */\r\n debug?: boolean;\r\n}\r\n\r\nexport interface AppMessageParams {\r\n role: string;\r\n content: unknown;\r\n}\r\n\r\ninterface ToolCallParams {\r\n name: string;\r\n arguments?: Record<string, unknown>;\r\n}\r\n\r\ninterface ResourceContent {\r\n blob?: string;\r\n text?: string;\r\n}\r\n\r\ninterface ResourceResponse {\r\n contents: ResourceContent[];\r\n}\r\n\r\n// ============================================\r\n// Constants\r\n// ============================================\r\n\r\nconst HOST_INFO = { name: 'mcp-ts-host', version: '1.0.0' };\r\n\r\n/** Sandbox permissions - minimal set required for MCP Apps to function */\r\nconst SANDBOX_PERMISSIONS = [\r\n 'allow-scripts', // Required for app JavaScript execution\r\n 'allow-forms', // Required for form submissions\r\n 'allow-same-origin', // Required for Blob URL correctness\r\n 'allow-modals', // Required for dialogs/alerts\r\n 'allow-popups', // Required for opening links\r\n 'allow-downloads' // Required for file downloads\r\n].join(' ');\r\n\r\n/** Supported MCP App URI schemes */\r\nconst MCP_URI_SCHEMES = ['ui://', 'mcp-app://'] as const;\r\n\r\n// ============================================\r\n// AppHost Class\r\n// ============================================\r\n\r\n/**\r\n * Host for MCP Apps embedded in iframes.\r\n * Manages secure communication between the app and the MCP server.\r\n */\r\nexport class AppHost {\r\n private bridge: AppBridge;\r\n private sessionId?: string;\r\n private resourceCache = new Map<string, Promise<ResourceResponse | null>>();\r\n private debug: boolean;\r\n\r\n /** Callback for app messages (e.g., chat messages from the app) */\r\n public onAppMessage?: (params: AppMessageParams) => void;\r\n\r\n constructor(\r\n private readonly client: AppHostClient,\r\n private readonly iframe: HTMLIFrameElement,\r\n options?: AppHostOptions\r\n ) {\r\n this.debug = options?.debug ?? false;\r\n this.configureSandbox();\r\n this.bridge = this.initializeBridge();\r\n }\r\n\r\n // ============================================\r\n // Public API\r\n // ============================================\r\n\r\n /**\r\n * Start the host. This prepares the bridge handlers but doesn't connect yet.\r\n * The actual connection happens in launch() after HTML is loaded.\r\n * @returns Promise that resolves immediately (bridge connects during launch)\r\n */\r\n async start(): Promise<void> {\r\n // Bridge handlers are already registered in constructor.\r\n // Connection happens in launch() after HTML is loaded.\r\n this.log('Host started, ready to launch');\r\n }\r\n\r\n /**\r\n * Preload UI resources to enable instant app loading.\r\n * Call this when tools are discovered to cache their UI resources.\r\n */\r\n preload(tools: Array<{ _meta?: unknown }>): void {\r\n for (const tool of tools) {\r\n const uri = this.extractUiResourceUri(tool);\r\n if (!uri || this.resourceCache.has(uri)) continue;\r\n\r\n const promise = this.preloadResource(uri);\r\n this.resourceCache.set(uri, promise);\r\n }\r\n }\r\n\r\n /**\r\n * Launch an MCP App from a URL or MCP resource URI.\r\n * Loads the HTML first, then establishes bridge connection.\r\n */\r\n async launch(url: string, sessionId?: string): Promise<void> {\r\n if (sessionId) this.sessionId = sessionId;\r\n\r\n // Set up initialization promise BEFORE connecting\r\n const initializedPromise = this.onAppReady();\r\n\r\n // Load HTML into iframe first\r\n if (this.isMcpUri(url)) {\r\n await this.launchMcpApp(url);\r\n } else {\r\n this.iframe.src = url;\r\n }\r\n\r\n // Wait for iframe to load before connecting bridge\r\n await this.onIframeReady();\r\n\r\n // Connect the bridge (HTML is loaded, contentWindow is ready)\r\n await this.connectBridge();\r\n\r\n // Wait for app to signal it's initialized (with timeout)\r\n this.log('Waiting for app initialization');\r\n await Promise.race([\r\n initializedPromise,\r\n new Promise<void>((resolve) => setTimeout(() => {\r\n this.log('Initialization timeout - continuing anyway', 'warn');\r\n resolve();\r\n }, 3000))\r\n ]);\r\n this.log('App launched and ready');\r\n }\r\n\r\n /**\r\n * Wait for app to signal initialization complete\r\n */\r\n private onAppReady(): Promise<void> {\r\n return new Promise<void>((resolve) => {\r\n const originalHandler = this.bridge.oninitialized;\r\n this.bridge.oninitialized = (...args) => {\r\n this.log('App initialized');\r\n resolve();\r\n this.bridge.oninitialized = originalHandler;\r\n originalHandler?.(...args);\r\n };\r\n });\r\n }\r\n\r\n /**\r\n * Wait for iframe to finish loading\r\n */\r\n private onIframeReady(): Promise<void> {\r\n return new Promise((resolve) => {\r\n if (this.iframe.contentDocument?.readyState === 'complete') {\r\n resolve();\r\n return;\r\n }\r\n this.iframe.addEventListener('load', () => resolve(), { once: true });\r\n });\r\n }\r\n\r\n /**\r\n * Send tool input arguments to the MCP App.\r\n * Call this after launch() when tool input is available.\r\n */\r\n sendToolInput(args: Record<string, unknown>): void {\r\n this.log('Sending tool input to app');\r\n this.bridge.sendToolInput({ arguments: args });\r\n }\r\n\r\n /**\r\n * Send tool result to the MCP App.\r\n * Call this when the tool call completes.\r\n */\r\n sendToolResult(result: unknown): void {\r\n this.log('Sending tool result to app');\r\n this.bridge.sendToolResult(result as any);\r\n }\r\n\r\n /**\r\n * Send tool cancellation to the MCP App.\r\n * Call this when the tool call is cancelled or fails.\r\n */\r\n sendToolCancelled(reason: string): void {\r\n this.log('Sending tool cancellation to app');\r\n this.bridge.sendToolCancelled({ reason });\r\n }\r\n\r\n // ============================================\r\n // Private: Initialization\r\n // ============================================\r\n\r\n private configureSandbox(): void {\r\n if (this.iframe.sandbox.value !== SANDBOX_PERMISSIONS) {\r\n this.iframe.sandbox.value = SANDBOX_PERMISSIONS;\r\n }\r\n }\r\n\r\n private initializeBridge(): AppBridge {\r\n const bridge = new AppBridge(\r\n null,\r\n HOST_INFO,\r\n {\r\n openLinks: {},\r\n serverTools: {},\r\n logging: {},\r\n // Declare support for model context updates\r\n updateModelContext: { text: {} },\r\n },\r\n {\r\n // Initial host context\r\n hostContext: {\r\n theme: 'dark',\r\n platform: 'web',\r\n containerDimensions: { maxHeight: 6000 },\r\n displayMode: 'inline',\r\n availableDisplayModes: ['inline', 'fullscreen'],\r\n },\r\n }\r\n );\r\n\r\n // Register handlers - must be done BEFORE connect()\r\n bridge.oncalltool = (params) => this.handleToolCall(params);\r\n bridge.onopenlink = this.handleOpenLink.bind(this);\r\n bridge.onmessage = this.handleMessage.bind(this);\r\n bridge.onloggingmessage = (params) => this.log(`App log [${params.level}]: ${params.data}`);\r\n bridge.onupdatemodelcontext = async () => ({});\r\n bridge.onsizechange = async ({ width, height }) => {\r\n if (height !== undefined) this.iframe.style.height = `${height}px`;\r\n if (width !== undefined) this.iframe.style.minWidth = `min(${width}px, 100%)`;\r\n return {};\r\n };\r\n bridge.onrequestdisplaymode = async (params) => ({\r\n mode: params.mode === 'fullscreen' ? 'fullscreen' : 'inline'\r\n });\r\n\r\n return bridge;\r\n }\r\n\r\n private async connectBridge(): Promise<void> {\r\n this.log('Connecting bridge to iframe');\r\n\r\n const transport = new PostMessageTransport(\r\n this.iframe.contentWindow!,\r\n this.iframe.contentWindow!\r\n );\r\n\r\n try {\r\n await this.bridge.connect(transport);\r\n this.log('Bridge connected successfully');\r\n } catch (error) {\r\n this.log('Bridge connection failed', 'error');\r\n throw error;\r\n }\r\n }\r\n\r\n // ============================================\r\n // Private: Bridge Event Handlers\r\n // ============================================\r\n\r\n private async handleToolCall(params: ToolCallParams) {\r\n if (!this.client.isConnected()) {\r\n throw new Error('Client disconnected');\r\n }\r\n\r\n const sessionId = await this.getSessionId();\r\n if (!sessionId) {\r\n throw new Error('No active session');\r\n }\r\n\r\n const result = await this.client.callTool(\r\n sessionId,\r\n params.name,\r\n params.arguments ?? {}\r\n );\r\n return result as any;\r\n }\r\n\r\n private async handleOpenLink(params: { url: string }): Promise<Record<string, never>> {\r\n window.open(params.url, '_blank', 'noopener,noreferrer');\r\n return {};\r\n }\r\n\r\n private async handleMessage(params: AppMessageParams): Promise<Record<string, never>> {\r\n this.onAppMessage?.(params);\r\n return {};\r\n }\r\n\r\n // ============================================\r\n // Private: Resource Loading\r\n // ============================================\r\n\r\n private async launchMcpApp(uri: string): Promise<void> {\r\n if (!this.client.isConnected()) {\r\n throw new Error('Client must be connected');\r\n }\r\n\r\n const sessionId = await this.getSessionId();\r\n if (!sessionId) {\r\n throw new Error('No active session');\r\n }\r\n\r\n // Fetch resource using cache hierarchy: SSEClient cache → local cache → direct fetch\r\n const response = await this.fetchResourceWithCache(sessionId, uri);\r\n if (!response?.contents?.length) {\r\n throw new Error(`Empty resource: ${uri}`);\r\n }\r\n\r\n const content = response.contents[0];\r\n const html = this.decodeContent(content);\r\n if (!html) {\r\n throw new Error(`Invalid content in resource: ${uri}`);\r\n }\r\n\r\n // Render via Blob URL for clean isolation\r\n const blob = new Blob([html], { type: 'text/html' });\r\n this.iframe.src = URL.createObjectURL(blob);\r\n }\r\n\r\n private async fetchResourceWithCache(sessionId: string, uri: string): Promise<ResourceResponse> {\r\n // Priority 1: SSEClient's built-in cache (best performance)\r\n if (this.hasClientCache()) {\r\n return (this.client as any).getOrFetchResource(sessionId, uri);\r\n }\r\n\r\n // Priority 2: Local preload cache\r\n const cached = this.resourceCache.get(uri);\r\n if (cached) {\r\n const result = await cached;\r\n if (result) return result;\r\n }\r\n\r\n // Priority 3: Direct fetch\r\n return this.client.readResource(sessionId, uri) as Promise<ResourceResponse>;\r\n }\r\n\r\n private async preloadResource(uri: string): Promise<ResourceResponse | null> {\r\n try {\r\n const sessionId = await this.getSessionId();\r\n if (!sessionId) return null;\r\n return await this.client.readResource(sessionId, uri) as ResourceResponse;\r\n } catch (error) {\r\n this.log(`Preload failed for ${uri}`, 'warn');\r\n return null;\r\n }\r\n }\r\n\r\n // ============================================\r\n // Private: Utilities\r\n // ============================================\r\n\r\n private async getSessionId(): Promise<string | undefined> {\r\n if (this.sessionId) return this.sessionId;\r\n const result = await this.client.getSessions();\r\n return result.sessions?.[0]?.sessionId;\r\n }\r\n\r\n private isMcpUri(url: string): boolean {\r\n return MCP_URI_SCHEMES.some(scheme => url.startsWith(scheme));\r\n }\r\n\r\n private hasClientCache(): boolean {\r\n return 'getOrFetchResource' in this.client &&\r\n typeof (this.client as any).getOrFetchResource === 'function';\r\n }\r\n\r\n private extractUiResourceUri(tool: { _meta?: unknown }): string | undefined {\r\n const meta = tool._meta as { ui?: { resourceUri?: string; uri?: string } } | undefined;\r\n if (!meta?.ui) return undefined;\r\n return meta.ui.resourceUri ?? meta.ui.uri;\r\n }\r\n\r\n private decodeContent(content: ResourceContent): string | undefined {\r\n if (content.blob) {\r\n return atob(content.blob);\r\n }\r\n return content.text;\r\n }\r\n\r\n private log(message: string, level: 'info' | 'warn' | 'error' = 'info'): void {\r\n if (!this.debug && level === 'info') return;\r\n\r\n const prefix = '[AppHost]';\r\n switch (level) {\r\n case 'warn':\r\n console.warn(prefix, message);\r\n break;\r\n case 'error':\r\n console.error(prefix, message);\r\n break;\r\n default:\r\n console.log(prefix, message);\r\n }\r\n }\r\n}\r\n","import { useEffect, useRef, useState, useCallback } from 'react';\r\nimport type { SSEClient } from '../core/sse-client';\r\nimport { AppHost } from '../core/app-host';\r\n\r\n/**\r\n * Hook to host an MCP App in a React component\r\n *\r\n * Optimized for instant loading:\r\n * - Creates AppHost synchronously\r\n * - Starts bridge connection immediately\r\n * - Returns host before connection completes (ready to call launch)\r\n *\r\n * @param client - Connected SSEClient instance\r\n * @param iframeRef - Reference to the iframe element\r\n * @param options - Optional configuration\r\n * @returns Object containing the AppHost instance (or null) and error state\r\n */\r\nexport function useAppHost(\r\n client: SSEClient,\r\n iframeRef: React.RefObject<HTMLIFrameElement>,\r\n options?: {\r\n /** Callback when the App sends a message (e.g. to chat) */\r\n onMessage?: (params: { role: string; content: unknown }) => void;\r\n }\r\n) {\r\n const [host, setHost] = useState<AppHost | null>(null);\r\n const [error, setError] = useState<Error | null>(null);\r\n const initializingRef = useRef(false);\r\n\r\n // Store latest callback in ref to avoid re-initializing AppHost on callback change\r\n const onMessageRef = useRef(options?.onMessage);\r\n useEffect(() => {\r\n onMessageRef.current = options?.onMessage;\r\n }, [options?.onMessage]);\r\n\r\n useEffect(() => {\r\n if (!client || !iframeRef.current || initializingRef.current) return;\r\n\r\n // Prevent double initialization in strict mode\r\n initializingRef.current = true;\r\n\r\n const initHost = async () => {\r\n try {\r\n // Initialize AppHost with security enforcement\r\n const appHost = new AppHost(client, iframeRef.current!);\r\n\r\n // Register message handler\r\n appHost.onAppMessage = (params) => {\r\n onMessageRef.current?.(params);\r\n };\r\n\r\n // Set host immediately so launch can be called\r\n // (launch will wait for bridge if needed)\r\n setHost(appHost);\r\n\r\n // Start bridge connection (this is fast, just sets up PostMessage)\r\n await appHost.start();\r\n } catch (err) {\r\n console.error('[useAppHost] Failed to initialize AppHost:', err);\r\n setError(err instanceof Error ? err : new Error(String(err)));\r\n }\r\n };\r\n\r\n initHost();\r\n\r\n return () => {\r\n initializingRef.current = false;\r\n setHost(null);\r\n };\r\n }, [client, iframeRef]);\r\n\r\n return { host, error };\r\n}\r\n","/**\n * MCP Apps Hook\n *\n * Provides utilities for rendering interactive UI components from MCP servers.\n */\n\nimport React, { useState, useEffect, useCallback, useRef, memo } from 'react';\nimport { useAppHost } from './use-app-host.js';\nimport type { SSEClient } from '../core/sse-client.js';\n\nexport interface McpClient {\n connections: Array<{\n sessionId: string;\n tools: Array<{\n name: string;\n mcpApp?: {\n resourceUri: string;\n };\n _meta?: {\n ui?: {\n resourceUri?: string;\n };\n 'ui/resourceUri'?: string;\n };\n }>;\n }>;\n sseClient?: SSEClient | null;\n}\n\nexport interface McpAppMetadata {\n toolName: string;\n resourceUri: string;\n sessionId: string;\n}\n\ninterface McpAppRendererProps {\n metadata: McpAppMetadata;\n input?: Record<string, unknown>;\n result?: unknown;\n status: 'executing' | 'inProgress' | 'complete' | 'idle';\n sseClient?: SSEClient | null;\n /** Custom CSS class for the container */\n className?: string;\n}\n\n/**\n * Internal component that renders the MCP app in a sandboxed iframe\n */\nconst McpAppRenderer = memo(function McpAppRenderer({\n metadata,\n input,\n result,\n status,\n sseClient,\n className,\n}: McpAppRendererProps) {\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const { host, error: hostError } = useAppHost(sseClient as SSEClient, iframeRef);\n const [isLaunched, setIsLaunched] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n // Track which data has been sent to prevent duplicates\n const sentInputRef = useRef(false);\n const sentResultRef = useRef(false);\n const lastInputRef = useRef(input);\n const lastResultRef = useRef(result);\n const lastStatusRef = useRef(status);\n\n // Launch the app when host is ready\n useEffect(() => {\n if (!host || !metadata.resourceUri || !metadata.sessionId) return;\n\n host\n .launch(metadata.resourceUri, metadata.sessionId)\n .then(() => setIsLaunched(true))\n .catch((err) => setError(err instanceof Error ? err : new Error(String(err))));\n }, [host, metadata.resourceUri, metadata.sessionId]);\n\n // Send tool input when available or when it changes\n useEffect(() => {\n if (!host || !isLaunched || !input) return;\n \n // Send if never sent, or if input changed\n if (!sentInputRef.current || JSON.stringify(input) !== JSON.stringify(lastInputRef.current)) {\n sentInputRef.current = true;\n lastInputRef.current = input;\n host.sendToolInput(input);\n }\n }, [host, isLaunched, input]);\n\n // Send tool result when complete or when it changes\n useEffect(() => {\n if (!host || !isLaunched || result === undefined) return;\n if (status !== 'complete') return;\n\n // Send if never sent, or if result changed\n if (!sentResultRef.current || JSON.stringify(result) !== JSON.stringify(lastResultRef.current)) {\n sentResultRef.current = true;\n lastResultRef.current = result;\n const formattedResult =\n typeof result === 'string'\n ? { content: [{ type: 'text', text: result }] }\n : result;\n host.sendToolResult(formattedResult);\n }\n }, [host, isLaunched, result, status]);\n\n // Reset sent flags when tool status resets to executing (new tool call)\n useEffect(() => {\n if (status === 'executing' && lastStatusRef.current !== 'executing') {\n sentInputRef.current = false;\n sentResultRef.current = false;\n }\n lastStatusRef.current = status;\n }, [status]);\n\n // Display errors\n const displayError = error || hostError;\n if (displayError) {\n return (\n <div className={`p-4 bg-red-900/20 border border-red-700 rounded text-red-200 ${className || ''}`}>\n Error: {displayError.message || String(displayError)}\n </div>\n );\n }\n\n return (\n <div className={`w-full border border-gray-700 rounded overflow-hidden bg-white min-h-96 my-2 relative ${className || ''}`}>\n <iframe\n ref={iframeRef}\n sandbox=\"allow-scripts allow-same-origin allow-forms allow-modals allow-popups allow-downloads\"\n className=\"w-full h-full min-h-96\"\n style={{ height: 'auto' }}\n title=\"MCP App\"\n />\n {!isLaunched && (\n <div className=\"absolute inset-0 bg-gray-900/50 flex items-center justify-center pointer-events-none\">\n <div className=\"w-6 h-6 border-2 border-blue-500 border-t-transparent rounded-full animate-spin\" />\n </div>\n )}\n </div>\n );\n});\n\n/**\n * Simple hook to get MCP app metadata\n *\n * @param mcpClient - The MCP client from useMcp() or context\n * @returns Object with getAppMetadata function and McpAppRenderer component\n *\n * @example\n * ```tsx\n * function ToolRenderer(props) {\n * const { getAppMetadata, McpAppRenderer } = useMcpApps(mcpClient);\n * const metadata = getAppMetadata(props.name);\n *\n * if (!metadata) return null;\n * return (\n * <McpAppRenderer\n * metadata={metadata}\n * input={props.args}\n * result={props.result}\n * status={props.status}\n * />\n * );\n * }\n * ```\n */\nexport function useMcpApps(mcpClient: McpClient | null) {\n /**\n * Get MCP app metadata for a tool name\n * This is fast and can be called on every render\n */\n const getAppMetadata = useCallback(\n (toolName: string): McpAppMetadata | undefined => {\n if (!mcpClient) return undefined;\n\n const extractedName = extractToolName(toolName);\n\n for (const conn of mcpClient.connections) {\n for (const tool of conn.tools) {\n const candidateName = extractToolName(tool.name);\n // Check both locations: direct mcpApp or _meta.ui\n const resourceUri =\n tool.mcpApp?.resourceUri ??\n tool._meta?.ui?.resourceUri ??\n tool._meta?.['ui/resourceUri'];\n\n if (resourceUri && candidateName === extractedName) {\n return {\n toolName: candidateName,\n resourceUri,\n sessionId: conn.sessionId,\n };\n }\n }\n }\n\n return undefined;\n },\n [mcpClient]\n );\n\n return { getAppMetadata, McpAppRenderer };\n}\n\n/**\n * Extract the base tool name, removing any prefixes\n */\nfunction extractToolName(fullName: string): string {\n // Handle patterns like \"tool_abc123_get-time\" -> \"get-time\"\n const match = fullName.match(/(?:tool_[^_]+_)?(.+)$/);\n return match?.[1] || fullName;\n}\n"]}
|
package/dist/client/react.mjs
CHANGED
|
@@ -932,7 +932,8 @@ var McpAppRenderer = memo(function McpAppRenderer2({
|
|
|
932
932
|
input,
|
|
933
933
|
result,
|
|
934
934
|
status,
|
|
935
|
-
sseClient
|
|
935
|
+
sseClient,
|
|
936
|
+
className
|
|
936
937
|
}) {
|
|
937
938
|
const iframeRef = useRef(null);
|
|
938
939
|
const { host, error: hostError } = useAppHost(sseClient, iframeRef);
|
|
@@ -974,12 +975,12 @@ var McpAppRenderer = memo(function McpAppRenderer2({
|
|
|
974
975
|
}, [status]);
|
|
975
976
|
const displayError = error || hostError;
|
|
976
977
|
if (displayError) {
|
|
977
|
-
return /* @__PURE__ */ jsxs("div", { className:
|
|
978
|
+
return /* @__PURE__ */ jsxs("div", { className: `p-4 bg-red-900/20 border border-red-700 rounded text-red-200 ${className || ""}`, children: [
|
|
978
979
|
"Error: ",
|
|
979
980
|
displayError.message || String(displayError)
|
|
980
981
|
] });
|
|
981
982
|
}
|
|
982
|
-
return /* @__PURE__ */ jsxs("div", { className:
|
|
983
|
+
return /* @__PURE__ */ jsxs("div", { className: `w-full border border-gray-700 rounded overflow-hidden bg-white min-h-96 my-2 relative ${className || ""}`, children: [
|
|
983
984
|
/* @__PURE__ */ jsx(
|
|
984
985
|
"iframe",
|
|
985
986
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/client/core/sse-client.ts","../../src/client/react/use-mcp.ts","../../src/client/core/app-host.ts","../../src/client/react/use-app-host.ts","../../src/client/react/use-mcp-apps.tsx"],"names":["useState","useRef","useEffect","McpAppRenderer","useCallback"],"mappings":"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","file":"react.mjs","sourcesContent":["/**\r\n * SSE Client for MCP Connections\r\n *\r\n * Browser-side client that manages real-time communication with the MCP server\r\n * using Server-Sent Events (SSE) for server→client streaming and HTTP POST for\r\n * client→server RPC requests.\r\n *\r\n * Key features:\r\n * - Direct HTTP response for RPC calls (bypasses SSE latency)\r\n * - Resource preloading for instant MCP App UI loading\r\n * - Automatic reconnection with exponential backoff\r\n * - Type-safe RPC methods\r\n */\r\n\r\nimport { nanoid } from 'nanoid';\r\nimport type {\r\n McpConnectionEvent,\r\n McpObservabilityEvent,\r\n McpAppsUIEvent\r\n} from '../../shared/events.js';\r\nimport type {\r\n McpRpcRequest,\r\n McpRpcResponse,\r\n McpRpcMethod,\r\n McpRpcParams,\r\n ConnectParams,\r\n SessionListResult,\r\n ConnectResult,\r\n DisconnectResult,\r\n RestoreSessionResult,\r\n FinishAuthResult,\r\n ListToolsRpcResult,\r\n ListPromptsResult,\r\n ListResourcesResult,\r\n} from '../../shared/types.js';\r\n// ============================================\r\n// Types & Interfaces\r\n// ============================================\r\n\r\nexport interface SSEClientOptions {\r\n /** SSE endpoint URL */\r\n url: string;\r\n\r\n /** User/Client identifier */\r\n identity: string;\r\n\r\n /** Optional auth token for authenticated requests */\r\n authToken?: string;\r\n\r\n /** Callback for MCP connection state changes */\r\n onConnectionEvent?: (event: McpConnectionEvent) => void;\r\n\r\n /** Callback for observability/logging events */\r\n onObservabilityEvent?: (event: McpObservabilityEvent) => void;\r\n\r\n /** Callback for connection status changes */\r\n onStatusChange?: (status: ConnectionStatus) => void;\r\n\r\n /** Callback for MCP App UI events */\r\n onEvent?: (event: McpAppsUIEvent) => void;\r\n\r\n /** Request timeout in milliseconds @default 60000 */\r\n requestTimeout?: number;\r\n\r\n /** Enable debug logging @default false */\r\n debug?: boolean;\r\n}\r\n\r\nexport type ConnectionStatus = 'connecting' | 'connected' | 'disconnected' | 'error';\r\n\r\ninterface PendingRequest {\r\n resolve: (value: unknown) => void;\r\n reject: (error: Error) => void;\r\n timeoutId: ReturnType<typeof setTimeout>;\r\n}\r\n\r\ninterface ToolUiMetadata {\r\n resourceUri?: string;\r\n uri?: string;\r\n visibility?: string[];\r\n}\r\n\r\n// ============================================\r\n// Constants\r\n// ============================================\r\n\r\nconst DEFAULT_REQUEST_TIMEOUT = 60000;\r\nconst MAX_RECONNECT_ATTEMPTS = 5;\r\nconst BASE_RECONNECT_DELAY = 1000;\r\n\r\n// ============================================\r\n// SSEClient Class\r\n// ============================================\r\n\r\n/**\r\n * SSE Client for real-time MCP connection management\r\n */\r\nexport class SSEClient {\r\n private eventSource: EventSource | null = null;\r\n private pendingRequests = new Map<string, PendingRequest>();\r\n private resourceCache = new Map<string, Promise<unknown>>();\r\n\r\n private reconnectAttempts = 0;\r\n private isManuallyDisconnected = false;\r\n private connectionPromise: Promise<void> | null = null;\r\n private connectionResolver: (() => void) | null = null;\r\n\r\n constructor(private readonly options: SSEClientOptions) {}\r\n\r\n // ============================================\r\n // Connection Management\r\n // ============================================\r\n\r\n /**\r\n * Connect to the SSE endpoint\r\n */\r\n connect(): void {\r\n if (this.eventSource) {\r\n return; // Already connected\r\n }\r\n\r\n this.isManuallyDisconnected = false;\r\n this.options.onStatusChange?.('connecting');\r\n this.connectionPromise = new Promise((resolve) => {\r\n this.connectionResolver = resolve;\r\n });\r\n\r\n const url = this.buildUrl();\r\n this.eventSource = new EventSource(url);\r\n this.setupEventListeners();\r\n }\r\n\r\n /**\r\n * Disconnect from the SSE endpoint\r\n */\r\n disconnect(): void {\r\n this.isManuallyDisconnected = true;\r\n\r\n if (this.eventSource) {\r\n this.eventSource.close();\r\n this.eventSource = null;\r\n }\r\n\r\n this.connectionPromise = null;\r\n this.connectionResolver = null;\r\n this.rejectAllPendingRequests(new Error('Connection closed'));\r\n this.options.onStatusChange?.('disconnected');\r\n }\r\n\r\n /**\r\n * Check if connected to the SSE endpoint\r\n */\r\n isConnected(): boolean {\r\n return this.eventSource?.readyState === EventSource.OPEN;\r\n }\r\n\r\n // ============================================\r\n // RPC Methods\r\n // ============================================\r\n\r\n async getSessions(): Promise<SessionListResult> {\r\n return this.sendRequest<SessionListResult>('getSessions');\r\n }\r\n\r\n async connectToServer(params: ConnectParams): Promise<ConnectResult> {\r\n return this.sendRequest<ConnectResult>('connect', params);\r\n }\r\n\r\n async disconnectFromServer(sessionId: string): Promise<DisconnectResult> {\r\n return this.sendRequest<DisconnectResult>('disconnect', { sessionId });\r\n }\r\n\r\n async listTools(sessionId: string): Promise<ListToolsRpcResult> {\r\n return this.sendRequest<ListToolsRpcResult>('listTools', { sessionId });\r\n }\r\n\r\n async callTool(\r\n sessionId: string,\r\n toolName: string,\r\n toolArgs: Record<string, unknown>\r\n ): Promise<unknown> {\r\n const result = await this.sendRequest('callTool', { sessionId, toolName, toolArgs });\r\n this.emitUiEventIfPresent(result, sessionId, toolName);\r\n return result;\r\n }\r\n\r\n async restoreSession(sessionId: string): Promise<RestoreSessionResult> {\r\n return this.sendRequest<RestoreSessionResult>('restoreSession', { sessionId });\r\n }\r\n\r\n async finishAuth(sessionId: string, code: string): Promise<FinishAuthResult> {\r\n return this.sendRequest<FinishAuthResult>('finishAuth', { sessionId, code });\r\n }\r\n\r\n async listPrompts(sessionId: string): Promise<ListPromptsResult> {\r\n return this.sendRequest<ListPromptsResult>('listPrompts', { sessionId });\r\n }\r\n\r\n async getPrompt(sessionId: string, name: string, args?: Record<string, string>): Promise<unknown> {\r\n return this.sendRequest('getPrompt', { sessionId, name, args });\r\n }\r\n\r\n async listResources(sessionId: string): Promise<ListResourcesResult> {\r\n return this.sendRequest<ListResourcesResult>('listResources', { sessionId });\r\n }\r\n\r\n async readResource(sessionId: string, uri: string): Promise<unknown> {\r\n return this.sendRequest('readResource', { sessionId, uri });\r\n }\r\n\r\n // ============================================\r\n // Resource Preloading (for instant UI loading)\r\n // ============================================\r\n\r\n /**\r\n * Preload UI resources for tools that have UI metadata.\r\n * Call this when tools are discovered to enable instant MCP App UI loading.\r\n */\r\n preloadToolUiResources(sessionId: string, tools: Array<{ name: string; _meta?: unknown }>): void {\r\n for (const tool of tools) {\r\n const uri = this.extractUiResourceUri(tool);\r\n if (!uri) continue;\r\n\r\n if (this.resourceCache.has(uri)) {\r\n this.log(`Resource already cached: ${uri}`);\r\n continue;\r\n }\r\n\r\n this.log(`Preloading UI resource for tool \"${tool.name}\": ${uri}`);\r\n const promise = this.sendRequest('readResource', { sessionId, uri })\r\n .catch((err) => {\r\n this.log(`Failed to preload resource ${uri}: ${err.message}`, 'warn');\r\n this.resourceCache.delete(uri);\r\n return null;\r\n });\r\n\r\n this.resourceCache.set(uri, promise);\r\n }\r\n }\r\n\r\n /**\r\n * Get a preloaded resource from cache, or fetch if not cached.\r\n */\r\n getOrFetchResource(sessionId: string, uri: string): Promise<unknown> {\r\n const cached = this.resourceCache.get(uri);\r\n if (cached) {\r\n this.log(`Cache hit for resource: ${uri}`);\r\n return cached;\r\n }\r\n\r\n this.log(`Cache miss, fetching resource: ${uri}`);\r\n const promise = this.sendRequest('readResource', { sessionId, uri });\r\n this.resourceCache.set(uri, promise);\r\n return promise;\r\n }\r\n\r\n /**\r\n * Check if a resource is already cached\r\n */\r\n hasPreloadedResource(uri: string): boolean {\r\n return this.resourceCache.has(uri);\r\n }\r\n\r\n /**\r\n * Clear the resource cache\r\n */\r\n clearResourceCache(): void {\r\n this.resourceCache.clear();\r\n }\r\n\r\n // ============================================\r\n // Private: Request Handling\r\n // ============================================\r\n\r\n /**\r\n * Send an RPC request and return the response directly from HTTP.\r\n * This bypasses SSE latency by returning results in the HTTP response body.\r\n */\r\n private async sendRequest<T = unknown>(method: McpRpcMethod, params?: McpRpcParams): Promise<T> {\r\n if (this.connectionPromise) {\r\n await this.connectionPromise;\r\n }\r\n\r\n const request: McpRpcRequest = {\r\n id: `rpc_${nanoid(10)}`,\r\n method,\r\n params,\r\n };\r\n\r\n const response = await fetch(this.buildUrl(), {\r\n method: 'POST',\r\n headers: this.buildHeaders(),\r\n body: JSON.stringify(request),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\r\n }\r\n\r\n const data = await response.json() as McpRpcResponse;\r\n return this.parseRpcResponse<T>(data, request.id);\r\n }\r\n\r\n /**\r\n * Parse RPC response and handle different response formats\r\n */\r\n private parseRpcResponse<T>(data: McpRpcResponse, requestId: string): T | Promise<T> {\r\n // Fast path: Direct response (new behavior)\r\n if ('result' in data) {\r\n return data.result as T;\r\n }\r\n\r\n // Error response\r\n if ('error' in data && data.error) {\r\n throw new Error(data.error.message || 'Unknown RPC error');\r\n }\r\n\r\n // Legacy path: Acknowledgment only (wait for SSE)\r\n // Kept for backwards compatibility with older servers\r\n if ('acknowledged' in data) {\r\n return this.waitForSseResponse<T>(requestId);\r\n }\r\n\r\n throw new Error('Invalid RPC response format');\r\n }\r\n\r\n /**\r\n * Wait for RPC response via SSE (legacy fallback)\r\n */\r\n private waitForSseResponse<T>(requestId: string): Promise<T> {\r\n const timeoutMs = this.options.requestTimeout ?? DEFAULT_REQUEST_TIMEOUT;\r\n\r\n return new Promise<T>((resolve, reject) => {\r\n const timeoutId = setTimeout(() => {\r\n this.pendingRequests.delete(requestId);\r\n reject(new Error(`Request timeout after ${timeoutMs}ms`));\r\n }, timeoutMs);\r\n\r\n this.pendingRequests.set(requestId, {\r\n resolve: resolve as (value: unknown) => void,\r\n reject,\r\n timeoutId,\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Handle RPC response received via SSE (legacy)\r\n */\r\n private handleRpcResponse(response: McpRpcResponse): void {\r\n const pending = this.pendingRequests.get(response.id);\r\n if (!pending) return;\r\n\r\n clearTimeout(pending.timeoutId);\r\n this.pendingRequests.delete(response.id);\r\n\r\n if (response.error) {\r\n pending.reject(new Error(response.error.message));\r\n } else {\r\n pending.resolve(response.result);\r\n }\r\n }\r\n\r\n // ============================================\r\n // Private: Event Handling\r\n // ============================================\r\n\r\n private setupEventListeners(): void {\r\n if (!this.eventSource) return;\r\n\r\n this.eventSource.addEventListener('open', () => {\r\n this.log('Connected');\r\n this.reconnectAttempts = 0;\r\n this.options.onStatusChange?.('connected');\r\n });\r\n\r\n this.eventSource.addEventListener('connected', () => {\r\n this.log('Server ready');\r\n this.connectionResolver?.();\r\n this.connectionResolver = null;\r\n });\r\n\r\n this.eventSource.addEventListener('connection', (e: MessageEvent) => {\r\n const event = JSON.parse(e.data) as McpConnectionEvent;\r\n this.options.onConnectionEvent?.(event);\r\n });\r\n\r\n this.eventSource.addEventListener('observability', (e: MessageEvent) => {\r\n const event = JSON.parse(e.data) as McpObservabilityEvent;\r\n this.options.onObservabilityEvent?.(event);\r\n });\r\n\r\n this.eventSource.addEventListener('rpc-response', (e: MessageEvent) => {\r\n const response = JSON.parse(e.data) as McpRpcResponse;\r\n this.handleRpcResponse(response);\r\n });\r\n\r\n this.eventSource.addEventListener('error', () => {\r\n this.log('Connection error', 'error');\r\n this.options.onStatusChange?.('error');\r\n this.attemptReconnect();\r\n });\r\n }\r\n\r\n private attemptReconnect(): void {\r\n if (this.isManuallyDisconnected || this.reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {\r\n return;\r\n }\r\n\r\n this.reconnectAttempts++;\r\n const delay = BASE_RECONNECT_DELAY * this.reconnectAttempts;\r\n this.log(`Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts}/${MAX_RECONNECT_ATTEMPTS})`);\r\n\r\n setTimeout(() => {\r\n this.disconnect();\r\n this.connect();\r\n }, delay);\r\n }\r\n\r\n // ============================================\r\n // Private: Utilities\r\n // ============================================\r\n\r\n private buildUrl(): string {\r\n const url = new URL(this.options.url, globalThis.location?.origin);\r\n url.searchParams.set('identity', this.options.identity);\r\n if (this.options.authToken) {\r\n url.searchParams.set('token', this.options.authToken);\r\n }\r\n return url.toString();\r\n }\r\n\r\n private buildHeaders(): HeadersInit {\r\n const headers: HeadersInit = {\r\n 'Content-Type': 'application/json',\r\n };\r\n if (this.options.authToken) {\r\n headers['Authorization'] = `Bearer ${this.options.authToken}`;\r\n }\r\n return headers;\r\n }\r\n\r\n private rejectAllPendingRequests(error: Error): void {\r\n for (const [, pending] of this.pendingRequests) {\r\n clearTimeout(pending.timeoutId);\r\n pending.reject(error);\r\n }\r\n this.pendingRequests.clear();\r\n }\r\n\r\n private extractUiResourceUri(tool: { name: string; _meta?: unknown }): string | undefined {\r\n const meta = (tool._meta as { ui?: ToolUiMetadata })?.ui;\r\n if (!meta || typeof meta !== 'object') return undefined;\r\n\r\n // Check visibility constraint\r\n if (meta.visibility && !meta.visibility.includes('app')) return undefined;\r\n\r\n // Support both 'resourceUri' and 'uri' field names\r\n return meta.resourceUri ?? meta.uri;\r\n }\r\n\r\n private emitUiEventIfPresent(result: unknown, sessionId: string, toolName: string): void {\r\n const meta = (result as { _meta?: { ui?: ToolUiMetadata } })?._meta;\r\n const resourceUri = meta?.ui?.resourceUri ?? (meta as any)?.['ui/resourceUri'];\r\n\r\n if (resourceUri) {\r\n this.options.onEvent?.({\r\n type: 'mcp-apps-ui',\r\n sessionId,\r\n resourceUri,\r\n toolName,\r\n result,\r\n timestamp: Date.now(),\r\n });\r\n }\r\n }\r\n\r\n private log(message: string, level: 'info' | 'warn' | 'error' = 'info'): void {\r\n if (!this.options.debug && level === 'info') return;\r\n\r\n const prefix = '[SSEClient]';\r\n switch (level) {\r\n case 'warn':\r\n console.warn(prefix, message);\r\n break;\r\n case 'error':\r\n console.error(prefix, message);\r\n break;\r\n default:\r\n console.log(prefix, message);\r\n }\r\n }\r\n}\r\n","/**\r\n * useMcp React Hook\r\n * Manages MCP connections with SSE-based real-time updates\r\n * Based on Cloudflare's agents pattern\r\n */\r\n\r\nimport { useEffect, useRef, useState, useCallback } from 'react';\r\nimport { SSEClient, type SSEClientOptions } from '../core/sse-client';\r\nimport type { McpConnectionEvent, McpConnectionState } from '../../shared/events';\r\nimport type {\r\n ToolInfo,\r\n FinishAuthResult,\r\n ListToolsRpcResult,\r\n ListPromptsResult,\r\n ListResourcesResult,\r\n SessionInfo,\r\n} from '../../shared/types';\r\n\r\nexport interface UseMcpOptions {\r\n /**\r\n * SSE endpoint URL\r\n */\r\n url: string;\r\n\r\n /**\r\n * User/Client identifier\r\n */\r\n identity: string;\r\n\r\n /**\r\n * Optional auth token\r\n */\r\n authToken?: string;\r\n\r\n /**\r\n * Auto-connect on mount\r\n * @default true\r\n */\r\n autoConnect?: boolean;\r\n\r\n /**\r\n * Auto-initialize sessions on mount\r\n * @default true\r\n */\r\n autoInitialize?: boolean;\r\n\r\n /**\r\n * Connection event callback\r\n */\r\n onConnectionEvent?: (event: McpConnectionEvent) => void;\r\n\r\n /**\r\n * Debug logging callback\r\n */\r\n onLog?: (level: string, message: string, metadata?: Record<string, unknown>) => void;\r\n /**\r\n * Optional callback to handle OAuth redirects (e.g. for popup flow)\r\n * If provided, this will be called instead of window.location.href assignment\r\n */\r\n onRedirect?: (url: string) => void;\r\n\r\n /**\r\n * Request timeout in milliseconds\r\n * @default 60000\r\n */\r\n requestTimeout?: number;\r\n}\r\n\r\nexport interface McpConnection {\r\n sessionId: string;\r\n serverId: string;\r\n serverName: string;\r\n serverUrl?: string;\r\n transport?: string;\r\n state: McpConnectionState;\r\n tools: ToolInfo[];\r\n error?: string;\r\n connectedAt?: Date;\r\n}\r\n\r\nexport interface McpClient {\r\n /**\r\n * All connections\r\n */\r\n connections: McpConnection[];\r\n\r\n /**\r\n * SSE connection status\r\n */\r\n status: 'connecting' | 'connected' | 'disconnected' | 'error';\r\n\r\n /**\r\n * Whether initializing\r\n */\r\n isInitializing: boolean;\r\n\r\n /**\r\n * Connect to an MCP server\r\n */\r\n connect: (params: {\r\n serverId: string;\r\n serverName: string;\r\n serverUrl: string;\r\n callbackUrl: string;\r\n transportType?: 'sse' | 'streamable_http';\r\n }) => Promise<string>;\r\n\r\n /**\r\n * Disconnect from an MCP server\r\n */\r\n disconnect: (sessionId: string) => Promise<void>;\r\n\r\n /**\r\n * Get connection by session ID\r\n */\r\n getConnection: (sessionId: string) => McpConnection | undefined;\r\n\r\n /**\r\n * Get connection by server ID\r\n */\r\n getConnectionByServerId: (serverId: string) => McpConnection | undefined;\r\n\r\n /**\r\n * Check if server is connected\r\n */\r\n isServerConnected: (serverId: string) => boolean;\r\n\r\n /**\r\n * Get tools for a session\r\n */\r\n getTools: (sessionId: string) => ToolInfo[];\r\n\r\n /**\r\n * Refresh all connections\r\n */\r\n refresh: () => Promise<void>;\r\n\r\n /**\r\n * Manually connect SSE\r\n */\r\n connectSSE: () => void;\r\n\r\n /**\r\n * Manually disconnect SSE\r\n */\r\n disconnectSSE: () => void;\r\n\r\n /**\r\n * Complete OAuth authorization\r\n */\r\n finishAuth: (sessionId: string, code: string) => Promise<FinishAuthResult>;\r\n\r\n /**\r\n * Call a tool from a session\r\n */\r\n callTool: (\r\n sessionId: string,\r\n toolName: string,\r\n toolArgs: Record<string, unknown>\r\n ) => Promise<unknown>;\r\n\r\n /**\r\n * List available tools for a session\r\n */\r\n listTools: (sessionId: string) => Promise<ListToolsRpcResult>;\r\n\r\n /**\r\n * List available prompts for a session\r\n */\r\n listPrompts: (sessionId: string) => Promise<ListPromptsResult>;\r\n\r\n /**\r\n * Get a specific prompt with arguments\r\n */\r\n getPrompt: (sessionId: string, name: string, args?: Record<string, string>) => Promise<unknown>;\r\n\r\n /**\r\n * List available resources for a session\r\n */\r\n listResources: (sessionId: string) => Promise<ListResourcesResult>;\r\n\r\n /**\r\n * Read a specific resource\r\n */\r\n readResource: (sessionId: string, uri: string) => Promise<unknown>;\r\n\r\n /**\r\n * Access the underlying SSEClient instance (for advanced usage like AppHost)\r\n */\r\n sseClient: SSEClient | null;\r\n}\r\n\r\n/**\r\n * React hook for MCP connection management with SSE\r\n */\r\nexport function useMcp(options: UseMcpOptions): McpClient {\r\n const {\r\n url,\r\n identity,\r\n authToken,\r\n autoConnect = true,\r\n autoInitialize = true,\r\n onConnectionEvent,\r\n onLog,\r\n onRedirect,\r\n } = options;\r\n\r\n const clientRef = useRef<SSEClient | null>(null);\r\n const isMountedRef = useRef(true);\r\n\r\n const [connections, setConnections] = useState<McpConnection[]>([]);\r\n const [status, setStatus] = useState<'connecting' | 'connected' | 'disconnected' | 'error'>(\r\n 'disconnected'\r\n );\r\n const [isInitializing, setIsInitializing] = useState(false);\r\n\r\n /**\r\n * Initialize SSE client\r\n */\r\n useEffect(() => {\r\n isMountedRef.current = true;\r\n\r\n const clientOptions: SSEClientOptions = {\r\n url,\r\n identity,\r\n authToken,\r\n onConnectionEvent: (event) => {\r\n // Update local state based on event\r\n updateConnectionsFromEvent(event);\r\n\r\n // Call user callback\r\n onConnectionEvent?.(event);\r\n },\r\n onObservabilityEvent: (event) => {\r\n onLog?.(event.level || 'info', event.message || event.displayMessage || 'No message', event.metadata);\r\n },\r\n onStatusChange: (newStatus) => {\r\n if (isMountedRef.current) {\r\n setStatus(newStatus);\r\n }\r\n },\r\n requestTimeout: options.requestTimeout,\r\n };\r\n\r\n const client = new SSEClient(clientOptions);\r\n clientRef.current = client;\r\n\r\n if (autoConnect) {\r\n client.connect();\r\n\r\n if (autoInitialize) {\r\n loadSessions();\r\n }\r\n }\r\n\r\n return () => {\r\n isMountedRef.current = false;\r\n client.disconnect();\r\n };\r\n }, [url, identity, authToken, autoConnect, autoInitialize]);\r\n\r\n /**\r\n * Update connections based on event\r\n */\r\n const updateConnectionsFromEvent = useCallback((event: McpConnectionEvent) => {\r\n if (!isMountedRef.current) return;\r\n\r\n setConnections((prev: McpConnection[]) => {\r\n switch (event.type) {\r\n case 'state_changed': {\r\n const existing = prev.find((c: McpConnection) => c.sessionId === event.sessionId);\r\n if (existing) {\r\n return prev.map((c: McpConnection) =>\r\n c.sessionId === event.sessionId ? { ...c, state: event.state } : c\r\n );\r\n } else {\r\n return [\r\n ...prev,\r\n {\r\n sessionId: event.sessionId,\r\n serverId: event.serverId,\r\n serverName: event.serverName,\r\n state: event.state,\r\n tools: [],\r\n },\r\n ];\r\n }\r\n }\r\n\r\n case 'tools_discovered': {\r\n // Preload UI resources for instant loading when tools are discovered\r\n if (clientRef.current && event.tools?.length) {\r\n clientRef.current.preloadToolUiResources(event.sessionId, event.tools);\r\n }\r\n\r\n return prev.map((c: McpConnection) =>\r\n c.sessionId === event.sessionId ? { ...c, tools: event.tools, state: 'READY' } : c\r\n );\r\n }\r\n\r\n case 'auth_required': {\r\n // Handle OAuth redirect\r\n if (event.authUrl) {\r\n onLog?.('info', `OAuth required - redirecting to ${event.authUrl}`, { authUrl: event.authUrl });\r\n\r\n if (onRedirect) {\r\n onRedirect(event.authUrl);\r\n } else if (typeof window !== 'undefined') {\r\n window.location.href = event.authUrl;\r\n }\r\n }\r\n return prev.map((c: McpConnection) =>\r\n c.sessionId === event.sessionId ? { ...c, state: 'AUTHENTICATING' } : c\r\n );\r\n }\r\n\r\n case 'error': {\r\n return prev.map((c: McpConnection) =>\r\n c.sessionId === event.sessionId ? { ...c, state: 'FAILED', error: event.error } : c\r\n );\r\n }\r\n\r\n case 'disconnected': {\r\n return prev.filter((c: McpConnection) => c.sessionId !== event.sessionId);\r\n }\r\n\r\n default:\r\n return prev;\r\n }\r\n });\r\n }, [onLog]);\r\n\r\n /**\r\n * Load sessions from server\r\n */\r\n const loadSessions = useCallback(async () => {\r\n if (!clientRef.current) return;\r\n\r\n try {\r\n setIsInitializing(true);\r\n\r\n const result = await clientRef.current.getSessions();\r\n const sessions = result.sessions || [];\r\n\r\n // Initialize connections\r\n if (isMountedRef.current) {\r\n setConnections(\r\n sessions.map((s: SessionInfo) => ({\r\n sessionId: s.sessionId,\r\n serverId: s.serverId ?? 'unknown',\r\n serverName: s.serverName ?? 'Unknown Server',\r\n serverUrl: s.serverUrl,\r\n transport: s.transport,\r\n state: 'VALIDATING' as McpConnectionState,\r\n tools: [],\r\n }))\r\n );\r\n }\r\n\r\n // Validate each session in parallel\r\n await Promise.all(\r\n sessions.map(async (session: SessionInfo) => {\r\n if (clientRef.current) {\r\n try {\r\n await clientRef.current.restoreSession(session.sessionId);\r\n } catch (error) {\r\n console.error(`[useMcp] Failed to validate session ${session.sessionId}:`, error);\r\n }\r\n }\r\n })\r\n );\r\n } catch (error) {\r\n console.error('[useMcp] Failed to load sessions:', error);\r\n onLog?.('error', 'Failed to load sessions', { error });\r\n } finally {\r\n if (isMountedRef.current) {\r\n setIsInitializing(false);\r\n }\r\n }\r\n }, [onLog]);\r\n\r\n /**\r\n * Connect to an MCP server\r\n */\r\n const connect = useCallback(\r\n async (params: {\r\n serverId: string;\r\n serverName: string;\r\n serverUrl: string;\r\n callbackUrl: string;\r\n transportType?: 'sse' | 'streamable_http';\r\n }): Promise<string> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n const result = await clientRef.current.connectToServer(params);\r\n return result.sessionId;\r\n },\r\n []\r\n );\r\n\r\n /**\r\n * Disconnect from an MCP server\r\n */\r\n const disconnect = useCallback(async (sessionId: string): Promise<void> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n await clientRef.current.disconnectFromServer(sessionId);\r\n\r\n // Remove from local state\r\n if (isMountedRef.current) {\r\n setConnections((prev: McpConnection[]) => prev.filter((c: McpConnection) => c.sessionId !== sessionId));\r\n }\r\n }, []);\r\n\r\n /**\r\n * Refresh all connections\r\n */\r\n const refresh = useCallback(async () => {\r\n await loadSessions();\r\n }, [loadSessions]);\r\n\r\n /**\r\n * Manually connect SSE\r\n */\r\n const connectSSE = useCallback(() => {\r\n clientRef.current?.connect();\r\n }, []);\r\n\r\n /**\r\n * Manually disconnect SSE\r\n */\r\n const disconnectSSE = useCallback(() => {\r\n clientRef.current?.disconnect();\r\n }, []);\r\n\r\n /**\r\n * Complete OAuth authorization\r\n */\r\n const finishAuth = useCallback(async (sessionId: string, code: string): Promise<FinishAuthResult> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n return await clientRef.current.finishAuth(sessionId, code);\r\n }, []);\r\n\r\n /**\r\n * Call a tool\r\n */\r\n const callTool = useCallback(\r\n async (\r\n sessionId: string,\r\n toolName: string,\r\n toolArgs: Record<string, unknown>\r\n ): Promise<unknown> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n return await clientRef.current.callTool(sessionId, toolName, toolArgs);\r\n },\r\n []\r\n );\r\n\r\n /**\r\n * List tools (refresh tool list)\r\n */\r\n const listTools = useCallback(async (sessionId: string): Promise<ListToolsRpcResult> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n return await clientRef.current.listTools(sessionId);\r\n }, []);\r\n\r\n /**\r\n * List prompts\r\n */\r\n const listPrompts = useCallback(async (sessionId: string): Promise<ListPromptsResult> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n return await clientRef.current.listPrompts(sessionId);\r\n }, []);\r\n\r\n /**\r\n * Get a specific prompt\r\n */\r\n const getPrompt = useCallback(\r\n async (sessionId: string, name: string, args?: Record<string, string>): Promise<unknown> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n return await clientRef.current.getPrompt(sessionId, name, args);\r\n },\r\n []\r\n );\r\n\r\n /**\r\n * List resources\r\n */\r\n const listResources = useCallback(async (sessionId: string): Promise<ListResourcesResult> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n return await clientRef.current.listResources(sessionId);\r\n }, []);\r\n\r\n /**\r\n * Read a specific resource\r\n */\r\n const readResource = useCallback(async (sessionId: string, uri: string): Promise<unknown> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n return await clientRef.current.readResource(sessionId, uri);\r\n }, []);\r\n\r\n // Utility functions\r\n const getConnection = useCallback(\r\n (sessionId: string) => connections.find((c: McpConnection) => c.sessionId === sessionId),\r\n [connections]\r\n );\r\n\r\n const getConnectionByServerId = useCallback(\r\n (serverId: string) => connections.find((c: McpConnection) => c.serverId === serverId),\r\n [connections]\r\n );\r\n\r\n const isServerConnected = useCallback(\r\n (serverId: string) => {\r\n const conn = getConnectionByServerId(serverId);\r\n return conn?.state === 'CONNECTED';\r\n },\r\n [getConnectionByServerId]\r\n );\r\n\r\n const getTools = useCallback(\r\n (sessionId: string) => {\r\n const conn = getConnection(sessionId);\r\n return conn?.tools || [];\r\n },\r\n [getConnection]\r\n );\r\n\r\n return {\r\n connections,\r\n status,\r\n isInitializing,\r\n connect,\r\n disconnect,\r\n getConnection,\r\n getConnectionByServerId,\r\n isServerConnected,\r\n getTools,\r\n refresh,\r\n connectSSE,\r\n disconnectSSE,\r\n finishAuth,\r\n callTool,\r\n listTools,\r\n listPrompts,\r\n getPrompt,\r\n listResources,\r\n readResource,\r\n sseClient: clientRef.current,\r\n };\r\n}\r\n","/**\r\n * MCP App Host\r\n *\r\n * Bridges the gap between an iframe (MCP App) and the SSEClient (MCP Server).\r\n * Handles secure iframe sandboxing, resource loading, and bi-directional\r\n * communication via the AppBridge protocol.\r\n *\r\n * Key features:\r\n * - Secure iframe sandboxing with minimal permissions\r\n * - Resource preloading for instant MCP App UI loading\r\n * - Cache-aware resource fetching (SSEClient cache → local cache → direct fetch)\r\n * - Support for ui:// and mcp-app:// resource URIs\r\n */\r\n\r\nimport { AppBridge, PostMessageTransport } from '@modelcontextprotocol/ext-apps/app-bridge';\r\nimport type { AppHostClient } from './types';\r\n\r\n// ============================================\r\n// Types & Interfaces\r\n// ============================================\r\n\r\nexport interface AppHostOptions {\r\n /** Enable debug logging @default false */\r\n debug?: boolean;\r\n}\r\n\r\nexport interface AppMessageParams {\r\n role: string;\r\n content: unknown;\r\n}\r\n\r\ninterface ToolCallParams {\r\n name: string;\r\n arguments?: Record<string, unknown>;\r\n}\r\n\r\ninterface ResourceContent {\r\n blob?: string;\r\n text?: string;\r\n}\r\n\r\ninterface ResourceResponse {\r\n contents: ResourceContent[];\r\n}\r\n\r\n// ============================================\r\n// Constants\r\n// ============================================\r\n\r\nconst HOST_INFO = { name: 'mcp-ts-host', version: '1.0.0' };\r\n\r\n/** Sandbox permissions - minimal set required for MCP Apps to function */\r\nconst SANDBOX_PERMISSIONS = [\r\n 'allow-scripts', // Required for app JavaScript execution\r\n 'allow-forms', // Required for form submissions\r\n 'allow-same-origin', // Required for Blob URL correctness\r\n 'allow-modals', // Required for dialogs/alerts\r\n 'allow-popups', // Required for opening links\r\n 'allow-downloads' // Required for file downloads\r\n].join(' ');\r\n\r\n/** Supported MCP App URI schemes */\r\nconst MCP_URI_SCHEMES = ['ui://', 'mcp-app://'] as const;\r\n\r\n// ============================================\r\n// AppHost Class\r\n// ============================================\r\n\r\n/**\r\n * Host for MCP Apps embedded in iframes.\r\n * Manages secure communication between the app and the MCP server.\r\n */\r\nexport class AppHost {\r\n private bridge: AppBridge;\r\n private sessionId?: string;\r\n private resourceCache = new Map<string, Promise<ResourceResponse | null>>();\r\n private debug: boolean;\r\n\r\n /** Callback for app messages (e.g., chat messages from the app) */\r\n public onAppMessage?: (params: AppMessageParams) => void;\r\n\r\n constructor(\r\n private readonly client: AppHostClient,\r\n private readonly iframe: HTMLIFrameElement,\r\n options?: AppHostOptions\r\n ) {\r\n this.debug = options?.debug ?? false;\r\n this.configureSandbox();\r\n this.bridge = this.initializeBridge();\r\n }\r\n\r\n // ============================================\r\n // Public API\r\n // ============================================\r\n\r\n /**\r\n * Start the host. This prepares the bridge handlers but doesn't connect yet.\r\n * The actual connection happens in launch() after HTML is loaded.\r\n * @returns Promise that resolves immediately (bridge connects during launch)\r\n */\r\n async start(): Promise<void> {\r\n // Bridge handlers are already registered in constructor.\r\n // Connection happens in launch() after HTML is loaded.\r\n this.log('Host started, ready to launch');\r\n }\r\n\r\n /**\r\n * Preload UI resources to enable instant app loading.\r\n * Call this when tools are discovered to cache their UI resources.\r\n */\r\n preload(tools: Array<{ _meta?: unknown }>): void {\r\n for (const tool of tools) {\r\n const uri = this.extractUiResourceUri(tool);\r\n if (!uri || this.resourceCache.has(uri)) continue;\r\n\r\n const promise = this.preloadResource(uri);\r\n this.resourceCache.set(uri, promise);\r\n }\r\n }\r\n\r\n /**\r\n * Launch an MCP App from a URL or MCP resource URI.\r\n * Loads the HTML first, then establishes bridge connection.\r\n */\r\n async launch(url: string, sessionId?: string): Promise<void> {\r\n if (sessionId) this.sessionId = sessionId;\r\n\r\n // Set up initialization promise BEFORE connecting\r\n const initializedPromise = this.onAppReady();\r\n\r\n // Load HTML into iframe first\r\n if (this.isMcpUri(url)) {\r\n await this.launchMcpApp(url);\r\n } else {\r\n this.iframe.src = url;\r\n }\r\n\r\n // Wait for iframe to load before connecting bridge\r\n await this.onIframeReady();\r\n\r\n // Connect the bridge (HTML is loaded, contentWindow is ready)\r\n await this.connectBridge();\r\n\r\n // Wait for app to signal it's initialized (with timeout)\r\n this.log('Waiting for app initialization');\r\n await Promise.race([\r\n initializedPromise,\r\n new Promise<void>((resolve) => setTimeout(() => {\r\n this.log('Initialization timeout - continuing anyway', 'warn');\r\n resolve();\r\n }, 3000))\r\n ]);\r\n this.log('App launched and ready');\r\n }\r\n\r\n /**\r\n * Wait for app to signal initialization complete\r\n */\r\n private onAppReady(): Promise<void> {\r\n return new Promise<void>((resolve) => {\r\n const originalHandler = this.bridge.oninitialized;\r\n this.bridge.oninitialized = (...args) => {\r\n this.log('App initialized');\r\n resolve();\r\n this.bridge.oninitialized = originalHandler;\r\n originalHandler?.(...args);\r\n };\r\n });\r\n }\r\n\r\n /**\r\n * Wait for iframe to finish loading\r\n */\r\n private onIframeReady(): Promise<void> {\r\n return new Promise((resolve) => {\r\n if (this.iframe.contentDocument?.readyState === 'complete') {\r\n resolve();\r\n return;\r\n }\r\n this.iframe.addEventListener('load', () => resolve(), { once: true });\r\n });\r\n }\r\n\r\n /**\r\n * Send tool input arguments to the MCP App.\r\n * Call this after launch() when tool input is available.\r\n */\r\n sendToolInput(args: Record<string, unknown>): void {\r\n this.log('Sending tool input to app');\r\n this.bridge.sendToolInput({ arguments: args });\r\n }\r\n\r\n /**\r\n * Send tool result to the MCP App.\r\n * Call this when the tool call completes.\r\n */\r\n sendToolResult(result: unknown): void {\r\n this.log('Sending tool result to app');\r\n this.bridge.sendToolResult(result as any);\r\n }\r\n\r\n /**\r\n * Send tool cancellation to the MCP App.\r\n * Call this when the tool call is cancelled or fails.\r\n */\r\n sendToolCancelled(reason: string): void {\r\n this.log('Sending tool cancellation to app');\r\n this.bridge.sendToolCancelled({ reason });\r\n }\r\n\r\n // ============================================\r\n // Private: Initialization\r\n // ============================================\r\n\r\n private configureSandbox(): void {\r\n if (this.iframe.sandbox.value !== SANDBOX_PERMISSIONS) {\r\n this.iframe.sandbox.value = SANDBOX_PERMISSIONS;\r\n }\r\n }\r\n\r\n private initializeBridge(): AppBridge {\r\n const bridge = new AppBridge(\r\n null,\r\n HOST_INFO,\r\n {\r\n openLinks: {},\r\n serverTools: {},\r\n logging: {},\r\n // Declare support for model context updates\r\n updateModelContext: { text: {} },\r\n },\r\n {\r\n // Initial host context\r\n hostContext: {\r\n theme: 'dark',\r\n platform: 'web',\r\n containerDimensions: { maxHeight: 6000 },\r\n displayMode: 'inline',\r\n availableDisplayModes: ['inline', 'fullscreen'],\r\n },\r\n }\r\n );\r\n\r\n // Register handlers - must be done BEFORE connect()\r\n bridge.oncalltool = (params) => this.handleToolCall(params);\r\n bridge.onopenlink = this.handleOpenLink.bind(this);\r\n bridge.onmessage = this.handleMessage.bind(this);\r\n bridge.onloggingmessage = (params) => this.log(`App log [${params.level}]: ${params.data}`);\r\n bridge.onupdatemodelcontext = async () => ({});\r\n bridge.onsizechange = async ({ width, height }) => {\r\n if (height !== undefined) this.iframe.style.height = `${height}px`;\r\n if (width !== undefined) this.iframe.style.minWidth = `min(${width}px, 100%)`;\r\n return {};\r\n };\r\n bridge.onrequestdisplaymode = async (params) => ({\r\n mode: params.mode === 'fullscreen' ? 'fullscreen' : 'inline'\r\n });\r\n\r\n return bridge;\r\n }\r\n\r\n private async connectBridge(): Promise<void> {\r\n this.log('Connecting bridge to iframe');\r\n\r\n const transport = new PostMessageTransport(\r\n this.iframe.contentWindow!,\r\n this.iframe.contentWindow!\r\n );\r\n\r\n try {\r\n await this.bridge.connect(transport);\r\n this.log('Bridge connected successfully');\r\n } catch (error) {\r\n this.log('Bridge connection failed', 'error');\r\n throw error;\r\n }\r\n }\r\n\r\n // ============================================\r\n // Private: Bridge Event Handlers\r\n // ============================================\r\n\r\n private async handleToolCall(params: ToolCallParams) {\r\n if (!this.client.isConnected()) {\r\n throw new Error('Client disconnected');\r\n }\r\n\r\n const sessionId = await this.getSessionId();\r\n if (!sessionId) {\r\n throw new Error('No active session');\r\n }\r\n\r\n const result = await this.client.callTool(\r\n sessionId,\r\n params.name,\r\n params.arguments ?? {}\r\n );\r\n return result as any;\r\n }\r\n\r\n private async handleOpenLink(params: { url: string }): Promise<Record<string, never>> {\r\n window.open(params.url, '_blank', 'noopener,noreferrer');\r\n return {};\r\n }\r\n\r\n private async handleMessage(params: AppMessageParams): Promise<Record<string, never>> {\r\n this.onAppMessage?.(params);\r\n return {};\r\n }\r\n\r\n // ============================================\r\n // Private: Resource Loading\r\n // ============================================\r\n\r\n private async launchMcpApp(uri: string): Promise<void> {\r\n if (!this.client.isConnected()) {\r\n throw new Error('Client must be connected');\r\n }\r\n\r\n const sessionId = await this.getSessionId();\r\n if (!sessionId) {\r\n throw new Error('No active session');\r\n }\r\n\r\n // Fetch resource using cache hierarchy: SSEClient cache → local cache → direct fetch\r\n const response = await this.fetchResourceWithCache(sessionId, uri);\r\n if (!response?.contents?.length) {\r\n throw new Error(`Empty resource: ${uri}`);\r\n }\r\n\r\n const content = response.contents[0];\r\n const html = this.decodeContent(content);\r\n if (!html) {\r\n throw new Error(`Invalid content in resource: ${uri}`);\r\n }\r\n\r\n // Render via Blob URL for clean isolation\r\n const blob = new Blob([html], { type: 'text/html' });\r\n this.iframe.src = URL.createObjectURL(blob);\r\n }\r\n\r\n private async fetchResourceWithCache(sessionId: string, uri: string): Promise<ResourceResponse> {\r\n // Priority 1: SSEClient's built-in cache (best performance)\r\n if (this.hasClientCache()) {\r\n return (this.client as any).getOrFetchResource(sessionId, uri);\r\n }\r\n\r\n // Priority 2: Local preload cache\r\n const cached = this.resourceCache.get(uri);\r\n if (cached) {\r\n const result = await cached;\r\n if (result) return result;\r\n }\r\n\r\n // Priority 3: Direct fetch\r\n return this.client.readResource(sessionId, uri) as Promise<ResourceResponse>;\r\n }\r\n\r\n private async preloadResource(uri: string): Promise<ResourceResponse | null> {\r\n try {\r\n const sessionId = await this.getSessionId();\r\n if (!sessionId) return null;\r\n return await this.client.readResource(sessionId, uri) as ResourceResponse;\r\n } catch (error) {\r\n this.log(`Preload failed for ${uri}`, 'warn');\r\n return null;\r\n }\r\n }\r\n\r\n // ============================================\r\n // Private: Utilities\r\n // ============================================\r\n\r\n private async getSessionId(): Promise<string | undefined> {\r\n if (this.sessionId) return this.sessionId;\r\n const result = await this.client.getSessions();\r\n return result.sessions?.[0]?.sessionId;\r\n }\r\n\r\n private isMcpUri(url: string): boolean {\r\n return MCP_URI_SCHEMES.some(scheme => url.startsWith(scheme));\r\n }\r\n\r\n private hasClientCache(): boolean {\r\n return 'getOrFetchResource' in this.client &&\r\n typeof (this.client as any).getOrFetchResource === 'function';\r\n }\r\n\r\n private extractUiResourceUri(tool: { _meta?: unknown }): string | undefined {\r\n const meta = tool._meta as { ui?: { resourceUri?: string; uri?: string } } | undefined;\r\n if (!meta?.ui) return undefined;\r\n return meta.ui.resourceUri ?? meta.ui.uri;\r\n }\r\n\r\n private decodeContent(content: ResourceContent): string | undefined {\r\n if (content.blob) {\r\n return atob(content.blob);\r\n }\r\n return content.text;\r\n }\r\n\r\n private log(message: string, level: 'info' | 'warn' | 'error' = 'info'): void {\r\n if (!this.debug && level === 'info') return;\r\n\r\n const prefix = '[AppHost]';\r\n switch (level) {\r\n case 'warn':\r\n console.warn(prefix, message);\r\n break;\r\n case 'error':\r\n console.error(prefix, message);\r\n break;\r\n default:\r\n console.log(prefix, message);\r\n }\r\n }\r\n}\r\n","import { useEffect, useRef, useState, useCallback } from 'react';\r\nimport type { SSEClient } from '../core/sse-client';\r\nimport { AppHost } from '../core/app-host';\r\n\r\n/**\r\n * Hook to host an MCP App in a React component\r\n *\r\n * Optimized for instant loading:\r\n * - Creates AppHost synchronously\r\n * - Starts bridge connection immediately\r\n * - Returns host before connection completes (ready to call launch)\r\n *\r\n * @param client - Connected SSEClient instance\r\n * @param iframeRef - Reference to the iframe element\r\n * @param options - Optional configuration\r\n * @returns Object containing the AppHost instance (or null) and error state\r\n */\r\nexport function useAppHost(\r\n client: SSEClient,\r\n iframeRef: React.RefObject<HTMLIFrameElement>,\r\n options?: {\r\n /** Callback when the App sends a message (e.g. to chat) */\r\n onMessage?: (params: { role: string; content: unknown }) => void;\r\n }\r\n) {\r\n const [host, setHost] = useState<AppHost | null>(null);\r\n const [error, setError] = useState<Error | null>(null);\r\n const initializingRef = useRef(false);\r\n\r\n // Store latest callback in ref to avoid re-initializing AppHost on callback change\r\n const onMessageRef = useRef(options?.onMessage);\r\n useEffect(() => {\r\n onMessageRef.current = options?.onMessage;\r\n }, [options?.onMessage]);\r\n\r\n useEffect(() => {\r\n if (!client || !iframeRef.current || initializingRef.current) return;\r\n\r\n // Prevent double initialization in strict mode\r\n initializingRef.current = true;\r\n\r\n const initHost = async () => {\r\n try {\r\n // Initialize AppHost with security enforcement\r\n const appHost = new AppHost(client, iframeRef.current!);\r\n\r\n // Register message handler\r\n appHost.onAppMessage = (params) => {\r\n onMessageRef.current?.(params);\r\n };\r\n\r\n // Set host immediately so launch can be called\r\n // (launch will wait for bridge if needed)\r\n setHost(appHost);\r\n\r\n // Start bridge connection (this is fast, just sets up PostMessage)\r\n await appHost.start();\r\n } catch (err) {\r\n console.error('[useAppHost] Failed to initialize AppHost:', err);\r\n setError(err instanceof Error ? err : new Error(String(err)));\r\n }\r\n };\r\n\r\n initHost();\r\n\r\n return () => {\r\n initializingRef.current = false;\r\n setHost(null);\r\n };\r\n }, [client, iframeRef]);\r\n\r\n return { host, error };\r\n}\r\n","/**\n * Simplified MCP Apps Hook - Fixed for no flickering\n *\n * The key insight: React component identity must be stable.\n * We return a stable McpAppRenderer component and separate metadata lookup.\n */\n\nimport React, { useState, useEffect, useCallback, useRef, memo } from 'react';\nimport { useAppHost } from './use-app-host.js';\nimport type { SSEClient } from '../core/sse-client.js';\n\nexport interface McpClient {\n connections: Array<{\n sessionId: string;\n tools: Array<{\n name: string;\n mcpApp?: {\n resourceUri: string;\n };\n _meta?: {\n ui?: {\n resourceUri?: string;\n };\n 'ui/resourceUri'?: string;\n };\n }>;\n }>;\n sseClient?: SSEClient | null;\n}\n\nexport interface McpAppMetadata {\n toolName: string;\n resourceUri: string;\n sessionId: string;\n}\n\ninterface McpAppRendererProps {\n metadata: McpAppMetadata;\n input?: Record<string, unknown>;\n result?: unknown;\n status: 'executing' | 'inProgress' | 'complete' | 'idle';\n sseClient?: SSEClient | null;\n}\n\n/**\n * Stable renderer component - memoized to prevent flickering\n * Uses refs to track data changes and send updates to the iframe\n */\nconst McpAppRenderer = memo(function McpAppRenderer({\n metadata,\n input,\n result,\n status,\n sseClient,\n}: McpAppRendererProps) {\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const { host, error: hostError } = useAppHost(sseClient as SSEClient, iframeRef);\n const [isLaunched, setIsLaunched] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n // Track which data has been sent to prevent duplicates\n const sentInputRef = useRef(false);\n const sentResultRef = useRef(false);\n const lastInputRef = useRef(input);\n const lastResultRef = useRef(result);\n const lastStatusRef = useRef(status);\n\n // Launch the app when host is ready\n useEffect(() => {\n if (!host || !metadata.resourceUri || !metadata.sessionId) return;\n\n host\n .launch(metadata.resourceUri, metadata.sessionId)\n .then(() => setIsLaunched(true))\n .catch((err) => setError(err instanceof Error ? err : new Error(String(err))));\n }, [host, metadata.resourceUri, metadata.sessionId]);\n\n // Send tool input when available or when it changes\n useEffect(() => {\n if (!host || !isLaunched || !input) return;\n \n // Send if never sent, or if input changed\n if (!sentInputRef.current || JSON.stringify(input) !== JSON.stringify(lastInputRef.current)) {\n sentInputRef.current = true;\n lastInputRef.current = input;\n host.sendToolInput(input);\n }\n }, [host, isLaunched, input]);\n\n // Send tool result when complete or when it changes\n useEffect(() => {\n if (!host || !isLaunched || result === undefined) return;\n if (status !== 'complete') return;\n\n // Send if never sent, or if result changed\n if (!sentResultRef.current || JSON.stringify(result) !== JSON.stringify(lastResultRef.current)) {\n sentResultRef.current = true;\n lastResultRef.current = result;\n const formattedResult =\n typeof result === 'string'\n ? { content: [{ type: 'text', text: result }] }\n : result;\n host.sendToolResult(formattedResult);\n }\n }, [host, isLaunched, result, status]);\n\n // Reset sent flags when tool status resets to executing (new tool call)\n useEffect(() => {\n if (status === 'executing' && lastStatusRef.current !== 'executing') {\n sentInputRef.current = false;\n sentResultRef.current = false;\n }\n lastStatusRef.current = status;\n }, [status]);\n\n // Display errors\n const displayError = error || hostError;\n if (displayError) {\n return (\n <div className=\"p-4 bg-red-900/20 border border-red-700 rounded text-red-200\">\n Error: {displayError.message || String(displayError)}\n </div>\n );\n }\n\n return (\n <div className=\"w-full border border-gray-700 rounded overflow-hidden bg-white min-h-96 my-2 relative\">\n <iframe\n ref={iframeRef}\n sandbox=\"allow-scripts allow-same-origin allow-forms allow-modals allow-popups allow-downloads\"\n className=\"w-full h-full min-h-96\"\n style={{ height: 'auto' }}\n title=\"MCP App\"\n />\n {!isLaunched && (\n <div className=\"absolute inset-0 bg-gray-900/50 flex items-center justify-center pointer-events-none\">\n <div className=\"w-6 h-6 border-2 border-blue-500 border-t-transparent rounded-full animate-spin\" />\n </div>\n )}\n </div>\n );\n});\n\n/**\n * Simple hook to get MCP app metadata\n *\n * @param mcpClient - The MCP client from useMcp() or context\n * @returns Object with getAppMetadata function and McpAppRenderer component\n *\n * @example\n * ```tsx\n * function ToolRenderer(props) {\n * const { getAppMetadata, McpAppRenderer } = useMcpApps(mcpClient);\n * const metadata = getAppMetadata(props.name);\n *\n * if (!metadata) return null;\n * return (\n * <McpAppRenderer\n * metadata={metadata}\n * input={props.args}\n * result={props.result}\n * status={props.status}\n * />\n * );\n * }\n * ```\n */\nexport function useMcpApps(mcpClient: McpClient | null) {\n /**\n * Get MCP app metadata for a tool name\n * This is fast and can be called on every render\n */\n const getAppMetadata = useCallback(\n (toolName: string): McpAppMetadata | undefined => {\n if (!mcpClient) return undefined;\n\n const extractedName = extractToolName(toolName);\n\n for (const conn of mcpClient.connections) {\n for (const tool of conn.tools) {\n const candidateName = extractToolName(tool.name);\n // Check both locations: direct mcpApp or _meta.ui\n const resourceUri =\n tool.mcpApp?.resourceUri ??\n tool._meta?.ui?.resourceUri ??\n tool._meta?.['ui/resourceUri'];\n\n if (resourceUri && candidateName === extractedName) {\n return {\n toolName: candidateName,\n resourceUri,\n sessionId: conn.sessionId,\n };\n }\n }\n }\n\n return undefined;\n },\n [mcpClient]\n );\n\n return { getAppMetadata, McpAppRenderer };\n}\n\n/**\n * Extract the base tool name, removing any prefixes\n */\nfunction extractToolName(fullName: string): string {\n // Handle patterns like \"tool_abc123_get-time\" -> \"get-time\"\n const match = fullName.match(/(?:tool_[^_]+_)?(.+)$/);\n return match?.[1] || fullName;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/client/core/sse-client.ts","../../src/client/react/use-mcp.ts","../../src/client/core/app-host.ts","../../src/client/react/use-app-host.ts","../../src/client/react/use-mcp-apps.tsx"],"names":["useState","useRef","useEffect","McpAppRenderer","useCallback"],"mappings":"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","file":"react.mjs","sourcesContent":["/**\r\n * SSE Client for MCP Connections\r\n *\r\n * Browser-side client that manages real-time communication with the MCP server\r\n * using Server-Sent Events (SSE) for server→client streaming and HTTP POST for\r\n * client→server RPC requests.\r\n *\r\n * Key features:\r\n * - Direct HTTP response for RPC calls (bypasses SSE latency)\r\n * - Resource preloading for instant MCP App UI loading\r\n * - Automatic reconnection with exponential backoff\r\n * - Type-safe RPC methods\r\n */\r\n\r\nimport { nanoid } from 'nanoid';\r\nimport type {\r\n McpConnectionEvent,\r\n McpObservabilityEvent,\r\n McpAppsUIEvent\r\n} from '../../shared/events.js';\r\nimport type {\r\n McpRpcRequest,\r\n McpRpcResponse,\r\n McpRpcMethod,\r\n McpRpcParams,\r\n ConnectParams,\r\n SessionListResult,\r\n ConnectResult,\r\n DisconnectResult,\r\n RestoreSessionResult,\r\n FinishAuthResult,\r\n ListToolsRpcResult,\r\n ListPromptsResult,\r\n ListResourcesResult,\r\n} from '../../shared/types.js';\r\n// ============================================\r\n// Types & Interfaces\r\n// ============================================\r\n\r\nexport interface SSEClientOptions {\r\n /** SSE endpoint URL */\r\n url: string;\r\n\r\n /** User/Client identifier */\r\n identity: string;\r\n\r\n /** Optional auth token for authenticated requests */\r\n authToken?: string;\r\n\r\n /** Callback for MCP connection state changes */\r\n onConnectionEvent?: (event: McpConnectionEvent) => void;\r\n\r\n /** Callback for observability/logging events */\r\n onObservabilityEvent?: (event: McpObservabilityEvent) => void;\r\n\r\n /** Callback for connection status changes */\r\n onStatusChange?: (status: ConnectionStatus) => void;\r\n\r\n /** Callback for MCP App UI events */\r\n onEvent?: (event: McpAppsUIEvent) => void;\r\n\r\n /** Request timeout in milliseconds @default 60000 */\r\n requestTimeout?: number;\r\n\r\n /** Enable debug logging @default false */\r\n debug?: boolean;\r\n}\r\n\r\nexport type ConnectionStatus = 'connecting' | 'connected' | 'disconnected' | 'error';\r\n\r\ninterface PendingRequest {\r\n resolve: (value: unknown) => void;\r\n reject: (error: Error) => void;\r\n timeoutId: ReturnType<typeof setTimeout>;\r\n}\r\n\r\ninterface ToolUiMetadata {\r\n resourceUri?: string;\r\n uri?: string;\r\n visibility?: string[];\r\n}\r\n\r\n// ============================================\r\n// Constants\r\n// ============================================\r\n\r\nconst DEFAULT_REQUEST_TIMEOUT = 60000;\r\nconst MAX_RECONNECT_ATTEMPTS = 5;\r\nconst BASE_RECONNECT_DELAY = 1000;\r\n\r\n// ============================================\r\n// SSEClient Class\r\n// ============================================\r\n\r\n/**\r\n * SSE Client for real-time MCP connection management\r\n */\r\nexport class SSEClient {\r\n private eventSource: EventSource | null = null;\r\n private pendingRequests = new Map<string, PendingRequest>();\r\n private resourceCache = new Map<string, Promise<unknown>>();\r\n\r\n private reconnectAttempts = 0;\r\n private isManuallyDisconnected = false;\r\n private connectionPromise: Promise<void> | null = null;\r\n private connectionResolver: (() => void) | null = null;\r\n\r\n constructor(private readonly options: SSEClientOptions) {}\r\n\r\n // ============================================\r\n // Connection Management\r\n // ============================================\r\n\r\n /**\r\n * Connect to the SSE endpoint\r\n */\r\n connect(): void {\r\n if (this.eventSource) {\r\n return; // Already connected\r\n }\r\n\r\n this.isManuallyDisconnected = false;\r\n this.options.onStatusChange?.('connecting');\r\n this.connectionPromise = new Promise((resolve) => {\r\n this.connectionResolver = resolve;\r\n });\r\n\r\n const url = this.buildUrl();\r\n this.eventSource = new EventSource(url);\r\n this.setupEventListeners();\r\n }\r\n\r\n /**\r\n * Disconnect from the SSE endpoint\r\n */\r\n disconnect(): void {\r\n this.isManuallyDisconnected = true;\r\n\r\n if (this.eventSource) {\r\n this.eventSource.close();\r\n this.eventSource = null;\r\n }\r\n\r\n this.connectionPromise = null;\r\n this.connectionResolver = null;\r\n this.rejectAllPendingRequests(new Error('Connection closed'));\r\n this.options.onStatusChange?.('disconnected');\r\n }\r\n\r\n /**\r\n * Check if connected to the SSE endpoint\r\n */\r\n isConnected(): boolean {\r\n return this.eventSource?.readyState === EventSource.OPEN;\r\n }\r\n\r\n // ============================================\r\n // RPC Methods\r\n // ============================================\r\n\r\n async getSessions(): Promise<SessionListResult> {\r\n return this.sendRequest<SessionListResult>('getSessions');\r\n }\r\n\r\n async connectToServer(params: ConnectParams): Promise<ConnectResult> {\r\n return this.sendRequest<ConnectResult>('connect', params);\r\n }\r\n\r\n async disconnectFromServer(sessionId: string): Promise<DisconnectResult> {\r\n return this.sendRequest<DisconnectResult>('disconnect', { sessionId });\r\n }\r\n\r\n async listTools(sessionId: string): Promise<ListToolsRpcResult> {\r\n return this.sendRequest<ListToolsRpcResult>('listTools', { sessionId });\r\n }\r\n\r\n async callTool(\r\n sessionId: string,\r\n toolName: string,\r\n toolArgs: Record<string, unknown>\r\n ): Promise<unknown> {\r\n const result = await this.sendRequest('callTool', { sessionId, toolName, toolArgs });\r\n this.emitUiEventIfPresent(result, sessionId, toolName);\r\n return result;\r\n }\r\n\r\n async restoreSession(sessionId: string): Promise<RestoreSessionResult> {\r\n return this.sendRequest<RestoreSessionResult>('restoreSession', { sessionId });\r\n }\r\n\r\n async finishAuth(sessionId: string, code: string): Promise<FinishAuthResult> {\r\n return this.sendRequest<FinishAuthResult>('finishAuth', { sessionId, code });\r\n }\r\n\r\n async listPrompts(sessionId: string): Promise<ListPromptsResult> {\r\n return this.sendRequest<ListPromptsResult>('listPrompts', { sessionId });\r\n }\r\n\r\n async getPrompt(sessionId: string, name: string, args?: Record<string, string>): Promise<unknown> {\r\n return this.sendRequest('getPrompt', { sessionId, name, args });\r\n }\r\n\r\n async listResources(sessionId: string): Promise<ListResourcesResult> {\r\n return this.sendRequest<ListResourcesResult>('listResources', { sessionId });\r\n }\r\n\r\n async readResource(sessionId: string, uri: string): Promise<unknown> {\r\n return this.sendRequest('readResource', { sessionId, uri });\r\n }\r\n\r\n // ============================================\r\n // Resource Preloading (for instant UI loading)\r\n // ============================================\r\n\r\n /**\r\n * Preload UI resources for tools that have UI metadata.\r\n * Call this when tools are discovered to enable instant MCP App UI loading.\r\n */\r\n preloadToolUiResources(sessionId: string, tools: Array<{ name: string; _meta?: unknown }>): void {\r\n for (const tool of tools) {\r\n const uri = this.extractUiResourceUri(tool);\r\n if (!uri) continue;\r\n\r\n if (this.resourceCache.has(uri)) {\r\n this.log(`Resource already cached: ${uri}`);\r\n continue;\r\n }\r\n\r\n this.log(`Preloading UI resource for tool \"${tool.name}\": ${uri}`);\r\n const promise = this.sendRequest('readResource', { sessionId, uri })\r\n .catch((err) => {\r\n this.log(`Failed to preload resource ${uri}: ${err.message}`, 'warn');\r\n this.resourceCache.delete(uri);\r\n return null;\r\n });\r\n\r\n this.resourceCache.set(uri, promise);\r\n }\r\n }\r\n\r\n /**\r\n * Get a preloaded resource from cache, or fetch if not cached.\r\n */\r\n getOrFetchResource(sessionId: string, uri: string): Promise<unknown> {\r\n const cached = this.resourceCache.get(uri);\r\n if (cached) {\r\n this.log(`Cache hit for resource: ${uri}`);\r\n return cached;\r\n }\r\n\r\n this.log(`Cache miss, fetching resource: ${uri}`);\r\n const promise = this.sendRequest('readResource', { sessionId, uri });\r\n this.resourceCache.set(uri, promise);\r\n return promise;\r\n }\r\n\r\n /**\r\n * Check if a resource is already cached\r\n */\r\n hasPreloadedResource(uri: string): boolean {\r\n return this.resourceCache.has(uri);\r\n }\r\n\r\n /**\r\n * Clear the resource cache\r\n */\r\n clearResourceCache(): void {\r\n this.resourceCache.clear();\r\n }\r\n\r\n // ============================================\r\n // Private: Request Handling\r\n // ============================================\r\n\r\n /**\r\n * Send an RPC request and return the response directly from HTTP.\r\n * This bypasses SSE latency by returning results in the HTTP response body.\r\n */\r\n private async sendRequest<T = unknown>(method: McpRpcMethod, params?: McpRpcParams): Promise<T> {\r\n if (this.connectionPromise) {\r\n await this.connectionPromise;\r\n }\r\n\r\n const request: McpRpcRequest = {\r\n id: `rpc_${nanoid(10)}`,\r\n method,\r\n params,\r\n };\r\n\r\n const response = await fetch(this.buildUrl(), {\r\n method: 'POST',\r\n headers: this.buildHeaders(),\r\n body: JSON.stringify(request),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\r\n }\r\n\r\n const data = await response.json() as McpRpcResponse;\r\n return this.parseRpcResponse<T>(data, request.id);\r\n }\r\n\r\n /**\r\n * Parse RPC response and handle different response formats\r\n */\r\n private parseRpcResponse<T>(data: McpRpcResponse, requestId: string): T | Promise<T> {\r\n // Fast path: Direct response (new behavior)\r\n if ('result' in data) {\r\n return data.result as T;\r\n }\r\n\r\n // Error response\r\n if ('error' in data && data.error) {\r\n throw new Error(data.error.message || 'Unknown RPC error');\r\n }\r\n\r\n // Legacy path: Acknowledgment only (wait for SSE)\r\n // Kept for backwards compatibility with older servers\r\n if ('acknowledged' in data) {\r\n return this.waitForSseResponse<T>(requestId);\r\n }\r\n\r\n throw new Error('Invalid RPC response format');\r\n }\r\n\r\n /**\r\n * Wait for RPC response via SSE (legacy fallback)\r\n */\r\n private waitForSseResponse<T>(requestId: string): Promise<T> {\r\n const timeoutMs = this.options.requestTimeout ?? DEFAULT_REQUEST_TIMEOUT;\r\n\r\n return new Promise<T>((resolve, reject) => {\r\n const timeoutId = setTimeout(() => {\r\n this.pendingRequests.delete(requestId);\r\n reject(new Error(`Request timeout after ${timeoutMs}ms`));\r\n }, timeoutMs);\r\n\r\n this.pendingRequests.set(requestId, {\r\n resolve: resolve as (value: unknown) => void,\r\n reject,\r\n timeoutId,\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Handle RPC response received via SSE (legacy)\r\n */\r\n private handleRpcResponse(response: McpRpcResponse): void {\r\n const pending = this.pendingRequests.get(response.id);\r\n if (!pending) return;\r\n\r\n clearTimeout(pending.timeoutId);\r\n this.pendingRequests.delete(response.id);\r\n\r\n if (response.error) {\r\n pending.reject(new Error(response.error.message));\r\n } else {\r\n pending.resolve(response.result);\r\n }\r\n }\r\n\r\n // ============================================\r\n // Private: Event Handling\r\n // ============================================\r\n\r\n private setupEventListeners(): void {\r\n if (!this.eventSource) return;\r\n\r\n this.eventSource.addEventListener('open', () => {\r\n this.log('Connected');\r\n this.reconnectAttempts = 0;\r\n this.options.onStatusChange?.('connected');\r\n });\r\n\r\n this.eventSource.addEventListener('connected', () => {\r\n this.log('Server ready');\r\n this.connectionResolver?.();\r\n this.connectionResolver = null;\r\n });\r\n\r\n this.eventSource.addEventListener('connection', (e: MessageEvent) => {\r\n const event = JSON.parse(e.data) as McpConnectionEvent;\r\n this.options.onConnectionEvent?.(event);\r\n });\r\n\r\n this.eventSource.addEventListener('observability', (e: MessageEvent) => {\r\n const event = JSON.parse(e.data) as McpObservabilityEvent;\r\n this.options.onObservabilityEvent?.(event);\r\n });\r\n\r\n this.eventSource.addEventListener('rpc-response', (e: MessageEvent) => {\r\n const response = JSON.parse(e.data) as McpRpcResponse;\r\n this.handleRpcResponse(response);\r\n });\r\n\r\n this.eventSource.addEventListener('error', () => {\r\n this.log('Connection error', 'error');\r\n this.options.onStatusChange?.('error');\r\n this.attemptReconnect();\r\n });\r\n }\r\n\r\n private attemptReconnect(): void {\r\n if (this.isManuallyDisconnected || this.reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {\r\n return;\r\n }\r\n\r\n this.reconnectAttempts++;\r\n const delay = BASE_RECONNECT_DELAY * this.reconnectAttempts;\r\n this.log(`Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts}/${MAX_RECONNECT_ATTEMPTS})`);\r\n\r\n setTimeout(() => {\r\n this.disconnect();\r\n this.connect();\r\n }, delay);\r\n }\r\n\r\n // ============================================\r\n // Private: Utilities\r\n // ============================================\r\n\r\n private buildUrl(): string {\r\n const url = new URL(this.options.url, globalThis.location?.origin);\r\n url.searchParams.set('identity', this.options.identity);\r\n if (this.options.authToken) {\r\n url.searchParams.set('token', this.options.authToken);\r\n }\r\n return url.toString();\r\n }\r\n\r\n private buildHeaders(): HeadersInit {\r\n const headers: HeadersInit = {\r\n 'Content-Type': 'application/json',\r\n };\r\n if (this.options.authToken) {\r\n headers['Authorization'] = `Bearer ${this.options.authToken}`;\r\n }\r\n return headers;\r\n }\r\n\r\n private rejectAllPendingRequests(error: Error): void {\r\n for (const [, pending] of this.pendingRequests) {\r\n clearTimeout(pending.timeoutId);\r\n pending.reject(error);\r\n }\r\n this.pendingRequests.clear();\r\n }\r\n\r\n private extractUiResourceUri(tool: { name: string; _meta?: unknown }): string | undefined {\r\n const meta = (tool._meta as { ui?: ToolUiMetadata })?.ui;\r\n if (!meta || typeof meta !== 'object') return undefined;\r\n\r\n // Check visibility constraint\r\n if (meta.visibility && !meta.visibility.includes('app')) return undefined;\r\n\r\n // Support both 'resourceUri' and 'uri' field names\r\n return meta.resourceUri ?? meta.uri;\r\n }\r\n\r\n private emitUiEventIfPresent(result: unknown, sessionId: string, toolName: string): void {\r\n const meta = (result as { _meta?: { ui?: ToolUiMetadata } })?._meta;\r\n const resourceUri = meta?.ui?.resourceUri ?? (meta as any)?.['ui/resourceUri'];\r\n\r\n if (resourceUri) {\r\n this.options.onEvent?.({\r\n type: 'mcp-apps-ui',\r\n sessionId,\r\n resourceUri,\r\n toolName,\r\n result,\r\n timestamp: Date.now(),\r\n });\r\n }\r\n }\r\n\r\n private log(message: string, level: 'info' | 'warn' | 'error' = 'info'): void {\r\n if (!this.options.debug && level === 'info') return;\r\n\r\n const prefix = '[SSEClient]';\r\n switch (level) {\r\n case 'warn':\r\n console.warn(prefix, message);\r\n break;\r\n case 'error':\r\n console.error(prefix, message);\r\n break;\r\n default:\r\n console.log(prefix, message);\r\n }\r\n }\r\n}\r\n","/**\r\n * useMcp React Hook\r\n * Manages MCP connections with SSE-based real-time updates\r\n * Based on Cloudflare's agents pattern\r\n */\r\n\r\nimport { useEffect, useRef, useState, useCallback } from 'react';\r\nimport { SSEClient, type SSEClientOptions } from '../core/sse-client';\r\nimport type { McpConnectionEvent, McpConnectionState } from '../../shared/events';\r\nimport type {\r\n ToolInfo,\r\n FinishAuthResult,\r\n ListToolsRpcResult,\r\n ListPromptsResult,\r\n ListResourcesResult,\r\n SessionInfo,\r\n} from '../../shared/types';\r\n\r\nexport interface UseMcpOptions {\r\n /**\r\n * SSE endpoint URL\r\n */\r\n url: string;\r\n\r\n /**\r\n * User/Client identifier\r\n */\r\n identity: string;\r\n\r\n /**\r\n * Optional auth token\r\n */\r\n authToken?: string;\r\n\r\n /**\r\n * Auto-connect on mount\r\n * @default true\r\n */\r\n autoConnect?: boolean;\r\n\r\n /**\r\n * Auto-initialize sessions on mount\r\n * @default true\r\n */\r\n autoInitialize?: boolean;\r\n\r\n /**\r\n * Connection event callback\r\n */\r\n onConnectionEvent?: (event: McpConnectionEvent) => void;\r\n\r\n /**\r\n * Debug logging callback\r\n */\r\n onLog?: (level: string, message: string, metadata?: Record<string, unknown>) => void;\r\n /**\r\n * Optional callback to handle OAuth redirects (e.g. for popup flow)\r\n * If provided, this will be called instead of window.location.href assignment\r\n */\r\n onRedirect?: (url: string) => void;\r\n\r\n /**\r\n * Request timeout in milliseconds\r\n * @default 60000\r\n */\r\n requestTimeout?: number;\r\n}\r\n\r\nexport interface McpConnection {\r\n sessionId: string;\r\n serverId: string;\r\n serverName: string;\r\n serverUrl?: string;\r\n transport?: string;\r\n state: McpConnectionState;\r\n tools: ToolInfo[];\r\n error?: string;\r\n connectedAt?: Date;\r\n}\r\n\r\nexport interface McpClient {\r\n /**\r\n * All connections\r\n */\r\n connections: McpConnection[];\r\n\r\n /**\r\n * SSE connection status\r\n */\r\n status: 'connecting' | 'connected' | 'disconnected' | 'error';\r\n\r\n /**\r\n * Whether initializing\r\n */\r\n isInitializing: boolean;\r\n\r\n /**\r\n * Connect to an MCP server\r\n */\r\n connect: (params: {\r\n serverId: string;\r\n serverName: string;\r\n serverUrl: string;\r\n callbackUrl: string;\r\n transportType?: 'sse' | 'streamable_http';\r\n }) => Promise<string>;\r\n\r\n /**\r\n * Disconnect from an MCP server\r\n */\r\n disconnect: (sessionId: string) => Promise<void>;\r\n\r\n /**\r\n * Get connection by session ID\r\n */\r\n getConnection: (sessionId: string) => McpConnection | undefined;\r\n\r\n /**\r\n * Get connection by server ID\r\n */\r\n getConnectionByServerId: (serverId: string) => McpConnection | undefined;\r\n\r\n /**\r\n * Check if server is connected\r\n */\r\n isServerConnected: (serverId: string) => boolean;\r\n\r\n /**\r\n * Get tools for a session\r\n */\r\n getTools: (sessionId: string) => ToolInfo[];\r\n\r\n /**\r\n * Refresh all connections\r\n */\r\n refresh: () => Promise<void>;\r\n\r\n /**\r\n * Manually connect SSE\r\n */\r\n connectSSE: () => void;\r\n\r\n /**\r\n * Manually disconnect SSE\r\n */\r\n disconnectSSE: () => void;\r\n\r\n /**\r\n * Complete OAuth authorization\r\n */\r\n finishAuth: (sessionId: string, code: string) => Promise<FinishAuthResult>;\r\n\r\n /**\r\n * Call a tool from a session\r\n */\r\n callTool: (\r\n sessionId: string,\r\n toolName: string,\r\n toolArgs: Record<string, unknown>\r\n ) => Promise<unknown>;\r\n\r\n /**\r\n * List available tools for a session\r\n */\r\n listTools: (sessionId: string) => Promise<ListToolsRpcResult>;\r\n\r\n /**\r\n * List available prompts for a session\r\n */\r\n listPrompts: (sessionId: string) => Promise<ListPromptsResult>;\r\n\r\n /**\r\n * Get a specific prompt with arguments\r\n */\r\n getPrompt: (sessionId: string, name: string, args?: Record<string, string>) => Promise<unknown>;\r\n\r\n /**\r\n * List available resources for a session\r\n */\r\n listResources: (sessionId: string) => Promise<ListResourcesResult>;\r\n\r\n /**\r\n * Read a specific resource\r\n */\r\n readResource: (sessionId: string, uri: string) => Promise<unknown>;\r\n\r\n /**\r\n * Access the underlying SSEClient instance (for advanced usage like AppHost)\r\n */\r\n sseClient: SSEClient | null;\r\n}\r\n\r\n/**\r\n * React hook for MCP connection management with SSE\r\n */\r\nexport function useMcp(options: UseMcpOptions): McpClient {\r\n const {\r\n url,\r\n identity,\r\n authToken,\r\n autoConnect = true,\r\n autoInitialize = true,\r\n onConnectionEvent,\r\n onLog,\r\n onRedirect,\r\n } = options;\r\n\r\n const clientRef = useRef<SSEClient | null>(null);\r\n const isMountedRef = useRef(true);\r\n\r\n const [connections, setConnections] = useState<McpConnection[]>([]);\r\n const [status, setStatus] = useState<'connecting' | 'connected' | 'disconnected' | 'error'>(\r\n 'disconnected'\r\n );\r\n const [isInitializing, setIsInitializing] = useState(false);\r\n\r\n /**\r\n * Initialize SSE client\r\n */\r\n useEffect(() => {\r\n isMountedRef.current = true;\r\n\r\n const clientOptions: SSEClientOptions = {\r\n url,\r\n identity,\r\n authToken,\r\n onConnectionEvent: (event) => {\r\n // Update local state based on event\r\n updateConnectionsFromEvent(event);\r\n\r\n // Call user callback\r\n onConnectionEvent?.(event);\r\n },\r\n onObservabilityEvent: (event) => {\r\n onLog?.(event.level || 'info', event.message || event.displayMessage || 'No message', event.metadata);\r\n },\r\n onStatusChange: (newStatus) => {\r\n if (isMountedRef.current) {\r\n setStatus(newStatus);\r\n }\r\n },\r\n requestTimeout: options.requestTimeout,\r\n };\r\n\r\n const client = new SSEClient(clientOptions);\r\n clientRef.current = client;\r\n\r\n if (autoConnect) {\r\n client.connect();\r\n\r\n if (autoInitialize) {\r\n loadSessions();\r\n }\r\n }\r\n\r\n return () => {\r\n isMountedRef.current = false;\r\n client.disconnect();\r\n };\r\n }, [url, identity, authToken, autoConnect, autoInitialize]);\r\n\r\n /**\r\n * Update connections based on event\r\n */\r\n const updateConnectionsFromEvent = useCallback((event: McpConnectionEvent) => {\r\n if (!isMountedRef.current) return;\r\n\r\n setConnections((prev: McpConnection[]) => {\r\n switch (event.type) {\r\n case 'state_changed': {\r\n const existing = prev.find((c: McpConnection) => c.sessionId === event.sessionId);\r\n if (existing) {\r\n return prev.map((c: McpConnection) =>\r\n c.sessionId === event.sessionId ? { ...c, state: event.state } : c\r\n );\r\n } else {\r\n return [\r\n ...prev,\r\n {\r\n sessionId: event.sessionId,\r\n serverId: event.serverId,\r\n serverName: event.serverName,\r\n state: event.state,\r\n tools: [],\r\n },\r\n ];\r\n }\r\n }\r\n\r\n case 'tools_discovered': {\r\n // Preload UI resources for instant loading when tools are discovered\r\n if (clientRef.current && event.tools?.length) {\r\n clientRef.current.preloadToolUiResources(event.sessionId, event.tools);\r\n }\r\n\r\n return prev.map((c: McpConnection) =>\r\n c.sessionId === event.sessionId ? { ...c, tools: event.tools, state: 'READY' } : c\r\n );\r\n }\r\n\r\n case 'auth_required': {\r\n // Handle OAuth redirect\r\n if (event.authUrl) {\r\n onLog?.('info', `OAuth required - redirecting to ${event.authUrl}`, { authUrl: event.authUrl });\r\n\r\n if (onRedirect) {\r\n onRedirect(event.authUrl);\r\n } else if (typeof window !== 'undefined') {\r\n window.location.href = event.authUrl;\r\n }\r\n }\r\n return prev.map((c: McpConnection) =>\r\n c.sessionId === event.sessionId ? { ...c, state: 'AUTHENTICATING' } : c\r\n );\r\n }\r\n\r\n case 'error': {\r\n return prev.map((c: McpConnection) =>\r\n c.sessionId === event.sessionId ? { ...c, state: 'FAILED', error: event.error } : c\r\n );\r\n }\r\n\r\n case 'disconnected': {\r\n return prev.filter((c: McpConnection) => c.sessionId !== event.sessionId);\r\n }\r\n\r\n default:\r\n return prev;\r\n }\r\n });\r\n }, [onLog]);\r\n\r\n /**\r\n * Load sessions from server\r\n */\r\n const loadSessions = useCallback(async () => {\r\n if (!clientRef.current) return;\r\n\r\n try {\r\n setIsInitializing(true);\r\n\r\n const result = await clientRef.current.getSessions();\r\n const sessions = result.sessions || [];\r\n\r\n // Initialize connections\r\n if (isMountedRef.current) {\r\n setConnections(\r\n sessions.map((s: SessionInfo) => ({\r\n sessionId: s.sessionId,\r\n serverId: s.serverId ?? 'unknown',\r\n serverName: s.serverName ?? 'Unknown Server',\r\n serverUrl: s.serverUrl,\r\n transport: s.transport,\r\n state: 'VALIDATING' as McpConnectionState,\r\n tools: [],\r\n }))\r\n );\r\n }\r\n\r\n // Validate each session in parallel\r\n await Promise.all(\r\n sessions.map(async (session: SessionInfo) => {\r\n if (clientRef.current) {\r\n try {\r\n await clientRef.current.restoreSession(session.sessionId);\r\n } catch (error) {\r\n console.error(`[useMcp] Failed to validate session ${session.sessionId}:`, error);\r\n }\r\n }\r\n })\r\n );\r\n } catch (error) {\r\n console.error('[useMcp] Failed to load sessions:', error);\r\n onLog?.('error', 'Failed to load sessions', { error });\r\n } finally {\r\n if (isMountedRef.current) {\r\n setIsInitializing(false);\r\n }\r\n }\r\n }, [onLog]);\r\n\r\n /**\r\n * Connect to an MCP server\r\n */\r\n const connect = useCallback(\r\n async (params: {\r\n serverId: string;\r\n serverName: string;\r\n serverUrl: string;\r\n callbackUrl: string;\r\n transportType?: 'sse' | 'streamable_http';\r\n }): Promise<string> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n const result = await clientRef.current.connectToServer(params);\r\n return result.sessionId;\r\n },\r\n []\r\n );\r\n\r\n /**\r\n * Disconnect from an MCP server\r\n */\r\n const disconnect = useCallback(async (sessionId: string): Promise<void> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n await clientRef.current.disconnectFromServer(sessionId);\r\n\r\n // Remove from local state\r\n if (isMountedRef.current) {\r\n setConnections((prev: McpConnection[]) => prev.filter((c: McpConnection) => c.sessionId !== sessionId));\r\n }\r\n }, []);\r\n\r\n /**\r\n * Refresh all connections\r\n */\r\n const refresh = useCallback(async () => {\r\n await loadSessions();\r\n }, [loadSessions]);\r\n\r\n /**\r\n * Manually connect SSE\r\n */\r\n const connectSSE = useCallback(() => {\r\n clientRef.current?.connect();\r\n }, []);\r\n\r\n /**\r\n * Manually disconnect SSE\r\n */\r\n const disconnectSSE = useCallback(() => {\r\n clientRef.current?.disconnect();\r\n }, []);\r\n\r\n /**\r\n * Complete OAuth authorization\r\n */\r\n const finishAuth = useCallback(async (sessionId: string, code: string): Promise<FinishAuthResult> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n return await clientRef.current.finishAuth(sessionId, code);\r\n }, []);\r\n\r\n /**\r\n * Call a tool\r\n */\r\n const callTool = useCallback(\r\n async (\r\n sessionId: string,\r\n toolName: string,\r\n toolArgs: Record<string, unknown>\r\n ): Promise<unknown> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n return await clientRef.current.callTool(sessionId, toolName, toolArgs);\r\n },\r\n []\r\n );\r\n\r\n /**\r\n * List tools (refresh tool list)\r\n */\r\n const listTools = useCallback(async (sessionId: string): Promise<ListToolsRpcResult> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n return await clientRef.current.listTools(sessionId);\r\n }, []);\r\n\r\n /**\r\n * List prompts\r\n */\r\n const listPrompts = useCallback(async (sessionId: string): Promise<ListPromptsResult> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n return await clientRef.current.listPrompts(sessionId);\r\n }, []);\r\n\r\n /**\r\n * Get a specific prompt\r\n */\r\n const getPrompt = useCallback(\r\n async (sessionId: string, name: string, args?: Record<string, string>): Promise<unknown> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n return await clientRef.current.getPrompt(sessionId, name, args);\r\n },\r\n []\r\n );\r\n\r\n /**\r\n * List resources\r\n */\r\n const listResources = useCallback(async (sessionId: string): Promise<ListResourcesResult> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n return await clientRef.current.listResources(sessionId);\r\n }, []);\r\n\r\n /**\r\n * Read a specific resource\r\n */\r\n const readResource = useCallback(async (sessionId: string, uri: string): Promise<unknown> => {\r\n if (!clientRef.current) {\r\n throw new Error('SSE client not initialized');\r\n }\r\n\r\n return await clientRef.current.readResource(sessionId, uri);\r\n }, []);\r\n\r\n // Utility functions\r\n const getConnection = useCallback(\r\n (sessionId: string) => connections.find((c: McpConnection) => c.sessionId === sessionId),\r\n [connections]\r\n );\r\n\r\n const getConnectionByServerId = useCallback(\r\n (serverId: string) => connections.find((c: McpConnection) => c.serverId === serverId),\r\n [connections]\r\n );\r\n\r\n const isServerConnected = useCallback(\r\n (serverId: string) => {\r\n const conn = getConnectionByServerId(serverId);\r\n return conn?.state === 'CONNECTED';\r\n },\r\n [getConnectionByServerId]\r\n );\r\n\r\n const getTools = useCallback(\r\n (sessionId: string) => {\r\n const conn = getConnection(sessionId);\r\n return conn?.tools || [];\r\n },\r\n [getConnection]\r\n );\r\n\r\n return {\r\n connections,\r\n status,\r\n isInitializing,\r\n connect,\r\n disconnect,\r\n getConnection,\r\n getConnectionByServerId,\r\n isServerConnected,\r\n getTools,\r\n refresh,\r\n connectSSE,\r\n disconnectSSE,\r\n finishAuth,\r\n callTool,\r\n listTools,\r\n listPrompts,\r\n getPrompt,\r\n listResources,\r\n readResource,\r\n sseClient: clientRef.current,\r\n };\r\n}\r\n","/**\r\n * MCP App Host\r\n *\r\n * Bridges the gap between an iframe (MCP App) and the SSEClient (MCP Server).\r\n * Handles secure iframe sandboxing, resource loading, and bi-directional\r\n * communication via the AppBridge protocol.\r\n *\r\n * Key features:\r\n * - Secure iframe sandboxing with minimal permissions\r\n * - Resource preloading for instant MCP App UI loading\r\n * - Cache-aware resource fetching (SSEClient cache → local cache → direct fetch)\r\n * - Support for ui:// and mcp-app:// resource URIs\r\n */\r\n\r\nimport { AppBridge, PostMessageTransport } from '@modelcontextprotocol/ext-apps/app-bridge';\r\nimport type { AppHostClient } from './types';\r\n\r\n// ============================================\r\n// Types & Interfaces\r\n// ============================================\r\n\r\nexport interface AppHostOptions {\r\n /** Enable debug logging @default false */\r\n debug?: boolean;\r\n}\r\n\r\nexport interface AppMessageParams {\r\n role: string;\r\n content: unknown;\r\n}\r\n\r\ninterface ToolCallParams {\r\n name: string;\r\n arguments?: Record<string, unknown>;\r\n}\r\n\r\ninterface ResourceContent {\r\n blob?: string;\r\n text?: string;\r\n}\r\n\r\ninterface ResourceResponse {\r\n contents: ResourceContent[];\r\n}\r\n\r\n// ============================================\r\n// Constants\r\n// ============================================\r\n\r\nconst HOST_INFO = { name: 'mcp-ts-host', version: '1.0.0' };\r\n\r\n/** Sandbox permissions - minimal set required for MCP Apps to function */\r\nconst SANDBOX_PERMISSIONS = [\r\n 'allow-scripts', // Required for app JavaScript execution\r\n 'allow-forms', // Required for form submissions\r\n 'allow-same-origin', // Required for Blob URL correctness\r\n 'allow-modals', // Required for dialogs/alerts\r\n 'allow-popups', // Required for opening links\r\n 'allow-downloads' // Required for file downloads\r\n].join(' ');\r\n\r\n/** Supported MCP App URI schemes */\r\nconst MCP_URI_SCHEMES = ['ui://', 'mcp-app://'] as const;\r\n\r\n// ============================================\r\n// AppHost Class\r\n// ============================================\r\n\r\n/**\r\n * Host for MCP Apps embedded in iframes.\r\n * Manages secure communication between the app and the MCP server.\r\n */\r\nexport class AppHost {\r\n private bridge: AppBridge;\r\n private sessionId?: string;\r\n private resourceCache = new Map<string, Promise<ResourceResponse | null>>();\r\n private debug: boolean;\r\n\r\n /** Callback for app messages (e.g., chat messages from the app) */\r\n public onAppMessage?: (params: AppMessageParams) => void;\r\n\r\n constructor(\r\n private readonly client: AppHostClient,\r\n private readonly iframe: HTMLIFrameElement,\r\n options?: AppHostOptions\r\n ) {\r\n this.debug = options?.debug ?? false;\r\n this.configureSandbox();\r\n this.bridge = this.initializeBridge();\r\n }\r\n\r\n // ============================================\r\n // Public API\r\n // ============================================\r\n\r\n /**\r\n * Start the host. This prepares the bridge handlers but doesn't connect yet.\r\n * The actual connection happens in launch() after HTML is loaded.\r\n * @returns Promise that resolves immediately (bridge connects during launch)\r\n */\r\n async start(): Promise<void> {\r\n // Bridge handlers are already registered in constructor.\r\n // Connection happens in launch() after HTML is loaded.\r\n this.log('Host started, ready to launch');\r\n }\r\n\r\n /**\r\n * Preload UI resources to enable instant app loading.\r\n * Call this when tools are discovered to cache their UI resources.\r\n */\r\n preload(tools: Array<{ _meta?: unknown }>): void {\r\n for (const tool of tools) {\r\n const uri = this.extractUiResourceUri(tool);\r\n if (!uri || this.resourceCache.has(uri)) continue;\r\n\r\n const promise = this.preloadResource(uri);\r\n this.resourceCache.set(uri, promise);\r\n }\r\n }\r\n\r\n /**\r\n * Launch an MCP App from a URL or MCP resource URI.\r\n * Loads the HTML first, then establishes bridge connection.\r\n */\r\n async launch(url: string, sessionId?: string): Promise<void> {\r\n if (sessionId) this.sessionId = sessionId;\r\n\r\n // Set up initialization promise BEFORE connecting\r\n const initializedPromise = this.onAppReady();\r\n\r\n // Load HTML into iframe first\r\n if (this.isMcpUri(url)) {\r\n await this.launchMcpApp(url);\r\n } else {\r\n this.iframe.src = url;\r\n }\r\n\r\n // Wait for iframe to load before connecting bridge\r\n await this.onIframeReady();\r\n\r\n // Connect the bridge (HTML is loaded, contentWindow is ready)\r\n await this.connectBridge();\r\n\r\n // Wait for app to signal it's initialized (with timeout)\r\n this.log('Waiting for app initialization');\r\n await Promise.race([\r\n initializedPromise,\r\n new Promise<void>((resolve) => setTimeout(() => {\r\n this.log('Initialization timeout - continuing anyway', 'warn');\r\n resolve();\r\n }, 3000))\r\n ]);\r\n this.log('App launched and ready');\r\n }\r\n\r\n /**\r\n * Wait for app to signal initialization complete\r\n */\r\n private onAppReady(): Promise<void> {\r\n return new Promise<void>((resolve) => {\r\n const originalHandler = this.bridge.oninitialized;\r\n this.bridge.oninitialized = (...args) => {\r\n this.log('App initialized');\r\n resolve();\r\n this.bridge.oninitialized = originalHandler;\r\n originalHandler?.(...args);\r\n };\r\n });\r\n }\r\n\r\n /**\r\n * Wait for iframe to finish loading\r\n */\r\n private onIframeReady(): Promise<void> {\r\n return new Promise((resolve) => {\r\n if (this.iframe.contentDocument?.readyState === 'complete') {\r\n resolve();\r\n return;\r\n }\r\n this.iframe.addEventListener('load', () => resolve(), { once: true });\r\n });\r\n }\r\n\r\n /**\r\n * Send tool input arguments to the MCP App.\r\n * Call this after launch() when tool input is available.\r\n */\r\n sendToolInput(args: Record<string, unknown>): void {\r\n this.log('Sending tool input to app');\r\n this.bridge.sendToolInput({ arguments: args });\r\n }\r\n\r\n /**\r\n * Send tool result to the MCP App.\r\n * Call this when the tool call completes.\r\n */\r\n sendToolResult(result: unknown): void {\r\n this.log('Sending tool result to app');\r\n this.bridge.sendToolResult(result as any);\r\n }\r\n\r\n /**\r\n * Send tool cancellation to the MCP App.\r\n * Call this when the tool call is cancelled or fails.\r\n */\r\n sendToolCancelled(reason: string): void {\r\n this.log('Sending tool cancellation to app');\r\n this.bridge.sendToolCancelled({ reason });\r\n }\r\n\r\n // ============================================\r\n // Private: Initialization\r\n // ============================================\r\n\r\n private configureSandbox(): void {\r\n if (this.iframe.sandbox.value !== SANDBOX_PERMISSIONS) {\r\n this.iframe.sandbox.value = SANDBOX_PERMISSIONS;\r\n }\r\n }\r\n\r\n private initializeBridge(): AppBridge {\r\n const bridge = new AppBridge(\r\n null,\r\n HOST_INFO,\r\n {\r\n openLinks: {},\r\n serverTools: {},\r\n logging: {},\r\n // Declare support for model context updates\r\n updateModelContext: { text: {} },\r\n },\r\n {\r\n // Initial host context\r\n hostContext: {\r\n theme: 'dark',\r\n platform: 'web',\r\n containerDimensions: { maxHeight: 6000 },\r\n displayMode: 'inline',\r\n availableDisplayModes: ['inline', 'fullscreen'],\r\n },\r\n }\r\n );\r\n\r\n // Register handlers - must be done BEFORE connect()\r\n bridge.oncalltool = (params) => this.handleToolCall(params);\r\n bridge.onopenlink = this.handleOpenLink.bind(this);\r\n bridge.onmessage = this.handleMessage.bind(this);\r\n bridge.onloggingmessage = (params) => this.log(`App log [${params.level}]: ${params.data}`);\r\n bridge.onupdatemodelcontext = async () => ({});\r\n bridge.onsizechange = async ({ width, height }) => {\r\n if (height !== undefined) this.iframe.style.height = `${height}px`;\r\n if (width !== undefined) this.iframe.style.minWidth = `min(${width}px, 100%)`;\r\n return {};\r\n };\r\n bridge.onrequestdisplaymode = async (params) => ({\r\n mode: params.mode === 'fullscreen' ? 'fullscreen' : 'inline'\r\n });\r\n\r\n return bridge;\r\n }\r\n\r\n private async connectBridge(): Promise<void> {\r\n this.log('Connecting bridge to iframe');\r\n\r\n const transport = new PostMessageTransport(\r\n this.iframe.contentWindow!,\r\n this.iframe.contentWindow!\r\n );\r\n\r\n try {\r\n await this.bridge.connect(transport);\r\n this.log('Bridge connected successfully');\r\n } catch (error) {\r\n this.log('Bridge connection failed', 'error');\r\n throw error;\r\n }\r\n }\r\n\r\n // ============================================\r\n // Private: Bridge Event Handlers\r\n // ============================================\r\n\r\n private async handleToolCall(params: ToolCallParams) {\r\n if (!this.client.isConnected()) {\r\n throw new Error('Client disconnected');\r\n }\r\n\r\n const sessionId = await this.getSessionId();\r\n if (!sessionId) {\r\n throw new Error('No active session');\r\n }\r\n\r\n const result = await this.client.callTool(\r\n sessionId,\r\n params.name,\r\n params.arguments ?? {}\r\n );\r\n return result as any;\r\n }\r\n\r\n private async handleOpenLink(params: { url: string }): Promise<Record<string, never>> {\r\n window.open(params.url, '_blank', 'noopener,noreferrer');\r\n return {};\r\n }\r\n\r\n private async handleMessage(params: AppMessageParams): Promise<Record<string, never>> {\r\n this.onAppMessage?.(params);\r\n return {};\r\n }\r\n\r\n // ============================================\r\n // Private: Resource Loading\r\n // ============================================\r\n\r\n private async launchMcpApp(uri: string): Promise<void> {\r\n if (!this.client.isConnected()) {\r\n throw new Error('Client must be connected');\r\n }\r\n\r\n const sessionId = await this.getSessionId();\r\n if (!sessionId) {\r\n throw new Error('No active session');\r\n }\r\n\r\n // Fetch resource using cache hierarchy: SSEClient cache → local cache → direct fetch\r\n const response = await this.fetchResourceWithCache(sessionId, uri);\r\n if (!response?.contents?.length) {\r\n throw new Error(`Empty resource: ${uri}`);\r\n }\r\n\r\n const content = response.contents[0];\r\n const html = this.decodeContent(content);\r\n if (!html) {\r\n throw new Error(`Invalid content in resource: ${uri}`);\r\n }\r\n\r\n // Render via Blob URL for clean isolation\r\n const blob = new Blob([html], { type: 'text/html' });\r\n this.iframe.src = URL.createObjectURL(blob);\r\n }\r\n\r\n private async fetchResourceWithCache(sessionId: string, uri: string): Promise<ResourceResponse> {\r\n // Priority 1: SSEClient's built-in cache (best performance)\r\n if (this.hasClientCache()) {\r\n return (this.client as any).getOrFetchResource(sessionId, uri);\r\n }\r\n\r\n // Priority 2: Local preload cache\r\n const cached = this.resourceCache.get(uri);\r\n if (cached) {\r\n const result = await cached;\r\n if (result) return result;\r\n }\r\n\r\n // Priority 3: Direct fetch\r\n return this.client.readResource(sessionId, uri) as Promise<ResourceResponse>;\r\n }\r\n\r\n private async preloadResource(uri: string): Promise<ResourceResponse | null> {\r\n try {\r\n const sessionId = await this.getSessionId();\r\n if (!sessionId) return null;\r\n return await this.client.readResource(sessionId, uri) as ResourceResponse;\r\n } catch (error) {\r\n this.log(`Preload failed for ${uri}`, 'warn');\r\n return null;\r\n }\r\n }\r\n\r\n // ============================================\r\n // Private: Utilities\r\n // ============================================\r\n\r\n private async getSessionId(): Promise<string | undefined> {\r\n if (this.sessionId) return this.sessionId;\r\n const result = await this.client.getSessions();\r\n return result.sessions?.[0]?.sessionId;\r\n }\r\n\r\n private isMcpUri(url: string): boolean {\r\n return MCP_URI_SCHEMES.some(scheme => url.startsWith(scheme));\r\n }\r\n\r\n private hasClientCache(): boolean {\r\n return 'getOrFetchResource' in this.client &&\r\n typeof (this.client as any).getOrFetchResource === 'function';\r\n }\r\n\r\n private extractUiResourceUri(tool: { _meta?: unknown }): string | undefined {\r\n const meta = tool._meta as { ui?: { resourceUri?: string; uri?: string } } | undefined;\r\n if (!meta?.ui) return undefined;\r\n return meta.ui.resourceUri ?? meta.ui.uri;\r\n }\r\n\r\n private decodeContent(content: ResourceContent): string | undefined {\r\n if (content.blob) {\r\n return atob(content.blob);\r\n }\r\n return content.text;\r\n }\r\n\r\n private log(message: string, level: 'info' | 'warn' | 'error' = 'info'): void {\r\n if (!this.debug && level === 'info') return;\r\n\r\n const prefix = '[AppHost]';\r\n switch (level) {\r\n case 'warn':\r\n console.warn(prefix, message);\r\n break;\r\n case 'error':\r\n console.error(prefix, message);\r\n break;\r\n default:\r\n console.log(prefix, message);\r\n }\r\n }\r\n}\r\n","import { useEffect, useRef, useState, useCallback } from 'react';\r\nimport type { SSEClient } from '../core/sse-client';\r\nimport { AppHost } from '../core/app-host';\r\n\r\n/**\r\n * Hook to host an MCP App in a React component\r\n *\r\n * Optimized for instant loading:\r\n * - Creates AppHost synchronously\r\n * - Starts bridge connection immediately\r\n * - Returns host before connection completes (ready to call launch)\r\n *\r\n * @param client - Connected SSEClient instance\r\n * @param iframeRef - Reference to the iframe element\r\n * @param options - Optional configuration\r\n * @returns Object containing the AppHost instance (or null) and error state\r\n */\r\nexport function useAppHost(\r\n client: SSEClient,\r\n iframeRef: React.RefObject<HTMLIFrameElement>,\r\n options?: {\r\n /** Callback when the App sends a message (e.g. to chat) */\r\n onMessage?: (params: { role: string; content: unknown }) => void;\r\n }\r\n) {\r\n const [host, setHost] = useState<AppHost | null>(null);\r\n const [error, setError] = useState<Error | null>(null);\r\n const initializingRef = useRef(false);\r\n\r\n // Store latest callback in ref to avoid re-initializing AppHost on callback change\r\n const onMessageRef = useRef(options?.onMessage);\r\n useEffect(() => {\r\n onMessageRef.current = options?.onMessage;\r\n }, [options?.onMessage]);\r\n\r\n useEffect(() => {\r\n if (!client || !iframeRef.current || initializingRef.current) return;\r\n\r\n // Prevent double initialization in strict mode\r\n initializingRef.current = true;\r\n\r\n const initHost = async () => {\r\n try {\r\n // Initialize AppHost with security enforcement\r\n const appHost = new AppHost(client, iframeRef.current!);\r\n\r\n // Register message handler\r\n appHost.onAppMessage = (params) => {\r\n onMessageRef.current?.(params);\r\n };\r\n\r\n // Set host immediately so launch can be called\r\n // (launch will wait for bridge if needed)\r\n setHost(appHost);\r\n\r\n // Start bridge connection (this is fast, just sets up PostMessage)\r\n await appHost.start();\r\n } catch (err) {\r\n console.error('[useAppHost] Failed to initialize AppHost:', err);\r\n setError(err instanceof Error ? err : new Error(String(err)));\r\n }\r\n };\r\n\r\n initHost();\r\n\r\n return () => {\r\n initializingRef.current = false;\r\n setHost(null);\r\n };\r\n }, [client, iframeRef]);\r\n\r\n return { host, error };\r\n}\r\n","/**\n * MCP Apps Hook\n *\n * Provides utilities for rendering interactive UI components from MCP servers.\n */\n\nimport React, { useState, useEffect, useCallback, useRef, memo } from 'react';\nimport { useAppHost } from './use-app-host.js';\nimport type { SSEClient } from '../core/sse-client.js';\n\nexport interface McpClient {\n connections: Array<{\n sessionId: string;\n tools: Array<{\n name: string;\n mcpApp?: {\n resourceUri: string;\n };\n _meta?: {\n ui?: {\n resourceUri?: string;\n };\n 'ui/resourceUri'?: string;\n };\n }>;\n }>;\n sseClient?: SSEClient | null;\n}\n\nexport interface McpAppMetadata {\n toolName: string;\n resourceUri: string;\n sessionId: string;\n}\n\ninterface McpAppRendererProps {\n metadata: McpAppMetadata;\n input?: Record<string, unknown>;\n result?: unknown;\n status: 'executing' | 'inProgress' | 'complete' | 'idle';\n sseClient?: SSEClient | null;\n /** Custom CSS class for the container */\n className?: string;\n}\n\n/**\n * Internal component that renders the MCP app in a sandboxed iframe\n */\nconst McpAppRenderer = memo(function McpAppRenderer({\n metadata,\n input,\n result,\n status,\n sseClient,\n className,\n}: McpAppRendererProps) {\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const { host, error: hostError } = useAppHost(sseClient as SSEClient, iframeRef);\n const [isLaunched, setIsLaunched] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n // Track which data has been sent to prevent duplicates\n const sentInputRef = useRef(false);\n const sentResultRef = useRef(false);\n const lastInputRef = useRef(input);\n const lastResultRef = useRef(result);\n const lastStatusRef = useRef(status);\n\n // Launch the app when host is ready\n useEffect(() => {\n if (!host || !metadata.resourceUri || !metadata.sessionId) return;\n\n host\n .launch(metadata.resourceUri, metadata.sessionId)\n .then(() => setIsLaunched(true))\n .catch((err) => setError(err instanceof Error ? err : new Error(String(err))));\n }, [host, metadata.resourceUri, metadata.sessionId]);\n\n // Send tool input when available or when it changes\n useEffect(() => {\n if (!host || !isLaunched || !input) return;\n \n // Send if never sent, or if input changed\n if (!sentInputRef.current || JSON.stringify(input) !== JSON.stringify(lastInputRef.current)) {\n sentInputRef.current = true;\n lastInputRef.current = input;\n host.sendToolInput(input);\n }\n }, [host, isLaunched, input]);\n\n // Send tool result when complete or when it changes\n useEffect(() => {\n if (!host || !isLaunched || result === undefined) return;\n if (status !== 'complete') return;\n\n // Send if never sent, or if result changed\n if (!sentResultRef.current || JSON.stringify(result) !== JSON.stringify(lastResultRef.current)) {\n sentResultRef.current = true;\n lastResultRef.current = result;\n const formattedResult =\n typeof result === 'string'\n ? { content: [{ type: 'text', text: result }] }\n : result;\n host.sendToolResult(formattedResult);\n }\n }, [host, isLaunched, result, status]);\n\n // Reset sent flags when tool status resets to executing (new tool call)\n useEffect(() => {\n if (status === 'executing' && lastStatusRef.current !== 'executing') {\n sentInputRef.current = false;\n sentResultRef.current = false;\n }\n lastStatusRef.current = status;\n }, [status]);\n\n // Display errors\n const displayError = error || hostError;\n if (displayError) {\n return (\n <div className={`p-4 bg-red-900/20 border border-red-700 rounded text-red-200 ${className || ''}`}>\n Error: {displayError.message || String(displayError)}\n </div>\n );\n }\n\n return (\n <div className={`w-full border border-gray-700 rounded overflow-hidden bg-white min-h-96 my-2 relative ${className || ''}`}>\n <iframe\n ref={iframeRef}\n sandbox=\"allow-scripts allow-same-origin allow-forms allow-modals allow-popups allow-downloads\"\n className=\"w-full h-full min-h-96\"\n style={{ height: 'auto' }}\n title=\"MCP App\"\n />\n {!isLaunched && (\n <div className=\"absolute inset-0 bg-gray-900/50 flex items-center justify-center pointer-events-none\">\n <div className=\"w-6 h-6 border-2 border-blue-500 border-t-transparent rounded-full animate-spin\" />\n </div>\n )}\n </div>\n );\n});\n\n/**\n * Simple hook to get MCP app metadata\n *\n * @param mcpClient - The MCP client from useMcp() or context\n * @returns Object with getAppMetadata function and McpAppRenderer component\n *\n * @example\n * ```tsx\n * function ToolRenderer(props) {\n * const { getAppMetadata, McpAppRenderer } = useMcpApps(mcpClient);\n * const metadata = getAppMetadata(props.name);\n *\n * if (!metadata) return null;\n * return (\n * <McpAppRenderer\n * metadata={metadata}\n * input={props.args}\n * result={props.result}\n * status={props.status}\n * />\n * );\n * }\n * ```\n */\nexport function useMcpApps(mcpClient: McpClient | null) {\n /**\n * Get MCP app metadata for a tool name\n * This is fast and can be called on every render\n */\n const getAppMetadata = useCallback(\n (toolName: string): McpAppMetadata | undefined => {\n if (!mcpClient) return undefined;\n\n const extractedName = extractToolName(toolName);\n\n for (const conn of mcpClient.connections) {\n for (const tool of conn.tools) {\n const candidateName = extractToolName(tool.name);\n // Check both locations: direct mcpApp or _meta.ui\n const resourceUri =\n tool.mcpApp?.resourceUri ??\n tool._meta?.ui?.resourceUri ??\n tool._meta?.['ui/resourceUri'];\n\n if (resourceUri && candidateName === extractedName) {\n return {\n toolName: candidateName,\n resourceUri,\n sessionId: conn.sessionId,\n };\n }\n }\n }\n\n return undefined;\n },\n [mcpClient]\n );\n\n return { getAppMetadata, McpAppRenderer };\n}\n\n/**\n * Extract the base tool name, removing any prefixes\n */\nfunction extractToolName(fullName: string): string {\n // Handle patterns like \"tool_abc123_get-time\" -> \"get-time\"\n const match = fullName.match(/(?:tool_[^_]+_)?(.+)$/);\n return match?.[1] || fullName;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* MCP Apps Hook
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* We return a stable McpAppRenderer component and separate metadata lookup.
|
|
4
|
+
* Provides utilities for rendering interactive UI components from MCP servers.
|
|
6
5
|
*/
|
|
7
6
|
|
|
8
7
|
import React, { useState, useEffect, useCallback, useRef, memo } from 'react';
|
|
@@ -40,11 +39,12 @@ interface McpAppRendererProps {
|
|
|
40
39
|
result?: unknown;
|
|
41
40
|
status: 'executing' | 'inProgress' | 'complete' | 'idle';
|
|
42
41
|
sseClient?: SSEClient | null;
|
|
42
|
+
/** Custom CSS class for the container */
|
|
43
|
+
className?: string;
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
/**
|
|
46
|
-
*
|
|
47
|
-
* Uses refs to track data changes and send updates to the iframe
|
|
47
|
+
* Internal component that renders the MCP app in a sandboxed iframe
|
|
48
48
|
*/
|
|
49
49
|
const McpAppRenderer = memo(function McpAppRenderer({
|
|
50
50
|
metadata,
|
|
@@ -52,6 +52,7 @@ const McpAppRenderer = memo(function McpAppRenderer({
|
|
|
52
52
|
result,
|
|
53
53
|
status,
|
|
54
54
|
sseClient,
|
|
55
|
+
className,
|
|
55
56
|
}: McpAppRendererProps) {
|
|
56
57
|
const iframeRef = useRef<HTMLIFrameElement>(null);
|
|
57
58
|
const { host, error: hostError } = useAppHost(sseClient as SSEClient, iframeRef);
|
|
@@ -117,14 +118,14 @@ const McpAppRenderer = memo(function McpAppRenderer({
|
|
|
117
118
|
const displayError = error || hostError;
|
|
118
119
|
if (displayError) {
|
|
119
120
|
return (
|
|
120
|
-
<div className=
|
|
121
|
+
<div className={`p-4 bg-red-900/20 border border-red-700 rounded text-red-200 ${className || ''}`}>
|
|
121
122
|
Error: {displayError.message || String(displayError)}
|
|
122
123
|
</div>
|
|
123
124
|
);
|
|
124
125
|
}
|
|
125
126
|
|
|
126
127
|
return (
|
|
127
|
-
<div className=
|
|
128
|
+
<div className={`w-full border border-gray-700 rounded overflow-hidden bg-white min-h-96 my-2 relative ${className || ''}`}>
|
|
128
129
|
<iframe
|
|
129
130
|
ref={iframeRef}
|
|
130
131
|
sandbox="allow-scripts allow-same-origin allow-forms allow-modals allow-popups allow-downloads"
|