@agent-native/core 0.22.19 → 0.22.20
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/embed-auth.d.ts.map +1 -1
- package/dist/client/embed-auth.js +85 -3
- package/dist/client/embed-auth.js.map +1 -1
- package/dist/client/mcp-apps/McpAppRenderer.d.ts +3 -0
- package/dist/client/mcp-apps/McpAppRenderer.d.ts.map +1 -1
- package/dist/client/mcp-apps/McpAppRenderer.js +86 -9
- package/dist/client/mcp-apps/McpAppRenderer.js.map +1 -1
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +73 -5
- package/dist/deploy/build.js.map +1 -1
- package/dist/mcp/build-server.d.ts.map +1 -1
- package/dist/mcp/build-server.js +40 -3
- package/dist/mcp/build-server.js.map +1 -1
- package/dist/mcp/builtin-tools.d.ts.map +1 -1
- package/dist/mcp/builtin-tools.js +6 -3
- package/dist/mcp/builtin-tools.js.map +1 -1
- package/dist/mcp/embed-app.d.ts +2 -2
- package/dist/mcp/embed-app.d.ts.map +1 -1
- package/dist/mcp/embed-app.js +390 -17
- package/dist/mcp/embed-app.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +37 -10
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/server/create-server.d.ts.map +1 -1
- package/dist/server/create-server.js +21 -7
- package/dist/server/create-server.js.map +1 -1
- package/dist/server/embed-route.d.ts.map +1 -1
- package/dist/server/embed-route.js +62 -21
- package/dist/server/embed-route.js.map +1 -1
- package/dist/server/security-headers.d.ts.map +1 -1
- package/dist/server/security-headers.js +9 -1
- package/dist/server/security-headers.js.map +1 -1
- package/dist/server/ssr-handler.d.ts +2 -0
- package/dist/server/ssr-handler.d.ts.map +1 -1
- package/dist/server/ssr-handler.js +66 -11
- package/dist/server/ssr-handler.js.map +1 -1
- package/dist/shared/mcp-embed-headers.d.ts +12 -0
- package/dist/shared/mcp-embed-headers.d.ts.map +1 -0
- package/dist/shared/mcp-embed-headers.js +51 -0
- package/dist/shared/mcp-embed-headers.js.map +1 -0
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +23 -0
- package/dist/vite/client.js.map +1 -1
- package/docs/content/actions.md +15 -5
- package/docs/content/external-agents.md +53 -27
- package/docs/content/mcp-protocol.md +29 -4
- package/package.json +1 -1
package/docs/content/actions.md
CHANGED
|
@@ -199,13 +199,23 @@ export default defineAction({
|
|
|
199
199
|
This advertises the MCP Apps extension (`io.modelcontextprotocol/ui`), exposes the HTML via MCP resources/templates, and includes standard MCP Apps plus ChatGPT Apps SDK widget metadata for compatible hosts. Keep `link` as the fallback for CLI and non-UI MCP clients; see [External Agents](/docs/external-agents#mcp-apps).
|
|
200
200
|
|
|
201
201
|
The helper launches the action's `link` target through `/_agent-native/embed/start` with a short-lived browser session, so routes such as full dashboards, filtered inboxes, drafts, and extension pages can reuse the app's React components directly.
|
|
202
|
+
ChatGPT uses a controlled route iframe to avoid web-sandbox auto-height
|
|
203
|
+
feedback loops. Claude web uses a single-frame mount path automatically: the
|
|
204
|
+
launcher fetches the signed route HTML inside Claude's MCP resource frame,
|
|
205
|
+
mounts the real app document there, and rewrites app-origin network calls back
|
|
206
|
+
to the original app with the embed token.
|
|
202
207
|
|
|
203
208
|
Embedded routes can use the exported client helpers for the MCP App host
|
|
204
|
-
bridge.
|
|
205
|
-
|
|
206
|
-
`agentNative.mcpHost
|
|
207
|
-
|
|
208
|
-
|
|
209
|
+
bridge. Direct and Claude-mounted route embeds post standard `ui/*` JSON-RPC
|
|
210
|
+
messages to the host, while the ChatGPT controlled-frame path and explicit
|
|
211
|
+
nested-iframe diagnostic path proxy `agentNative.mcpHost.*` messages through
|
|
212
|
+
the launch wrapper.
|
|
213
|
+
When a submitted app prompt should continue the host chat, call
|
|
214
|
+
`sendToAgentChat()` from the embedded route; it sends hidden model context and
|
|
215
|
+
then posts a visible user message through the host bridge where supported.
|
|
216
|
+
Design those routes with their own scrolling, because the MCP resource reports
|
|
217
|
+
a bounded inline height rather than asking the host to size itself to the full
|
|
218
|
+
app document.
|
|
209
219
|
|
|
210
220
|
## Standard actions {#standard-actions}
|
|
211
221
|
|
|
@@ -219,38 +219,55 @@ Claude Code and other CLI-first clients still receive the same resources and met
|
|
|
219
219
|
|
|
220
220
|
MCP App embeds are route embeds, not separate mini-products. `embedApp()`
|
|
221
221
|
starts from the action's `link` target, creates a short-lived embed session,
|
|
222
|
-
and
|
|
223
|
-
|
|
224
|
-
|
|
222
|
+
and launches that signed app route. Standard MCP Apps hosts can navigate the
|
|
223
|
+
MCP App frame itself. ChatGPT gets a controlled route iframe because its web
|
|
224
|
+
sandbox can otherwise auto-size a full app route into a feedback loop. Claude
|
|
225
|
+
web currently proxies MCP App content through `claudemcpcontent.com`; direct
|
|
226
|
+
route navigation can fetch the app HTML there without reliably running the
|
|
227
|
+
framework bootstrap, and a second nested iframe is easy for the host to block.
|
|
228
|
+
For Claude, the launcher fetches the signed app HTML and mounts that document
|
|
229
|
+
into the existing MCP resource frame, then rewrites app-origin
|
|
230
|
+
fetch/XHR/EventSource calls back to the app with the embed token. The app still
|
|
231
|
+
renders the normal route and React components. Design embedded routes so a
|
|
232
|
+
reload with the same signed URL reconstructs the same view.
|
|
225
233
|
|
|
226
234
|
ChatGPT gets a dedicated compatibility path through `window.openai`: the launch
|
|
227
235
|
document reads `toolInput`, `toolOutput`, and `toolResponseMetadata` directly,
|
|
228
236
|
then calls `create_embed_session` via `window.openai.callTool(...)`. Standard
|
|
229
|
-
MCP Apps hosts use the `ui/*` JSON-RPC bridge.
|
|
230
|
-
|
|
231
|
-
`ui/
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
237
|
+
MCP Apps hosts use the `ui/*` JSON-RPC bridge. Direct and Claude-mounted routes
|
|
238
|
+
can call `ui/update-model-context`, `ui/message`, `ui/open-link`, and
|
|
239
|
+
`ui/request-display-mode` through the host bridge helpers. When the ChatGPT or
|
|
240
|
+
explicit diagnostic iframe path is used, the wrapper relays the same host
|
|
241
|
+
actions over `agentNative.mcpHost.*` postMessage requests. Keep the result
|
|
242
|
+
shape identical for both paths: return a focused `link` and concise structured
|
|
243
|
+
content.
|
|
244
|
+
|
|
245
|
+
The resource shell owns the outer host size. Keep embedded app routes
|
|
246
|
+
internally scrollable and let the launcher report a bounded intrinsic height
|
|
247
|
+
rather than the full document height; otherwise host auto-resize can turn a
|
|
248
|
+
normal app page into a very tall chat artifact. A changed shell only affects
|
|
249
|
+
new MCP App resources and new tool calls. Old ChatGPT/Claude conversation
|
|
250
|
+
frames can keep the previous resource behavior, so verify sizing with a fresh
|
|
251
|
+
inline render before judging a fix.
|
|
252
|
+
|
|
253
|
+
You can force the nested diagnostic iframe with `embedMode: "iframe"`,
|
|
254
|
+
`renderMode: "iframe"`, `nested: true`, or `frame: "iframe"` when debugging
|
|
255
|
+
host behavior. If the iframe is blocked, `embedApp()` replaces it with an
|
|
256
|
+
open-app fallback: the user can retry inline, open a freshly minted embed
|
|
257
|
+
session through the host, or use the visible route URL. Keep the action's
|
|
258
|
+
`link` target useful on its own because it is still the universal escape hatch.
|
|
242
259
|
|
|
243
260
|
The host bridge is deliberately small:
|
|
244
261
|
|
|
245
|
-
| Mode
|
|
246
|
-
|
|
|
247
|
-
| direct
|
|
248
|
-
| direct
|
|
249
|
-
| direct
|
|
250
|
-
| direct
|
|
251
|
-
|
|
|
252
|
-
|
|
|
253
|
-
|
|
|
262
|
+
| Mode | Message type | Use it for |
|
|
263
|
+
| ------------------------ | ------------------------------------- | ---------------------------------------- |
|
|
264
|
+
| direct / Claude | `ui/update-model-context` | Hidden context for the host model |
|
|
265
|
+
| direct / Claude | `ui/message` | Post a visible user turn into the host |
|
|
266
|
+
| direct / Claude | `ui/open-link` | Open an external or app URL via the host |
|
|
267
|
+
| direct / Claude | `ui/request-display-mode` | Request `inline`, `fullscreen`, or `pip` |
|
|
268
|
+
| ChatGPT / iframe wrapper | `agentNative.mcpHostContext` | Theme, locale, host platform, dimensions |
|
|
269
|
+
| ChatGPT / iframe wrapper | `agentNative.embeddedAppReady` | Confirm the route iframe loaded |
|
|
270
|
+
| ChatGPT / iframe wrapper | `agentNative.mcpHost.*` / `.response` | Wrapper relay for host requests |
|
|
254
271
|
|
|
255
272
|
Embedded routes can use `updateMcpAppModelContext()`,
|
|
256
273
|
`openMcpAppHostLink()`, `requestMcpAppDisplayMode()`,
|
|
@@ -352,7 +369,6 @@ export default defineAction({
|
|
|
352
369
|
description: "Open the generated draft in the real Mail compose UI.",
|
|
353
370
|
iframeTitle: "Agent-Native Mail",
|
|
354
371
|
openLabel: "Open in Mail",
|
|
355
|
-
frameDomains: ["https:", "http://localhost:*", "http://127.0.0.1:*"],
|
|
356
372
|
}),
|
|
357
373
|
},
|
|
358
374
|
});
|
|
@@ -362,9 +378,16 @@ The MCP server advertises extension `io.modelcontextprotocol/ui`, adds `_meta.ui
|
|
|
362
378
|
|
|
363
379
|
Keep the existing `link` builder even when adding `mcpApp`. CLI-only clients, older hosts, and any host that does not render MCP Apps will ignore the UI metadata and still need the `"Open in … →"` link. `embedApp()` uses that link as its launch target, calls the app-only `create_embed_session` helper, exchanges a one-time SQL ticket at `/_agent-native/embed/start`, and navigates the MCP App frame to the target route with a short-lived browser session plus a bearer fallback for same-origin fetches. `open_app({ app, path, embed: true })` is the generic escape hatch for routes such as full dashboards, filtered inboxes, calendar draft views, analyses, and extension pages, and should be used liberally when the full app is the clearest review/edit surface.
|
|
364
380
|
|
|
381
|
+
`embedApp()` includes the MCP request origin in the resource CSP so the launcher
|
|
382
|
+
can fetch and, when explicitly requested, frame the signed first-party app
|
|
383
|
+
route. Only pass additional `frameDomains` for a custom MCP App that truly
|
|
384
|
+
embeds a third-party player.
|
|
385
|
+
|
|
365
386
|
Inside those `embedApp()` routes, `sendToAgentChat()` is embed-aware.
|
|
366
387
|
Auto-submitted prompts relay to the MCP host as `ui/update-model-context` plus
|
|
367
|
-
`ui/message
|
|
388
|
+
`ui/message`, so a button in the embedded app can intentionally continue the
|
|
389
|
+
Claude/ChatGPT conversation from the selected app state. `submit: false`
|
|
390
|
+
remains local prefill/review behavior.
|
|
368
391
|
|
|
369
392
|
### The `link` contract {#link-contract}
|
|
370
393
|
|
|
@@ -509,6 +532,9 @@ The fallback hosted `connect` flow never copies the deployment's shared secret.
|
|
|
509
532
|
- Test MCP Apps with the lightweight fixtures around `embedApp()` and
|
|
510
533
|
`McpAppRenderer`; they cover CSP, host context, app launch, and bridge
|
|
511
534
|
message behavior without needing a real external host.
|
|
535
|
+
- When validating ChatGPT or Claude web, trigger a fresh tool call after shell
|
|
536
|
+
changes and measure the visible iframe. Previously rendered frames in the
|
|
537
|
+
same conversation may still show cached height or launch behavior.
|
|
512
538
|
|
|
513
539
|
**Don't**
|
|
514
540
|
|
|
@@ -78,11 +78,26 @@ If an action declares `mcpApp`, the server also advertises the official MCP Apps
|
|
|
78
78
|
|
|
79
79
|
`embedApp()` is the low-level URL-first MCP App helper. It reads the action
|
|
80
80
|
result's open link, asks the app-only `create_embed_session` tool to mint a
|
|
81
|
-
route-scoped session, then
|
|
82
|
-
|
|
81
|
+
route-scoped session, then launches the resulting app route. ChatGPT and hosts
|
|
82
|
+
that allow direct route hydration launch the same signed app URL, but ChatGPT
|
|
83
|
+
keeps it in a controlled route iframe to avoid a web-sandbox auto-height
|
|
84
|
+
feedback loop. Claude web currently proxies MCP App content under
|
|
85
|
+
`claudemcpcontent.com`; direct route navigation can fetch app HTML there
|
|
86
|
+
without reliably running the framework bootstrap, and a second nested iframe is
|
|
87
|
+
easy for the host to block. For Claude, `embedApp()` fetches the signed app
|
|
88
|
+
HTML and mounts the real route document into the existing MCP resource frame,
|
|
89
|
+
with app-origin requests routed back to the original app using the embed token.
|
|
90
|
+
For normal action authoring, use `embedRoute()` when the action's
|
|
83
91
|
`link` and `mcpApp` should come from the same pure route builder. The route
|
|
84
92
|
itself should derive state from the URL and normal app data fetching.
|
|
85
93
|
|
|
94
|
+
The outer MCP resource reports a bounded inline height to the host and the app
|
|
95
|
+
route scrolls internally. Do not rely on host auto-resize measuring the full
|
|
96
|
+
document; in ChatGPT and Claude this can make a normal full-app route appear as
|
|
97
|
+
a huge chat artifact. Host conversations also keep already-rendered iframes, so
|
|
98
|
+
after changing the resource shell or `ui://` version, test a fresh tool call
|
|
99
|
+
rather than re-measuring an old frame.
|
|
100
|
+
|
|
86
101
|
Default direct embeds talk to the MCP Apps host through standard `ui/*`
|
|
87
102
|
JSON-RPC messages:
|
|
88
103
|
|
|
@@ -93,8 +108,9 @@ JSON-RPC messages:
|
|
|
93
108
|
| `ui/open-link` | `{ url }` |
|
|
94
109
|
| `ui/request-display-mode` | `{ mode }` |
|
|
95
110
|
|
|
96
|
-
|
|
97
|
-
|
|
111
|
+
The ChatGPT controlled-frame path and any explicit `embedMode: "iframe"` /
|
|
112
|
+
`renderMode: "iframe"` diagnostic path use the wrapper-to-route postMessage
|
|
113
|
+
relay:
|
|
98
114
|
|
|
99
115
|
| Direction | Type | Payload shape |
|
|
100
116
|
| --------------- | ---------------------------------------- | --------------------------------------------- |
|
|
@@ -104,8 +120,17 @@ keeps the old wrapper-to-route postMessage relay:
|
|
|
104
120
|
| route → wrapper | `agentNative.mcpHost.requestDisplayMode` | `{ requestId, mode }` |
|
|
105
121
|
| wrapper → route | `agentNative.mcpHost.response` | `{ requestId, ok, result?, error? }` |
|
|
106
122
|
|
|
123
|
+
`embedApp()` includes the MCP request origin in the resource CSP so the
|
|
124
|
+
launcher can fetch and, when explicitly requested, frame the signed first-party
|
|
125
|
+
route. Pass additional `frameDomains` only for custom third-party frames.
|
|
126
|
+
|
|
107
127
|
Host-mediated open links keep the iframe from choosing its own browser target.
|
|
108
128
|
Model context updates are opt-in and hidden from the user-facing transcript.
|
|
129
|
+
`ui/message` is the portable way for an embedded app button to ask the host to
|
|
130
|
+
post a visible user message and continue the chat. In agent-native routes,
|
|
131
|
+
`sendToAgentChat()` uses `ui/update-model-context` plus `ui/message` when
|
|
132
|
+
called from a submitted MCP App embed, while `submit: false` remains an
|
|
133
|
+
in-route draft/prefill path.
|
|
109
134
|
Display mode requests are best-effort: a host can honor, ignore, or reject the
|
|
110
135
|
request. Embedded routes must remain functional in the default inline mode.
|
|
111
136
|
|
package/package.json
CHANGED