@agent-native/core 0.22.19 → 0.22.21
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 +420 -29
- 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 +16 -5
- package/docs/content/external-agents.md +61 -26
- package/docs/content/mcp-protocol.md +32 -4
- package/package.json +1 -1
package/docs/content/actions.md
CHANGED
|
@@ -199,13 +199,24 @@ 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
|
+
Standard hosts navigate the MCP App frame directly to that signed route.
|
|
203
|
+
Claude web uses a single-frame transplant path that hydrates the signed app
|
|
204
|
+
HTML inside Claude's MCP App iframe because Claude does not reliably allow
|
|
205
|
+
app-owned child iframes or external frame navigation. ChatGPT web uses a
|
|
206
|
+
controlled route iframe for stable `window.openai` host APIs and bounded height
|
|
207
|
+
control.
|
|
202
208
|
|
|
203
209
|
Embedded routes can use the exported client helpers for the MCP App host
|
|
204
|
-
bridge.
|
|
205
|
-
|
|
206
|
-
`agentNative.mcpHost
|
|
207
|
-
|
|
208
|
-
|
|
210
|
+
bridge. Direct route embeds and Claude's transplanted route post standard
|
|
211
|
+
`ui/*` JSON-RPC messages to the host, while the ChatGPT controlled-frame path
|
|
212
|
+
and explicit diagnostic iframe path proxy `agentNative.mcpHost.*` messages
|
|
213
|
+
through the launch wrapper.
|
|
214
|
+
When a submitted app prompt should continue the host chat, call
|
|
215
|
+
`sendToAgentChat()` from the embedded route; it sends hidden model context and
|
|
216
|
+
then posts a visible user message through the host bridge where supported.
|
|
217
|
+
Design those routes with their own scrolling, because the MCP resource reports
|
|
218
|
+
a bounded inline height rather than asking the host to size itself to the full
|
|
219
|
+
app document.
|
|
209
220
|
|
|
210
221
|
## Standard actions {#standard-actions}
|
|
211
222
|
|
|
@@ -219,38 +219,64 @@ 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 when the host can hydrate the route directly. Claude web
|
|
224
|
+
uses a single-frame transplant path: the resource document fetches the signed
|
|
225
|
+
app HTML and hydrates it inside Claude's MCP App iframe because Claude does not
|
|
226
|
+
reliably allow app-owned child iframes or external frame navigation. ChatGPT
|
|
227
|
+
web gets a controlled route iframe because its Apps bridge gives us stable
|
|
228
|
+
`window.openai` host APIs and bounded height control. All paths point at the
|
|
229
|
+
same signed app route and render the normal route and React components. Design
|
|
230
|
+
embedded routes so a reload with the same signed URL reconstructs the same
|
|
231
|
+
view.
|
|
225
232
|
|
|
226
233
|
ChatGPT gets a dedicated compatibility path through `window.openai`: the launch
|
|
227
234
|
document reads `toolInput`, `toolOutput`, and `toolResponseMetadata` directly,
|
|
228
235
|
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
|
+
MCP Apps hosts use the `ui/*` JSON-RPC bridge. Directly hydrated routes can
|
|
237
|
+
call `ui/update-model-context`, `ui/message`, `ui/open-link`, and
|
|
238
|
+
`ui/request-display-mode` through the host bridge helpers. Claude's
|
|
239
|
+
transplanted route uses the same direct `ui/*` host bridge after hydration.
|
|
240
|
+
When the ChatGPT or explicit diagnostic iframe path is used, the wrapper
|
|
241
|
+
relays the same host actions over `agentNative.mcpHost.*` postMessage
|
|
242
|
+
requests. Keep the result shape identical for both paths: return a focused
|
|
243
|
+
`link` and concise structured 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
|
+
Claude uses the single-frame transplant path by default. You can also force it
|
|
254
|
+
in other hosts with `embedMode: "transplant"` or `frame: "transplant"` when
|
|
255
|
+
debugging host module-loading behavior. You can force the nested diagnostic iframe with
|
|
236
256
|
`embedMode: "iframe"`, `renderMode: "iframe"`, `nested: true`, or
|
|
237
|
-
`frame: "iframe"`.
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
257
|
+
`frame: "iframe"`. If the iframe is blocked, `embedApp()` replaces it with an
|
|
258
|
+
open-app fallback: the user can retry inline, open a freshly minted embed
|
|
259
|
+
session through the host, or use the visible route URL. Keep the action's
|
|
260
|
+
`link` target useful on its own because it is still the universal escape hatch.
|
|
261
|
+
|
|
262
|
+
When testing Claude through ngrok, use a production build (`agent-native build`
|
|
263
|
+
then `agent-native start`) or a deployed preview/production URL. Claude's
|
|
264
|
+
single-frame transplant path works with production asset chunks; raw Vite dev
|
|
265
|
+
modules such as `/app/root.tsx` can be protected by app auth and fail dynamic
|
|
266
|
+
imports from the Claude resource origin.
|
|
242
267
|
|
|
243
268
|
The host bridge is deliberately small:
|
|
244
269
|
|
|
245
|
-
| Mode
|
|
246
|
-
|
|
|
247
|
-
| direct
|
|
248
|
-
| direct
|
|
249
|
-
| direct
|
|
250
|
-
| direct
|
|
251
|
-
|
|
|
252
|
-
|
|
|
253
|
-
|
|
|
270
|
+
| Mode | Message type | Use it for |
|
|
271
|
+
| ---------------------- | ------------------------------------- | ---------------------------------------- |
|
|
272
|
+
| direct host route | `ui/update-model-context` | Hidden context for the host model |
|
|
273
|
+
| direct host route | `ui/message` | Post a visible user turn into the host |
|
|
274
|
+
| direct host route | `ui/open-link` | Open an external or app URL via the host |
|
|
275
|
+
| direct host route | `ui/request-display-mode` | Request `inline`, `fullscreen`, or `pip` |
|
|
276
|
+
| Claude transplant | `ui/*` | Same direct host bridge after hydration |
|
|
277
|
+
| ChatGPT / iframe route | `agentNative.mcpHostContext` | Theme, locale, host platform, dimensions |
|
|
278
|
+
| ChatGPT / iframe route | `agentNative.embeddedAppReady` | Confirm the route iframe loaded |
|
|
279
|
+
| ChatGPT / iframe route | `agentNative.mcpHost.*` / `.response` | Wrapper relay for host requests |
|
|
254
280
|
|
|
255
281
|
Embedded routes can use `updateMcpAppModelContext()`,
|
|
256
282
|
`openMcpAppHostLink()`, `requestMcpAppDisplayMode()`,
|
|
@@ -352,7 +378,6 @@ export default defineAction({
|
|
|
352
378
|
description: "Open the generated draft in the real Mail compose UI.",
|
|
353
379
|
iframeTitle: "Agent-Native Mail",
|
|
354
380
|
openLabel: "Open in Mail",
|
|
355
|
-
frameDomains: ["https:", "http://localhost:*", "http://127.0.0.1:*"],
|
|
356
381
|
}),
|
|
357
382
|
},
|
|
358
383
|
});
|
|
@@ -362,9 +387,16 @@ The MCP server advertises extension `io.modelcontextprotocol/ui`, adds `_meta.ui
|
|
|
362
387
|
|
|
363
388
|
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
389
|
|
|
390
|
+
`embedApp()` includes the MCP request origin in the resource CSP so the launcher
|
|
391
|
+
can fetch and, when explicitly requested, frame the signed first-party app
|
|
392
|
+
route. Only pass additional `frameDomains` for a custom MCP App that truly
|
|
393
|
+
embeds a third-party player.
|
|
394
|
+
|
|
365
395
|
Inside those `embedApp()` routes, `sendToAgentChat()` is embed-aware.
|
|
366
396
|
Auto-submitted prompts relay to the MCP host as `ui/update-model-context` plus
|
|
367
|
-
`ui/message
|
|
397
|
+
`ui/message`, so a button in the embedded app can intentionally continue the
|
|
398
|
+
Claude/ChatGPT conversation from the selected app state. `submit: false`
|
|
399
|
+
remains local prefill/review behavior.
|
|
368
400
|
|
|
369
401
|
### The `link` contract {#link-contract}
|
|
370
402
|
|
|
@@ -509,6 +541,9 @@ The fallback hosted `connect` flow never copies the deployment's shared secret.
|
|
|
509
541
|
- Test MCP Apps with the lightweight fixtures around `embedApp()` and
|
|
510
542
|
`McpAppRenderer`; they cover CSP, host context, app launch, and bridge
|
|
511
543
|
message behavior without needing a real external host.
|
|
544
|
+
- When validating ChatGPT or Claude web, trigger a fresh tool call after shell
|
|
545
|
+
changes and measure the visible iframe. Previously rendered frames in the
|
|
546
|
+
same conversation may still show cached height or launch behavior.
|
|
512
547
|
|
|
513
548
|
**Don't**
|
|
514
549
|
|
|
@@ -78,11 +78,24 @@ 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. Standard hosts
|
|
82
|
+
hydrate the signed route by navigating the MCP App frame itself. Claude web
|
|
83
|
+
uses a single-frame transplant path that fetches the signed app HTML and
|
|
84
|
+
hydrates it inside Claude's MCP App iframe because Claude does not reliably
|
|
85
|
+
allow app-owned child iframes or external frame navigation. ChatGPT web keeps
|
|
86
|
+
the signed app URL in a controlled route iframe for stable `window.openai`
|
|
87
|
+
host APIs and bounded height control.
|
|
88
|
+
For normal action authoring, use `embedRoute()` when the action's
|
|
83
89
|
`link` and `mcpApp` should come from the same pure route builder. The route
|
|
84
90
|
itself should derive state from the URL and normal app data fetching.
|
|
85
91
|
|
|
92
|
+
The outer MCP resource reports a bounded inline height to the host and the app
|
|
93
|
+
route scrolls internally. Do not rely on host auto-resize measuring the full
|
|
94
|
+
document; in ChatGPT and Claude this can make a normal full-app route appear as
|
|
95
|
+
a huge chat artifact. Host conversations also keep already-rendered iframes, so
|
|
96
|
+
after changing the resource shell or `ui://` version, test a fresh tool call
|
|
97
|
+
rather than re-measuring an old frame.
|
|
98
|
+
|
|
86
99
|
Default direct embeds talk to the MCP Apps host through standard `ui/*`
|
|
87
100
|
JSON-RPC messages:
|
|
88
101
|
|
|
@@ -93,8 +106,14 @@ JSON-RPC messages:
|
|
|
93
106
|
| `ui/open-link` | `{ url }` |
|
|
94
107
|
| `ui/request-display-mode` | `{ mode }` |
|
|
95
108
|
|
|
96
|
-
|
|
97
|
-
|
|
109
|
+
Claude's transplanted route uses the same `ui/*` bridge after hydration. Test
|
|
110
|
+
Claude against deployed/preview URLs or a local production build served with
|
|
111
|
+
`agent-native start`; raw Vite dev modules can be app-auth protected and fail
|
|
112
|
+
dynamic imports from Claude's resource origin.
|
|
113
|
+
|
|
114
|
+
The ChatGPT controlled-frame path and any explicit `embedMode: "iframe"` /
|
|
115
|
+
`renderMode: "iframe"` diagnostic path use the wrapper-to-route postMessage
|
|
116
|
+
relay:
|
|
98
117
|
|
|
99
118
|
| Direction | Type | Payload shape |
|
|
100
119
|
| --------------- | ---------------------------------------- | --------------------------------------------- |
|
|
@@ -104,8 +123,17 @@ keeps the old wrapper-to-route postMessage relay:
|
|
|
104
123
|
| route → wrapper | `agentNative.mcpHost.requestDisplayMode` | `{ requestId, mode }` |
|
|
105
124
|
| wrapper → route | `agentNative.mcpHost.response` | `{ requestId, ok, result?, error? }` |
|
|
106
125
|
|
|
126
|
+
`embedApp()` includes the MCP request origin in the resource CSP so the
|
|
127
|
+
launcher can fetch and, when explicitly requested, frame the signed first-party
|
|
128
|
+
route. Pass additional `frameDomains` only for custom third-party frames.
|
|
129
|
+
|
|
107
130
|
Host-mediated open links keep the iframe from choosing its own browser target.
|
|
108
131
|
Model context updates are opt-in and hidden from the user-facing transcript.
|
|
132
|
+
`ui/message` is the portable way for an embedded app button to ask the host to
|
|
133
|
+
post a visible user message and continue the chat. In agent-native routes,
|
|
134
|
+
`sendToAgentChat()` uses `ui/update-model-context` plus `ui/message` when
|
|
135
|
+
called from a submitted MCP App embed, while `submit: false` remains an
|
|
136
|
+
in-route draft/prefill path.
|
|
109
137
|
Display mode requests are best-effort: a host can honor, ignore, or reject the
|
|
110
138
|
request. Embedded routes must remain functional in the default inline mode.
|
|
111
139
|
|
package/package.json
CHANGED