@copilotkit/react-core 1.70.0 → 1.70.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/{copilotkit-CbZGwElm.d.mts → copilotkit--Jyzm6hS.d.mts} +50 -20
  2. package/dist/copilotkit--Jyzm6hS.d.mts.map +1 -0
  3. package/dist/{copilotkit-B7aFKfQR.mjs → copilotkit-B1jSvZeb.mjs} +395 -291
  4. package/dist/copilotkit-B1jSvZeb.mjs.map +1 -0
  5. package/dist/{copilotkit-BuzP0VeG.d.cts → copilotkit-BLYaCGcz.d.cts} +50 -20
  6. package/dist/copilotkit-BLYaCGcz.d.cts.map +1 -0
  7. package/dist/{copilotkit-BE76j111.cjs → copilotkit-DcFo270Y.cjs} +395 -291
  8. package/dist/copilotkit-DcFo270Y.cjs.map +1 -0
  9. package/dist/index.cjs +5 -4
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.d.cts +2 -2
  12. package/dist/index.d.cts.map +1 -1
  13. package/dist/index.d.mts +2 -2
  14. package/dist/index.d.mts.map +1 -1
  15. package/dist/index.mjs +5 -4
  16. package/dist/index.mjs.map +1 -1
  17. package/dist/index.umd.js +198 -207
  18. package/dist/index.umd.js.map +1 -1
  19. package/dist/v2/headless.cjs +58 -1
  20. package/dist/v2/headless.cjs.map +1 -1
  21. package/dist/v2/headless.mjs +59 -2
  22. package/dist/v2/headless.mjs.map +1 -1
  23. package/dist/v2/index.cjs +1 -1
  24. package/dist/v2/index.css +1 -1
  25. package/dist/v2/index.d.cts +1 -1
  26. package/dist/v2/index.d.mts +1 -1
  27. package/dist/v2/index.mjs +1 -1
  28. package/dist/v2/index.umd.js +395 -291
  29. package/dist/v2/index.umd.js.map +1 -1
  30. package/package.json +11 -8
  31. package/skills/react-core/SKILL.md +1 -1
  32. package/skills/react-core/references/attachments.md +20 -0
  33. package/skills/react-core/references/threads.md +1 -1
  34. package/dist/copilotkit-B7aFKfQR.mjs.map +0 -1
  35. package/dist/copilotkit-BE76j111.cjs.map +0 -1
  36. package/dist/copilotkit-BuzP0VeG.d.cts.map +0 -1
  37. package/dist/copilotkit-CbZGwElm.d.mts.map +0 -1
package/dist/index.umd.js CHANGED
@@ -282,6 +282,62 @@ react_markdown = __toESM(react_markdown);
282
282
  const useCopilotChatConfiguration = () => {
283
283
  return (0, react.useContext)(CopilotChatConfiguration);
284
284
  };
285
+ /**
286
+ * Reports modal open/close requests to the host, and — when `open` is
287
+ * supplied — makes the modal state of an already-established chat
288
+ * configuration **controlled** for the subtree it wraps.
289
+ *
290
+ * This is deliberately a scope component rather than another mode inside
291
+ * {@link CopilotChatConfigurationProvider}. The provider resolves modal state
292
+ * across a nested chain (own state, parent sync, drawer mutual-exclusion, the
293
+ * modal-closer registry); a controlled branch inside that resolution would add
294
+ * a fourth interacting mode. Overriding the context for the subtree instead
295
+ * leaves every one of those paths untouched:
296
+ *
297
+ * - `isModalOpen` is replaced with the host's `open`, so the rendered surface
298
+ * follows the prop from the very first frame (no open-then-close flash).
299
+ * - `setModalOpen` still calls the underlying setter, so the existing
300
+ * parent-sync and drawer mutual-exclusion side effects continue to run, and
301
+ * *then* reports the request through `onOpenChange`.
302
+ * - The wrapped setter is registered as the modal closer, so the drawer's
303
+ * mobile mutual-exclusion reaches the host instead of silently flipping
304
+ * state that nothing displays.
305
+ *
306
+ * A host that supplies `open` and ignores `onOpenChange` gets a modal pinned
307
+ * to `open`, which is the standard controlled-component contract. A host that
308
+ * supplies only `onOpenChange` is notified while the modal keeps managing
309
+ * itself.
310
+ *
311
+ * Renders `children` unchanged when no chat configuration is in scope.
312
+ */
313
+ const ControlledModalOpenScope = ({ children, open, onOpenChange }) => {
314
+ const parentConfig = (0, react.useContext)(CopilotChatConfiguration);
315
+ const parentSetModalOpen = parentConfig?.setModalOpen;
316
+ const registerModalCloser = parentConfig?.ɵregisterModalCloser;
317
+ const setModalOpen = (0, react.useCallback)((next) => {
318
+ parentSetModalOpen?.(next);
319
+ onOpenChange?.(next);
320
+ }, [parentSetModalOpen, onOpenChange]);
321
+ (0, react.useEffect)(() => {
322
+ if (!registerModalCloser) return;
323
+ return registerModalCloser(setModalOpen);
324
+ }, [registerModalCloser, setModalOpen]);
325
+ const configurationValue = (0, react.useMemo)(() => parentConfig ? {
326
+ ...parentConfig,
327
+ isModalOpen: open ?? parentConfig.isModalOpen,
328
+ setModalOpen
329
+ } : null, [
330
+ parentConfig,
331
+ open,
332
+ setModalOpen
333
+ ]);
334
+ if (!configurationValue) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children });
335
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChatConfiguration.Provider, {
336
+ value: configurationValue,
337
+ children
338
+ });
339
+ };
340
+ ControlledModalOpenScope.displayName = "ControlledModalOpenScope";
285
341
 
286
342
  //#endregion
287
343
  //#region src/v2/lib/react-core.ts
@@ -688,7 +744,6 @@ react_markdown = __toESM(react_markdown);
688
744
  newMessages: []
689
745
  };
690
746
  }
691
- const PROTOCOL_VERSION = "2025-06-18";
692
747
  function buildSandboxHTML(extraCspDomains) {
693
748
  const baseScriptSrc = "'self' 'wasm-unsafe-eval' 'unsafe-inline' 'unsafe-eval' blob: data: http://localhost:* https://localhost:*";
694
749
  const baseFrameSrc = "* blob: data: http://localhost:* https://localhost:*";
@@ -800,6 +855,13 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
800
855
  }
801
856
  };
802
857
  const mcpAppsRequestQueue = new MCPAppsRequestQueue();
858
+ const MCP_OPEN_LINK_BLOCKED_SCHEMES = new Set([
859
+ "javascript:",
860
+ "data:",
861
+ "vbscript:",
862
+ "blob:",
863
+ "file:"
864
+ ]);
803
865
  /**
804
866
  * Activity type for MCP Apps events - must match the middleware's MCPAppsActivityType
805
867
  */
@@ -815,18 +877,32 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
815
877
  serverId: zod.z.string().optional(),
816
878
  toolInput: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
817
879
  });
818
- function isRequest(msg) {
819
- return "id" in msg && "method" in msg;
820
- }
821
- function isNotification(msg) {
822
- return !("id" in msg) && "method" in msg;
823
- }
824
880
  /**
825
881
  * MCP Apps Extension Activity Renderer
826
882
  *
827
883
  * Renders MCP Apps UI in a sandboxed iframe with full protocol support.
828
884
  * Fetches resource content on-demand via proxied MCP requests.
829
885
  */
886
+ /**
887
+ * Permissive `ui/message` schema. ext-apps restricts the request to
888
+ * `role: "user"` with no `followUp`, but CopilotKit intentionally extends
889
+ * `ui/message` with `role` ("user" | "assistant") and `followUp` (documented
890
+ * behavior with dedicated tests). We register our own handler (instead of the
891
+ * bridge's strict `onmessage`) so those extensions survive the migration.
892
+ *
893
+ * Going forward, widgets SHOULD pass the extensions under
894
+ * `params._meta.copilotkit`; the top-level `role`/`followUp` fields are the
895
+ * legacy channel, kept for backward compatibility and slated for deprecation.
896
+ */
897
+ const CopilotKitUiMessageSchema = zod.z.object({
898
+ method: zod.z.literal("ui/message"),
899
+ params: zod.z.object({
900
+ role: zod.z.string().optional(),
901
+ content: zod.z.array(zod.z.any()).optional(),
902
+ followUp: zod.z.boolean().optional(),
903
+ _meta: zod.z.record(zod.z.string(), zod.z.any()).optional()
904
+ }).passthrough()
905
+ });
830
906
  const MCPAppsActivityRenderer = function MCPAppsActivityRenderer({ content, agent }) {
831
907
  const { copilotkit } = useCopilotKit();
832
908
  const containerRef = (0, react.useRef)(null);
@@ -840,41 +916,12 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
840
916
  contentRef.current = content;
841
917
  const agentRef = (0, react.useRef)(agent);
842
918
  agentRef.current = agent;
919
+ const bridgeRef = (0, react.useRef)(null);
843
920
  const fetchStateRef = (0, react.useRef)({
844
921
  inProgress: false,
845
922
  promise: null,
846
923
  resourceUri: null
847
924
  });
848
- const sendToIframe = (0, react.useCallback)((msg) => {
849
- if (iframeRef.current?.contentWindow) {
850
- console.log("[MCPAppsRenderer] Sending to iframe:", msg);
851
- iframeRef.current.contentWindow.postMessage(msg, "*");
852
- }
853
- }, []);
854
- const sendResponse = (0, react.useCallback)((id, result) => {
855
- sendToIframe({
856
- jsonrpc: "2.0",
857
- id,
858
- result
859
- });
860
- }, [sendToIframe]);
861
- const sendErrorResponse = (0, react.useCallback)((id, code, message) => {
862
- sendToIframe({
863
- jsonrpc: "2.0",
864
- id,
865
- error: {
866
- code,
867
- message
868
- }
869
- });
870
- }, [sendToIframe]);
871
- const sendNotification = (0, react.useCallback)((method, params) => {
872
- sendToIframe({
873
- jsonrpc: "2.0",
874
- method,
875
- params: params || {}
876
- });
877
- }, [sendToIframe]);
878
925
  (0, react.useEffect)(() => {
879
926
  const { resourceUri, serverHash, serverId } = content;
880
927
  if (fetchStateRef.current.inProgress && fetchStateRef.current.resourceUri === resourceUri) {
@@ -929,11 +976,15 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
929
976
  const container = containerRef.current;
930
977
  if (!container) return;
931
978
  let mounted = true;
932
- let messageHandler = null;
933
- let initialListener = null;
979
+ let bridge = null;
934
980
  let createdIframe = null;
935
981
  const setup = async () => {
936
982
  try {
983
+ const bridgeModule = await import("@modelcontextprotocol/ext-apps/app-bridge").catch((importErr) => {
984
+ throw new Error("MCP Apps require '@modelcontextprotocol/ext-apps' and its peer '@modelcontextprotocol/sdk'. Install them with: npm install @modelcontextprotocol/ext-apps @modelcontextprotocol/sdk", { cause: importErr });
985
+ });
986
+ if (!mounted) return;
987
+ const { AppBridge, PostMessageTransport } = bridgeModule;
937
988
  const iframe = document.createElement("iframe");
938
989
  createdIframe = iframe;
939
990
  iframe.style.width = "100%";
@@ -944,151 +995,108 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
944
995
  iframe.setAttribute("sandbox", "allow-scripts allow-same-origin allow-forms");
945
996
  iframe.setAttribute("data-testid", "mcp-app-iframe");
946
997
  iframe.setAttribute("title", "Interactive MCP application");
947
- const sandboxReady = new Promise((resolve) => {
948
- initialListener = (event) => {
949
- if (event.source === iframe.contentWindow) {
950
- if (event.data?.method === "ui/notifications/sandbox-proxy-ready") {
951
- if (initialListener) {
952
- window.removeEventListener("message", initialListener);
953
- initialListener = null;
954
- }
955
- resolve();
956
- }
957
- }
958
- };
959
- window.addEventListener("message", initialListener);
960
- });
961
- if (!mounted) {
962
- if (initialListener) {
963
- window.removeEventListener("message", initialListener);
964
- initialListener = null;
965
- }
966
- return;
967
- }
968
998
  const cspDomains = fetchedResource._meta?.ui?.csp?.resourceDomains;
969
999
  iframe.srcdoc = buildSandboxHTML(cspDomains);
970
1000
  iframeRef.current = iframe;
971
1001
  container.appendChild(iframe);
972
- await sandboxReady;
973
- if (!mounted) return;
974
- console.log("[MCPAppsRenderer] Sandbox proxy ready");
975
- messageHandler = async (event) => {
976
- if (event.source !== iframe.contentWindow) return;
977
- const msg = event.data;
978
- if (!msg || typeof msg !== "object" || msg.jsonrpc !== "2.0") return;
979
- console.log("[MCPAppsRenderer] Received from iframe:", msg);
980
- if (isRequest(msg)) switch (msg.method) {
981
- case "ui/initialize":
982
- sendResponse(msg.id, {
983
- protocolVersion: PROTOCOL_VERSION,
984
- hostInfo: {
985
- name: "CopilotKit MCP Apps Host",
986
- version: "1.0.0"
987
- },
988
- hostCapabilities: {
989
- openLinks: {},
990
- logging: {}
991
- },
992
- hostContext: {
993
- theme: "light",
994
- platform: "web"
995
- }
996
- });
997
- break;
998
- case "ui/message": {
999
- const currentAgent = agentRef.current;
1000
- if (!currentAgent) {
1001
- console.warn("[MCPAppsRenderer] ui/message: No agent available");
1002
- sendResponse(msg.id, { isError: false });
1003
- break;
1004
- }
1005
- try {
1006
- const params = msg.params;
1007
- const role = params.role || "user";
1008
- const textContent = params.content?.filter((c) => c.type === "text" && c.text).map((c) => c.text).join("\n") || "";
1009
- if (textContent) currentAgent.addMessage({
1010
- id: crypto.randomUUID(),
1011
- role,
1012
- content: textContent
1013
- });
1014
- sendResponse(msg.id, { isError: false });
1015
- if ((params.followUp ?? role === "user") && textContent) {
1016
- const capturedThreadId = currentAgent.threadId || "default";
1017
- mcpAppsRequestQueue.enqueue(currentAgent, () => ɵrunMcpFollowUp({
1018
- host: copilotkit,
1019
- agent: currentAgent,
1020
- capturedThreadId
1021
- })).catch((err) => console.error("[MCPAppsRenderer] ui/message agent run failed:", err));
1022
- }
1023
- } catch (err) {
1024
- console.error("[MCPAppsRenderer] ui/message error:", err);
1025
- sendResponse(msg.id, { isError: true });
1026
- }
1027
- break;
1028
- }
1029
- case "ui/open-link": {
1030
- const url = msg.params?.url;
1031
- if (url) {
1032
- window.open(url, "_blank", "noopener,noreferrer");
1033
- sendResponse(msg.id, { isError: false });
1034
- } else sendErrorResponse(msg.id, -32602, "Missing url parameter");
1035
- break;
1036
- }
1037
- case "tools/call": {
1038
- const { serverHash, serverId } = contentRef.current;
1039
- const currentAgent = agentRef.current;
1040
- if (!serverHash) {
1041
- sendErrorResponse(msg.id, -32603, "No server hash available for proxying");
1042
- break;
1043
- }
1044
- if (!currentAgent) {
1045
- sendErrorResponse(msg.id, -32603, "No agent available for proxying");
1046
- break;
1047
- }
1048
- try {
1049
- const runResult = await mcpAppsRequestQueue.enqueue(currentAgent, () => currentAgent.runAgent({ forwardedProps: { __proxiedMCPRequest: {
1050
- serverHash,
1051
- serverId,
1052
- method: "tools/call",
1053
- params: msg.params
1054
- } } }));
1055
- sendResponse(msg.id, runResult.result || {});
1056
- } catch (err) {
1057
- console.error("[MCPAppsRenderer] tools/call error:", err);
1058
- sendErrorResponse(msg.id, -32603, String(err));
1059
- }
1060
- break;
1061
- }
1062
- default: sendErrorResponse(msg.id, -32601, `Method not found: ${msg.method}`);
1063
- }
1064
- if (isNotification(msg)) switch (msg.method) {
1065
- case "ui/notifications/initialized":
1066
- console.log("[MCPAppsRenderer] Inner iframe initialized");
1067
- if (mounted) setIframeReady(true);
1068
- break;
1069
- case "ui/notifications/size-changed": {
1070
- const { width, height } = msg.params || {};
1071
- console.log("[MCPAppsRenderer] Size change:", {
1072
- width,
1073
- height
1074
- });
1075
- if (mounted) setIframeSize({
1076
- width: typeof width === "number" ? width : void 0,
1077
- height: typeof height === "number" ? height : void 0
1078
- });
1079
- break;
1080
- }
1081
- case "notifications/message":
1082
- console.log("[MCPAppsRenderer] App log:", msg.params);
1083
- break;
1084
- }
1085
- };
1086
- window.addEventListener("message", messageHandler);
1002
+ const win = iframe.contentWindow;
1003
+ if (!win) throw new Error("Sandbox iframe has no contentWindow");
1087
1004
  let html;
1088
1005
  if (fetchedResource.text) html = fetchedResource.text;
1089
1006
  else if (fetchedResource.blob) html = atob(fetchedResource.blob);
1090
1007
  else throw new Error("Resource has no text or blob content");
1091
- sendNotification("ui/notifications/sandbox-resource-ready", { html });
1008
+ bridge = new AppBridge(null, {
1009
+ name: "CopilotKit MCP Apps Host",
1010
+ version: "1.0.0"
1011
+ }, {
1012
+ openLinks: {},
1013
+ logging: {},
1014
+ message: { text: {} }
1015
+ }, { hostContext: {
1016
+ theme: "light",
1017
+ platform: "web"
1018
+ } });
1019
+ bridge.onsandboxready = () => {
1020
+ bridge?.sendSandboxResourceReady({ html });
1021
+ };
1022
+ bridge.setRequestHandler(CopilotKitUiMessageSchema, async (req) => {
1023
+ const currentAgent = agentRef.current;
1024
+ if (!currentAgent) {
1025
+ console.warn("[MCPAppsRenderer] ui/message: No agent available");
1026
+ return { isError: false };
1027
+ }
1028
+ try {
1029
+ const params = req.params;
1030
+ const ck = params._meta?.copilotkit ?? {};
1031
+ const role = ck.role || params.role || "user";
1032
+ const textContent = params.content?.filter((c) => c.type === "text" && c.text).map((c) => c.text).join("\n") || "";
1033
+ if (textContent) currentAgent.addMessage({
1034
+ id: crypto.randomUUID(),
1035
+ role,
1036
+ content: textContent
1037
+ });
1038
+ if ((ck.followUp ?? params.followUp ?? role === "user") && textContent) {
1039
+ const capturedThreadId = currentAgent.threadId || "default";
1040
+ mcpAppsRequestQueue.enqueue(currentAgent, () => ɵrunMcpFollowUp({
1041
+ host: copilotkit,
1042
+ agent: currentAgent,
1043
+ capturedThreadId
1044
+ })).catch((err) => console.error("[MCPAppsRenderer] ui/message agent run failed:", err));
1045
+ }
1046
+ return { isError: false };
1047
+ } catch (err) {
1048
+ console.error("[MCPAppsRenderer] ui/message error:", err);
1049
+ return { isError: true };
1050
+ }
1051
+ });
1052
+ bridge.onopenlink = async ({ url }) => {
1053
+ let parsed;
1054
+ try {
1055
+ parsed = new URL(url);
1056
+ } catch {
1057
+ console.warn("[MCPAppsRenderer] ui/open-link rejected: unparseable url");
1058
+ return { isError: true };
1059
+ }
1060
+ if (MCP_OPEN_LINK_BLOCKED_SCHEMES.has(parsed.protocol)) {
1061
+ console.warn("[MCPAppsRenderer] ui/open-link rejected: blocked scheme", parsed.protocol);
1062
+ return { isError: true };
1063
+ }
1064
+ window.open(url, "_blank", "noopener,noreferrer");
1065
+ return { isError: false };
1066
+ };
1067
+ bridge.oncalltool = async (params) => {
1068
+ const { serverHash, serverId } = contentRef.current;
1069
+ const currentAgent = agentRef.current;
1070
+ if (!serverHash) throw new Error("No server hash available for proxying");
1071
+ if (!currentAgent) throw new Error("No agent available for proxying");
1072
+ return (await mcpAppsRequestQueue.enqueue(currentAgent, () => currentAgent.runAgent({ forwardedProps: { __proxiedMCPRequest: {
1073
+ serverHash,
1074
+ serverId,
1075
+ method: "tools/call",
1076
+ params
1077
+ } } }))).result || { content: [] };
1078
+ };
1079
+ bridge.onsizechange = (p) => {
1080
+ if (!mounted) return;
1081
+ const { width, height } = p || {};
1082
+ setIframeSize({
1083
+ width: typeof width === "number" ? width : void 0,
1084
+ height: typeof height === "number" ? height : void 0
1085
+ });
1086
+ };
1087
+ bridge.oninitialized = () => {
1088
+ if (mounted) setIframeReady(true);
1089
+ };
1090
+ bridge.onloggingmessage = (p) => {
1091
+ console.log("[MCPAppsRenderer] App log:", p);
1092
+ };
1093
+ const transport = new PostMessageTransport(win, win);
1094
+ await bridge.connect(transport);
1095
+ if (!mounted) {
1096
+ await bridge.close();
1097
+ return;
1098
+ }
1099
+ bridgeRef.current = bridge;
1092
1100
  } catch (err) {
1093
1101
  console.error("[MCPAppsRenderer] Setup error:", err);
1094
1102
  if (mounted) setError(err instanceof Error ? err : new Error(String(err)));
@@ -1097,11 +1105,8 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
1097
1105
  setup();
1098
1106
  return () => {
1099
1107
  mounted = false;
1100
- if (initialListener) {
1101
- window.removeEventListener("message", initialListener);
1102
- initialListener = null;
1103
- }
1104
- if (messageHandler) window.removeEventListener("message", messageHandler);
1108
+ bridgeRef.current = null;
1109
+ bridge?.close();
1105
1110
  if (createdIframe) {
1106
1111
  createdIframe.remove();
1107
1112
  createdIframe = null;
@@ -1111,9 +1116,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
1111
1116
  }, [
1112
1117
  isLoading,
1113
1118
  fetchedResource,
1114
- sendNotification,
1115
- sendResponse,
1116
- sendErrorResponse
1119
+ copilotkit
1117
1120
  ]);
1118
1121
  (0, react.useEffect)(() => {
1119
1122
  if (iframeRef.current) {
@@ -1125,25 +1128,11 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
1125
1128
  }
1126
1129
  }, [iframeSize]);
1127
1130
  (0, react.useEffect)(() => {
1128
- if (iframeReady && content.toolInput) {
1129
- console.log("[MCPAppsRenderer] Sending tool input:", content.toolInput);
1130
- sendNotification("ui/notifications/tool-input", { arguments: content.toolInput });
1131
- }
1132
- }, [
1133
- iframeReady,
1134
- content.toolInput,
1135
- sendNotification
1136
- ]);
1131
+ if (iframeReady && content.toolInput) bridgeRef.current?.sendToolInput({ arguments: content.toolInput });
1132
+ }, [iframeReady, content.toolInput]);
1137
1133
  (0, react.useEffect)(() => {
1138
- if (iframeReady && content.result) {
1139
- console.log("[MCPAppsRenderer] Sending tool result:", content.result);
1140
- sendNotification("ui/notifications/tool-result", content.result);
1141
- }
1142
- }, [
1143
- iframeReady,
1144
- content.result,
1145
- sendNotification
1146
- ]);
1134
+ if (iframeReady && content.result) bridgeRef.current?.sendToolResult(content.result);
1135
+ }, [iframeReady, content.result]);
1147
1136
  const borderStyle = fetchedResource?._meta?.ui?.prefersBorder === true ? {
1148
1137
  borderRadius: "8px",
1149
1138
  backgroundColor: "#f9f9f9",
@@ -2820,7 +2809,8 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
2820
2809
  tool.name,
2821
2810
  tool.available,
2822
2811
  copilotkit,
2823
- JSON.stringify(extraDeps)
2812
+ JSON.stringify(extraDeps),
2813
+ JSON.stringify(tool.webmcp ?? null)
2824
2814
  ]);
2825
2815
  }
2826
2816
 
@@ -4537,7 +4527,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
4537
4527
  switch (error.code) {
4538
4528
  case _copilotkit_shared.CopilotKitErrorCode.MISSING_PUBLIC_API_KEY_ERROR: return { primary: {
4539
4529
  label: "Show me how",
4540
- onClick: () => window.open("https://docs.copilotkit.ai/premium/overview#getting-access", "_blank", "noopener,noreferrer")
4530
+ onClick: () => window.open("https://docs.copilotkit.ai/intelligence/overview#plans-and-access", "_blank", "noopener,noreferrer")
4541
4531
  } };
4542
4532
  case _copilotkit_shared.CopilotKitErrorCode.UPGRADE_REQUIRED_ERROR: return { primary: {
4543
4533
  label: "Upgrade",
@@ -6129,7 +6119,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
6129
6119
  * `useCopilotChatHeadless_c` is for building fully custom UI (headless UI) implementations.
6130
6120
  *
6131
6121
  * <Callout title="This is a CopilotKit Intelligence feature">
6132
- * Read more about <a href="/premium/overview">CopilotKit Intelligence</a>.
6122
+ * Read more about <a href="/intelligence/overview">CopilotKit Intelligence</a>.
6133
6123
  *
6134
6124
  * Usage is generous and **free** to get started.
6135
6125
  * </Callout>
@@ -6360,7 +6350,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
6360
6350
  * See https://docs.copilotkit.ai/reference/v2/hooks/useFrontendTool
6361
6351
  */
6362
6352
  function useFrontendTool(tool, dependencies) {
6363
- const { name, description, parameters, render, followUp, available } = tool;
6353
+ const { name, description, parameters, render, followUp, available, webmcp } = tool;
6364
6354
  const zodParameters = (0, _copilotkit_shared.getZodParameters)(parameters);
6365
6355
  const renderRef = (0, react.useRef)(render);
6366
6356
  (0, react.useEffect)(() => {
@@ -6391,7 +6381,8 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
6391
6381
  handler: tool.handler ? (args) => handlerRef.current?.(args) : void 0,
6392
6382
  followUp,
6393
6383
  render: normalizedRender,
6394
- available: available === void 0 ? void 0 : available !== "disabled"
6384
+ available: available === void 0 ? void 0 : available !== "disabled",
6385
+ webmcp
6395
6386
  });
6396
6387
  }
6397
6388