@copilotkit/mcp-apps-renderer 1.71.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 (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +45 -0
  3. package/dist/activity.cjs +9 -0
  4. package/dist/activity.d.cts +4 -0
  5. package/dist/activity.d.mts +4 -0
  6. package/dist/activity.mjs +5 -0
  7. package/dist/activity.umd.js +91 -0
  8. package/dist/activity.umd.js.map +1 -0
  9. package/dist/constants.cjs +32 -0
  10. package/dist/constants.cjs.map +1 -0
  11. package/dist/constants.d.cts +23 -0
  12. package/dist/constants.d.cts.map +1 -0
  13. package/dist/constants.d.mts +23 -0
  14. package/dist/constants.d.mts.map +1 -0
  15. package/dist/constants.mjs +30 -0
  16. package/dist/constants.mjs.map +1 -0
  17. package/dist/content-schema.cjs +23 -0
  18. package/dist/content-schema.cjs.map +1 -0
  19. package/dist/content-schema.d.cts +51 -0
  20. package/dist/content-schema.d.cts.map +1 -0
  21. package/dist/content-schema.d.mts +51 -0
  22. package/dist/content-schema.d.mts.map +1 -0
  23. package/dist/content-schema.mjs +23 -0
  24. package/dist/content-schema.mjs.map +1 -0
  25. package/dist/follow-up.cjs +34 -0
  26. package/dist/follow-up.cjs.map +1 -0
  27. package/dist/follow-up.d.cts +42 -0
  28. package/dist/follow-up.d.cts.map +1 -0
  29. package/dist/follow-up.d.mts +42 -0
  30. package/dist/follow-up.d.mts.map +1 -0
  31. package/dist/follow-up.mjs +33 -0
  32. package/dist/follow-up.mjs.map +1 -0
  33. package/dist/index.d.mts +7 -0
  34. package/dist/index.mjs +8 -0
  35. package/dist/request-queue.d.mts +31 -0
  36. package/dist/request-queue.d.mts.map +1 -0
  37. package/dist/request-queue.mjs +93 -0
  38. package/dist/request-queue.mjs.map +1 -0
  39. package/dist/sandbox.d.mts +16 -0
  40. package/dist/sandbox.d.mts.map +1 -0
  41. package/dist/sandbox.mjs +52 -0
  42. package/dist/sandbox.mjs.map +1 -0
  43. package/dist/session.d.mts +81 -0
  44. package/dist/session.d.mts.map +1 -0
  45. package/dist/session.mjs +221 -0
  46. package/dist/session.mjs.map +1 -0
  47. package/package.json +77 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) Atai Barkai
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,45 @@
1
+ # @copilotkit/mcp-apps-renderer
2
+
3
+ Framework-agnostic MCP Apps host for CopilotKit: the app↔host protocol on top of
4
+ [`@modelcontextprotocol/ext-apps`](https://www.npmjs.com/package/@modelcontextprotocol/ext-apps)
5
+ (AppBridge + PostMessage transport, sandbox proxy, per-thread request queue,
6
+ `ui/message` / `ui/open-link` / `tools/call` proxy, tool input/result forwarding,
7
+ `ui/request-display-mode`). The React / Vue / Angular renderers consume it as thin
8
+ adapters: they create the sandbox iframe and wire reactive state, while all
9
+ protocol logic lives in `bindMcpApp`.
10
+
11
+ ## Entry points
12
+
13
+ | Import | Contents | Bundle |
14
+ | ---------------------------------------- | ------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------- |
15
+ | `@copilotkit/mcp-apps-renderer` | `bindMcpApp` + the full session API | **ESM only** — it wraps the ESM-only ext-apps bridge, and is meant to be loaded lazily via a dynamic `import()`. |
16
+ | `@copilotkit/mcp-apps-renderer/activity` | `MCPAppsActivityType`, `MCPAppsActivityContentSchema`, `ɵrunMcpFollowUp` | ESM + CJS. Bridge-free: importing it to register the activity does **not** pull the ext-apps bundle. |
17
+
18
+ The root is ESM-only on purpose: `@modelcontextprotocol/ext-apps` ships ESM only,
19
+ so a CommonJS root would emit a `require()` of an ES module and fail with
20
+ `ERR_REQUIRE_ESM`. Consume `bindMcpApp` via a dynamic `import()` (which resolves
21
+ ESM from any module system), and import the bridge-free `/activity` surface for
22
+ synchronous activity registration.
23
+
24
+ ## Script-tag / UMD usage
25
+
26
+ This package also ships a UMD build of the bridge-free `/activity` entry:
27
+ `dist/activity.umd.js`, which defines the global
28
+ `CopilotKitMcpAppsRendererActivity`.
29
+
30
+ `@copilotkit/react-core`'s UMD build references that global (it externalizes
31
+ `@copilotkit/mcp-apps-renderer/activity` to register the built-in MCP Apps
32
+ activity). **Script-tag consumers of react-core's UMD must therefore load
33
+ `activity.umd.js` before `@copilotkit/react-core`'s UMD bundle**, alongside the
34
+ other UMD globals it depends on (React, `CopilotKitCore`,
35
+ `CopilotKitA2UIRenderer`, …):
36
+
37
+ ```html
38
+ <!-- ...React, @copilotkit/core, @copilotkit/a2ui-renderer, etc. first... -->
39
+ <script src="https://unpkg.com/@copilotkit/mcp-apps-renderer/dist/activity.umd.js"></script>
40
+ <script src="https://unpkg.com/@copilotkit/react-core/dist/index.umd.js"></script>
41
+ ```
42
+
43
+ Only the bridge-free `/activity` surface has a UMD build; the ext-apps bridge
44
+ itself (`bindMcpApp`) is loaded lazily via `import()` and is not part of the UMD
45
+ graph, so it only loads when an MCP App is actually rendered.
@@ -0,0 +1,9 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ const require_constants = require('./constants.cjs');
3
+ const require_content_schema = require('./content-schema.cjs');
4
+ const require_follow_up = require('./follow-up.cjs');
5
+
6
+ exports.MCPAppsActivityContentSchema = require_content_schema.MCPAppsActivityContentSchema;
7
+ exports.MCPAppsActivityType = require_constants.MCPAppsActivityType;
8
+ exports.MCP_OPEN_LINK_BLOCKED_SCHEMES = require_constants.MCP_OPEN_LINK_BLOCKED_SCHEMES;
9
+ exports.ɵrunMcpFollowUp = require_follow_up.ɵrunMcpFollowUp;
@@ -0,0 +1,4 @@
1
+ import { MCPAppsActivityType, MCP_OPEN_LINK_BLOCKED_SCHEMES } from "./constants.cjs";
2
+ import { MCPAppsActivityContent, MCPAppsActivityContentSchema } from "./content-schema.cjs";
3
+ import { ɵMcpFollowUpHost, ɵrunMcpFollowUp } from "./follow-up.cjs";
4
+ export { MCPAppsActivityContent, MCPAppsActivityContentSchema, MCPAppsActivityType, MCP_OPEN_LINK_BLOCKED_SCHEMES, ɵMcpFollowUpHost, ɵrunMcpFollowUp };
@@ -0,0 +1,4 @@
1
+ import { MCPAppsActivityType, MCP_OPEN_LINK_BLOCKED_SCHEMES } from "./constants.mjs";
2
+ import { MCPAppsActivityContent, MCPAppsActivityContentSchema } from "./content-schema.mjs";
3
+ import { ɵMcpFollowUpHost, ɵrunMcpFollowUp } from "./follow-up.mjs";
4
+ export { MCPAppsActivityContent, MCPAppsActivityContentSchema, MCPAppsActivityType, MCP_OPEN_LINK_BLOCKED_SCHEMES, ɵMcpFollowUpHost, ɵrunMcpFollowUp };
@@ -0,0 +1,5 @@
1
+ import { MCPAppsActivityType, MCP_OPEN_LINK_BLOCKED_SCHEMES } from "./constants.mjs";
2
+ import { MCPAppsActivityContentSchema } from "./content-schema.mjs";
3
+ import { ɵrunMcpFollowUp } from "./follow-up.mjs";
4
+
5
+ export { MCPAppsActivityContentSchema, MCPAppsActivityType, MCP_OPEN_LINK_BLOCKED_SCHEMES, ɵrunMcpFollowUp };
@@ -0,0 +1,91 @@
1
+ (function(global, factory) {
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('zod')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', 'zod'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.CopilotKitMcpAppsRendererActivity = {}), global.Zod));
5
+ })(this, function(exports, zod) {
6
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
7
+
8
+ //#region src/constants.ts
9
+ /**
10
+ * Activity type for MCP Apps events - must match the middleware's MCPAppsActivityType.
11
+ */
12
+ const MCPAppsActivityType = "mcp-apps";
13
+ /**
14
+ * URL schemes a widget may NOT open via ui/open-link. The ext-apps schema
15
+ * validates `url` as a plain string only (noopener/noreferrer does not restrict
16
+ * the scheme), so ui/open-link could otherwise become an XSS vector.
17
+ *
18
+ * We use a denylist rather than an allowlist on purpose: deep links use
19
+ * arbitrary, app-defined schemes (`myapp:`, `whatsapp:`, `slack:`, `spotify:`,
20
+ * `sms:`, ...) that an allowlist could never enumerate, and `window.open`ing them
21
+ * just hands off to an OS handler - it does not execute script in the page, so
22
+ * it is not an XSS risk. Universal links / App Links are plain `https:` URLs and
23
+ * pass regardless. What IS dangerous is the small, well-known set of schemes
24
+ * that execute script or render attacker HTML in the page context; block those
25
+ * and allow everything else (including deep links).
26
+ */
27
+ const MCP_OPEN_LINK_BLOCKED_SCHEMES = new Set([
28
+ "javascript:",
29
+ "data:",
30
+ "vbscript:",
31
+ "blob:",
32
+ "file:"
33
+ ]);
34
+
35
+ //#endregion
36
+ //#region src/content-schema.ts
37
+ /**
38
+ * Zod schema for MCP Apps activity content (middleware 0.0.2 format). The
39
+ * framework activity registries validate the activity content with this before
40
+ * handing it to the renderer/session.
41
+ */
42
+ const MCPAppsActivityContentSchema = zod.z.object({
43
+ result: zod.z.object({
44
+ content: zod.z.array(zod.z.any()).optional(),
45
+ structuredContent: zod.z.any().optional(),
46
+ isError: zod.z.boolean().optional()
47
+ }),
48
+ resourceUri: zod.z.string(),
49
+ serverHash: zod.z.string(),
50
+ serverId: zod.z.string().optional(),
51
+ toolInput: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
52
+ });
53
+
54
+ //#endregion
55
+ //#region src/follow-up.ts
56
+ /**
57
+ * Run an MCP app `ui/message` follow-up, scoped to the thread it was enqueued
58
+ * for (issue #5819).
59
+ *
60
+ * The MCP request queue delays follow-up work until the agent is idle. There is
61
+ * a single shared registry agent per id, and switching threads overwrites its
62
+ * `threadId`/`messages` in place. So if the host switches threads while a
63
+ * follow-up is queued, running it now would execute against — and stream into —
64
+ * the now-foreground thread.
65
+ *
66
+ * - **Same thread** (the common case): run on the shared agent, unchanged.
67
+ * - **Thread changed**: the shared agent has moved on, so the follow-up can no
68
+ * longer run in its originating thread's context. Drop it rather than leak it
69
+ * into the current thread. (The MCP app already received its `ui/message` ack
70
+ * at enqueue time; only the optional agent turn is skipped.)
71
+ *
72
+ * @internal exported for testing.
73
+ */
74
+ async function ɵrunMcpFollowUp({ host, agent, capturedThreadId }) {
75
+ const currentThreadId = agent.threadId || "default";
76
+ const originThreadId = capturedThreadId || "default";
77
+ if (currentThreadId === originThreadId) return host.runAgent({ agent });
78
+ console.warn(`[MCPAppsRenderer] ui/message follow-up dropped: the thread changed (${originThreadId} → ${currentThreadId}) between enqueue and execution, so running it would leak into the now-foreground thread.`);
79
+ return {
80
+ result: void 0,
81
+ newMessages: []
82
+ };
83
+ }
84
+
85
+ //#endregion
86
+ exports.MCPAppsActivityContentSchema = MCPAppsActivityContentSchema;
87
+ exports.MCPAppsActivityType = MCPAppsActivityType;
88
+ exports.MCP_OPEN_LINK_BLOCKED_SCHEMES = MCP_OPEN_LINK_BLOCKED_SCHEMES;
89
+ exports.ɵrunMcpFollowUp = ɵrunMcpFollowUp;
90
+ });
91
+ //# sourceMappingURL=activity.umd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity.umd.js","names":["z"],"sources":["../src/constants.ts","../src/content-schema.ts","../src/follow-up.ts"],"sourcesContent":["/**\n * Activity type for MCP Apps events - must match the middleware's MCPAppsActivityType.\n */\nexport const MCPAppsActivityType = \"mcp-apps\";\n\n/**\n * URL schemes a widget may NOT open via ui/open-link. The ext-apps schema\n * validates `url` as a plain string only (noopener/noreferrer does not restrict\n * the scheme), so ui/open-link could otherwise become an XSS vector.\n *\n * We use a denylist rather than an allowlist on purpose: deep links use\n * arbitrary, app-defined schemes (`myapp:`, `whatsapp:`, `slack:`, `spotify:`,\n * `sms:`, ...) that an allowlist could never enumerate, and `window.open`ing them\n * just hands off to an OS handler - it does not execute script in the page, so\n * it is not an XSS risk. Universal links / App Links are plain `https:` URLs and\n * pass regardless. What IS dangerous is the small, well-known set of schemes\n * that execute script or render attacker HTML in the page context; block those\n * and allow everything else (including deep links).\n */\nexport const MCP_OPEN_LINK_BLOCKED_SCHEMES = new Set([\n \"javascript:\",\n \"data:\",\n \"vbscript:\",\n \"blob:\",\n \"file:\",\n]);\n","import { z } from \"zod\";\n\n/**\n * Zod schema for MCP Apps activity content (middleware 0.0.2 format). The\n * framework activity registries validate the activity content with this before\n * handing it to the renderer/session.\n */\nexport const MCPAppsActivityContentSchema = z.object({\n result: z.object({\n content: z.array(z.any()).optional(),\n structuredContent: z.any().optional(),\n isError: z.boolean().optional(),\n }),\n // Resource URI to fetch (e.g., \"ui://server/dashboard\")\n resourceUri: z.string(),\n // MD5 hash of server config (renamed from serverId in 0.0.1)\n serverHash: z.string(),\n // Optional stable server ID from config (takes precedence over serverHash)\n serverId: z.string().optional(),\n // Original tool input arguments\n toolInput: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport type MCPAppsActivityContent = z.infer<\n typeof MCPAppsActivityContentSchema\n>;\n","import type { AbstractAgent, RunAgentResult } from \"@ag-ui/client\";\n\n/**\n * The subset of `CopilotKitCore` that {@link ɵrunMcpFollowUp} depends on.\n * Declared structurally so the runner can be unit-tested without a full core.\n */\nexport interface ɵMcpFollowUpHost {\n runAgent(params: { agent: AbstractAgent }): Promise<RunAgentResult>;\n}\n\n/**\n * Run an MCP app `ui/message` follow-up, scoped to the thread it was enqueued\n * for (issue #5819).\n *\n * The MCP request queue delays follow-up work until the agent is idle. There is\n * a single shared registry agent per id, and switching threads overwrites its\n * `threadId`/`messages` in place. So if the host switches threads while a\n * follow-up is queued, running it now would execute against — and stream into —\n * the now-foreground thread.\n *\n * - **Same thread** (the common case): run on the shared agent, unchanged.\n * - **Thread changed**: the shared agent has moved on, so the follow-up can no\n * longer run in its originating thread's context. Drop it rather than leak it\n * into the current thread. (The MCP app already received its `ui/message` ack\n * at enqueue time; only the optional agent turn is skipped.)\n *\n * @internal exported for testing.\n */\nexport async function ɵrunMcpFollowUp({\n host,\n agent,\n capturedThreadId,\n}: {\n host: ɵMcpFollowUpHost;\n agent: AbstractAgent;\n capturedThreadId: string;\n}): Promise<RunAgentResult> {\n const currentThreadId = agent.threadId || \"default\";\n const originThreadId = capturedThreadId || \"default\";\n\n if (currentThreadId === originThreadId) {\n return host.runAgent({ agent });\n }\n\n console.warn(\n \"[MCPAppsRenderer] ui/message follow-up dropped: the thread changed \" +\n `(${originThreadId} → ${currentThreadId}) between enqueue and execution, ` +\n \"so running it would leak into the now-foreground thread.\",\n );\n return { result: undefined, newMessages: [] };\n}\n"],"mappings":";;;;;;;;;;;CAGA,MAAa,sBAAsB;;;;;;;;;;;;;;;CAgBnC,MAAa,gCAAgC,IAAI,IAAI;EACnD;EACA;EACA;EACA;EACA;EACD,CAAC;;;;;;;;;CClBF,MAAa,+BAA+BA,MAAE,OAAO;EACnD,QAAQA,MAAE,OAAO;GACf,SAASA,MAAE,MAAMA,MAAE,KAAK,CAAC,CAAC,UAAU;GACpC,mBAAmBA,MAAE,KAAK,CAAC,UAAU;GACrC,SAASA,MAAE,SAAS,CAAC,UAAU;GAChC,CAAC;EAEF,aAAaA,MAAE,QAAQ;EAEvB,YAAYA,MAAE,QAAQ;EAEtB,UAAUA,MAAE,QAAQ,CAAC,UAAU;EAE/B,WAAWA,MAAE,OAAOA,MAAE,QAAQ,EAAEA,MAAE,SAAS,CAAC,CAAC,UAAU;EACxD,CAAC;;;;;;;;;;;;;;;;;;;;;;CCOF,eAAsB,gBAAgB,EACpC,MACA,OACA,oBAK0B;EAC1B,MAAM,kBAAkB,MAAM,YAAY;EAC1C,MAAM,iBAAiB,oBAAoB;AAE3C,MAAI,oBAAoB,eACtB,QAAO,KAAK,SAAS,EAAE,OAAO,CAAC;AAGjC,UAAQ,KACN,uEACM,eAAe,KAAK,gBAAgB,2FAE3C;AACD,SAAO;GAAE,QAAQ;GAAW,aAAa,EAAE;GAAE"}
@@ -0,0 +1,32 @@
1
+
2
+ //#region src/constants.ts
3
+ /**
4
+ * Activity type for MCP Apps events - must match the middleware's MCPAppsActivityType.
5
+ */
6
+ const MCPAppsActivityType = "mcp-apps";
7
+ /**
8
+ * URL schemes a widget may NOT open via ui/open-link. The ext-apps schema
9
+ * validates `url` as a plain string only (noopener/noreferrer does not restrict
10
+ * the scheme), so ui/open-link could otherwise become an XSS vector.
11
+ *
12
+ * We use a denylist rather than an allowlist on purpose: deep links use
13
+ * arbitrary, app-defined schemes (`myapp:`, `whatsapp:`, `slack:`, `spotify:`,
14
+ * `sms:`, ...) that an allowlist could never enumerate, and `window.open`ing them
15
+ * just hands off to an OS handler - it does not execute script in the page, so
16
+ * it is not an XSS risk. Universal links / App Links are plain `https:` URLs and
17
+ * pass regardless. What IS dangerous is the small, well-known set of schemes
18
+ * that execute script or render attacker HTML in the page context; block those
19
+ * and allow everything else (including deep links).
20
+ */
21
+ const MCP_OPEN_LINK_BLOCKED_SCHEMES = new Set([
22
+ "javascript:",
23
+ "data:",
24
+ "vbscript:",
25
+ "blob:",
26
+ "file:"
27
+ ]);
28
+
29
+ //#endregion
30
+ exports.MCPAppsActivityType = MCPAppsActivityType;
31
+ exports.MCP_OPEN_LINK_BLOCKED_SCHEMES = MCP_OPEN_LINK_BLOCKED_SCHEMES;
32
+ //# sourceMappingURL=constants.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.cjs","names":[],"sources":["../src/constants.ts"],"sourcesContent":["/**\n * Activity type for MCP Apps events - must match the middleware's MCPAppsActivityType.\n */\nexport const MCPAppsActivityType = \"mcp-apps\";\n\n/**\n * URL schemes a widget may NOT open via ui/open-link. The ext-apps schema\n * validates `url` as a plain string only (noopener/noreferrer does not restrict\n * the scheme), so ui/open-link could otherwise become an XSS vector.\n *\n * We use a denylist rather than an allowlist on purpose: deep links use\n * arbitrary, app-defined schemes (`myapp:`, `whatsapp:`, `slack:`, `spotify:`,\n * `sms:`, ...) that an allowlist could never enumerate, and `window.open`ing them\n * just hands off to an OS handler - it does not execute script in the page, so\n * it is not an XSS risk. Universal links / App Links are plain `https:` URLs and\n * pass regardless. What IS dangerous is the small, well-known set of schemes\n * that execute script or render attacker HTML in the page context; block those\n * and allow everything else (including deep links).\n */\nexport const MCP_OPEN_LINK_BLOCKED_SCHEMES = new Set([\n \"javascript:\",\n \"data:\",\n \"vbscript:\",\n \"blob:\",\n \"file:\",\n]);\n"],"mappings":";;;;;AAGA,MAAa,sBAAsB;;;;;;;;;;;;;;;AAgBnC,MAAa,gCAAgC,IAAI,IAAI;CACnD;CACA;CACA;CACA;CACA;CACD,CAAC"}
@@ -0,0 +1,23 @@
1
+ //#region src/constants.d.ts
2
+ /**
3
+ * Activity type for MCP Apps events - must match the middleware's MCPAppsActivityType.
4
+ */
5
+ declare const MCPAppsActivityType = "mcp-apps";
6
+ /**
7
+ * URL schemes a widget may NOT open via ui/open-link. The ext-apps schema
8
+ * validates `url` as a plain string only (noopener/noreferrer does not restrict
9
+ * the scheme), so ui/open-link could otherwise become an XSS vector.
10
+ *
11
+ * We use a denylist rather than an allowlist on purpose: deep links use
12
+ * arbitrary, app-defined schemes (`myapp:`, `whatsapp:`, `slack:`, `spotify:`,
13
+ * `sms:`, ...) that an allowlist could never enumerate, and `window.open`ing them
14
+ * just hands off to an OS handler - it does not execute script in the page, so
15
+ * it is not an XSS risk. Universal links / App Links are plain `https:` URLs and
16
+ * pass regardless. What IS dangerous is the small, well-known set of schemes
17
+ * that execute script or render attacker HTML in the page context; block those
18
+ * and allow everything else (including deep links).
19
+ */
20
+ declare const MCP_OPEN_LINK_BLOCKED_SCHEMES: Set<string>;
21
+ //#endregion
22
+ export { MCPAppsActivityType, MCP_OPEN_LINK_BLOCKED_SCHEMES };
23
+ //# sourceMappingURL=constants.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.cts","names":[],"sources":["../src/constants.ts"],"mappings":";;AAGA;;cAAa,mBAAA;;;AAgBb;;;;;;;;;;;;cAAa,6BAAA,EAA6B,GAAA"}
@@ -0,0 +1,23 @@
1
+ //#region src/constants.d.ts
2
+ /**
3
+ * Activity type for MCP Apps events - must match the middleware's MCPAppsActivityType.
4
+ */
5
+ declare const MCPAppsActivityType = "mcp-apps";
6
+ /**
7
+ * URL schemes a widget may NOT open via ui/open-link. The ext-apps schema
8
+ * validates `url` as a plain string only (noopener/noreferrer does not restrict
9
+ * the scheme), so ui/open-link could otherwise become an XSS vector.
10
+ *
11
+ * We use a denylist rather than an allowlist on purpose: deep links use
12
+ * arbitrary, app-defined schemes (`myapp:`, `whatsapp:`, `slack:`, `spotify:`,
13
+ * `sms:`, ...) that an allowlist could never enumerate, and `window.open`ing them
14
+ * just hands off to an OS handler - it does not execute script in the page, so
15
+ * it is not an XSS risk. Universal links / App Links are plain `https:` URLs and
16
+ * pass regardless. What IS dangerous is the small, well-known set of schemes
17
+ * that execute script or render attacker HTML in the page context; block those
18
+ * and allow everything else (including deep links).
19
+ */
20
+ declare const MCP_OPEN_LINK_BLOCKED_SCHEMES: Set<string>;
21
+ //#endregion
22
+ export { MCPAppsActivityType, MCP_OPEN_LINK_BLOCKED_SCHEMES };
23
+ //# sourceMappingURL=constants.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.mts","names":[],"sources":["../src/constants.ts"],"mappings":";;AAGA;;cAAa,mBAAA;;;AAgBb;;;;;;;;;;;;cAAa,6BAAA,EAA6B,GAAA"}
@@ -0,0 +1,30 @@
1
+ //#region src/constants.ts
2
+ /**
3
+ * Activity type for MCP Apps events - must match the middleware's MCPAppsActivityType.
4
+ */
5
+ const MCPAppsActivityType = "mcp-apps";
6
+ /**
7
+ * URL schemes a widget may NOT open via ui/open-link. The ext-apps schema
8
+ * validates `url` as a plain string only (noopener/noreferrer does not restrict
9
+ * the scheme), so ui/open-link could otherwise become an XSS vector.
10
+ *
11
+ * We use a denylist rather than an allowlist on purpose: deep links use
12
+ * arbitrary, app-defined schemes (`myapp:`, `whatsapp:`, `slack:`, `spotify:`,
13
+ * `sms:`, ...) that an allowlist could never enumerate, and `window.open`ing them
14
+ * just hands off to an OS handler - it does not execute script in the page, so
15
+ * it is not an XSS risk. Universal links / App Links are plain `https:` URLs and
16
+ * pass regardless. What IS dangerous is the small, well-known set of schemes
17
+ * that execute script or render attacker HTML in the page context; block those
18
+ * and allow everything else (including deep links).
19
+ */
20
+ const MCP_OPEN_LINK_BLOCKED_SCHEMES = new Set([
21
+ "javascript:",
22
+ "data:",
23
+ "vbscript:",
24
+ "blob:",
25
+ "file:"
26
+ ]);
27
+
28
+ //#endregion
29
+ export { MCPAppsActivityType, MCP_OPEN_LINK_BLOCKED_SCHEMES };
30
+ //# sourceMappingURL=constants.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.mjs","names":[],"sources":["../src/constants.ts"],"sourcesContent":["/**\n * Activity type for MCP Apps events - must match the middleware's MCPAppsActivityType.\n */\nexport const MCPAppsActivityType = \"mcp-apps\";\n\n/**\n * URL schemes a widget may NOT open via ui/open-link. The ext-apps schema\n * validates `url` as a plain string only (noopener/noreferrer does not restrict\n * the scheme), so ui/open-link could otherwise become an XSS vector.\n *\n * We use a denylist rather than an allowlist on purpose: deep links use\n * arbitrary, app-defined schemes (`myapp:`, `whatsapp:`, `slack:`, `spotify:`,\n * `sms:`, ...) that an allowlist could never enumerate, and `window.open`ing them\n * just hands off to an OS handler - it does not execute script in the page, so\n * it is not an XSS risk. Universal links / App Links are plain `https:` URLs and\n * pass regardless. What IS dangerous is the small, well-known set of schemes\n * that execute script or render attacker HTML in the page context; block those\n * and allow everything else (including deep links).\n */\nexport const MCP_OPEN_LINK_BLOCKED_SCHEMES = new Set([\n \"javascript:\",\n \"data:\",\n \"vbscript:\",\n \"blob:\",\n \"file:\",\n]);\n"],"mappings":";;;;AAGA,MAAa,sBAAsB;;;;;;;;;;;;;;;AAgBnC,MAAa,gCAAgC,IAAI,IAAI;CACnD;CACA;CACA;CACA;CACA;CACD,CAAC"}
@@ -0,0 +1,23 @@
1
+ let zod = require("zod");
2
+
3
+ //#region src/content-schema.ts
4
+ /**
5
+ * Zod schema for MCP Apps activity content (middleware 0.0.2 format). The
6
+ * framework activity registries validate the activity content with this before
7
+ * handing it to the renderer/session.
8
+ */
9
+ const MCPAppsActivityContentSchema = zod.z.object({
10
+ result: zod.z.object({
11
+ content: zod.z.array(zod.z.any()).optional(),
12
+ structuredContent: zod.z.any().optional(),
13
+ isError: zod.z.boolean().optional()
14
+ }),
15
+ resourceUri: zod.z.string(),
16
+ serverHash: zod.z.string(),
17
+ serverId: zod.z.string().optional(),
18
+ toolInput: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
19
+ });
20
+
21
+ //#endregion
22
+ exports.MCPAppsActivityContentSchema = MCPAppsActivityContentSchema;
23
+ //# sourceMappingURL=content-schema.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-schema.cjs","names":["z"],"sources":["../src/content-schema.ts"],"sourcesContent":["import { z } from \"zod\";\n\n/**\n * Zod schema for MCP Apps activity content (middleware 0.0.2 format). The\n * framework activity registries validate the activity content with this before\n * handing it to the renderer/session.\n */\nexport const MCPAppsActivityContentSchema = z.object({\n result: z.object({\n content: z.array(z.any()).optional(),\n structuredContent: z.any().optional(),\n isError: z.boolean().optional(),\n }),\n // Resource URI to fetch (e.g., \"ui://server/dashboard\")\n resourceUri: z.string(),\n // MD5 hash of server config (renamed from serverId in 0.0.1)\n serverHash: z.string(),\n // Optional stable server ID from config (takes precedence over serverHash)\n serverId: z.string().optional(),\n // Original tool input arguments\n toolInput: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport type MCPAppsActivityContent = z.infer<\n typeof MCPAppsActivityContentSchema\n>;\n"],"mappings":";;;;;;;;AAOA,MAAa,+BAA+BA,MAAE,OAAO;CACnD,QAAQA,MAAE,OAAO;EACf,SAASA,MAAE,MAAMA,MAAE,KAAK,CAAC,CAAC,UAAU;EACpC,mBAAmBA,MAAE,KAAK,CAAC,UAAU;EACrC,SAASA,MAAE,SAAS,CAAC,UAAU;EAChC,CAAC;CAEF,aAAaA,MAAE,QAAQ;CAEvB,YAAYA,MAAE,QAAQ;CAEtB,UAAUA,MAAE,QAAQ,CAAC,UAAU;CAE/B,WAAWA,MAAE,OAAOA,MAAE,QAAQ,EAAEA,MAAE,SAAS,CAAC,CAAC,UAAU;CACxD,CAAC"}
@@ -0,0 +1,51 @@
1
+ import { z } from "zod";
2
+
3
+ //#region src/content-schema.d.ts
4
+ /**
5
+ * Zod schema for MCP Apps activity content (middleware 0.0.2 format). The
6
+ * framework activity registries validate the activity content with this before
7
+ * handing it to the renderer/session.
8
+ */
9
+ declare const MCPAppsActivityContentSchema: z.ZodObject<{
10
+ result: z.ZodObject<{
11
+ content: z.ZodOptional<z.ZodArray<z.ZodAny, "many">>;
12
+ structuredContent: z.ZodOptional<z.ZodAny>;
13
+ isError: z.ZodOptional<z.ZodBoolean>;
14
+ }, "strip", z.ZodTypeAny, {
15
+ content?: any[] | undefined;
16
+ structuredContent?: any;
17
+ isError?: boolean | undefined;
18
+ }, {
19
+ content?: any[] | undefined;
20
+ structuredContent?: any;
21
+ isError?: boolean | undefined;
22
+ }>;
23
+ resourceUri: z.ZodString;
24
+ serverHash: z.ZodString;
25
+ serverId: z.ZodOptional<z.ZodString>;
26
+ toolInput: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
27
+ }, "strip", z.ZodTypeAny, {
28
+ result: {
29
+ content?: any[] | undefined;
30
+ structuredContent?: any;
31
+ isError?: boolean | undefined;
32
+ };
33
+ resourceUri: string;
34
+ serverHash: string;
35
+ serverId?: string | undefined;
36
+ toolInput?: Record<string, unknown> | undefined;
37
+ }, {
38
+ result: {
39
+ content?: any[] | undefined;
40
+ structuredContent?: any;
41
+ isError?: boolean | undefined;
42
+ };
43
+ resourceUri: string;
44
+ serverHash: string;
45
+ serverId?: string | undefined;
46
+ toolInput?: Record<string, unknown> | undefined;
47
+ }>;
48
+ type MCPAppsActivityContent = z.infer<typeof MCPAppsActivityContentSchema>;
49
+ //#endregion
50
+ export { MCPAppsActivityContent, MCPAppsActivityContentSchema };
51
+ //# sourceMappingURL=content-schema.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-schema.d.cts","names":[],"sources":["../src/content-schema.ts"],"mappings":";;;;;AAOA;;;cAAa,4BAAA,EAA4B,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAgB7B,sBAAA,GAAyB,CAAA,CAAE,KAAA,QAC9B,4BAAA"}
@@ -0,0 +1,51 @@
1
+ import { z } from "zod";
2
+
3
+ //#region src/content-schema.d.ts
4
+ /**
5
+ * Zod schema for MCP Apps activity content (middleware 0.0.2 format). The
6
+ * framework activity registries validate the activity content with this before
7
+ * handing it to the renderer/session.
8
+ */
9
+ declare const MCPAppsActivityContentSchema: z.ZodObject<{
10
+ result: z.ZodObject<{
11
+ content: z.ZodOptional<z.ZodArray<z.ZodAny, "many">>;
12
+ structuredContent: z.ZodOptional<z.ZodAny>;
13
+ isError: z.ZodOptional<z.ZodBoolean>;
14
+ }, "strip", z.ZodTypeAny, {
15
+ content?: any[] | undefined;
16
+ structuredContent?: any;
17
+ isError?: boolean | undefined;
18
+ }, {
19
+ content?: any[] | undefined;
20
+ structuredContent?: any;
21
+ isError?: boolean | undefined;
22
+ }>;
23
+ resourceUri: z.ZodString;
24
+ serverHash: z.ZodString;
25
+ serverId: z.ZodOptional<z.ZodString>;
26
+ toolInput: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
27
+ }, "strip", z.ZodTypeAny, {
28
+ result: {
29
+ content?: any[] | undefined;
30
+ structuredContent?: any;
31
+ isError?: boolean | undefined;
32
+ };
33
+ resourceUri: string;
34
+ serverHash: string;
35
+ serverId?: string | undefined;
36
+ toolInput?: Record<string, unknown> | undefined;
37
+ }, {
38
+ result: {
39
+ content?: any[] | undefined;
40
+ structuredContent?: any;
41
+ isError?: boolean | undefined;
42
+ };
43
+ resourceUri: string;
44
+ serverHash: string;
45
+ serverId?: string | undefined;
46
+ toolInput?: Record<string, unknown> | undefined;
47
+ }>;
48
+ type MCPAppsActivityContent = z.infer<typeof MCPAppsActivityContentSchema>;
49
+ //#endregion
50
+ export { MCPAppsActivityContent, MCPAppsActivityContentSchema };
51
+ //# sourceMappingURL=content-schema.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-schema.d.mts","names":[],"sources":["../src/content-schema.ts"],"mappings":";;;;;AAOA;;;cAAa,4BAAA,EAA4B,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAgB7B,sBAAA,GAAyB,CAAA,CAAE,KAAA,QAC9B,4BAAA"}
@@ -0,0 +1,23 @@
1
+ import { z } from "zod";
2
+
3
+ //#region src/content-schema.ts
4
+ /**
5
+ * Zod schema for MCP Apps activity content (middleware 0.0.2 format). The
6
+ * framework activity registries validate the activity content with this before
7
+ * handing it to the renderer/session.
8
+ */
9
+ const MCPAppsActivityContentSchema = z.object({
10
+ result: z.object({
11
+ content: z.array(z.any()).optional(),
12
+ structuredContent: z.any().optional(),
13
+ isError: z.boolean().optional()
14
+ }),
15
+ resourceUri: z.string(),
16
+ serverHash: z.string(),
17
+ serverId: z.string().optional(),
18
+ toolInput: z.record(z.string(), z.unknown()).optional()
19
+ });
20
+
21
+ //#endregion
22
+ export { MCPAppsActivityContentSchema };
23
+ //# sourceMappingURL=content-schema.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-schema.mjs","names":[],"sources":["../src/content-schema.ts"],"sourcesContent":["import { z } from \"zod\";\n\n/**\n * Zod schema for MCP Apps activity content (middleware 0.0.2 format). The\n * framework activity registries validate the activity content with this before\n * handing it to the renderer/session.\n */\nexport const MCPAppsActivityContentSchema = z.object({\n result: z.object({\n content: z.array(z.any()).optional(),\n structuredContent: z.any().optional(),\n isError: z.boolean().optional(),\n }),\n // Resource URI to fetch (e.g., \"ui://server/dashboard\")\n resourceUri: z.string(),\n // MD5 hash of server config (renamed from serverId in 0.0.1)\n serverHash: z.string(),\n // Optional stable server ID from config (takes precedence over serverHash)\n serverId: z.string().optional(),\n // Original tool input arguments\n toolInput: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport type MCPAppsActivityContent = z.infer<\n typeof MCPAppsActivityContentSchema\n>;\n"],"mappings":";;;;;;;;AAOA,MAAa,+BAA+B,EAAE,OAAO;CACnD,QAAQ,EAAE,OAAO;EACf,SAAS,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,UAAU;EACpC,mBAAmB,EAAE,KAAK,CAAC,UAAU;EACrC,SAAS,EAAE,SAAS,CAAC,UAAU;EAChC,CAAC;CAEF,aAAa,EAAE,QAAQ;CAEvB,YAAY,EAAE,QAAQ;CAEtB,UAAU,EAAE,QAAQ,CAAC,UAAU;CAE/B,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,SAAS,CAAC,CAAC,UAAU;CACxD,CAAC"}
@@ -0,0 +1,34 @@
1
+
2
+ //#region src/follow-up.ts
3
+ /**
4
+ * Run an MCP app `ui/message` follow-up, scoped to the thread it was enqueued
5
+ * for (issue #5819).
6
+ *
7
+ * The MCP request queue delays follow-up work until the agent is idle. There is
8
+ * a single shared registry agent per id, and switching threads overwrites its
9
+ * `threadId`/`messages` in place. So if the host switches threads while a
10
+ * follow-up is queued, running it now would execute against — and stream into —
11
+ * the now-foreground thread.
12
+ *
13
+ * - **Same thread** (the common case): run on the shared agent, unchanged.
14
+ * - **Thread changed**: the shared agent has moved on, so the follow-up can no
15
+ * longer run in its originating thread's context. Drop it rather than leak it
16
+ * into the current thread. (The MCP app already received its `ui/message` ack
17
+ * at enqueue time; only the optional agent turn is skipped.)
18
+ *
19
+ * @internal exported for testing.
20
+ */
21
+ async function ɵrunMcpFollowUp({ host, agent, capturedThreadId }) {
22
+ const currentThreadId = agent.threadId || "default";
23
+ const originThreadId = capturedThreadId || "default";
24
+ if (currentThreadId === originThreadId) return host.runAgent({ agent });
25
+ console.warn(`[MCPAppsRenderer] ui/message follow-up dropped: the thread changed (${originThreadId} → ${currentThreadId}) between enqueue and execution, so running it would leak into the now-foreground thread.`);
26
+ return {
27
+ result: void 0,
28
+ newMessages: []
29
+ };
30
+ }
31
+
32
+ //#endregion
33
+ exports.ɵrunMcpFollowUp = ɵrunMcpFollowUp;
34
+ //# sourceMappingURL=follow-up.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"follow-up.cjs","names":[],"sources":["../src/follow-up.ts"],"sourcesContent":["import type { AbstractAgent, RunAgentResult } from \"@ag-ui/client\";\n\n/**\n * The subset of `CopilotKitCore` that {@link ɵrunMcpFollowUp} depends on.\n * Declared structurally so the runner can be unit-tested without a full core.\n */\nexport interface ɵMcpFollowUpHost {\n runAgent(params: { agent: AbstractAgent }): Promise<RunAgentResult>;\n}\n\n/**\n * Run an MCP app `ui/message` follow-up, scoped to the thread it was enqueued\n * for (issue #5819).\n *\n * The MCP request queue delays follow-up work until the agent is idle. There is\n * a single shared registry agent per id, and switching threads overwrites its\n * `threadId`/`messages` in place. So if the host switches threads while a\n * follow-up is queued, running it now would execute against — and stream into —\n * the now-foreground thread.\n *\n * - **Same thread** (the common case): run on the shared agent, unchanged.\n * - **Thread changed**: the shared agent has moved on, so the follow-up can no\n * longer run in its originating thread's context. Drop it rather than leak it\n * into the current thread. (The MCP app already received its `ui/message` ack\n * at enqueue time; only the optional agent turn is skipped.)\n *\n * @internal exported for testing.\n */\nexport async function ɵrunMcpFollowUp({\n host,\n agent,\n capturedThreadId,\n}: {\n host: ɵMcpFollowUpHost;\n agent: AbstractAgent;\n capturedThreadId: string;\n}): Promise<RunAgentResult> {\n const currentThreadId = agent.threadId || \"default\";\n const originThreadId = capturedThreadId || \"default\";\n\n if (currentThreadId === originThreadId) {\n return host.runAgent({ agent });\n }\n\n console.warn(\n \"[MCPAppsRenderer] ui/message follow-up dropped: the thread changed \" +\n `(${originThreadId} → ${currentThreadId}) between enqueue and execution, ` +\n \"so running it would leak into the now-foreground thread.\",\n );\n return { result: undefined, newMessages: [] };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA4BA,eAAsB,gBAAgB,EACpC,MACA,OACA,oBAK0B;CAC1B,MAAM,kBAAkB,MAAM,YAAY;CAC1C,MAAM,iBAAiB,oBAAoB;AAE3C,KAAI,oBAAoB,eACtB,QAAO,KAAK,SAAS,EAAE,OAAO,CAAC;AAGjC,SAAQ,KACN,uEACM,eAAe,KAAK,gBAAgB,2FAE3C;AACD,QAAO;EAAE,QAAQ;EAAW,aAAa,EAAE;EAAE"}
@@ -0,0 +1,42 @@
1
+ import { AbstractAgent, RunAgentResult } from "@ag-ui/client";
2
+
3
+ //#region src/follow-up.d.ts
4
+ /**
5
+ * The subset of `CopilotKitCore` that {@link ɵrunMcpFollowUp} depends on.
6
+ * Declared structurally so the runner can be unit-tested without a full core.
7
+ */
8
+ interface ɵMcpFollowUpHost {
9
+ runAgent(params: {
10
+ agent: AbstractAgent;
11
+ }): Promise<RunAgentResult>;
12
+ }
13
+ /**
14
+ * Run an MCP app `ui/message` follow-up, scoped to the thread it was enqueued
15
+ * for (issue #5819).
16
+ *
17
+ * The MCP request queue delays follow-up work until the agent is idle. There is
18
+ * a single shared registry agent per id, and switching threads overwrites its
19
+ * `threadId`/`messages` in place. So if the host switches threads while a
20
+ * follow-up is queued, running it now would execute against — and stream into —
21
+ * the now-foreground thread.
22
+ *
23
+ * - **Same thread** (the common case): run on the shared agent, unchanged.
24
+ * - **Thread changed**: the shared agent has moved on, so the follow-up can no
25
+ * longer run in its originating thread's context. Drop it rather than leak it
26
+ * into the current thread. (The MCP app already received its `ui/message` ack
27
+ * at enqueue time; only the optional agent turn is skipped.)
28
+ *
29
+ * @internal exported for testing.
30
+ */
31
+ declare function ɵrunMcpFollowUp({
32
+ host,
33
+ agent,
34
+ capturedThreadId
35
+ }: {
36
+ host: ɵMcpFollowUpHost;
37
+ agent: AbstractAgent;
38
+ capturedThreadId: string;
39
+ }): Promise<RunAgentResult>;
40
+ //#endregion
41
+ export { ɵMcpFollowUpHost, ɵrunMcpFollowUp };
42
+ //# sourceMappingURL=follow-up.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"follow-up.d.cts","names":[],"sources":["../src/follow-up.ts"],"mappings":";;;;;AAMA;;UAAiB,gBAAA;EACf,QAAA,CAAS,MAAA;IAAU,KAAA,EAAO,aAAA;EAAA,IAAkB,OAAA,CAAQ,cAAA;AAAA;;;;;;;;;;AAqBtD;;;;;;;;;iBAAsB,eAAA,CAAA;EACpB,IAAA;EACA,KAAA;EACA;AAAA;EAEA,IAAA,EAAM,gBAAA;EACN,KAAA,EAAO,aAAA;EACP,gBAAA;AAAA,IACE,OAAA,CAAQ,cAAA"}
@@ -0,0 +1,42 @@
1
+ import { AbstractAgent, RunAgentResult } from "@ag-ui/client";
2
+
3
+ //#region src/follow-up.d.ts
4
+ /**
5
+ * The subset of `CopilotKitCore` that {@link ɵrunMcpFollowUp} depends on.
6
+ * Declared structurally so the runner can be unit-tested without a full core.
7
+ */
8
+ interface ɵMcpFollowUpHost {
9
+ runAgent(params: {
10
+ agent: AbstractAgent;
11
+ }): Promise<RunAgentResult>;
12
+ }
13
+ /**
14
+ * Run an MCP app `ui/message` follow-up, scoped to the thread it was enqueued
15
+ * for (issue #5819).
16
+ *
17
+ * The MCP request queue delays follow-up work until the agent is idle. There is
18
+ * a single shared registry agent per id, and switching threads overwrites its
19
+ * `threadId`/`messages` in place. So if the host switches threads while a
20
+ * follow-up is queued, running it now would execute against — and stream into —
21
+ * the now-foreground thread.
22
+ *
23
+ * - **Same thread** (the common case): run on the shared agent, unchanged.
24
+ * - **Thread changed**: the shared agent has moved on, so the follow-up can no
25
+ * longer run in its originating thread's context. Drop it rather than leak it
26
+ * into the current thread. (The MCP app already received its `ui/message` ack
27
+ * at enqueue time; only the optional agent turn is skipped.)
28
+ *
29
+ * @internal exported for testing.
30
+ */
31
+ declare function ɵrunMcpFollowUp({
32
+ host,
33
+ agent,
34
+ capturedThreadId
35
+ }: {
36
+ host: ɵMcpFollowUpHost;
37
+ agent: AbstractAgent;
38
+ capturedThreadId: string;
39
+ }): Promise<RunAgentResult>;
40
+ //#endregion
41
+ export { ɵMcpFollowUpHost, ɵrunMcpFollowUp };
42
+ //# sourceMappingURL=follow-up.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"follow-up.d.mts","names":[],"sources":["../src/follow-up.ts"],"mappings":";;;;;AAMA;;UAAiB,gBAAA;EACf,QAAA,CAAS,MAAA;IAAU,KAAA,EAAO,aAAA;EAAA,IAAkB,OAAA,CAAQ,cAAA;AAAA;;;;;;;;;;AAqBtD;;;;;;;;;iBAAsB,eAAA,CAAA;EACpB,IAAA;EACA,KAAA;EACA;AAAA;EAEA,IAAA,EAAM,gBAAA;EACN,KAAA,EAAO,aAAA;EACP,gBAAA;AAAA,IACE,OAAA,CAAQ,cAAA"}