@agent-native/core 0.77.1 → 0.77.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.
- package/corpus/core/CHANGELOG.md +15 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/mcp/build-server.ts +1 -1
- package/corpus/core/src/mcp/embed-app.ts +3 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/mcp/build-server.js +1 -1
- package/dist/mcp/build-server.js.map +1 -1
- package/dist/mcp/embed-app.d.ts.map +1 -1
- package/dist/mcp/embed-app.js +3 -1
- package/dist/mcp/embed-app.js.map +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/package.json +1 -1
package/corpus/core/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @agent-native/core
|
|
2
2
|
|
|
3
|
+
## 0.77.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 6d04136: MCP Apps: render inline embeds in a nested child iframe instead of transplanting
|
|
8
|
+
the app document on hosts where transplant breaks. Transplant boots the app via
|
|
9
|
+
cross-origin dynamic `import()` inside the host's opaque-origin sandbox, which
|
|
10
|
+
strict hosts block (blank "Loading app").
|
|
11
|
+
- `ui/*` bridge hosts (Cursor, Codex) now render in a nested child iframe.
|
|
12
|
+
- ChatGPT now uses its controlled nested frame: `isChatGptSandboxHost` was
|
|
13
|
+
removed from `shouldTransplantAppDocument`, which had forced ChatGPT to
|
|
14
|
+
transplant and hang blank.
|
|
15
|
+
|
|
16
|
+
Claude keeps the transplant path; `embedMode: "transplant"` still forces it.
|
|
17
|
+
|
|
3
18
|
## 0.77.1
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
package/corpus/core/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.77.
|
|
3
|
+
"version": "0.77.2",
|
|
4
4
|
"description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -750,7 +750,7 @@ function safeUiSegment(value: string | undefined, fallback: string): string {
|
|
|
750
750
|
|
|
751
751
|
// ChatGPT and Claude cache MCP App resource HTML by `ui://` URI. Bump this
|
|
752
752
|
// when the shared shell changes in a way that must invalidate host caches.
|
|
753
|
-
const MCP_APP_RESOURCE_SHELL_VERSION = "shell-
|
|
753
|
+
const MCP_APP_RESOURCE_SHELL_VERSION = "shell-v52";
|
|
754
754
|
|
|
755
755
|
function legacyDefaultMcpAppUri(config: MCPConfig, actionName: string): string {
|
|
756
756
|
const app = safeUiSegment(config.appId ?? config.name, "agent-native");
|
|
@@ -1229,9 +1229,11 @@ export function embedApp(
|
|
|
1229
1229
|
if (mode === "iframe" || mode === "nested" || render.frame === "iframe" || render.nested) {
|
|
1230
1230
|
return false;
|
|
1231
1231
|
}
|
|
1232
|
+
// ChatGPT is excluded so it uses the controlled nested frame instead:
|
|
1233
|
+
// transplant would cross-origin import() app chunks in its opaque-origin
|
|
1234
|
+
// sandbox, which it blocks (blank embed). embedMode "transplant" still forces it.
|
|
1232
1235
|
return (
|
|
1233
1236
|
isClaudeMcpContentHost() ||
|
|
1234
|
-
isChatGptSandboxHost() ||
|
|
1235
1237
|
mode === "transplant" ||
|
|
1236
1238
|
render.frame === "transplant"
|
|
1237
1239
|
);
|
package/dist/collab/routes.d.ts
CHANGED
|
@@ -42,8 +42,8 @@ export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import
|
|
|
42
42
|
*/
|
|
43
43
|
export declare const postCollabText: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
44
44
|
ok?: undefined;
|
|
45
|
-
text?: undefined;
|
|
46
45
|
error: string;
|
|
46
|
+
text?: undefined;
|
|
47
47
|
} | {
|
|
48
48
|
error?: undefined;
|
|
49
49
|
ok: boolean;
|
package/dist/mcp/build-server.js
CHANGED
|
@@ -494,7 +494,7 @@ function safeUiSegment(value, fallback) {
|
|
|
494
494
|
}
|
|
495
495
|
// ChatGPT and Claude cache MCP App resource HTML by `ui://` URI. Bump this
|
|
496
496
|
// when the shared shell changes in a way that must invalidate host caches.
|
|
497
|
-
const MCP_APP_RESOURCE_SHELL_VERSION = "shell-
|
|
497
|
+
const MCP_APP_RESOURCE_SHELL_VERSION = "shell-v52";
|
|
498
498
|
function legacyDefaultMcpAppUri(config, actionName) {
|
|
499
499
|
const app = safeUiSegment(config.appId ?? config.name, "agent-native");
|
|
500
500
|
const action = safeUiSegment(actionName, "tool");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-server.js","sourceRoot":"","sources":["../../src/mcp/build-server.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared MCP server builder.\n *\n * Extracted from `server.ts` so the stateless Streamable-HTTP mount\n * (`mountMCP`) and the stdio transport (`runMCPStdio --standalone`) build the\n * *same* MCP server from the *same* `ActionEntry` registry. Both surfaces:\n *\n * - expose every action as an MCP tool (+ the `ask-agent` meta-tool),\n * - append the framework deep-link block / `_meta` to every tool result,\n * - wrap `run()` / `askAgent()` in `runWithRequestContext` so per-user /\n * per-org scoping (accessFilter, resolveCredential, MCP visibility) is\n * honoured.\n *\n * `server.ts` re-exports `createMCPServerForRequest` and the auth helpers so\n * any (future) external importer of `@agent-native/core/mcp` keeps resolving.\n *\n * Node-only at the SDK level, but this module itself has no Node-only imports\n * — it can be bundled into the serverless function alongside `mountMCP`.\n */\n\nimport {\n MCP_APP_EXTENSION_ID,\n MCP_APP_MIME_TYPE,\n MCP_APP_RESOURCE_URI_META_KEY,\n type ActionMcpAppCsp,\n type ActionMcpAppResourceConfig,\n} from \"../action.js\";\nimport type { ActionEntry } from \"../agent/production-agent.js\";\nimport { isMcpActionResult } from \"../mcp-client/app-result.js\";\nimport { getConfiguredAppBasePath } from \"../server/app-base-path.js\";\nimport {\n buildDeepLink,\n toAbsoluteOpenUrl,\n toDesktopOpenUrl,\n toVsCodeOpenUrl,\n} from \"../server/deep-link.js\";\nimport {\n getRequestContext,\n getRequestOrgId,\n getRequestUserEmail,\n runWithRequestContext,\n} from \"../server/request-context.js\";\nimport {\n isAgentNativeOpenDeepLink,\n withCollapsedAgentSidebarParam,\n} from \"../shared/agent-sidebar-url.js\";\nimport { MCP_APP_CHAT_BRIDGE_QUERY_PARAM } from \"../shared/embed-auth.js\";\nimport { getBuiltinCrossAppTools } from \"./builtin-tools.js\";\nimport {\n MCP_CONNECT_OAUTH_CLIENT_ID,\n MCP_CONNECT_SCOPE,\n} from \"./connect-store.js\";\nimport { MCP_APP_REQUEST_ORIGIN_CSP_SOURCE } from \"./embed-app.js\";\nimport {\n MCP_OAUTH_SCOPES,\n hasMcpOAuthScope,\n verifyMcpOAuthAccessToken,\n} from \"./oauth-token.js\";\n\nexport interface MCPConfig {\n /** App name shown in MCP server info */\n name: string;\n /** Optional human-facing app title shown by MCP hosts that support titles. */\n title?: string;\n /**\n * Canonical app id (directory under `apps/`, e.g. `mail`) this MCP server\n * is mounted for. Optional & back-compat: when omitted the builtin\n * cross-app tools fall back to lowercasing `name`. Used by `open_app` /\n * `ask_app` / `create_workspace_app` to tell \"this app\" from a cross-app\n * target so they resolve the *target* app's origin rather than echoing the\n * current request origin.\n */\n appId?: string;\n /** App description */\n description: string;\n /** Optional canonical website URL for hosts that surface MCP app details. */\n websiteUrl?: string;\n /** Optional app icons for MCP hosts that render server branding. */\n icons?: Array<{\n src: string;\n mimeType?: string;\n sizes?: string[];\n theme?: \"light\" | \"dark\";\n }>;\n /** Version string (default \"1.0.0\") */\n version?: string;\n /** Action registry — same as agent chat and A2A */\n actions: Record<string, ActionEntry>;\n /**\n * Full (\"production\") action surface served to an **authenticated real\n * caller** — a connect-minted token, an `agent-native mcp install` stdio\n * proxy (owner-email header / `AGENT_NATIVE_OWNER_EMAIL`), or a deployed /\n * `AGENT_MODE=production` app. In local dev `actions` is intentionally the\n * sparse, dev-toggled surface (builtins + read-only public-agent actions)\n * so the local agent chat and unauthenticated dev probes don't see every\n * mutating tool; but per the external-agents contract a real caller that\n * connected with a token MUST get the full surface even in dev. When unset\n * (production, where `actions` already IS the full set) the swap is a\n * no-op. See `external-agents` skill, \"Dev vs production tool surface\".\n */\n productionActions?: Record<string, ActionEntry>;\n /** Handler for the ask-agent meta-tool — runs the full agent loop */\n askAgent?: (message: string) => Promise<string>;\n /**\n * Disable the generic cross-app builtin tools (`list_apps`, `open_app`,\n * `ask_app`, `create_workspace_app`, `list_templates`). They are merged in\n * by default so external agents get a stable verb set; a template action of\n * the same name always wins (template precedence). Set to `false` only for\n * a constrained / locked-down mount.\n */\n builtinCrossAppTools?: boolean;\n /**\n * Curated allow-list of action names served to **external connector** clients\n * on a hosted multi-tenant deployment.\n *\n * Whenever this list is non-empty it is active by default for **every**\n * caller — hosted connectors, code/stdio clients, and the local CLI alike.\n * The MCP server trims both the advertised tool list *and* the callable\n * surface to exactly these names (plus any builtin cross-app tools such as\n * `list_apps` / `open_app`). Any tool call for a name **not** in the list is\n * rejected — it is not merely hidden. This prevents the ~105-tool full\n * catalog from landing in every external agent's context window and removes\n * footguns (db-exec, seed-*, extension tools, browser-session tools, etc.)\n * from connectors. It is no longer gated behind an environment variable, and\n * the catalog is never inferred from the client name/user-agent.\n *\n * `tool-search` stays available in the compact catalog so any trimmed tool is\n * reachable on demand. Callers who need the full surface up front opt in\n * explicitly with `agent-native connect --full-catalog` (embeds a\n * `catalog_scope: \"full\"` claim in the connect-minted JWT) or the\n * deployment-wide `AGENT_NATIVE_MCP_FULL_CATALOG=1` env override.\n *\n * Declare this in your template's `createAgentChatPlugin` options rather than\n * setting it on `MCPConfig` directly; the plugin copies it through.\n */\n connectorCatalog?: string[];\n}\n\n/**\n * Identity extracted from a verified MCP bearer token / JWT. Used to wrap\n * `entry.run()` and `config.askAgent()` calls in `runWithRequestContext`\n * so downstream tools (db-query, accessFilter, resolveCredential) honour\n * per-user / per-org scoping. Without this wrap the MCP endpoint would\n * silently bypass tenant isolation. See finding #6 in\n * /tmp/security-audit/12-mcp-a2a-agent.md.\n */\nexport interface MCPCallerIdentity {\n userEmail: string | undefined;\n orgId?: string | undefined;\n orgDomain: string | undefined;\n /** Present only for standard remote MCP OAuth access tokens. */\n oauthScopes?: string[];\n /** Present only for standard remote MCP OAuth access tokens. */\n oauthClientId?: string;\n /** Present only for framework-minted first-party MCP client tokens. */\n firstPartyMcp?: boolean;\n}\n\n/** Per-request context used to turn an action's relative deep link into the\n * absolute web URL (and desktop `agentnative://` URL) the external agent\n * surfaces. Derived from the inbound request headers in `mountMCP`, or from\n * the resolved local app origin in the stdio standalone path. */\nexport interface MCPRequestMeta {\n /** Origin of the running app, e.g. `http://localhost:8100`. */\n origin?: string;\n /** Optional mount prefix for path-mounted apps, e.g. `/mail`. */\n basePath?: string;\n /** Optional client preference for which URL the *markdown* link uses. */\n target?: \"browser\" | \"desktop\" | \"terminal\";\n /**\n * Best-effort caller label derived from MCP transport headers. Chat-style\n * remote hosts should stay on the compact catalog; code/stdio clients can\n * explicitly identify themselves to keep the full action surface.\n */\n clientName?: string;\n /** Explicit framework client hint from `x-agent-native-mcp-client`. */\n clientHint?: string;\n /** Explicit opt-in to the full tool catalog for code/stdio style clients. */\n fullCatalog?: boolean;\n /**\n * The caller authenticated with a real credential (verified A2A/connect\n * JWT, matching ACCESS_TOKEN, or a forwarded owner-email header from\n * `agent-native mcp install`) — not the unauthenticated local dev-open\n * path. When true, `createMCPServerForRequest` serves\n * `config.productionActions` (the full surface) instead of the sparse dev\n * `config.actions`. Set by `mountMCP` from `verifyAuth`.\n */\n fullSurface?: boolean;\n /**\n * Whether this request may receive inline MCP App embeds (the `ui://`\n * resource reference hosts render in an iframe). Resolved once per request by\n * `createMCPServerForRequest` from `isMcpAppsInlineEnabled(identity)` — the\n * deploy-toggleable kill switch. When `false`, no MCP App resource is\n * advertised or referenced and tool results fall back to their deep-link\n * text. Defaults to disabled when unset.\n */\n inlineMcpApps?: boolean;\n}\n\n/**\n * Deploy-toggleable kill switch for inline MCP App embeds — the `ui://`\n * resource reference hosts like Codex / Cursor / ChatGPT render in a sandboxed\n * iframe. **Off by default**, so a not-yet-verified inline embed never reaches\n * normal users; flip it on per environment with `AGENT_NATIVE_MCP_APPS_INLINE=1`\n * and a redeploy. While the global switch is off, accounts listed in\n * `AGENT_NATIVE_MCP_APPS_INLINE_ALLOW_EMAILS` (comma/space separated) still get\n * inline embeds, so you can keep verifying a fix in production before enabling\n * it for everyone. Requires no skills/instructions change — when disabled, tool\n * results simply fall back to their deep-link text.\n */\nexport function isMcpAppsInlineEnabled(\n identity: MCPCallerIdentity | undefined,\n): boolean {\n const flag = process.env.AGENT_NATIVE_MCP_APPS_INLINE?.trim().toLowerCase();\n if (flag === \"1\" || flag === \"true\" || flag === \"yes\" || flag === \"on\") {\n return true;\n }\n const email = identity?.userEmail?.trim().toLowerCase();\n if (email) {\n const allowed = (\n process.env.AGENT_NATIVE_MCP_APPS_INLINE_ALLOW_EMAILS ?? \"\"\n )\n .split(/[\\s,]+/)\n .map((value) => value.trim().toLowerCase())\n .filter(Boolean);\n if (allowed.includes(email)) return true;\n }\n return false;\n}\n\ntype McpOAuthScope = (typeof MCP_OAUTH_SCOPES)[number];\n\nfunction isActionVisibleForOAuthScope(\n entry: ActionEntry,\n scopes: string[] | undefined,\n): boolean {\n if (!scopes) return true;\n const required: McpOAuthScope =\n entry.readOnly === true ? \"mcp:read\" : \"mcp:write\";\n return hasMcpOAuthScope(scopes, required);\n}\n\nconst COMPACT_MCP_APP_CATALOG_BUILTINS = new Set([\n \"list_apps\",\n \"open_app\",\n \"ask_app\",\n \"ask_app_status\",\n \"create_embed_session\",\n // `tool-search` MUST stay in every compact/connector surface: it is how a\n // compacted client discovers and loads any action on demand, which is what\n // makes \"small catalog by default\" safe instead of limiting.\n \"tool-search\",\n]);\n\nfunction isActionAdvertisedInCompactMcpAppCatalog(\n name: string,\n entry: ActionEntry,\n config: MCPConfig,\n): boolean {\n if (COMPACT_MCP_APP_CATALOG_BUILTINS.has(name)) return true;\n if (\n (entry.mcpApp as { compactCatalog?: unknown } | undefined)\n ?.compactCatalog === true\n ) {\n return true;\n }\n if (config.builtinCrossAppTools === false && entry.mcpApp?.resource) {\n return true;\n }\n return false;\n}\n\nfunction explicitlyRequestsFullMcpCatalog(\n requestMeta: MCPRequestMeta | undefined,\n): boolean {\n // Full catalog is a deliberate, rare opt-in — NEVER a default, and NEVER\n // inferred from the client name / user-agent. It is reached only by an\n // explicit deployment env or a token minted with\n // `agent-native connect --full-catalog` (which embeds `catalog_scope: \"full\"`,\n // surfaced here as requestMeta.fullCatalog). Dumping ~105 tool schemas\n // (100k+ tokens) into a context window just because a client called itself\n // \"code\"/\"cursor\"/\"codex\" was a recurring footgun. Everything else gets the\n // connector/compact catalog plus `tool-search`, which keeps every tool\n // reachable on demand.\n if (process.env.AGENT_NATIVE_MCP_FULL_CATALOG === \"1\") return true;\n return requestMeta?.fullCatalog === true;\n}\n\nconst warnedFullCatalogKeys = new Set<string>();\n\n/**\n * Loud, deduped warning emitted whenever the full MCP catalog is actually\n * served. Full catalog is a deliberate, rare opt-in (env or a `--full-catalog`\n * token claim); logging it makes an accidental ~100k-token tool dump visible\n * instead of silent, so a regression can't quietly reintroduce the footgun.\n */\nfunction warnFullCatalogServed(toolCount: number): void {\n const source =\n process.env.AGENT_NATIVE_MCP_FULL_CATALOG === \"1\"\n ? \"AGENT_NATIVE_MCP_FULL_CATALOG=1\"\n : \"a token minted with --full-catalog (catalog_scope:full)\";\n const key = `${source}:${toolCount}`;\n if (warnedFullCatalogKeys.has(key)) return;\n warnedFullCatalogKeys.add(key);\n console.warn(\n `[agent-native] Serving the FULL MCP tool catalog (${toolCount} tools) via ${source}. ` +\n `This is a large context payload meant to be a rare, explicit opt-in — most ` +\n `clients should use the default compact/connector catalog + tool-search instead.`,\n );\n}\n\n/**\n * Returns true when the given action name is in the template's connector\n * catalog, OR is a builtin cross-app tool that is always included for\n * external connector clients. Builtin tool names from\n * `COMPACT_MCP_APP_CATALOG_BUILTINS` are always allowed since they are the\n * stable external-agent verb set.\n */\nfunction isActionInConnectorCatalog(name: string, config: MCPConfig): boolean {\n if (COMPACT_MCP_APP_CATALOG_BUILTINS.has(name)) return true;\n if (!Array.isArray(config.connectorCatalog)) return false;\n return config.connectorCatalog.includes(name);\n}\n\ninterface ResolvedMcpAppResource {\n uri: string;\n legacyUris?: string[];\n name: string;\n title?: string;\n description?: string;\n html: ActionMcpAppResourceConfig[\"html\"];\n mimeType: typeof MCP_APP_MIME_TYPE;\n _meta?: Record<string, unknown>;\n}\n\ninterface McpAppResourceContext {\n actionName: string;\n appId?: string;\n requestOrigin?: string;\n}\n\ninterface VersionedMcpAppResourceUri {\n uri: string;\n legacyUris?: string[];\n}\n\nfunction metadataObject(value: unknown): Record<string, unknown> {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {};\n}\n\nfunction originString(value: unknown): string | undefined {\n if (typeof value !== \"string\" || !value.trim()) return undefined;\n try {\n return new URL(value).origin;\n } catch {\n return undefined;\n }\n}\n\nfunction hostSpecificDomainString(value: unknown): string | undefined {\n if (typeof value !== \"string\" || !value.trim()) return undefined;\n const trimmed = value.trim();\n try {\n new URL(trimmed);\n return undefined;\n } catch {\n return trimmed;\n }\n}\n\nfunction withMcpChatBridgeParam(urlOrPath: string): string {\n try {\n const base = \"http://agent-native.invalid\";\n const url = urlOrPath.startsWith(\"/\")\n ? new URL(urlOrPath, base)\n : new URL(urlOrPath);\n url.searchParams.set(MCP_APP_CHAT_BRIDGE_QUERY_PARAM, \"1\");\n return urlOrPath.startsWith(\"/\")\n ? `${url.pathname}${url.search}${url.hash}`\n : url.toString();\n } catch {\n return urlOrPath;\n }\n}\n\nfunction isEmbedStartUrl(value: string): boolean {\n try {\n const base = \"http://agent-native.invalid\";\n const url = value.startsWith(\"/\") ? new URL(value, base) : new URL(value);\n return url.pathname.includes(\"/_agent-native/embed/start\");\n } catch {\n return value.includes(\"/_agent-native/embed/start\");\n }\n}\n\nfunction routePathFromOpenUrl(value: string): string | null {\n try {\n const hasScheme = /^[a-z][a-z0-9+.-]*:\\/\\//i.test(value);\n const url = hasScheme\n ? new URL(value)\n : new URL(value, \"http://agent-native.invalid\");\n const route = `${url.pathname}${url.search}${url.hash}`;\n if (!route.startsWith(\"/\") || route.startsWith(\"//\")) return null;\n if (route.startsWith(\"/\\\\\")) return null;\n if (/^\\/[a-z][a-z0-9+.-]*:/i.test(route)) return null;\n return route;\n } catch {\n return null;\n }\n}\n\n/**\n * Recursively redact embed-ticket-bearing URLs from any value before it gets\n * serialized into a model-visible text payload. Embed start URLs carry a\n * single-use ticket that grants iframe access to the user's session — they\n * MUST stay in `_meta` (where the embed runtime can consume them) and never\n * appear in `content[].text` for the LLM. This is the generic safety net for\n * actions that return `{ embedStartUrl, ... }` without declaring\n * `mcpApp.resource` (the resource path already strips them via\n * `mcpAppStructuredContent`).\n *\n * Depth-capped to avoid pathological / circular structures. Strings that\n * embed an `isEmbedStartUrl` substring (e.g. a longer message that includes\n * the URL) are replaced with `[hidden embed URL]`.\n */\nfunction purgeEmbedStartUrls(value: unknown, depth = 0): unknown {\n if (depth > 5) return value;\n if (typeof value === \"string\") {\n return isEmbedStartUrl(value) ? \"[hidden embed URL]\" : value;\n }\n if (Array.isArray(value)) {\n return value.map((item) => purgeEmbedStartUrls(item, depth + 1));\n }\n if (value && typeof value === \"object\") {\n const out: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value as Record<string, unknown>)) {\n if (typeof val === \"string\" && isEmbedStartUrl(val)) {\n // Drop the key entirely for object-typed inputs so a tool result like\n // `{ embedStartUrl: \"...\" }` does not appear at all in the LLM text.\n continue;\n }\n out[key] = purgeEmbedStartUrls(val, depth + 1);\n }\n return out;\n }\n return value;\n}\n\nfunction mcpAppEmbedOpenLinkMeta(\n result: unknown,\n resource: ResolvedMcpAppResource,\n meta: MCPRequestMeta | undefined,\n): Record<string, unknown> {\n const out = metadataObject(result);\n const embedStartUrl =\n typeof out.embedStartUrl === \"string\"\n ? out.embedStartUrl\n : out.embed === true &&\n typeof out.url === \"string\" &&\n out.url.includes(\"/_agent-native/embed/start\")\n ? out.url\n : null;\n if (!embedStartUrl) return {};\n\n const webUrl = toAbsoluteOpenUrl(\n withMcpChatBridgeParam(embedStartUrl),\n meta?.origin,\n );\n const deepLinkUrl =\n typeof out.deepLinkUrl === \"string\" ? out.deepLinkUrl : null;\n const fallbackLabel = resource.title ?? resource.name ?? \"app\";\n const label =\n typeof out.app === \"string\" && out.app.trim()\n ? `Open ${out.app.trim()}`\n : fallbackLabel;\n const view =\n typeof out.view === \"string\" && out.view.trim()\n ? out.view.trim()\n : typeof out.path === \"string\" && out.path.trim()\n ? out.path.trim()\n : undefined;\n // Only fabricate an open URL when there is a real path-like value: an\n // explicit deepLinkUrl, or a non-embed `out.url`, or a leading-slash\n // `view`/`path` that's already a route. Bare view-name strings like\n // \"inbox\" or \"deck\" must NOT be turned into `${origin}/inbox` — apps\n // route views at app-specific paths (e.g. slides routes `view: \"deck\"`\n // at `/deck/:id`), so a synthesized origin-relative URL is just a 404.\n // In that case omit `openLink` entirely; the embedStart meta carries\n // the actual launch reference.\n const pathFromRouteLike =\n view && view.startsWith(\"/\")\n ? view\n : typeof out.path === \"string\" && out.path.trim().startsWith(\"/\")\n ? out.path.trim()\n : undefined;\n const explicitOpenUrl = deepLinkUrl\n ? deepLinkUrl\n : typeof out.url === \"string\" && !isEmbedStartUrl(out.url)\n ? out.url\n : pathFromRouteLike;\n const safeOpenUrl = explicitOpenUrl\n ? toAbsoluteOpenUrl(explicitOpenUrl, meta?.origin)\n : null;\n // Embed open links expose the safe browser target in `webUrl`, but the\n // desktop URL must enter the app through the registered scheme so Electron\n // can focus the right webview. Preserve the full route/query in the `to`\n // param; focus ids are often only present on `url`, not `out.params`.\n const desktopDeepLinkUrl = (() => {\n if (!safeOpenUrl) return null;\n const app =\n typeof out.app === \"string\" && out.app.trim()\n ? out.app.trim()\n : undefined;\n if (!app) return safeOpenUrl;\n if (isAgentNativeOpenDeepLink(safeOpenUrl)) {\n return toDesktopOpenUrl(safeOpenUrl);\n }\n const targetRoute = routePathFromOpenUrl(safeOpenUrl);\n if (!targetRoute) return safeOpenUrl;\n const viewParam =\n typeof out.view === \"string\" && out.view.trim() ? out.view.trim() : \"\";\n const params =\n out.params && typeof out.params === \"object\" && !Array.isArray(out.params)\n ? (out.params as Record<\n string,\n string | number | boolean | null | undefined\n >)\n : undefined;\n return toDesktopOpenUrl(\n buildDeepLink({\n app,\n view: viewParam,\n to: targetRoute,\n ...(params ? { params } : {}),\n }),\n );\n })();\n\n return {\n \"agent-native/embedStart\": {\n startUrl: webUrl,\n ...(typeof out.embedExpiresAt === \"number\"\n ? { expiresAt: out.embedExpiresAt }\n : {}),\n },\n ...(safeOpenUrl\n ? {\n \"agent-native/openLink\": {\n label,\n ...(view ? { view } : {}),\n webUrl: safeOpenUrl,\n desktopUrl: desktopDeepLinkUrl ?? safeOpenUrl,\n vscodeUrl: toVsCodeOpenUrl(safeOpenUrl),\n },\n }\n : {}),\n };\n}\n\nasync function withServerMintedMcpAppEmbedStart(\n result: unknown,\n meta: MCPRequestMeta | undefined,\n): Promise<unknown> {\n if (!result || typeof result !== \"object\" || Array.isArray(result)) {\n return result;\n }\n\n const out = result as Record<string, unknown>;\n if (out.embed !== true) return result;\n if (typeof out.embedStartUrl === \"string\" && out.embedStartUrl.trim()) {\n return result;\n }\n if (\n typeof out.url === \"string\" &&\n out.url.trim() &&\n isEmbedStartUrl(out.url)\n ) {\n return result;\n }\n\n const candidate = [out.url, out.path, out.deepLinkUrl].find(\n (value): value is string =>\n typeof value === \"string\" && value.trim().length > 0,\n );\n if (!candidate) return result;\n\n const trimmed = candidate.trim();\n const isPath = trimmed.startsWith(\"/\") && !trimmed.startsWith(\"//\");\n const isAbsoluteHttp = /^https?:\\/\\//i.test(trimmed);\n if (!isPath && !isAbsoluteHttp) return result;\n if (isAbsoluteHttp && !meta?.origin) return result;\n\n const ctx = getRequestContext();\n const ownerEmail = ctx?.userEmail?.trim();\n if (!ownerEmail) return result;\n\n const { normalizeEmbedTargetPath, createEmbedSessionTicket } =\n await import(\"../server/embed-session.js\");\n const { buildEmbedStartPath } = await import(\"../server/embed-route.js\");\n const targetPath = normalizeEmbedTargetPath(\n withMcpChatBridgeParam(trimmed),\n meta?.origin,\n );\n if (!targetPath) return result;\n\n const ticket = await createEmbedSessionTicket({\n ownerEmail,\n orgId: ctx?.orgId,\n targetPath,\n scope: typeof out.chrome === \"string\" ? out.chrome : null,\n });\n const startPath = buildEmbedStartPath(ticket.ticket);\n const embedStartUrl = meta?.origin\n ? new URL(startPath, meta.origin).toString()\n : startPath;\n\n return {\n ...out,\n embedStartUrl,\n embedTargetPath: targetPath,\n embedExpiresAt: ticket.expiresAt,\n };\n}\n\n/**\n * Build the deep-link content block + structured `_meta` for a tool result.\n * Best-effort: any throw / nullish link is swallowed so a bad `link` builder\n * never fails the tool call.\n */\nexport function buildLinkArtifacts(\n entry: ActionEntry,\n args: Record<string, any>,\n result: any,\n meta: MCPRequestMeta | undefined,\n): {\n block?: { type: \"text\"; text: string };\n _meta?: Record<string, unknown>;\n} {\n if (typeof entry.link !== \"function\") return {};\n try {\n const lk = entry.link({ args: args ?? {}, result });\n if (!lk?.url) return {};\n const linkUrl = isAgentNativeOpenDeepLink(lk.url)\n ? withCollapsedAgentSidebarParam(lk.url)\n : lk.url;\n const webUrl = toAbsoluteOpenUrl(linkUrl, meta?.origin);\n const desktopUrl = toDesktopOpenUrl(linkUrl);\n const vscodeUrl = toVsCodeOpenUrl(webUrl);\n const markdownUrl = meta?.target === \"desktop\" ? desktopUrl : webUrl;\n return {\n block: { type: \"text\", text: `\\n\\n[${lk.label} →](${markdownUrl})` },\n _meta: {\n \"agent-native/openLink\": {\n label: lk.label,\n view: lk.view,\n webUrl,\n desktopUrl,\n vscodeUrl,\n },\n },\n };\n } catch {\n return {};\n }\n}\n\n/**\n * Merge the generic cross-app builtin tools into the config's action\n * registry. **Template actions take precedence**: if a template defines an\n * action with the same name as a builtin (e.g. its own `list_apps`), the\n * template entry wins and the builtin is dropped. This mirrors the\n * template-over-workspace-core precedence in `autoDiscoverActions`.\n *\n * The builtins are pure-ish navigators / scaffolders; they call back into the\n * same `config.actions` / `config.askAgent` so there is no second agent loop.\n */\nfunction mergeBuiltinTools(\n config: MCPConfig,\n baseActions: Record<string, ActionEntry>,\n requestMeta?: MCPRequestMeta,\n): Record<string, ActionEntry> {\n if (config.builtinCrossAppTools === false) return baseActions;\n const builtins = getBuiltinCrossAppTools(config, requestMeta);\n const merged: Record<string, ActionEntry> = { ...builtins };\n // Template / app actions overwrite same-named builtins.\n for (const [name, entry] of Object.entries(baseActions)) {\n merged[name] = entry;\n }\n return merged;\n}\n\nfunction absoluteMetadataUrl(\n value: string | undefined,\n requestMeta?: MCPRequestMeta,\n): string | undefined {\n const trimmed = value?.trim();\n if (!trimmed) return undefined;\n try {\n if (requestMeta?.origin) {\n const basePath = requestMeta.basePath ?? getConfiguredAppBasePath();\n const appBase = `${requestMeta.origin.replace(/\\/+$/, \"\")}${basePath}/`;\n const appLocalValue =\n trimmed.startsWith(\"/\") && !trimmed.startsWith(\"//\")\n ? trimmed.replace(/^\\/+/, \"\")\n : trimmed;\n return new URL(appLocalValue, appBase).href;\n }\n return new URL(trimmed).href;\n } catch {\n return trimmed;\n }\n}\n\nfunction mcpServerInfo(config: MCPConfig, requestMeta?: MCPRequestMeta) {\n const websiteUrl = absoluteMetadataUrl(config.websiteUrl, requestMeta);\n const icons = config.icons\n ?.map((icon) => {\n const src = absoluteMetadataUrl(icon.src, requestMeta);\n if (!src) return null;\n return {\n src,\n ...(icon.mimeType ? { mimeType: icon.mimeType } : {}),\n ...(icon.sizes?.length ? { sizes: icon.sizes } : {}),\n ...(icon.theme ? { theme: icon.theme } : {}),\n };\n })\n .filter((icon): icon is NonNullable<typeof icon> => Boolean(icon));\n return {\n name: config.name,\n version: config.version ?? \"1.0.0\",\n ...(config.title?.trim() ? { title: config.title.trim() } : {}),\n ...(config.description?.trim()\n ? { description: config.description.trim() }\n : {}),\n ...(websiteUrl ? { websiteUrl } : {}),\n ...(icons?.length ? { icons } : {}),\n };\n}\n\nfunction safeUiSegment(value: string | undefined, fallback: string): string {\n const normalized = (value || fallback)\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9._-]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n return normalized || fallback;\n}\n\n// ChatGPT and Claude cache MCP App resource HTML by `ui://` URI. Bump this\n// when the shared shell changes in a way that must invalidate host caches.\nconst MCP_APP_RESOURCE_SHELL_VERSION = \"shell-v51\";\n\nfunction legacyDefaultMcpAppUri(config: MCPConfig, actionName: string): string {\n const app = safeUiSegment(config.appId ?? config.name, \"agent-native\");\n const action = safeUiSegment(actionName, \"tool\");\n return `ui://${app}/${action}`;\n}\n\nfunction versionMcpAppResourceUri(\n rawUri: string,\n): VersionedMcpAppResourceUri | null {\n const uri = rawUri.trim();\n if (!uri.startsWith(\"ui://\")) return null;\n const versionSuffix = `/${MCP_APP_RESOURCE_SHELL_VERSION}`;\n let versionedUri: string;\n try {\n const parsed = new URL(uri);\n const path = parsed.pathname.replace(/\\/+$/g, \"\");\n parsed.pathname = /\\/shell-v\\d+$/.test(path)\n ? path.replace(/\\/shell-v\\d+$/, versionSuffix)\n : `${path}${versionSuffix}`;\n versionedUri = parsed.toString();\n } catch {\n return null;\n }\n return {\n uri: versionedUri,\n ...(versionedUri !== uri ? { legacyUris: [uri] } : {}),\n };\n}\n\nfunction unversionMcpAppResourceUri(uri: string): string | null {\n if (!uri.startsWith(\"ui://\")) return null;\n try {\n const parsed = new URL(uri);\n parsed.pathname = parsed.pathname\n .replace(/\\/+$/g, \"\")\n .replace(/\\/shell-v\\d+$/g, \"\");\n return parsed.toString();\n } catch {\n return null;\n }\n}\n\nfunction normalizeMcpAppResourceUriForMatch(uri: unknown): string | null {\n if (typeof uri !== \"string\") return null;\n const trimmed = uri.trim();\n if (!trimmed.startsWith(\"ui://\")) return null;\n return (\n unversionMcpAppResourceUri(trimmed) ??\n trimmed.replace(/\\/+$/g, \"\").replace(/\\/shell-v\\d+(?=([?#]|$))/g, \"\")\n );\n}\n\nfunction matchesMcpAppResourceUri(\n resourceUri: VersionedMcpAppResourceUri,\n requestedUri: unknown,\n): boolean {\n if (typeof requestedUri !== \"string\") return false;\n const requested = requestedUri.trim();\n if (resourceUri.uri === requested) return true;\n if (resourceUri.legacyUris?.includes(requested)) return true;\n const requestedBase = normalizeMcpAppResourceUriForMatch(requested);\n const currentBase = normalizeMcpAppResourceUriForMatch(resourceUri.uri);\n return Boolean(requestedBase && currentBase && requestedBase === currentBase);\n}\n\nfunction getMcpAppResourceUri(\n config: MCPConfig,\n actionName: string,\n entry: ActionEntry,\n): VersionedMcpAppResourceUri | null {\n const resource = entry.mcpApp?.resource;\n if (!resource) return null;\n const baseUri =\n resource.uri?.trim() || legacyDefaultMcpAppUri(config, actionName);\n return versionMcpAppResourceUri(baseUri);\n}\n\nfunction expandRequestOriginSources(\n sources: string[] | undefined,\n requestMeta?: MCPRequestMeta,\n): string[] | undefined {\n if (!sources) return undefined;\n const origin = requestMeta?.origin;\n return sources.flatMap((source) =>\n source === MCP_APP_REQUEST_ORIGIN_CSP_SOURCE && origin\n ? [origin]\n : [source],\n );\n}\n\nfunction openAiWidgetCsp(\n cspConfig: ActionMcpAppCsp | undefined,\n requestMeta?: MCPRequestMeta,\n): Record<string, string[]> | undefined {\n if (!cspConfig) return undefined;\n const csp: Record<string, string[]> = {};\n const connectDomains = expandRequestOriginSources(\n cspConfig.connectDomains,\n requestMeta,\n );\n const resourceDomains = expandRequestOriginSources(\n cspConfig.resourceDomains,\n requestMeta,\n );\n const frameDomains = expandRequestOriginSources(\n cspConfig.frameDomains,\n requestMeta,\n );\n if (connectDomains?.length) csp.connect_domains = connectDomains;\n if (resourceDomains?.length) csp.resource_domains = resourceDomains;\n if (frameDomains?.length) csp.frame_domains = frameDomains;\n return Object.keys(csp).length > 0 ? csp : undefined;\n}\n\nfunction mcpAppUiMeta(\n resource: ActionMcpAppResourceConfig,\n resolvedCsp: ActionMcpAppCsp | undefined,\n requestMeta?: MCPRequestMeta,\n description?: string,\n): Record<string, unknown> | undefined {\n const base =\n resource._meta && typeof resource._meta === \"object\"\n ? { ...resource._meta }\n : {};\n const existingUi =\n base.ui && typeof base.ui === \"object\" && !Array.isArray(base.ui)\n ? (base.ui as Record<string, unknown>)\n : {};\n const ui: Record<string, unknown> = { ...existingUi };\n delete ui.domain;\n if (resolvedCsp) {\n ui.csp = {\n ...resolvedCsp,\n connectDomains: expandRequestOriginSources(\n resolvedCsp.connectDomains,\n requestMeta,\n ),\n resourceDomains: expandRequestOriginSources(\n resolvedCsp.resourceDomains,\n requestMeta,\n ),\n frameDomains: expandRequestOriginSources(\n resolvedCsp.frameDomains,\n requestMeta,\n ),\n baseUriDomains: expandRequestOriginSources(\n resolvedCsp.baseUriDomains,\n requestMeta,\n ),\n };\n }\n if (resource.permissions) ui.permissions = resource.permissions;\n const hostSpecificDomain =\n hostSpecificDomainString(resource.domain) ??\n hostSpecificDomainString(existingUi.domain);\n if (hostSpecificDomain) ui.domain = hostSpecificDomain;\n const openAiWidgetDomain =\n originString(resource.domain) ??\n originString(ui.domain) ??\n originString(existingUi.domain) ??\n originString(requestMeta?.origin);\n if (typeof resource.prefersBorder === \"boolean\") {\n ui.prefersBorder = resource.prefersBorder;\n }\n if (Object.keys(ui).length > 0) base.ui = ui;\n if (description && base[\"openai/widgetDescription\"] == null) {\n base[\"openai/widgetDescription\"] = description;\n }\n if (\n typeof resource.prefersBorder === \"boolean\" &&\n base[\"openai/widgetPrefersBorder\"] == null\n ) {\n base[\"openai/widgetPrefersBorder\"] = resource.prefersBorder;\n }\n const openAiCsp = openAiWidgetCsp(resolvedCsp, requestMeta);\n if (openAiCsp && base[\"openai/widgetCSP\"] == null) {\n base[\"openai/widgetCSP\"] = openAiCsp;\n }\n if (openAiWidgetDomain && base[\"openai/widgetDomain\"] == null) {\n base[\"openai/widgetDomain\"] = openAiWidgetDomain;\n }\n return Object.keys(base).length > 0 ? base : undefined;\n}\n\nasync function resolveMcpAppCsp(\n resource: ActionMcpAppResourceConfig,\n ctx: McpAppResourceContext,\n): Promise<ActionMcpAppCsp | undefined> {\n if (!resource.csp) return undefined;\n return typeof resource.csp === \"function\"\n ? await resource.csp(ctx)\n : resource.csp;\n}\n\nasync function resolveMcpAppResource(\n config: MCPConfig,\n actionName: string,\n entry: ActionEntry,\n requestMeta?: MCPRequestMeta,\n): Promise<ResolvedMcpAppResource | null> {\n const resource = entry.mcpApp?.resource;\n if (!resource) return null;\n // NB: the inline kill switch is intentionally NOT enforced here. This\n // resolver also backs `resources/read`, which must keep serving the shell\n // for a URI the host already holds (e.g. a cached descriptor) so it degrades\n // gracefully instead of throwing a hard `-32603`. The switch is enforced at\n // the *advertisement/render* sites (`tools/list` descriptor meta,\n // `tools/call` result meta, `resources/list`) so disabled embeds never get\n // advertised in the first place.\n const resolvedUri = getMcpAppResourceUri(config, actionName, entry);\n if (!resolvedUri) return null;\n const description = resource.description ?? entry.tool.description;\n const resolvedCsp = await resolveMcpAppCsp(resource, {\n actionName,\n appId: config.appId,\n requestOrigin: requestMeta?.origin,\n });\n const resourceMeta = mcpAppUiMeta(\n resource,\n resolvedCsp,\n requestMeta,\n description,\n );\n return {\n uri: resolvedUri.uri,\n ...(resolvedUri.legacyUris ? { legacyUris: resolvedUri.legacyUris } : {}),\n name: resource.name?.trim() || actionName,\n ...(resource.title ? { title: resource.title } : {}),\n ...(description ? { description } : {}),\n html: resource.html,\n mimeType: resource.mimeType ?? MCP_APP_MIME_TYPE,\n ...(resourceMeta ? { _meta: resourceMeta } : {}),\n };\n}\n\nasync function resolveMcpAppResourceSafely(\n config: MCPConfig,\n actionName: string,\n entry: ActionEntry,\n requestMeta?: MCPRequestMeta,\n): Promise<ResolvedMcpAppResource | null> {\n try {\n return await resolveMcpAppResource(config, actionName, entry, requestMeta);\n } catch (error) {\n console.warn(\n `[mcp] Skipping MCP App resource for action \"${actionName}\" because its metadata could not be resolved.`,\n error,\n );\n return null;\n }\n}\n\nasync function getMcpAppResources(\n config: MCPConfig,\n actions: Record<string, ActionEntry>,\n requestMeta?: MCPRequestMeta,\n): Promise<ResolvedMcpAppResource[]> {\n // Advertisement path (resources/list + resources/templates/list): suppressed\n // by the inline kill switch so disabled embeds are never listed.\n if (!requestMeta?.inlineMcpApps) return [];\n const resources = await Promise.all(\n Object.entries(actions).map(([name, entry]) =>\n resolveMcpAppResourceSafely(config, name, entry, requestMeta),\n ),\n );\n return resources.filter((resource): resource is ResolvedMcpAppResource =>\n Boolean(resource),\n );\n}\n\nfunction renderMcpAppHtml(\n resource: ResolvedMcpAppResource,\n actionName: string,\n config: MCPConfig,\n requestMeta?: MCPRequestMeta,\n): string {\n if (typeof resource.html === \"function\") {\n return resource.html({\n actionName,\n appId: config.appId,\n requestOrigin: requestMeta?.origin,\n });\n }\n return resource.html;\n}\n\nfunction openAiToolDescriptorMeta(\n resource: ResolvedMcpAppResource,\n): Record<string, unknown> {\n const label = resource.title ?? resource.name;\n const widgetCsp = metadataObject(resource._meta?.[\"openai/widgetCSP\"]);\n return {\n \"openai/outputTemplate\": resource.uri,\n \"openai/toolInvocation/invoking\": `Opening ${label}`,\n \"openai/toolInvocation/invoked\": `${label} ready`,\n \"openai/widgetAccessible\": true,\n ...(Object.keys(widgetCsp).length > 0\n ? { \"openai/widgetCSP\": widgetCsp }\n : {}),\n };\n}\n\nfunction openAiToolResultMeta(\n resource: ResolvedMcpAppResource,\n): Record<string, unknown> {\n const label = resource.title ?? resource.name;\n const widgetCsp = metadataObject(resource._meta?.[\"openai/widgetCSP\"]);\n return {\n \"openai/outputTemplate\": resource.uri,\n \"openai/toolInvocation/invoking\": `Opening ${label}`,\n \"openai/toolInvocation/invoked\": `${label} ready`,\n \"openai/widgetAccessible\": true,\n ...(Object.keys(widgetCsp).length > 0\n ? { \"openai/widgetCSP\": widgetCsp }\n : {}),\n };\n}\n\nfunction mcpAppToolUiMeta(\n resource: ResolvedMcpAppResource,\n visibility: unknown,\n): Record<string, unknown> {\n return {\n resourceUri: resource.uri,\n visibility: Array.isArray(visibility) ? visibility : [\"model\", \"app\"],\n };\n}\n\nfunction primitiveValue(value: unknown): value is string | number | boolean {\n return (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n );\n}\n\nfunction mcpAppStructuredContent(\n result: unknown,\n meta: Record<string, unknown> | undefined,\n): Record<string, unknown> {\n const out: Record<string, unknown> =\n result && typeof result === \"object\" && !Array.isArray(result)\n ? { ...(result as Record<string, unknown>) }\n : primitiveValue(result)\n ? { result }\n : {};\n for (const key of [\"embedStartUrl\", \"startUrl\"]) {\n const value = out[key];\n if (typeof value === \"string\" && isEmbedStartUrl(value)) delete out[key];\n }\n if (typeof out.url === \"string\" && isEmbedStartUrl(out.url)) {\n delete out.url;\n }\n // Internal embed-routing fields belong in `_meta[\"agent-native/embedStart\"]`\n // (consumed by the embed runtime), not in `structuredContent` (read by the\n // LLM). `embedTargetPath` reveals the exact route + thread/draft id the user\n // is looking at; `embedExpiresAt` is an unintended timestamp; ticket-bearing\n // fields are single-use credentials. Drop all of them unconditionally.\n for (const key of [\n \"embedTargetPath\",\n \"embedExpiresAt\",\n \"ticket\",\n \"embedTicket\",\n ]) {\n delete out[key];\n }\n for (const key of Object.keys(out)) {\n if (/Ticket$/.test(key)) delete out[key];\n }\n const openLink = meta?.[\"agent-native/openLink\"];\n if (openLink && typeof openLink === \"object\" && !Array.isArray(openLink)) {\n const webUrl = (openLink as Record<string, unknown>).webUrl;\n if (typeof webUrl === \"string\" && isEmbedStartUrl(webUrl)) {\n return Object.keys(out).length > 0 ? out : { status: \"ok\" };\n }\n out.openLink = openLink;\n if (typeof webUrl === \"string\" && !out.url) out.url = webUrl;\n }\n return Object.keys(out).length > 0 ? out : { status: \"ok\" };\n}\n\nfunction truncateToolText(value: string, max = 2000): string {\n if (value.length <= max) return value;\n return `${value.slice(0, max - 1)}…`;\n}\n\nfunction conciseMcpAppToolText(\n name: string,\n result: unknown,\n structuredContent: Record<string, unknown>,\n): string {\n if (typeof result === \"string\") return truncateToolText(result);\n const message = structuredContent.message;\n if (typeof message === \"string\" && message.trim()) {\n return truncateToolText(message.trim());\n }\n const title = structuredContent.title ?? structuredContent.name;\n if (typeof title === \"string\" && title.trim()) {\n return `${title.trim()} is ready.`;\n }\n const id = structuredContent.id;\n if (typeof id === \"string\" && id.trim()) {\n return `${name} completed for ${id.trim()}.`;\n }\n return `${name} completed.`;\n}\n\nfunction isSuccessOnlyResult(value: Record<string, unknown>): boolean {\n const keys = Object.keys(value);\n if (keys.length === 0) return true;\n return keys.every((key) => {\n const item = value[key];\n if (key === \"ok\" || key === \"success\") return item === true;\n if (key === \"status\") {\n return item === \"ok\" || item === \"success\" || item === \"completed\";\n }\n return false;\n });\n}\n\nfunction conciseToolResultText(name: string, result: unknown): string {\n const purged = purgeEmbedStartUrls(result);\n if (typeof purged === \"string\") return truncateToolText(purged);\n if (purged === true || purged == null) return `${name} completed.`;\n if (purged && typeof purged === \"object\" && !Array.isArray(purged)) {\n const record = purged as Record<string, unknown>;\n const message = record.message ?? record.summary;\n if (typeof message === \"string\" && message.trim()) {\n return truncateToolText(message.trim());\n }\n const id = record.id ?? record.planId ?? record.commentId;\n const title = record.title ?? record.name;\n if (typeof title === \"string\" && title.trim()) {\n const titleText = title.trim();\n return typeof id === \"string\" && id.trim()\n ? `${titleText} (${id.trim()}) is ready.`\n : `${titleText} is ready.`;\n }\n if (typeof id === \"string\" && id.trim()) {\n return `${name} completed for ${id.trim()}.`;\n }\n const link = record.url ?? record.webUrl ?? record.path;\n if (typeof link === \"string\" && link.trim()) {\n return `${name} completed: ${truncateToolText(link.trim(), 500)}`;\n }\n if (isSuccessOnlyResult(record)) return `${name} completed.`;\n }\n const text = JSON.stringify(purged);\n return text === undefined ? `${name} completed.` : truncateToolText(text);\n}\n\n// ---------------------------------------------------------------------------\n// MCP Server creation — converts ActionEntry registry to MCP tools\n// ---------------------------------------------------------------------------\n\n/**\n * Build a fully-wired MCP `Server` for a single request / session.\n *\n * Shared by the stateless Streamable-HTTP mount (`mountMCP`) and the stdio\n * standalone transport. The HTTP mount passes the per-request origin via\n * `requestMeta`; the stdio standalone path passes the resolved local app\n * origin so deep links still become absolute URLs.\n */\nexport async function createMCPServerForRequest(\n config: MCPConfig,\n identity: MCPCallerIdentity | undefined,\n requestMeta?: MCPRequestMeta,\n) {\n const { Server } = await import(\"@modelcontextprotocol/sdk/server/index.js\");\n const {\n ListToolsRequestSchema,\n CallToolRequestSchema,\n ListResourcesRequestSchema,\n ReadResourceRequestSchema,\n ListResourceTemplatesRequestSchema,\n } = await import(\"@modelcontextprotocol/sdk/types.js\");\n\n // Resolve the effective caller identity. JWT / header-derived identity\n // (passed by `mountMCP` via `verifyAuth`) wins. When the caller passed no\n // identity — the stdio **standalone** path — fall back to the\n // `AGENT_NATIVE_OWNER_EMAIL` env the `agent-native mcp install` flow writes\n // into the `agent-native mcp serve` process env, so standalone tool runs are\n // tenant-scoped to the configured owner instead of running unscoped. Stays\n // undefined for true dev-open (no token, no secret, no owner) — behavior\n // there is unchanged.\n const ownerFromEnv = process.env.AGENT_NATIVE_OWNER_EMAIL?.trim();\n const effectiveIdentity: MCPCallerIdentity | undefined =\n identity ??\n (ownerFromEnv\n ? { userEmail: ownerFromEnv, orgDomain: undefined }\n : undefined);\n\n // Resolve the inline-MCP-App kill switch once per request from the effective\n // identity + environment, then thread it through `requestMeta` so every\n // resource/tool handler below honors the same decision. An explicit value on\n // the incoming meta (tests / embedded callers) wins.\n requestMeta = {\n ...(requestMeta ?? {}),\n inlineMcpApps:\n requestMeta?.inlineMcpApps ?? isMcpAppsInlineEnabled(effectiveIdentity),\n };\n\n // The action set the request handlers operate on = base actions + generic\n // cross-app builtins (template wins on name collision). An authenticated\n // real caller (connect-minted token / `mcp install` owner / production —\n // `requestMeta.fullSurface`, or the stdio standalone path identified by\n // `AGENT_NATIVE_OWNER_EMAIL`) gets the full `productionActions` surface\n // even in local dev; the unauthenticated dev-open path keeps the sparse\n // `config.actions`. See `external-agents` skill, \"Dev vs production tool\n // surface\".\n const useFullSurface = requestMeta?.fullSurface === true || !!ownerFromEnv;\n const baseActions =\n useFullSurface && config.productionActions\n ? config.productionActions\n : config.actions;\n const actions = mergeBuiltinTools(config, baseActions, requestMeta);\n const visibleActions = Object.fromEntries(\n Object.entries(actions).filter(([, entry]) =>\n isActionVisibleForOAuthScope(entry, effectiveIdentity?.oauthScopes),\n ),\n );\n const fullCatalogRequested = explicitlyRequestsFullMcpCatalog(requestMeta);\n // Compact/connector is the DEFAULT for every caller — hosted connectors,\n // code clients (Claude Code / Cursor / Codex), and the local CLI alike. The\n // full ~105-tool catalog is served only on the explicit opt-in above, so a\n // host can never dump every action schema into one giant tool card. The\n // `mcp:apps` scope still lands on this compact MCP-Apps surface; with no\n // opt-in, everyone else does too.\n const compactMcpAppCatalog = !fullCatalogRequested;\n const advertisedActionsBeforeConnector = compactMcpAppCatalog\n ? Object.fromEntries(\n Object.entries(visibleActions).filter(([name, entry]) =>\n isActionAdvertisedInCompactMcpAppCatalog(name, entry, config),\n ),\n )\n : visibleActions;\n // Connector-catalog tier: when a template declares a connector allow-list,\n // serve exactly that curated surface (+ cross-app builtins + tool-search) to\n // external callers unless they explicitly opted into the full catalog. This\n // is active by default whenever a catalog is declared — no env flag required —\n // so the ~105-tool full catalog can never leak just because a deployment\n // forgot to set one. It also keeps db-exec / seed-* / extension /\n // browser-session footguns off the external surface.\n const connectorCatalogActive =\n Array.isArray(config.connectorCatalog) &&\n config.connectorCatalog.length > 0 &&\n !fullCatalogRequested;\n // When the connector catalog is active, filter directly from visibleActions\n // rather than advertisedActionsBeforeConnector. This ensures the connector\n // tier is an independent, template-declared surface that doesn't accidentally\n // narrow to just the compact-catalog builtins when shouldUseCompactMcpCatalogByDefault\n // would have activated the compact catalog for the same caller.\n const advertisedActions = connectorCatalogActive\n ? Object.fromEntries(\n Object.entries(visibleActions).filter(([name]) =>\n isActionInConnectorCatalog(name, config),\n ),\n )\n : advertisedActionsBeforeConnector;\n if (fullCatalogRequested) {\n warnFullCatalogServed(Object.keys(advertisedActions).length);\n }\n const supportsMcpApps =\n compactMcpAppCatalog ||\n Object.values(advertisedActions).some((entry) =>\n Boolean(entry.mcpApp?.resource),\n );\n const server = new Server(mcpServerInfo(config, requestMeta), {\n capabilities: {\n tools: {},\n ...(supportsMcpApps\n ? {\n resources: {},\n extensions: {\n [MCP_APP_EXTENSION_ID]: {\n mimeTypes: [MCP_APP_MIME_TYPE],\n },\n },\n }\n : {}),\n },\n });\n\n // Resolve orgId once per request (DB lookup) so subsequent wraps are\n // synchronous. The caller identity may be undefined for true dev-open —\n // in that case we run with no userEmail/orgId, which makes downstream\n // tools that require per-user scope return empty results rather than\n // cross-tenant data (the safe default).\n const orgIdPromise = effectiveIdentity?.orgId\n ? Promise.resolve(effectiveIdentity.orgId)\n : resolveOrgIdFromDomain(effectiveIdentity?.orgDomain);\n\n /**\n * Wrap a callback in\n * `runWithRequestContext({ userEmail, orgId, requestOrigin }, fn)`.\n * Both the tools/list and tools/call handlers go through this so\n * downstream `accessFilter`, `resolveCredential`, and per-user MCP\n * visibility checks see the verified caller's identity. `requestOrigin`\n * is the live server origin derived from the inbound request (same value\n * used to absolutize deep links) so actions that build fetchable URLs\n * (e.g. design `export-coding-handoff`'s signed raw-code URL) resolve the\n * correct local-workspace origin instead of a prod/localhost fallback.\n */\n async function withCallerContext<T>(fn: () => Promise<T>): Promise<T> {\n const orgId = await orgIdPromise;\n return runWithRequestContext(\n {\n userEmail: effectiveIdentity?.userEmail,\n orgId,\n ...(requestMeta?.origin ? { requestOrigin: requestMeta.origin } : {}),\n },\n fn,\n ) as Promise<T>;\n }\n\n // tools/list — return all actions + ask-agent meta-tool. Wrapped in the\n // request context so per-user MCP visibility (mcp-client/visibility.ts)\n // applies to the listing too.\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n return withCallerContext(async () => {\n const tools = await Promise.all(\n Object.entries(advertisedActions).map(async ([name, entry]) => {\n const hasLink = typeof entry.link === \"function\";\n const mcpAppResource = await resolveMcpAppResourceSafely(\n config,\n name,\n entry,\n requestMeta,\n );\n const rawToolMeta =\n (entry.tool as any)._meta &&\n typeof (entry.tool as any)._meta === \"object\" &&\n !Array.isArray((entry.tool as any)._meta)\n ? { ...((entry.tool as any)._meta as Record<string, unknown>) }\n : {};\n const toolMeta = {\n ...rawToolMeta,\n // Advertisement path: only tag the tool with its inline-embed\n // descriptor when the kill switch is on, so disabled embeds never\n // prompt a host to render/read the `ui://` resource.\n ...(mcpAppResource && requestMeta?.inlineMcpApps\n ? {\n ...openAiToolDescriptorMeta(mcpAppResource),\n [MCP_APP_RESOURCE_URI_META_KEY]: mcpAppResource.uri,\n ui: mcpAppToolUiMeta(\n mcpAppResource,\n entry.mcpApp?.visibility ??\n metadataObject(rawToolMeta.ui).visibility,\n ),\n }\n : {}),\n };\n const baseDescription = entry.tool.description ?? name;\n const annotations: Record<string, unknown> = {\n readOnlyHint: entry.readOnly === true,\n destructiveHint: entry.publicAgent?.isConsequential === true,\n openWorldHint: false,\n };\n if (hasLink) annotations[\"agent-native/producesOpenLink\"] = true;\n return {\n name,\n description: hasLink\n ? `${baseDescription} After calling, surface the returned \"Open in … →\" link to the user.`\n : baseDescription,\n inputSchema: entry.tool.parameters ?? {\n type: \"object\" as const,\n properties: {},\n },\n ...(Object.keys(toolMeta).length > 0 ? { _meta: toolMeta } : {}),\n annotations,\n };\n }),\n );\n\n if (\n !compactMcpAppCatalog &&\n !connectorCatalogActive &&\n config.askAgent &&\n hasMcpOAuthScope(effectiveIdentity?.oauthScopes, \"mcp:write\")\n ) {\n tools.push({\n name: \"ask-agent\",\n description:\n \"Send a natural-language message to the app's AI agent and get a response. \" +\n \"Use this for complex, multi-step tasks that require the agent's reasoning \" +\n \"and full context about the app.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n message: {\n type: \"string\",\n description: \"The message to send to the agent\",\n },\n },\n required: [\"message\"],\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n openWorldHint: false,\n },\n });\n }\n\n return { tools };\n });\n });\n\n // tools/call — dispatch to action registry or ask-agent. Wrapped in the\n // request context so the action's `run(args)` and `askAgent()` execute\n // with the verified caller's identity, not the platform default.\n server.setRequestHandler(CallToolRequestSchema, async (request: any) => {\n return withCallerContext(async () => {\n const { name, arguments: args } = request.params;\n\n if (name === \"ask-agent\" && config.askAgent) {\n if (compactMcpAppCatalog || connectorCatalogActive) {\n return {\n content: [{ type: \"text\", text: `Unknown tool: ${name}` }],\n isError: true,\n };\n }\n if (!hasMcpOAuthScope(effectiveIdentity?.oauthScopes, \"mcp:write\")) {\n return {\n content: [\n {\n type: \"text\",\n text: \"Forbidden: OAuth scope does not allow ask-agent\",\n },\n ],\n isError: true,\n };\n }\n const message = args?.message ?? \"\";\n try {\n const result = await config.askAgent(message);\n return { content: [{ type: \"text\", text: result }] };\n } catch (err: any) {\n return {\n content: [{ type: \"text\", text: `Error: ${err.message}` }],\n isError: true,\n };\n }\n }\n\n // Connector-catalog tier: when active, callableActions === advertisedActions\n // (the filtered set). Non-listed tools are not callable — mirroring how\n // compactMcpAppCatalog gates calls on advertisedActions.\n const callableActions =\n compactMcpAppCatalog || connectorCatalogActive\n ? advertisedActions\n : actions;\n const entry = callableActions[name];\n if (!entry) {\n return {\n content: [{ type: \"text\", text: `Unknown tool: ${name}` }],\n isError: true,\n };\n }\n if (\n !isActionVisibleForOAuthScope(entry, effectiveIdentity?.oauthScopes)\n ) {\n return {\n content: [\n {\n type: \"text\",\n text: `Forbidden: OAuth scope does not allow tool ${name}`,\n },\n ],\n isError: true,\n };\n }\n\n try {\n // We're inside `withCallerContext`, so the request-context getters\n // resolve the verified MCP caller's identity (do NOT inject a dev\n // fallback). Tag the call as an external-agent MCP dispatch.\n const result = await entry.run((args as Record<string, string>) ?? {}, {\n userEmail: getRequestUserEmail(),\n orgId: getRequestOrgId() ?? null,\n caller: \"mcp\",\n actionName: name,\n });\n const mcpResult = isMcpActionResult(result) ? result : null;\n const rawResult = mcpResult ? mcpResult.raw : result;\n const resultForClient = mcpResult ? mcpResult.text : result;\n const mcpResultIsError =\n !!mcpResult &&\n !!mcpResult.raw &&\n typeof mcpResult.raw === \"object\" &&\n (mcpResult.raw as Record<string, unknown>).isError === true;\n // Render path: only treat the result as an inline embed when the kill\n // switch is on. When off, `mcpAppResource` is null so every embed\n // branch below degrades to the plain deep-link artifacts the tool would\n // otherwise return — no `openai/outputTemplate`, no minted embed-start,\n // no embed structuredContent — so the host shows a link, not an iframe.\n const mcpAppResource = requestMeta?.inlineMcpApps\n ? await resolveMcpAppResourceSafely(config, name, entry, requestMeta)\n : null;\n const rawResultForClient = mcpAppResource\n ? await withServerMintedMcpAppEmbedStart(rawResult, requestMeta)\n : rawResult;\n const { block, _meta } = buildLinkArtifacts(\n entry,\n (args as Record<string, any>) ?? {},\n rawResultForClient,\n requestMeta,\n );\n const responseMeta: Record<string, unknown> = {\n ...(_meta ?? {}),\n ...(mcpAppResource\n ? mcpAppEmbedOpenLinkMeta(\n rawResultForClient,\n mcpAppResource,\n requestMeta,\n )\n : {}),\n ...(mcpAppResource ? openAiToolResultMeta(mcpAppResource) : {}),\n };\n const toolUiMeta = metadataObject((entry.tool as any)._meta?.ui);\n const toolVisibility = toolUiMeta.visibility;\n const isAppOnlyVisibility =\n Array.isArray(toolVisibility) &&\n toolVisibility.length > 0 &&\n toolVisibility.every((v) => v === \"app\");\n const structuredContent = mcpAppResource\n ? mcpAppStructuredContent(rawResultForClient, responseMeta)\n : isAppOnlyVisibility &&\n rawResult &&\n typeof rawResult === \"object\" &&\n !Array.isArray(rawResult)\n ? (rawResult as Record<string, unknown>)\n : undefined;\n const text = mcpAppResource\n ? conciseMcpAppToolText(name, resultForClient, structuredContent!)\n : conciseToolResultText(name, resultForClient);\n const content: any[] = [{ type: \"text\", text }];\n if (block) content.push(block);\n return {\n content,\n ...(mcpResultIsError ? { isError: true } : {}),\n ...(structuredContent ? { structuredContent } : {}),\n ...(Object.keys(responseMeta).length > 0\n ? { _meta: responseMeta }\n : {}),\n };\n } catch (err: any) {\n return {\n content: [{ type: \"text\", text: `Error: ${err.message}` }],\n isError: true,\n };\n }\n });\n });\n\n if (supportsMcpApps) {\n server.setRequestHandler(ListResourcesRequestSchema, async () => {\n return withCallerContext(async () => {\n const mcpAppResources = await getMcpAppResources(\n config,\n advertisedActions,\n requestMeta,\n );\n return {\n resources: mcpAppResources.map((resource) => ({\n uri: resource.uri,\n name: resource.name,\n ...(resource.title ? { title: resource.title } : {}),\n ...(resource.description\n ? { description: resource.description }\n : {}),\n mimeType: resource.mimeType,\n ...(resource._meta ? { _meta: resource._meta } : {}),\n })),\n };\n });\n });\n\n server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => {\n return withCallerContext(async () => {\n const mcpAppResources = await getMcpAppResources(\n config,\n advertisedActions,\n requestMeta,\n );\n return {\n resourceTemplates: mcpAppResources.map((resource) => ({\n uriTemplate: resource.uri,\n name: resource.name,\n ...(resource.title ? { title: resource.title } : {}),\n ...(resource.description\n ? { description: resource.description }\n : {}),\n mimeType: resource.mimeType,\n ...(resource._meta ? { _meta: resource._meta } : {}),\n })),\n };\n });\n });\n\n server.setRequestHandler(\n ReadResourceRequestSchema,\n async (request: any) => {\n return withCallerContext(async () => {\n const uri = request.params?.uri;\n let found: {\n actionName: string;\n resource: ResolvedMcpAppResource;\n } | null = null;\n for (const [name, entry] of Object.entries(advertisedActions)) {\n const resourceUri = getMcpAppResourceUri(config, name, entry);\n if (!resourceUri || !matchesMcpAppResourceUri(resourceUri, uri)) {\n continue;\n }\n const resource = await resolveMcpAppResourceSafely(\n config,\n name,\n entry,\n requestMeta,\n );\n if (resource) {\n found = { actionName: name, resource };\n break;\n }\n // resolveMcpAppResourceSafely returned null (e.g. an async resolver\n // threw) — keep scanning the remaining candidates rather than\n // aborting and reporting the resource as missing.\n }\n if (!found) {\n throw new Error(`MCP App resource not found: ${uri}`);\n }\n return {\n contents: [\n {\n uri,\n mimeType: found.resource.mimeType,\n text: renderMcpAppHtml(\n found.resource,\n found.actionName,\n config,\n requestMeta,\n ),\n ...(found.resource._meta\n ? { _meta: found.resource._meta }\n : {}),\n },\n ],\n };\n });\n },\n );\n }\n\n return server;\n}\n\n// ---------------------------------------------------------------------------\n// Auth — reuses the same pattern as A2A (Bearer token or JWT). Shared so the\n// HTTP mount and any stdio-side auth-aware helper resolve identity identically.\n// ---------------------------------------------------------------------------\n\nexport function getAccessTokens(): string[] {\n const single = process.env.ACCESS_TOKEN;\n const multi = process.env.ACCESS_TOKENS;\n const tokens: string[] = [];\n if (single) tokens.push(single);\n if (multi) {\n tokens.push(\n ...multi\n .split(\",\")\n .map((t) => t.trim())\n .filter(Boolean),\n );\n }\n return tokens;\n}\n\n/**\n * Resolve the caller identity for a static-token (or dev-open) auth path.\n *\n * Static `ACCESS_TOKEN` / `ACCESS_TOKENS` auth carries no per-caller claims,\n * so without this the MCP endpoint would run every tool with\n * `userEmail === undefined` and per-user / per-org scoped actions\n * (`accessFilter`, `resolveAccess`, `resolveCredential`) would return\n * empty / wrong data. The `agent-native mcp install` flow writes\n * `AGENT_NATIVE_OWNER_EMAIL` into the client config env and the stdio proxy\n * forwards it as the `X-Agent-Native-Owner-Email` request header (see\n * `mcp/stdio.ts#authHeaders`). We trust that owner hint *only* on the\n * static-token path — JWT auth already carries a cryptographically verified\n * `sub`, so the header is ignored there and never widens JWT scope.\n *\n * Precedence is server-trusted-first: the server process's\n * `AGENT_NATIVE_OWNER_EMAIL` env (set out-of-band by the operator / deploy)\n * ALWAYS wins, and a client-supplied `X-Agent-Native-Owner-Email` header is\n * honored *only as a fallback when that env is unset*. A static `ACCESS_TOKEN`\n * is a shared bearer secret; letting a request header override a\n * server-configured owner would let anyone holding a leaked token act as any\n * user. The header path remains for the single-tenant local-dev install flow\n * where the app server process has no owner env and the token *is* the\n * workspace secret; multi-tenant deployments must use A2A JWT (verified `sub`),\n * not a static token, for per-user scope.\n *\n * Returns `undefined` when no owner email is available (true dev-open: no\n * token, no secret, no owner) so behavior there stays unchanged.\n */\nfunction deriveStaticTokenIdentity(\n ownerEmailHeader: string | undefined,\n): MCPCallerIdentity | undefined {\n const owner =\n process.env.AGENT_NATIVE_OWNER_EMAIL?.trim() ||\n (typeof ownerEmailHeader === \"string\" && ownerEmailHeader.trim()) ||\n \"\";\n if (!owner) return undefined;\n return { userEmail: owner, orgDomain: undefined };\n}\n\nexport function getBearerToken(\n authHeader: string | undefined,\n): string | undefined {\n if (!authHeader) return undefined;\n const match = /^Bearer\\s+(.+)$/i.exec(authHeader.trim());\n return match?.[1]?.trim() || undefined;\n}\n\nfunction addSecretCandidate(\n candidates: string[],\n secret: string | null | undefined,\n): void {\n const trimmed = secret?.trim();\n if (!trimmed || candidates.includes(trimmed)) return;\n candidates.push(trimmed);\n}\n\nasync function verifyA2AJwtForMcp(\n token: string,\n resourceUrl?: string | string[],\n): Promise<Record<string, unknown> | null> {\n const jose = await import(\"jose\");\n let unverifiedPayload: Record<string, unknown> | null = null;\n try {\n unverifiedPayload = jose.decodeJwt(token) as Record<string, unknown>;\n } catch {\n return null;\n }\n\n const candidateSecrets: string[] = [];\n addSecretCandidate(candidateSecrets, process.env.A2A_SECRET);\n\n const orgDomain =\n typeof unverifiedPayload.org_domain === \"string\"\n ? unverifiedPayload.org_domain\n : undefined;\n if (orgDomain) {\n try {\n const { getA2ASecretByDomain } = await import(\"../org/context.js\");\n addSecretCandidate(\n candidateSecrets,\n await getA2ASecretByDomain(orgDomain),\n );\n } catch {\n // DB not ready or org lookup unavailable — fall back to other candidates.\n }\n }\n\n const firstPartyMcp = unverifiedPayload.agent_native_first_party_mcp === true;\n const audiences = firstPartyMcp ? mcpAudienceList(resourceUrl) : null;\n if (firstPartyMcp && !audiences?.length) return null;\n\n for (const secret of candidateSecrets) {\n const encodedSecret = new TextEncoder().encode(secret);\n for (const audience of audiences ?? [undefined]) {\n try {\n const { payload } = await jose.jwtVerify(\n token,\n encodedSecret,\n audience ? { audience } : undefined,\n );\n return payload as Record<string, unknown>;\n } catch {\n // Try the next candidate without exposing which secret matched.\n }\n }\n }\n\n return null;\n}\n\nfunction mcpAudienceList(resource: string | string[] | undefined): string[] {\n const raw = Array.isArray(resource) ? resource : resource ? [resource] : [];\n const seen = new Set<string>();\n const out: string[] = [];\n for (const value of raw) {\n const normalized = value.replace(/\\/+$/, \"\");\n if (normalized && !seen.has(normalized)) {\n seen.add(normalized);\n out.push(normalized);\n }\n }\n return out;\n}\n\nasync function isConnectTokenAllowed(\n jti: string | undefined,\n): Promise<boolean> {\n if (!jti) return false;\n try {\n const { isJtiRevoked, touchTokenUsed } = await import(\"./connect-store.js\");\n if (await isJtiRevoked(jti)) return false;\n // Best-effort usage telemetry — never blocks / throws.\n void touchTokenUsed(jti);\n } catch {\n // Store import / lookup failed — fail open. Signature verification already\n // passed; this only gates explicit revokes.\n }\n return true;\n}\n\n/**\n * Verify the inbound auth header. Returns:\n * - { authed: true, identity } when verified — `identity` is derived from\n * the JWT (`sub` / `org_domain`) for JWT auth, or from the\n * `AGENT_NATIVE_OWNER_EMAIL` env / `X-Agent-Native-Owner-Email` header\n * for static-token auth (the `agent-native mcp install` flow). `identity`\n * is undefined only for true dev-open with no owner hint.\n * - { authed: false } on rejection.\n *\n * When A2A_SECRET is set we extract the JWT's `sub` (caller email) and\n * `org_domain` claims so the MCP endpoint can wrap tool runs in\n * `runWithRequestContext({ userEmail, orgId })`. Without that wrap, the\n * MCP endpoint loses tenant identity and downstream `accessFilter` /\n * `resolveCredential` calls fall back to platform-wide defaults.\n *\n * `ownerEmailHeader` is the forwarded `X-Agent-Native-Owner-Email` value; it\n * is consulted ONLY on the static-token / dev-open path (never to influence\n * verified JWT identity), so the install flow runs tools as the configured\n * owner instead of an unscoped anonymous caller.\n */\nexport async function verifyAuth(\n authHeader: string | undefined,\n ownerEmailHeader?: string | undefined,\n options: { allowDevOpen?: boolean; resourceUrl?: string | string[] } = {},\n): Promise<{\n authed: boolean;\n identity?: MCPCallerIdentity;\n /**\n * The caller presented a real credential — a verified A2A/connect JWT, a\n * matching ACCESS_TOKEN, or (on the no-auth-configured path) a forwarded\n * owner-email header from `agent-native mcp install`. Drives the full vs\n * sparse MCP tool surface in local dev. The pure unauthenticated dev-open\n * path (no secret, no token, no owner header) is `false`.\n */\n fullSurface?: boolean;\n /**\n * The caller explicitly opted up to the full connector catalog by minting\n * their token with `--full-catalog` (or equivalent). When `true`, the\n * compact/connector-catalog tier filter (active by default whenever a\n * `connectorCatalog` is declared) is bypassed for this caller. Derived from a\n * `catalog_scope: \"full\"` claim in the verified A2A/connect JWT.\n */\n fullCatalog?: boolean;\n}> {\n // No auth configured → allow only when the route caller has already\n // established that this is a loopback/local dev request. Still honour an\n // owner hint there so the local install/connect flow stays tenant-scoped.\n const accessTokens = getAccessTokens();\n const hasA2ASecret = !!process.env.A2A_SECRET?.trim();\n const token = getBearerToken(authHeader);\n if (token) {\n const oauthIdentity = await verifyMcpOAuthAccessToken(\n token,\n options.resourceUrl,\n );\n if (oauthIdentity) {\n if (\n oauthIdentity.clientId === MCP_CONNECT_OAUTH_CLIENT_ID &&\n !(await isConnectTokenAllowed(oauthIdentity.jti))\n ) {\n return { authed: false };\n }\n return {\n authed: true,\n identity: {\n userEmail: oauthIdentity.userEmail,\n ...(oauthIdentity.orgId ? { orgId: oauthIdentity.orgId } : {}),\n orgDomain: oauthIdentity.orgDomain,\n oauthScopes: oauthIdentity.scopes,\n oauthClientId: oauthIdentity.clientId,\n },\n fullSurface: true,\n // Per-token opt-up: `catalog_scope: \"full\"` in the OAuth token\n // bypasses the connector-catalog tier filter on hosted deployments.\n fullCatalog: oauthIdentity.catalogScope === \"full\",\n };\n }\n }\n if (accessTokens.length === 0 && !hasA2ASecret && !token) {\n if (options.allowDevOpen === false) {\n return { authed: false };\n }\n return {\n authed: true,\n identity: deriveStaticTokenIdentity(ownerEmailHeader),\n // `mcp install`'s stdio proxy forwards an owner-email header even when\n // the local app has no secret configured — that is a real, identified\n // caller and gets the full surface. A bare browser/curl dev probe with\n // no owner hint stays on the sparse dev surface.\n fullSurface: !!(ownerEmailHeader && ownerEmailHeader.trim()),\n };\n }\n\n if (!token) return { authed: false };\n\n // Try an A2A JWT via the shared A2A_SECRET first, then the caller org's\n // synced A2A secret when the token carries org_domain.\n const payload = await verifyA2AJwtForMcp(token, options.resourceUrl);\n if (payload) {\n const tokenScope =\n typeof payload.scope === \"string\" ? payload.scope : undefined;\n if (tokenScope && tokenScope !== MCP_CONNECT_SCOPE) {\n return { authed: false };\n }\n\n // Connect-minted tokens (scope === \"mcp-connect\") carry a random `jti`\n // and are individually revocable. Only these tokens hit the revoke\n // store — ordinary A2A delegation JWTs skip the DB lookup entirely so\n // the hot path is unchanged. The signature was already\n // cryptographically verified, so failing open here only widens the\n // explicit-revoke gate, never the trust boundary.\n if (tokenScope === MCP_CONNECT_SCOPE) {\n if (!(await isConnectTokenAllowed(payload.jti as string | undefined))) {\n return { authed: false };\n }\n }\n\n return {\n authed: true,\n identity: {\n userEmail: typeof payload.sub === \"string\" ? payload.sub : undefined,\n // Org SERVICE tokens (connect-minted, synthetic `svc-*@service.<org>`\n // subject) carry the org id directly as an `org_id` claim so the\n // resolved identity is org-scoped even when the org has no domain\n // mapping. Personal/delegation JWTs don't set the claim — unchanged.\n ...(typeof payload.org_id === \"string\" && payload.org_id\n ? { orgId: payload.org_id as string }\n : {}),\n orgDomain:\n typeof payload.org_domain === \"string\"\n ? (payload.org_domain as string)\n : undefined,\n ...(payload.agent_native_first_party_mcp === true\n ? { firstPartyMcp: true }\n : {}),\n },\n // Verified JWT (connect-minted or A2A delegation) — a real caller.\n fullSurface: true,\n // Per-token opt-up: `catalog_scope: \"full\"` embedded at mint time via\n // `agent-native connect --full-catalog` bypasses the connector-catalog\n // tier filter on hosted multi-tenant deployments.\n fullCatalog: payload.catalog_scope === \"full\",\n };\n }\n\n if (accessTokens.length === 0 && !hasA2ASecret) {\n if (options.allowDevOpen === false) {\n return { authed: false };\n }\n return {\n authed: true,\n identity: deriveStaticTokenIdentity(ownerEmailHeader),\n fullSurface: !!(ownerEmailHeader && ownerEmailHeader.trim()),\n };\n }\n\n // Try ACCESS_TOKEN / ACCESS_TOKENS exact match. Static tokens carry no\n // per-caller claims, so derive identity from the forwarded owner-email\n // hint (install flow) — otherwise tools would run unscoped. Compare in\n // constant time (matching the rest of this subsystem's secret-comparison\n // discipline); node:crypto is imported dynamically because this module is\n // bundled into the serverless function and avoids static Node-only imports.\n if (accessTokens.length > 0) {\n const { timingSafeEqual } = await import(\"node:crypto\");\n const candidate = Buffer.from(token, \"utf8\");\n const matched = accessTokens.some((configured) => {\n const expected = Buffer.from(configured, \"utf8\");\n return (\n expected.length === candidate.length &&\n timingSafeEqual(expected, candidate)\n );\n });\n if (matched) {\n return {\n authed: true,\n identity: deriveStaticTokenIdentity(ownerEmailHeader),\n // Matched a configured ACCESS_TOKEN — a real caller.\n fullSurface: true,\n };\n }\n }\n\n return { authed: false };\n}\n\nexport async function resolveOrgIdFromDomain(\n orgDomain: string | undefined,\n): Promise<string | undefined> {\n if (!orgDomain) return undefined;\n try {\n const { resolveOrgByDomain } = await import(\"../org/context.js\");\n const org = await resolveOrgByDomain(orgDomain);\n return org?.orgId ?? undefined;\n } catch {\n return undefined;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"build-server.js","sourceRoot":"","sources":["../../src/mcp/build-server.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared MCP server builder.\n *\n * Extracted from `server.ts` so the stateless Streamable-HTTP mount\n * (`mountMCP`) and the stdio transport (`runMCPStdio --standalone`) build the\n * *same* MCP server from the *same* `ActionEntry` registry. Both surfaces:\n *\n * - expose every action as an MCP tool (+ the `ask-agent` meta-tool),\n * - append the framework deep-link block / `_meta` to every tool result,\n * - wrap `run()` / `askAgent()` in `runWithRequestContext` so per-user /\n * per-org scoping (accessFilter, resolveCredential, MCP visibility) is\n * honoured.\n *\n * `server.ts` re-exports `createMCPServerForRequest` and the auth helpers so\n * any (future) external importer of `@agent-native/core/mcp` keeps resolving.\n *\n * Node-only at the SDK level, but this module itself has no Node-only imports\n * — it can be bundled into the serverless function alongside `mountMCP`.\n */\n\nimport {\n MCP_APP_EXTENSION_ID,\n MCP_APP_MIME_TYPE,\n MCP_APP_RESOURCE_URI_META_KEY,\n type ActionMcpAppCsp,\n type ActionMcpAppResourceConfig,\n} from \"../action.js\";\nimport type { ActionEntry } from \"../agent/production-agent.js\";\nimport { isMcpActionResult } from \"../mcp-client/app-result.js\";\nimport { getConfiguredAppBasePath } from \"../server/app-base-path.js\";\nimport {\n buildDeepLink,\n toAbsoluteOpenUrl,\n toDesktopOpenUrl,\n toVsCodeOpenUrl,\n} from \"../server/deep-link.js\";\nimport {\n getRequestContext,\n getRequestOrgId,\n getRequestUserEmail,\n runWithRequestContext,\n} from \"../server/request-context.js\";\nimport {\n isAgentNativeOpenDeepLink,\n withCollapsedAgentSidebarParam,\n} from \"../shared/agent-sidebar-url.js\";\nimport { MCP_APP_CHAT_BRIDGE_QUERY_PARAM } from \"../shared/embed-auth.js\";\nimport { getBuiltinCrossAppTools } from \"./builtin-tools.js\";\nimport {\n MCP_CONNECT_OAUTH_CLIENT_ID,\n MCP_CONNECT_SCOPE,\n} from \"./connect-store.js\";\nimport { MCP_APP_REQUEST_ORIGIN_CSP_SOURCE } from \"./embed-app.js\";\nimport {\n MCP_OAUTH_SCOPES,\n hasMcpOAuthScope,\n verifyMcpOAuthAccessToken,\n} from \"./oauth-token.js\";\n\nexport interface MCPConfig {\n /** App name shown in MCP server info */\n name: string;\n /** Optional human-facing app title shown by MCP hosts that support titles. */\n title?: string;\n /**\n * Canonical app id (directory under `apps/`, e.g. `mail`) this MCP server\n * is mounted for. Optional & back-compat: when omitted the builtin\n * cross-app tools fall back to lowercasing `name`. Used by `open_app` /\n * `ask_app` / `create_workspace_app` to tell \"this app\" from a cross-app\n * target so they resolve the *target* app's origin rather than echoing the\n * current request origin.\n */\n appId?: string;\n /** App description */\n description: string;\n /** Optional canonical website URL for hosts that surface MCP app details. */\n websiteUrl?: string;\n /** Optional app icons for MCP hosts that render server branding. */\n icons?: Array<{\n src: string;\n mimeType?: string;\n sizes?: string[];\n theme?: \"light\" | \"dark\";\n }>;\n /** Version string (default \"1.0.0\") */\n version?: string;\n /** Action registry — same as agent chat and A2A */\n actions: Record<string, ActionEntry>;\n /**\n * Full (\"production\") action surface served to an **authenticated real\n * caller** — a connect-minted token, an `agent-native mcp install` stdio\n * proxy (owner-email header / `AGENT_NATIVE_OWNER_EMAIL`), or a deployed /\n * `AGENT_MODE=production` app. In local dev `actions` is intentionally the\n * sparse, dev-toggled surface (builtins + read-only public-agent actions)\n * so the local agent chat and unauthenticated dev probes don't see every\n * mutating tool; but per the external-agents contract a real caller that\n * connected with a token MUST get the full surface even in dev. When unset\n * (production, where `actions` already IS the full set) the swap is a\n * no-op. See `external-agents` skill, \"Dev vs production tool surface\".\n */\n productionActions?: Record<string, ActionEntry>;\n /** Handler for the ask-agent meta-tool — runs the full agent loop */\n askAgent?: (message: string) => Promise<string>;\n /**\n * Disable the generic cross-app builtin tools (`list_apps`, `open_app`,\n * `ask_app`, `create_workspace_app`, `list_templates`). They are merged in\n * by default so external agents get a stable verb set; a template action of\n * the same name always wins (template precedence). Set to `false` only for\n * a constrained / locked-down mount.\n */\n builtinCrossAppTools?: boolean;\n /**\n * Curated allow-list of action names served to **external connector** clients\n * on a hosted multi-tenant deployment.\n *\n * Whenever this list is non-empty it is active by default for **every**\n * caller — hosted connectors, code/stdio clients, and the local CLI alike.\n * The MCP server trims both the advertised tool list *and* the callable\n * surface to exactly these names (plus any builtin cross-app tools such as\n * `list_apps` / `open_app`). Any tool call for a name **not** in the list is\n * rejected — it is not merely hidden. This prevents the ~105-tool full\n * catalog from landing in every external agent's context window and removes\n * footguns (db-exec, seed-*, extension tools, browser-session tools, etc.)\n * from connectors. It is no longer gated behind an environment variable, and\n * the catalog is never inferred from the client name/user-agent.\n *\n * `tool-search` stays available in the compact catalog so any trimmed tool is\n * reachable on demand. Callers who need the full surface up front opt in\n * explicitly with `agent-native connect --full-catalog` (embeds a\n * `catalog_scope: \"full\"` claim in the connect-minted JWT) or the\n * deployment-wide `AGENT_NATIVE_MCP_FULL_CATALOG=1` env override.\n *\n * Declare this in your template's `createAgentChatPlugin` options rather than\n * setting it on `MCPConfig` directly; the plugin copies it through.\n */\n connectorCatalog?: string[];\n}\n\n/**\n * Identity extracted from a verified MCP bearer token / JWT. Used to wrap\n * `entry.run()` and `config.askAgent()` calls in `runWithRequestContext`\n * so downstream tools (db-query, accessFilter, resolveCredential) honour\n * per-user / per-org scoping. Without this wrap the MCP endpoint would\n * silently bypass tenant isolation. See finding #6 in\n * /tmp/security-audit/12-mcp-a2a-agent.md.\n */\nexport interface MCPCallerIdentity {\n userEmail: string | undefined;\n orgId?: string | undefined;\n orgDomain: string | undefined;\n /** Present only for standard remote MCP OAuth access tokens. */\n oauthScopes?: string[];\n /** Present only for standard remote MCP OAuth access tokens. */\n oauthClientId?: string;\n /** Present only for framework-minted first-party MCP client tokens. */\n firstPartyMcp?: boolean;\n}\n\n/** Per-request context used to turn an action's relative deep link into the\n * absolute web URL (and desktop `agentnative://` URL) the external agent\n * surfaces. Derived from the inbound request headers in `mountMCP`, or from\n * the resolved local app origin in the stdio standalone path. */\nexport interface MCPRequestMeta {\n /** Origin of the running app, e.g. `http://localhost:8100`. */\n origin?: string;\n /** Optional mount prefix for path-mounted apps, e.g. `/mail`. */\n basePath?: string;\n /** Optional client preference for which URL the *markdown* link uses. */\n target?: \"browser\" | \"desktop\" | \"terminal\";\n /**\n * Best-effort caller label derived from MCP transport headers. Chat-style\n * remote hosts should stay on the compact catalog; code/stdio clients can\n * explicitly identify themselves to keep the full action surface.\n */\n clientName?: string;\n /** Explicit framework client hint from `x-agent-native-mcp-client`. */\n clientHint?: string;\n /** Explicit opt-in to the full tool catalog for code/stdio style clients. */\n fullCatalog?: boolean;\n /**\n * The caller authenticated with a real credential (verified A2A/connect\n * JWT, matching ACCESS_TOKEN, or a forwarded owner-email header from\n * `agent-native mcp install`) — not the unauthenticated local dev-open\n * path. When true, `createMCPServerForRequest` serves\n * `config.productionActions` (the full surface) instead of the sparse dev\n * `config.actions`. Set by `mountMCP` from `verifyAuth`.\n */\n fullSurface?: boolean;\n /**\n * Whether this request may receive inline MCP App embeds (the `ui://`\n * resource reference hosts render in an iframe). Resolved once per request by\n * `createMCPServerForRequest` from `isMcpAppsInlineEnabled(identity)` — the\n * deploy-toggleable kill switch. When `false`, no MCP App resource is\n * advertised or referenced and tool results fall back to their deep-link\n * text. Defaults to disabled when unset.\n */\n inlineMcpApps?: boolean;\n}\n\n/**\n * Deploy-toggleable kill switch for inline MCP App embeds — the `ui://`\n * resource reference hosts like Codex / Cursor / ChatGPT render in a sandboxed\n * iframe. **Off by default**, so a not-yet-verified inline embed never reaches\n * normal users; flip it on per environment with `AGENT_NATIVE_MCP_APPS_INLINE=1`\n * and a redeploy. While the global switch is off, accounts listed in\n * `AGENT_NATIVE_MCP_APPS_INLINE_ALLOW_EMAILS` (comma/space separated) still get\n * inline embeds, so you can keep verifying a fix in production before enabling\n * it for everyone. Requires no skills/instructions change — when disabled, tool\n * results simply fall back to their deep-link text.\n */\nexport function isMcpAppsInlineEnabled(\n identity: MCPCallerIdentity | undefined,\n): boolean {\n const flag = process.env.AGENT_NATIVE_MCP_APPS_INLINE?.trim().toLowerCase();\n if (flag === \"1\" || flag === \"true\" || flag === \"yes\" || flag === \"on\") {\n return true;\n }\n const email = identity?.userEmail?.trim().toLowerCase();\n if (email) {\n const allowed = (\n process.env.AGENT_NATIVE_MCP_APPS_INLINE_ALLOW_EMAILS ?? \"\"\n )\n .split(/[\\s,]+/)\n .map((value) => value.trim().toLowerCase())\n .filter(Boolean);\n if (allowed.includes(email)) return true;\n }\n return false;\n}\n\ntype McpOAuthScope = (typeof MCP_OAUTH_SCOPES)[number];\n\nfunction isActionVisibleForOAuthScope(\n entry: ActionEntry,\n scopes: string[] | undefined,\n): boolean {\n if (!scopes) return true;\n const required: McpOAuthScope =\n entry.readOnly === true ? \"mcp:read\" : \"mcp:write\";\n return hasMcpOAuthScope(scopes, required);\n}\n\nconst COMPACT_MCP_APP_CATALOG_BUILTINS = new Set([\n \"list_apps\",\n \"open_app\",\n \"ask_app\",\n \"ask_app_status\",\n \"create_embed_session\",\n // `tool-search` MUST stay in every compact/connector surface: it is how a\n // compacted client discovers and loads any action on demand, which is what\n // makes \"small catalog by default\" safe instead of limiting.\n \"tool-search\",\n]);\n\nfunction isActionAdvertisedInCompactMcpAppCatalog(\n name: string,\n entry: ActionEntry,\n config: MCPConfig,\n): boolean {\n if (COMPACT_MCP_APP_CATALOG_BUILTINS.has(name)) return true;\n if (\n (entry.mcpApp as { compactCatalog?: unknown } | undefined)\n ?.compactCatalog === true\n ) {\n return true;\n }\n if (config.builtinCrossAppTools === false && entry.mcpApp?.resource) {\n return true;\n }\n return false;\n}\n\nfunction explicitlyRequestsFullMcpCatalog(\n requestMeta: MCPRequestMeta | undefined,\n): boolean {\n // Full catalog is a deliberate, rare opt-in — NEVER a default, and NEVER\n // inferred from the client name / user-agent. It is reached only by an\n // explicit deployment env or a token minted with\n // `agent-native connect --full-catalog` (which embeds `catalog_scope: \"full\"`,\n // surfaced here as requestMeta.fullCatalog). Dumping ~105 tool schemas\n // (100k+ tokens) into a context window just because a client called itself\n // \"code\"/\"cursor\"/\"codex\" was a recurring footgun. Everything else gets the\n // connector/compact catalog plus `tool-search`, which keeps every tool\n // reachable on demand.\n if (process.env.AGENT_NATIVE_MCP_FULL_CATALOG === \"1\") return true;\n return requestMeta?.fullCatalog === true;\n}\n\nconst warnedFullCatalogKeys = new Set<string>();\n\n/**\n * Loud, deduped warning emitted whenever the full MCP catalog is actually\n * served. Full catalog is a deliberate, rare opt-in (env or a `--full-catalog`\n * token claim); logging it makes an accidental ~100k-token tool dump visible\n * instead of silent, so a regression can't quietly reintroduce the footgun.\n */\nfunction warnFullCatalogServed(toolCount: number): void {\n const source =\n process.env.AGENT_NATIVE_MCP_FULL_CATALOG === \"1\"\n ? \"AGENT_NATIVE_MCP_FULL_CATALOG=1\"\n : \"a token minted with --full-catalog (catalog_scope:full)\";\n const key = `${source}:${toolCount}`;\n if (warnedFullCatalogKeys.has(key)) return;\n warnedFullCatalogKeys.add(key);\n console.warn(\n `[agent-native] Serving the FULL MCP tool catalog (${toolCount} tools) via ${source}. ` +\n `This is a large context payload meant to be a rare, explicit opt-in — most ` +\n `clients should use the default compact/connector catalog + tool-search instead.`,\n );\n}\n\n/**\n * Returns true when the given action name is in the template's connector\n * catalog, OR is a builtin cross-app tool that is always included for\n * external connector clients. Builtin tool names from\n * `COMPACT_MCP_APP_CATALOG_BUILTINS` are always allowed since they are the\n * stable external-agent verb set.\n */\nfunction isActionInConnectorCatalog(name: string, config: MCPConfig): boolean {\n if (COMPACT_MCP_APP_CATALOG_BUILTINS.has(name)) return true;\n if (!Array.isArray(config.connectorCatalog)) return false;\n return config.connectorCatalog.includes(name);\n}\n\ninterface ResolvedMcpAppResource {\n uri: string;\n legacyUris?: string[];\n name: string;\n title?: string;\n description?: string;\n html: ActionMcpAppResourceConfig[\"html\"];\n mimeType: typeof MCP_APP_MIME_TYPE;\n _meta?: Record<string, unknown>;\n}\n\ninterface McpAppResourceContext {\n actionName: string;\n appId?: string;\n requestOrigin?: string;\n}\n\ninterface VersionedMcpAppResourceUri {\n uri: string;\n legacyUris?: string[];\n}\n\nfunction metadataObject(value: unknown): Record<string, unknown> {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {};\n}\n\nfunction originString(value: unknown): string | undefined {\n if (typeof value !== \"string\" || !value.trim()) return undefined;\n try {\n return new URL(value).origin;\n } catch {\n return undefined;\n }\n}\n\nfunction hostSpecificDomainString(value: unknown): string | undefined {\n if (typeof value !== \"string\" || !value.trim()) return undefined;\n const trimmed = value.trim();\n try {\n new URL(trimmed);\n return undefined;\n } catch {\n return trimmed;\n }\n}\n\nfunction withMcpChatBridgeParam(urlOrPath: string): string {\n try {\n const base = \"http://agent-native.invalid\";\n const url = urlOrPath.startsWith(\"/\")\n ? new URL(urlOrPath, base)\n : new URL(urlOrPath);\n url.searchParams.set(MCP_APP_CHAT_BRIDGE_QUERY_PARAM, \"1\");\n return urlOrPath.startsWith(\"/\")\n ? `${url.pathname}${url.search}${url.hash}`\n : url.toString();\n } catch {\n return urlOrPath;\n }\n}\n\nfunction isEmbedStartUrl(value: string): boolean {\n try {\n const base = \"http://agent-native.invalid\";\n const url = value.startsWith(\"/\") ? new URL(value, base) : new URL(value);\n return url.pathname.includes(\"/_agent-native/embed/start\");\n } catch {\n return value.includes(\"/_agent-native/embed/start\");\n }\n}\n\nfunction routePathFromOpenUrl(value: string): string | null {\n try {\n const hasScheme = /^[a-z][a-z0-9+.-]*:\\/\\//i.test(value);\n const url = hasScheme\n ? new URL(value)\n : new URL(value, \"http://agent-native.invalid\");\n const route = `${url.pathname}${url.search}${url.hash}`;\n if (!route.startsWith(\"/\") || route.startsWith(\"//\")) return null;\n if (route.startsWith(\"/\\\\\")) return null;\n if (/^\\/[a-z][a-z0-9+.-]*:/i.test(route)) return null;\n return route;\n } catch {\n return null;\n }\n}\n\n/**\n * Recursively redact embed-ticket-bearing URLs from any value before it gets\n * serialized into a model-visible text payload. Embed start URLs carry a\n * single-use ticket that grants iframe access to the user's session — they\n * MUST stay in `_meta` (where the embed runtime can consume them) and never\n * appear in `content[].text` for the LLM. This is the generic safety net for\n * actions that return `{ embedStartUrl, ... }` without declaring\n * `mcpApp.resource` (the resource path already strips them via\n * `mcpAppStructuredContent`).\n *\n * Depth-capped to avoid pathological / circular structures. Strings that\n * embed an `isEmbedStartUrl` substring (e.g. a longer message that includes\n * the URL) are replaced with `[hidden embed URL]`.\n */\nfunction purgeEmbedStartUrls(value: unknown, depth = 0): unknown {\n if (depth > 5) return value;\n if (typeof value === \"string\") {\n return isEmbedStartUrl(value) ? \"[hidden embed URL]\" : value;\n }\n if (Array.isArray(value)) {\n return value.map((item) => purgeEmbedStartUrls(item, depth + 1));\n }\n if (value && typeof value === \"object\") {\n const out: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value as Record<string, unknown>)) {\n if (typeof val === \"string\" && isEmbedStartUrl(val)) {\n // Drop the key entirely for object-typed inputs so a tool result like\n // `{ embedStartUrl: \"...\" }` does not appear at all in the LLM text.\n continue;\n }\n out[key] = purgeEmbedStartUrls(val, depth + 1);\n }\n return out;\n }\n return value;\n}\n\nfunction mcpAppEmbedOpenLinkMeta(\n result: unknown,\n resource: ResolvedMcpAppResource,\n meta: MCPRequestMeta | undefined,\n): Record<string, unknown> {\n const out = metadataObject(result);\n const embedStartUrl =\n typeof out.embedStartUrl === \"string\"\n ? out.embedStartUrl\n : out.embed === true &&\n typeof out.url === \"string\" &&\n out.url.includes(\"/_agent-native/embed/start\")\n ? out.url\n : null;\n if (!embedStartUrl) return {};\n\n const webUrl = toAbsoluteOpenUrl(\n withMcpChatBridgeParam(embedStartUrl),\n meta?.origin,\n );\n const deepLinkUrl =\n typeof out.deepLinkUrl === \"string\" ? out.deepLinkUrl : null;\n const fallbackLabel = resource.title ?? resource.name ?? \"app\";\n const label =\n typeof out.app === \"string\" && out.app.trim()\n ? `Open ${out.app.trim()}`\n : fallbackLabel;\n const view =\n typeof out.view === \"string\" && out.view.trim()\n ? out.view.trim()\n : typeof out.path === \"string\" && out.path.trim()\n ? out.path.trim()\n : undefined;\n // Only fabricate an open URL when there is a real path-like value: an\n // explicit deepLinkUrl, or a non-embed `out.url`, or a leading-slash\n // `view`/`path` that's already a route. Bare view-name strings like\n // \"inbox\" or \"deck\" must NOT be turned into `${origin}/inbox` — apps\n // route views at app-specific paths (e.g. slides routes `view: \"deck\"`\n // at `/deck/:id`), so a synthesized origin-relative URL is just a 404.\n // In that case omit `openLink` entirely; the embedStart meta carries\n // the actual launch reference.\n const pathFromRouteLike =\n view && view.startsWith(\"/\")\n ? view\n : typeof out.path === \"string\" && out.path.trim().startsWith(\"/\")\n ? out.path.trim()\n : undefined;\n const explicitOpenUrl = deepLinkUrl\n ? deepLinkUrl\n : typeof out.url === \"string\" && !isEmbedStartUrl(out.url)\n ? out.url\n : pathFromRouteLike;\n const safeOpenUrl = explicitOpenUrl\n ? toAbsoluteOpenUrl(explicitOpenUrl, meta?.origin)\n : null;\n // Embed open links expose the safe browser target in `webUrl`, but the\n // desktop URL must enter the app through the registered scheme so Electron\n // can focus the right webview. Preserve the full route/query in the `to`\n // param; focus ids are often only present on `url`, not `out.params`.\n const desktopDeepLinkUrl = (() => {\n if (!safeOpenUrl) return null;\n const app =\n typeof out.app === \"string\" && out.app.trim()\n ? out.app.trim()\n : undefined;\n if (!app) return safeOpenUrl;\n if (isAgentNativeOpenDeepLink(safeOpenUrl)) {\n return toDesktopOpenUrl(safeOpenUrl);\n }\n const targetRoute = routePathFromOpenUrl(safeOpenUrl);\n if (!targetRoute) return safeOpenUrl;\n const viewParam =\n typeof out.view === \"string\" && out.view.trim() ? out.view.trim() : \"\";\n const params =\n out.params && typeof out.params === \"object\" && !Array.isArray(out.params)\n ? (out.params as Record<\n string,\n string | number | boolean | null | undefined\n >)\n : undefined;\n return toDesktopOpenUrl(\n buildDeepLink({\n app,\n view: viewParam,\n to: targetRoute,\n ...(params ? { params } : {}),\n }),\n );\n })();\n\n return {\n \"agent-native/embedStart\": {\n startUrl: webUrl,\n ...(typeof out.embedExpiresAt === \"number\"\n ? { expiresAt: out.embedExpiresAt }\n : {}),\n },\n ...(safeOpenUrl\n ? {\n \"agent-native/openLink\": {\n label,\n ...(view ? { view } : {}),\n webUrl: safeOpenUrl,\n desktopUrl: desktopDeepLinkUrl ?? safeOpenUrl,\n vscodeUrl: toVsCodeOpenUrl(safeOpenUrl),\n },\n }\n : {}),\n };\n}\n\nasync function withServerMintedMcpAppEmbedStart(\n result: unknown,\n meta: MCPRequestMeta | undefined,\n): Promise<unknown> {\n if (!result || typeof result !== \"object\" || Array.isArray(result)) {\n return result;\n }\n\n const out = result as Record<string, unknown>;\n if (out.embed !== true) return result;\n if (typeof out.embedStartUrl === \"string\" && out.embedStartUrl.trim()) {\n return result;\n }\n if (\n typeof out.url === \"string\" &&\n out.url.trim() &&\n isEmbedStartUrl(out.url)\n ) {\n return result;\n }\n\n const candidate = [out.url, out.path, out.deepLinkUrl].find(\n (value): value is string =>\n typeof value === \"string\" && value.trim().length > 0,\n );\n if (!candidate) return result;\n\n const trimmed = candidate.trim();\n const isPath = trimmed.startsWith(\"/\") && !trimmed.startsWith(\"//\");\n const isAbsoluteHttp = /^https?:\\/\\//i.test(trimmed);\n if (!isPath && !isAbsoluteHttp) return result;\n if (isAbsoluteHttp && !meta?.origin) return result;\n\n const ctx = getRequestContext();\n const ownerEmail = ctx?.userEmail?.trim();\n if (!ownerEmail) return result;\n\n const { normalizeEmbedTargetPath, createEmbedSessionTicket } =\n await import(\"../server/embed-session.js\");\n const { buildEmbedStartPath } = await import(\"../server/embed-route.js\");\n const targetPath = normalizeEmbedTargetPath(\n withMcpChatBridgeParam(trimmed),\n meta?.origin,\n );\n if (!targetPath) return result;\n\n const ticket = await createEmbedSessionTicket({\n ownerEmail,\n orgId: ctx?.orgId,\n targetPath,\n scope: typeof out.chrome === \"string\" ? out.chrome : null,\n });\n const startPath = buildEmbedStartPath(ticket.ticket);\n const embedStartUrl = meta?.origin\n ? new URL(startPath, meta.origin).toString()\n : startPath;\n\n return {\n ...out,\n embedStartUrl,\n embedTargetPath: targetPath,\n embedExpiresAt: ticket.expiresAt,\n };\n}\n\n/**\n * Build the deep-link content block + structured `_meta` for a tool result.\n * Best-effort: any throw / nullish link is swallowed so a bad `link` builder\n * never fails the tool call.\n */\nexport function buildLinkArtifacts(\n entry: ActionEntry,\n args: Record<string, any>,\n result: any,\n meta: MCPRequestMeta | undefined,\n): {\n block?: { type: \"text\"; text: string };\n _meta?: Record<string, unknown>;\n} {\n if (typeof entry.link !== \"function\") return {};\n try {\n const lk = entry.link({ args: args ?? {}, result });\n if (!lk?.url) return {};\n const linkUrl = isAgentNativeOpenDeepLink(lk.url)\n ? withCollapsedAgentSidebarParam(lk.url)\n : lk.url;\n const webUrl = toAbsoluteOpenUrl(linkUrl, meta?.origin);\n const desktopUrl = toDesktopOpenUrl(linkUrl);\n const vscodeUrl = toVsCodeOpenUrl(webUrl);\n const markdownUrl = meta?.target === \"desktop\" ? desktopUrl : webUrl;\n return {\n block: { type: \"text\", text: `\\n\\n[${lk.label} →](${markdownUrl})` },\n _meta: {\n \"agent-native/openLink\": {\n label: lk.label,\n view: lk.view,\n webUrl,\n desktopUrl,\n vscodeUrl,\n },\n },\n };\n } catch {\n return {};\n }\n}\n\n/**\n * Merge the generic cross-app builtin tools into the config's action\n * registry. **Template actions take precedence**: if a template defines an\n * action with the same name as a builtin (e.g. its own `list_apps`), the\n * template entry wins and the builtin is dropped. This mirrors the\n * template-over-workspace-core precedence in `autoDiscoverActions`.\n *\n * The builtins are pure-ish navigators / scaffolders; they call back into the\n * same `config.actions` / `config.askAgent` so there is no second agent loop.\n */\nfunction mergeBuiltinTools(\n config: MCPConfig,\n baseActions: Record<string, ActionEntry>,\n requestMeta?: MCPRequestMeta,\n): Record<string, ActionEntry> {\n if (config.builtinCrossAppTools === false) return baseActions;\n const builtins = getBuiltinCrossAppTools(config, requestMeta);\n const merged: Record<string, ActionEntry> = { ...builtins };\n // Template / app actions overwrite same-named builtins.\n for (const [name, entry] of Object.entries(baseActions)) {\n merged[name] = entry;\n }\n return merged;\n}\n\nfunction absoluteMetadataUrl(\n value: string | undefined,\n requestMeta?: MCPRequestMeta,\n): string | undefined {\n const trimmed = value?.trim();\n if (!trimmed) return undefined;\n try {\n if (requestMeta?.origin) {\n const basePath = requestMeta.basePath ?? getConfiguredAppBasePath();\n const appBase = `${requestMeta.origin.replace(/\\/+$/, \"\")}${basePath}/`;\n const appLocalValue =\n trimmed.startsWith(\"/\") && !trimmed.startsWith(\"//\")\n ? trimmed.replace(/^\\/+/, \"\")\n : trimmed;\n return new URL(appLocalValue, appBase).href;\n }\n return new URL(trimmed).href;\n } catch {\n return trimmed;\n }\n}\n\nfunction mcpServerInfo(config: MCPConfig, requestMeta?: MCPRequestMeta) {\n const websiteUrl = absoluteMetadataUrl(config.websiteUrl, requestMeta);\n const icons = config.icons\n ?.map((icon) => {\n const src = absoluteMetadataUrl(icon.src, requestMeta);\n if (!src) return null;\n return {\n src,\n ...(icon.mimeType ? { mimeType: icon.mimeType } : {}),\n ...(icon.sizes?.length ? { sizes: icon.sizes } : {}),\n ...(icon.theme ? { theme: icon.theme } : {}),\n };\n })\n .filter((icon): icon is NonNullable<typeof icon> => Boolean(icon));\n return {\n name: config.name,\n version: config.version ?? \"1.0.0\",\n ...(config.title?.trim() ? { title: config.title.trim() } : {}),\n ...(config.description?.trim()\n ? { description: config.description.trim() }\n : {}),\n ...(websiteUrl ? { websiteUrl } : {}),\n ...(icons?.length ? { icons } : {}),\n };\n}\n\nfunction safeUiSegment(value: string | undefined, fallback: string): string {\n const normalized = (value || fallback)\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9._-]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n return normalized || fallback;\n}\n\n// ChatGPT and Claude cache MCP App resource HTML by `ui://` URI. Bump this\n// when the shared shell changes in a way that must invalidate host caches.\nconst MCP_APP_RESOURCE_SHELL_VERSION = \"shell-v52\";\n\nfunction legacyDefaultMcpAppUri(config: MCPConfig, actionName: string): string {\n const app = safeUiSegment(config.appId ?? config.name, \"agent-native\");\n const action = safeUiSegment(actionName, \"tool\");\n return `ui://${app}/${action}`;\n}\n\nfunction versionMcpAppResourceUri(\n rawUri: string,\n): VersionedMcpAppResourceUri | null {\n const uri = rawUri.trim();\n if (!uri.startsWith(\"ui://\")) return null;\n const versionSuffix = `/${MCP_APP_RESOURCE_SHELL_VERSION}`;\n let versionedUri: string;\n try {\n const parsed = new URL(uri);\n const path = parsed.pathname.replace(/\\/+$/g, \"\");\n parsed.pathname = /\\/shell-v\\d+$/.test(path)\n ? path.replace(/\\/shell-v\\d+$/, versionSuffix)\n : `${path}${versionSuffix}`;\n versionedUri = parsed.toString();\n } catch {\n return null;\n }\n return {\n uri: versionedUri,\n ...(versionedUri !== uri ? { legacyUris: [uri] } : {}),\n };\n}\n\nfunction unversionMcpAppResourceUri(uri: string): string | null {\n if (!uri.startsWith(\"ui://\")) return null;\n try {\n const parsed = new URL(uri);\n parsed.pathname = parsed.pathname\n .replace(/\\/+$/g, \"\")\n .replace(/\\/shell-v\\d+$/g, \"\");\n return parsed.toString();\n } catch {\n return null;\n }\n}\n\nfunction normalizeMcpAppResourceUriForMatch(uri: unknown): string | null {\n if (typeof uri !== \"string\") return null;\n const trimmed = uri.trim();\n if (!trimmed.startsWith(\"ui://\")) return null;\n return (\n unversionMcpAppResourceUri(trimmed) ??\n trimmed.replace(/\\/+$/g, \"\").replace(/\\/shell-v\\d+(?=([?#]|$))/g, \"\")\n );\n}\n\nfunction matchesMcpAppResourceUri(\n resourceUri: VersionedMcpAppResourceUri,\n requestedUri: unknown,\n): boolean {\n if (typeof requestedUri !== \"string\") return false;\n const requested = requestedUri.trim();\n if (resourceUri.uri === requested) return true;\n if (resourceUri.legacyUris?.includes(requested)) return true;\n const requestedBase = normalizeMcpAppResourceUriForMatch(requested);\n const currentBase = normalizeMcpAppResourceUriForMatch(resourceUri.uri);\n return Boolean(requestedBase && currentBase && requestedBase === currentBase);\n}\n\nfunction getMcpAppResourceUri(\n config: MCPConfig,\n actionName: string,\n entry: ActionEntry,\n): VersionedMcpAppResourceUri | null {\n const resource = entry.mcpApp?.resource;\n if (!resource) return null;\n const baseUri =\n resource.uri?.trim() || legacyDefaultMcpAppUri(config, actionName);\n return versionMcpAppResourceUri(baseUri);\n}\n\nfunction expandRequestOriginSources(\n sources: string[] | undefined,\n requestMeta?: MCPRequestMeta,\n): string[] | undefined {\n if (!sources) return undefined;\n const origin = requestMeta?.origin;\n return sources.flatMap((source) =>\n source === MCP_APP_REQUEST_ORIGIN_CSP_SOURCE && origin\n ? [origin]\n : [source],\n );\n}\n\nfunction openAiWidgetCsp(\n cspConfig: ActionMcpAppCsp | undefined,\n requestMeta?: MCPRequestMeta,\n): Record<string, string[]> | undefined {\n if (!cspConfig) return undefined;\n const csp: Record<string, string[]> = {};\n const connectDomains = expandRequestOriginSources(\n cspConfig.connectDomains,\n requestMeta,\n );\n const resourceDomains = expandRequestOriginSources(\n cspConfig.resourceDomains,\n requestMeta,\n );\n const frameDomains = expandRequestOriginSources(\n cspConfig.frameDomains,\n requestMeta,\n );\n if (connectDomains?.length) csp.connect_domains = connectDomains;\n if (resourceDomains?.length) csp.resource_domains = resourceDomains;\n if (frameDomains?.length) csp.frame_domains = frameDomains;\n return Object.keys(csp).length > 0 ? csp : undefined;\n}\n\nfunction mcpAppUiMeta(\n resource: ActionMcpAppResourceConfig,\n resolvedCsp: ActionMcpAppCsp | undefined,\n requestMeta?: MCPRequestMeta,\n description?: string,\n): Record<string, unknown> | undefined {\n const base =\n resource._meta && typeof resource._meta === \"object\"\n ? { ...resource._meta }\n : {};\n const existingUi =\n base.ui && typeof base.ui === \"object\" && !Array.isArray(base.ui)\n ? (base.ui as Record<string, unknown>)\n : {};\n const ui: Record<string, unknown> = { ...existingUi };\n delete ui.domain;\n if (resolvedCsp) {\n ui.csp = {\n ...resolvedCsp,\n connectDomains: expandRequestOriginSources(\n resolvedCsp.connectDomains,\n requestMeta,\n ),\n resourceDomains: expandRequestOriginSources(\n resolvedCsp.resourceDomains,\n requestMeta,\n ),\n frameDomains: expandRequestOriginSources(\n resolvedCsp.frameDomains,\n requestMeta,\n ),\n baseUriDomains: expandRequestOriginSources(\n resolvedCsp.baseUriDomains,\n requestMeta,\n ),\n };\n }\n if (resource.permissions) ui.permissions = resource.permissions;\n const hostSpecificDomain =\n hostSpecificDomainString(resource.domain) ??\n hostSpecificDomainString(existingUi.domain);\n if (hostSpecificDomain) ui.domain = hostSpecificDomain;\n const openAiWidgetDomain =\n originString(resource.domain) ??\n originString(ui.domain) ??\n originString(existingUi.domain) ??\n originString(requestMeta?.origin);\n if (typeof resource.prefersBorder === \"boolean\") {\n ui.prefersBorder = resource.prefersBorder;\n }\n if (Object.keys(ui).length > 0) base.ui = ui;\n if (description && base[\"openai/widgetDescription\"] == null) {\n base[\"openai/widgetDescription\"] = description;\n }\n if (\n typeof resource.prefersBorder === \"boolean\" &&\n base[\"openai/widgetPrefersBorder\"] == null\n ) {\n base[\"openai/widgetPrefersBorder\"] = resource.prefersBorder;\n }\n const openAiCsp = openAiWidgetCsp(resolvedCsp, requestMeta);\n if (openAiCsp && base[\"openai/widgetCSP\"] == null) {\n base[\"openai/widgetCSP\"] = openAiCsp;\n }\n if (openAiWidgetDomain && base[\"openai/widgetDomain\"] == null) {\n base[\"openai/widgetDomain\"] = openAiWidgetDomain;\n }\n return Object.keys(base).length > 0 ? base : undefined;\n}\n\nasync function resolveMcpAppCsp(\n resource: ActionMcpAppResourceConfig,\n ctx: McpAppResourceContext,\n): Promise<ActionMcpAppCsp | undefined> {\n if (!resource.csp) return undefined;\n return typeof resource.csp === \"function\"\n ? await resource.csp(ctx)\n : resource.csp;\n}\n\nasync function resolveMcpAppResource(\n config: MCPConfig,\n actionName: string,\n entry: ActionEntry,\n requestMeta?: MCPRequestMeta,\n): Promise<ResolvedMcpAppResource | null> {\n const resource = entry.mcpApp?.resource;\n if (!resource) return null;\n // NB: the inline kill switch is intentionally NOT enforced here. This\n // resolver also backs `resources/read`, which must keep serving the shell\n // for a URI the host already holds (e.g. a cached descriptor) so it degrades\n // gracefully instead of throwing a hard `-32603`. The switch is enforced at\n // the *advertisement/render* sites (`tools/list` descriptor meta,\n // `tools/call` result meta, `resources/list`) so disabled embeds never get\n // advertised in the first place.\n const resolvedUri = getMcpAppResourceUri(config, actionName, entry);\n if (!resolvedUri) return null;\n const description = resource.description ?? entry.tool.description;\n const resolvedCsp = await resolveMcpAppCsp(resource, {\n actionName,\n appId: config.appId,\n requestOrigin: requestMeta?.origin,\n });\n const resourceMeta = mcpAppUiMeta(\n resource,\n resolvedCsp,\n requestMeta,\n description,\n );\n return {\n uri: resolvedUri.uri,\n ...(resolvedUri.legacyUris ? { legacyUris: resolvedUri.legacyUris } : {}),\n name: resource.name?.trim() || actionName,\n ...(resource.title ? { title: resource.title } : {}),\n ...(description ? { description } : {}),\n html: resource.html,\n mimeType: resource.mimeType ?? MCP_APP_MIME_TYPE,\n ...(resourceMeta ? { _meta: resourceMeta } : {}),\n };\n}\n\nasync function resolveMcpAppResourceSafely(\n config: MCPConfig,\n actionName: string,\n entry: ActionEntry,\n requestMeta?: MCPRequestMeta,\n): Promise<ResolvedMcpAppResource | null> {\n try {\n return await resolveMcpAppResource(config, actionName, entry, requestMeta);\n } catch (error) {\n console.warn(\n `[mcp] Skipping MCP App resource for action \"${actionName}\" because its metadata could not be resolved.`,\n error,\n );\n return null;\n }\n}\n\nasync function getMcpAppResources(\n config: MCPConfig,\n actions: Record<string, ActionEntry>,\n requestMeta?: MCPRequestMeta,\n): Promise<ResolvedMcpAppResource[]> {\n // Advertisement path (resources/list + resources/templates/list): suppressed\n // by the inline kill switch so disabled embeds are never listed.\n if (!requestMeta?.inlineMcpApps) return [];\n const resources = await Promise.all(\n Object.entries(actions).map(([name, entry]) =>\n resolveMcpAppResourceSafely(config, name, entry, requestMeta),\n ),\n );\n return resources.filter((resource): resource is ResolvedMcpAppResource =>\n Boolean(resource),\n );\n}\n\nfunction renderMcpAppHtml(\n resource: ResolvedMcpAppResource,\n actionName: string,\n config: MCPConfig,\n requestMeta?: MCPRequestMeta,\n): string {\n if (typeof resource.html === \"function\") {\n return resource.html({\n actionName,\n appId: config.appId,\n requestOrigin: requestMeta?.origin,\n });\n }\n return resource.html;\n}\n\nfunction openAiToolDescriptorMeta(\n resource: ResolvedMcpAppResource,\n): Record<string, unknown> {\n const label = resource.title ?? resource.name;\n const widgetCsp = metadataObject(resource._meta?.[\"openai/widgetCSP\"]);\n return {\n \"openai/outputTemplate\": resource.uri,\n \"openai/toolInvocation/invoking\": `Opening ${label}`,\n \"openai/toolInvocation/invoked\": `${label} ready`,\n \"openai/widgetAccessible\": true,\n ...(Object.keys(widgetCsp).length > 0\n ? { \"openai/widgetCSP\": widgetCsp }\n : {}),\n };\n}\n\nfunction openAiToolResultMeta(\n resource: ResolvedMcpAppResource,\n): Record<string, unknown> {\n const label = resource.title ?? resource.name;\n const widgetCsp = metadataObject(resource._meta?.[\"openai/widgetCSP\"]);\n return {\n \"openai/outputTemplate\": resource.uri,\n \"openai/toolInvocation/invoking\": `Opening ${label}`,\n \"openai/toolInvocation/invoked\": `${label} ready`,\n \"openai/widgetAccessible\": true,\n ...(Object.keys(widgetCsp).length > 0\n ? { \"openai/widgetCSP\": widgetCsp }\n : {}),\n };\n}\n\nfunction mcpAppToolUiMeta(\n resource: ResolvedMcpAppResource,\n visibility: unknown,\n): Record<string, unknown> {\n return {\n resourceUri: resource.uri,\n visibility: Array.isArray(visibility) ? visibility : [\"model\", \"app\"],\n };\n}\n\nfunction primitiveValue(value: unknown): value is string | number | boolean {\n return (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n );\n}\n\nfunction mcpAppStructuredContent(\n result: unknown,\n meta: Record<string, unknown> | undefined,\n): Record<string, unknown> {\n const out: Record<string, unknown> =\n result && typeof result === \"object\" && !Array.isArray(result)\n ? { ...(result as Record<string, unknown>) }\n : primitiveValue(result)\n ? { result }\n : {};\n for (const key of [\"embedStartUrl\", \"startUrl\"]) {\n const value = out[key];\n if (typeof value === \"string\" && isEmbedStartUrl(value)) delete out[key];\n }\n if (typeof out.url === \"string\" && isEmbedStartUrl(out.url)) {\n delete out.url;\n }\n // Internal embed-routing fields belong in `_meta[\"agent-native/embedStart\"]`\n // (consumed by the embed runtime), not in `structuredContent` (read by the\n // LLM). `embedTargetPath` reveals the exact route + thread/draft id the user\n // is looking at; `embedExpiresAt` is an unintended timestamp; ticket-bearing\n // fields are single-use credentials. Drop all of them unconditionally.\n for (const key of [\n \"embedTargetPath\",\n \"embedExpiresAt\",\n \"ticket\",\n \"embedTicket\",\n ]) {\n delete out[key];\n }\n for (const key of Object.keys(out)) {\n if (/Ticket$/.test(key)) delete out[key];\n }\n const openLink = meta?.[\"agent-native/openLink\"];\n if (openLink && typeof openLink === \"object\" && !Array.isArray(openLink)) {\n const webUrl = (openLink as Record<string, unknown>).webUrl;\n if (typeof webUrl === \"string\" && isEmbedStartUrl(webUrl)) {\n return Object.keys(out).length > 0 ? out : { status: \"ok\" };\n }\n out.openLink = openLink;\n if (typeof webUrl === \"string\" && !out.url) out.url = webUrl;\n }\n return Object.keys(out).length > 0 ? out : { status: \"ok\" };\n}\n\nfunction truncateToolText(value: string, max = 2000): string {\n if (value.length <= max) return value;\n return `${value.slice(0, max - 1)}…`;\n}\n\nfunction conciseMcpAppToolText(\n name: string,\n result: unknown,\n structuredContent: Record<string, unknown>,\n): string {\n if (typeof result === \"string\") return truncateToolText(result);\n const message = structuredContent.message;\n if (typeof message === \"string\" && message.trim()) {\n return truncateToolText(message.trim());\n }\n const title = structuredContent.title ?? structuredContent.name;\n if (typeof title === \"string\" && title.trim()) {\n return `${title.trim()} is ready.`;\n }\n const id = structuredContent.id;\n if (typeof id === \"string\" && id.trim()) {\n return `${name} completed for ${id.trim()}.`;\n }\n return `${name} completed.`;\n}\n\nfunction isSuccessOnlyResult(value: Record<string, unknown>): boolean {\n const keys = Object.keys(value);\n if (keys.length === 0) return true;\n return keys.every((key) => {\n const item = value[key];\n if (key === \"ok\" || key === \"success\") return item === true;\n if (key === \"status\") {\n return item === \"ok\" || item === \"success\" || item === \"completed\";\n }\n return false;\n });\n}\n\nfunction conciseToolResultText(name: string, result: unknown): string {\n const purged = purgeEmbedStartUrls(result);\n if (typeof purged === \"string\") return truncateToolText(purged);\n if (purged === true || purged == null) return `${name} completed.`;\n if (purged && typeof purged === \"object\" && !Array.isArray(purged)) {\n const record = purged as Record<string, unknown>;\n const message = record.message ?? record.summary;\n if (typeof message === \"string\" && message.trim()) {\n return truncateToolText(message.trim());\n }\n const id = record.id ?? record.planId ?? record.commentId;\n const title = record.title ?? record.name;\n if (typeof title === \"string\" && title.trim()) {\n const titleText = title.trim();\n return typeof id === \"string\" && id.trim()\n ? `${titleText} (${id.trim()}) is ready.`\n : `${titleText} is ready.`;\n }\n if (typeof id === \"string\" && id.trim()) {\n return `${name} completed for ${id.trim()}.`;\n }\n const link = record.url ?? record.webUrl ?? record.path;\n if (typeof link === \"string\" && link.trim()) {\n return `${name} completed: ${truncateToolText(link.trim(), 500)}`;\n }\n if (isSuccessOnlyResult(record)) return `${name} completed.`;\n }\n const text = JSON.stringify(purged);\n return text === undefined ? `${name} completed.` : truncateToolText(text);\n}\n\n// ---------------------------------------------------------------------------\n// MCP Server creation — converts ActionEntry registry to MCP tools\n// ---------------------------------------------------------------------------\n\n/**\n * Build a fully-wired MCP `Server` for a single request / session.\n *\n * Shared by the stateless Streamable-HTTP mount (`mountMCP`) and the stdio\n * standalone transport. The HTTP mount passes the per-request origin via\n * `requestMeta`; the stdio standalone path passes the resolved local app\n * origin so deep links still become absolute URLs.\n */\nexport async function createMCPServerForRequest(\n config: MCPConfig,\n identity: MCPCallerIdentity | undefined,\n requestMeta?: MCPRequestMeta,\n) {\n const { Server } = await import(\"@modelcontextprotocol/sdk/server/index.js\");\n const {\n ListToolsRequestSchema,\n CallToolRequestSchema,\n ListResourcesRequestSchema,\n ReadResourceRequestSchema,\n ListResourceTemplatesRequestSchema,\n } = await import(\"@modelcontextprotocol/sdk/types.js\");\n\n // Resolve the effective caller identity. JWT / header-derived identity\n // (passed by `mountMCP` via `verifyAuth`) wins. When the caller passed no\n // identity — the stdio **standalone** path — fall back to the\n // `AGENT_NATIVE_OWNER_EMAIL` env the `agent-native mcp install` flow writes\n // into the `agent-native mcp serve` process env, so standalone tool runs are\n // tenant-scoped to the configured owner instead of running unscoped. Stays\n // undefined for true dev-open (no token, no secret, no owner) — behavior\n // there is unchanged.\n const ownerFromEnv = process.env.AGENT_NATIVE_OWNER_EMAIL?.trim();\n const effectiveIdentity: MCPCallerIdentity | undefined =\n identity ??\n (ownerFromEnv\n ? { userEmail: ownerFromEnv, orgDomain: undefined }\n : undefined);\n\n // Resolve the inline-MCP-App kill switch once per request from the effective\n // identity + environment, then thread it through `requestMeta` so every\n // resource/tool handler below honors the same decision. An explicit value on\n // the incoming meta (tests / embedded callers) wins.\n requestMeta = {\n ...(requestMeta ?? {}),\n inlineMcpApps:\n requestMeta?.inlineMcpApps ?? isMcpAppsInlineEnabled(effectiveIdentity),\n };\n\n // The action set the request handlers operate on = base actions + generic\n // cross-app builtins (template wins on name collision). An authenticated\n // real caller (connect-minted token / `mcp install` owner / production —\n // `requestMeta.fullSurface`, or the stdio standalone path identified by\n // `AGENT_NATIVE_OWNER_EMAIL`) gets the full `productionActions` surface\n // even in local dev; the unauthenticated dev-open path keeps the sparse\n // `config.actions`. See `external-agents` skill, \"Dev vs production tool\n // surface\".\n const useFullSurface = requestMeta?.fullSurface === true || !!ownerFromEnv;\n const baseActions =\n useFullSurface && config.productionActions\n ? config.productionActions\n : config.actions;\n const actions = mergeBuiltinTools(config, baseActions, requestMeta);\n const visibleActions = Object.fromEntries(\n Object.entries(actions).filter(([, entry]) =>\n isActionVisibleForOAuthScope(entry, effectiveIdentity?.oauthScopes),\n ),\n );\n const fullCatalogRequested = explicitlyRequestsFullMcpCatalog(requestMeta);\n // Compact/connector is the DEFAULT for every caller — hosted connectors,\n // code clients (Claude Code / Cursor / Codex), and the local CLI alike. The\n // full ~105-tool catalog is served only on the explicit opt-in above, so a\n // host can never dump every action schema into one giant tool card. The\n // `mcp:apps` scope still lands on this compact MCP-Apps surface; with no\n // opt-in, everyone else does too.\n const compactMcpAppCatalog = !fullCatalogRequested;\n const advertisedActionsBeforeConnector = compactMcpAppCatalog\n ? Object.fromEntries(\n Object.entries(visibleActions).filter(([name, entry]) =>\n isActionAdvertisedInCompactMcpAppCatalog(name, entry, config),\n ),\n )\n : visibleActions;\n // Connector-catalog tier: when a template declares a connector allow-list,\n // serve exactly that curated surface (+ cross-app builtins + tool-search) to\n // external callers unless they explicitly opted into the full catalog. This\n // is active by default whenever a catalog is declared — no env flag required —\n // so the ~105-tool full catalog can never leak just because a deployment\n // forgot to set one. It also keeps db-exec / seed-* / extension /\n // browser-session footguns off the external surface.\n const connectorCatalogActive =\n Array.isArray(config.connectorCatalog) &&\n config.connectorCatalog.length > 0 &&\n !fullCatalogRequested;\n // When the connector catalog is active, filter directly from visibleActions\n // rather than advertisedActionsBeforeConnector. This ensures the connector\n // tier is an independent, template-declared surface that doesn't accidentally\n // narrow to just the compact-catalog builtins when shouldUseCompactMcpCatalogByDefault\n // would have activated the compact catalog for the same caller.\n const advertisedActions = connectorCatalogActive\n ? Object.fromEntries(\n Object.entries(visibleActions).filter(([name]) =>\n isActionInConnectorCatalog(name, config),\n ),\n )\n : advertisedActionsBeforeConnector;\n if (fullCatalogRequested) {\n warnFullCatalogServed(Object.keys(advertisedActions).length);\n }\n const supportsMcpApps =\n compactMcpAppCatalog ||\n Object.values(advertisedActions).some((entry) =>\n Boolean(entry.mcpApp?.resource),\n );\n const server = new Server(mcpServerInfo(config, requestMeta), {\n capabilities: {\n tools: {},\n ...(supportsMcpApps\n ? {\n resources: {},\n extensions: {\n [MCP_APP_EXTENSION_ID]: {\n mimeTypes: [MCP_APP_MIME_TYPE],\n },\n },\n }\n : {}),\n },\n });\n\n // Resolve orgId once per request (DB lookup) so subsequent wraps are\n // synchronous. The caller identity may be undefined for true dev-open —\n // in that case we run with no userEmail/orgId, which makes downstream\n // tools that require per-user scope return empty results rather than\n // cross-tenant data (the safe default).\n const orgIdPromise = effectiveIdentity?.orgId\n ? Promise.resolve(effectiveIdentity.orgId)\n : resolveOrgIdFromDomain(effectiveIdentity?.orgDomain);\n\n /**\n * Wrap a callback in\n * `runWithRequestContext({ userEmail, orgId, requestOrigin }, fn)`.\n * Both the tools/list and tools/call handlers go through this so\n * downstream `accessFilter`, `resolveCredential`, and per-user MCP\n * visibility checks see the verified caller's identity. `requestOrigin`\n * is the live server origin derived from the inbound request (same value\n * used to absolutize deep links) so actions that build fetchable URLs\n * (e.g. design `export-coding-handoff`'s signed raw-code URL) resolve the\n * correct local-workspace origin instead of a prod/localhost fallback.\n */\n async function withCallerContext<T>(fn: () => Promise<T>): Promise<T> {\n const orgId = await orgIdPromise;\n return runWithRequestContext(\n {\n userEmail: effectiveIdentity?.userEmail,\n orgId,\n ...(requestMeta?.origin ? { requestOrigin: requestMeta.origin } : {}),\n },\n fn,\n ) as Promise<T>;\n }\n\n // tools/list — return all actions + ask-agent meta-tool. Wrapped in the\n // request context so per-user MCP visibility (mcp-client/visibility.ts)\n // applies to the listing too.\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n return withCallerContext(async () => {\n const tools = await Promise.all(\n Object.entries(advertisedActions).map(async ([name, entry]) => {\n const hasLink = typeof entry.link === \"function\";\n const mcpAppResource = await resolveMcpAppResourceSafely(\n config,\n name,\n entry,\n requestMeta,\n );\n const rawToolMeta =\n (entry.tool as any)._meta &&\n typeof (entry.tool as any)._meta === \"object\" &&\n !Array.isArray((entry.tool as any)._meta)\n ? { ...((entry.tool as any)._meta as Record<string, unknown>) }\n : {};\n const toolMeta = {\n ...rawToolMeta,\n // Advertisement path: only tag the tool with its inline-embed\n // descriptor when the kill switch is on, so disabled embeds never\n // prompt a host to render/read the `ui://` resource.\n ...(mcpAppResource && requestMeta?.inlineMcpApps\n ? {\n ...openAiToolDescriptorMeta(mcpAppResource),\n [MCP_APP_RESOURCE_URI_META_KEY]: mcpAppResource.uri,\n ui: mcpAppToolUiMeta(\n mcpAppResource,\n entry.mcpApp?.visibility ??\n metadataObject(rawToolMeta.ui).visibility,\n ),\n }\n : {}),\n };\n const baseDescription = entry.tool.description ?? name;\n const annotations: Record<string, unknown> = {\n readOnlyHint: entry.readOnly === true,\n destructiveHint: entry.publicAgent?.isConsequential === true,\n openWorldHint: false,\n };\n if (hasLink) annotations[\"agent-native/producesOpenLink\"] = true;\n return {\n name,\n description: hasLink\n ? `${baseDescription} After calling, surface the returned \"Open in … →\" link to the user.`\n : baseDescription,\n inputSchema: entry.tool.parameters ?? {\n type: \"object\" as const,\n properties: {},\n },\n ...(Object.keys(toolMeta).length > 0 ? { _meta: toolMeta } : {}),\n annotations,\n };\n }),\n );\n\n if (\n !compactMcpAppCatalog &&\n !connectorCatalogActive &&\n config.askAgent &&\n hasMcpOAuthScope(effectiveIdentity?.oauthScopes, \"mcp:write\")\n ) {\n tools.push({\n name: \"ask-agent\",\n description:\n \"Send a natural-language message to the app's AI agent and get a response. \" +\n \"Use this for complex, multi-step tasks that require the agent's reasoning \" +\n \"and full context about the app.\",\n inputSchema: {\n type: \"object\" as const,\n properties: {\n message: {\n type: \"string\",\n description: \"The message to send to the agent\",\n },\n },\n required: [\"message\"],\n },\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n openWorldHint: false,\n },\n });\n }\n\n return { tools };\n });\n });\n\n // tools/call — dispatch to action registry or ask-agent. Wrapped in the\n // request context so the action's `run(args)` and `askAgent()` execute\n // with the verified caller's identity, not the platform default.\n server.setRequestHandler(CallToolRequestSchema, async (request: any) => {\n return withCallerContext(async () => {\n const { name, arguments: args } = request.params;\n\n if (name === \"ask-agent\" && config.askAgent) {\n if (compactMcpAppCatalog || connectorCatalogActive) {\n return {\n content: [{ type: \"text\", text: `Unknown tool: ${name}` }],\n isError: true,\n };\n }\n if (!hasMcpOAuthScope(effectiveIdentity?.oauthScopes, \"mcp:write\")) {\n return {\n content: [\n {\n type: \"text\",\n text: \"Forbidden: OAuth scope does not allow ask-agent\",\n },\n ],\n isError: true,\n };\n }\n const message = args?.message ?? \"\";\n try {\n const result = await config.askAgent(message);\n return { content: [{ type: \"text\", text: result }] };\n } catch (err: any) {\n return {\n content: [{ type: \"text\", text: `Error: ${err.message}` }],\n isError: true,\n };\n }\n }\n\n // Connector-catalog tier: when active, callableActions === advertisedActions\n // (the filtered set). Non-listed tools are not callable — mirroring how\n // compactMcpAppCatalog gates calls on advertisedActions.\n const callableActions =\n compactMcpAppCatalog || connectorCatalogActive\n ? advertisedActions\n : actions;\n const entry = callableActions[name];\n if (!entry) {\n return {\n content: [{ type: \"text\", text: `Unknown tool: ${name}` }],\n isError: true,\n };\n }\n if (\n !isActionVisibleForOAuthScope(entry, effectiveIdentity?.oauthScopes)\n ) {\n return {\n content: [\n {\n type: \"text\",\n text: `Forbidden: OAuth scope does not allow tool ${name}`,\n },\n ],\n isError: true,\n };\n }\n\n try {\n // We're inside `withCallerContext`, so the request-context getters\n // resolve the verified MCP caller's identity (do NOT inject a dev\n // fallback). Tag the call as an external-agent MCP dispatch.\n const result = await entry.run((args as Record<string, string>) ?? {}, {\n userEmail: getRequestUserEmail(),\n orgId: getRequestOrgId() ?? null,\n caller: \"mcp\",\n actionName: name,\n });\n const mcpResult = isMcpActionResult(result) ? result : null;\n const rawResult = mcpResult ? mcpResult.raw : result;\n const resultForClient = mcpResult ? mcpResult.text : result;\n const mcpResultIsError =\n !!mcpResult &&\n !!mcpResult.raw &&\n typeof mcpResult.raw === \"object\" &&\n (mcpResult.raw as Record<string, unknown>).isError === true;\n // Render path: only treat the result as an inline embed when the kill\n // switch is on. When off, `mcpAppResource` is null so every embed\n // branch below degrades to the plain deep-link artifacts the tool would\n // otherwise return — no `openai/outputTemplate`, no minted embed-start,\n // no embed structuredContent — so the host shows a link, not an iframe.\n const mcpAppResource = requestMeta?.inlineMcpApps\n ? await resolveMcpAppResourceSafely(config, name, entry, requestMeta)\n : null;\n const rawResultForClient = mcpAppResource\n ? await withServerMintedMcpAppEmbedStart(rawResult, requestMeta)\n : rawResult;\n const { block, _meta } = buildLinkArtifacts(\n entry,\n (args as Record<string, any>) ?? {},\n rawResultForClient,\n requestMeta,\n );\n const responseMeta: Record<string, unknown> = {\n ...(_meta ?? {}),\n ...(mcpAppResource\n ? mcpAppEmbedOpenLinkMeta(\n rawResultForClient,\n mcpAppResource,\n requestMeta,\n )\n : {}),\n ...(mcpAppResource ? openAiToolResultMeta(mcpAppResource) : {}),\n };\n const toolUiMeta = metadataObject((entry.tool as any)._meta?.ui);\n const toolVisibility = toolUiMeta.visibility;\n const isAppOnlyVisibility =\n Array.isArray(toolVisibility) &&\n toolVisibility.length > 0 &&\n toolVisibility.every((v) => v === \"app\");\n const structuredContent = mcpAppResource\n ? mcpAppStructuredContent(rawResultForClient, responseMeta)\n : isAppOnlyVisibility &&\n rawResult &&\n typeof rawResult === \"object\" &&\n !Array.isArray(rawResult)\n ? (rawResult as Record<string, unknown>)\n : undefined;\n const text = mcpAppResource\n ? conciseMcpAppToolText(name, resultForClient, structuredContent!)\n : conciseToolResultText(name, resultForClient);\n const content: any[] = [{ type: \"text\", text }];\n if (block) content.push(block);\n return {\n content,\n ...(mcpResultIsError ? { isError: true } : {}),\n ...(structuredContent ? { structuredContent } : {}),\n ...(Object.keys(responseMeta).length > 0\n ? { _meta: responseMeta }\n : {}),\n };\n } catch (err: any) {\n return {\n content: [{ type: \"text\", text: `Error: ${err.message}` }],\n isError: true,\n };\n }\n });\n });\n\n if (supportsMcpApps) {\n server.setRequestHandler(ListResourcesRequestSchema, async () => {\n return withCallerContext(async () => {\n const mcpAppResources = await getMcpAppResources(\n config,\n advertisedActions,\n requestMeta,\n );\n return {\n resources: mcpAppResources.map((resource) => ({\n uri: resource.uri,\n name: resource.name,\n ...(resource.title ? { title: resource.title } : {}),\n ...(resource.description\n ? { description: resource.description }\n : {}),\n mimeType: resource.mimeType,\n ...(resource._meta ? { _meta: resource._meta } : {}),\n })),\n };\n });\n });\n\n server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => {\n return withCallerContext(async () => {\n const mcpAppResources = await getMcpAppResources(\n config,\n advertisedActions,\n requestMeta,\n );\n return {\n resourceTemplates: mcpAppResources.map((resource) => ({\n uriTemplate: resource.uri,\n name: resource.name,\n ...(resource.title ? { title: resource.title } : {}),\n ...(resource.description\n ? { description: resource.description }\n : {}),\n mimeType: resource.mimeType,\n ...(resource._meta ? { _meta: resource._meta } : {}),\n })),\n };\n });\n });\n\n server.setRequestHandler(\n ReadResourceRequestSchema,\n async (request: any) => {\n return withCallerContext(async () => {\n const uri = request.params?.uri;\n let found: {\n actionName: string;\n resource: ResolvedMcpAppResource;\n } | null = null;\n for (const [name, entry] of Object.entries(advertisedActions)) {\n const resourceUri = getMcpAppResourceUri(config, name, entry);\n if (!resourceUri || !matchesMcpAppResourceUri(resourceUri, uri)) {\n continue;\n }\n const resource = await resolveMcpAppResourceSafely(\n config,\n name,\n entry,\n requestMeta,\n );\n if (resource) {\n found = { actionName: name, resource };\n break;\n }\n // resolveMcpAppResourceSafely returned null (e.g. an async resolver\n // threw) — keep scanning the remaining candidates rather than\n // aborting and reporting the resource as missing.\n }\n if (!found) {\n throw new Error(`MCP App resource not found: ${uri}`);\n }\n return {\n contents: [\n {\n uri,\n mimeType: found.resource.mimeType,\n text: renderMcpAppHtml(\n found.resource,\n found.actionName,\n config,\n requestMeta,\n ),\n ...(found.resource._meta\n ? { _meta: found.resource._meta }\n : {}),\n },\n ],\n };\n });\n },\n );\n }\n\n return server;\n}\n\n// ---------------------------------------------------------------------------\n// Auth — reuses the same pattern as A2A (Bearer token or JWT). Shared so the\n// HTTP mount and any stdio-side auth-aware helper resolve identity identically.\n// ---------------------------------------------------------------------------\n\nexport function getAccessTokens(): string[] {\n const single = process.env.ACCESS_TOKEN;\n const multi = process.env.ACCESS_TOKENS;\n const tokens: string[] = [];\n if (single) tokens.push(single);\n if (multi) {\n tokens.push(\n ...multi\n .split(\",\")\n .map((t) => t.trim())\n .filter(Boolean),\n );\n }\n return tokens;\n}\n\n/**\n * Resolve the caller identity for a static-token (or dev-open) auth path.\n *\n * Static `ACCESS_TOKEN` / `ACCESS_TOKENS` auth carries no per-caller claims,\n * so without this the MCP endpoint would run every tool with\n * `userEmail === undefined` and per-user / per-org scoped actions\n * (`accessFilter`, `resolveAccess`, `resolveCredential`) would return\n * empty / wrong data. The `agent-native mcp install` flow writes\n * `AGENT_NATIVE_OWNER_EMAIL` into the client config env and the stdio proxy\n * forwards it as the `X-Agent-Native-Owner-Email` request header (see\n * `mcp/stdio.ts#authHeaders`). We trust that owner hint *only* on the\n * static-token path — JWT auth already carries a cryptographically verified\n * `sub`, so the header is ignored there and never widens JWT scope.\n *\n * Precedence is server-trusted-first: the server process's\n * `AGENT_NATIVE_OWNER_EMAIL` env (set out-of-band by the operator / deploy)\n * ALWAYS wins, and a client-supplied `X-Agent-Native-Owner-Email` header is\n * honored *only as a fallback when that env is unset*. A static `ACCESS_TOKEN`\n * is a shared bearer secret; letting a request header override a\n * server-configured owner would let anyone holding a leaked token act as any\n * user. The header path remains for the single-tenant local-dev install flow\n * where the app server process has no owner env and the token *is* the\n * workspace secret; multi-tenant deployments must use A2A JWT (verified `sub`),\n * not a static token, for per-user scope.\n *\n * Returns `undefined` when no owner email is available (true dev-open: no\n * token, no secret, no owner) so behavior there stays unchanged.\n */\nfunction deriveStaticTokenIdentity(\n ownerEmailHeader: string | undefined,\n): MCPCallerIdentity | undefined {\n const owner =\n process.env.AGENT_NATIVE_OWNER_EMAIL?.trim() ||\n (typeof ownerEmailHeader === \"string\" && ownerEmailHeader.trim()) ||\n \"\";\n if (!owner) return undefined;\n return { userEmail: owner, orgDomain: undefined };\n}\n\nexport function getBearerToken(\n authHeader: string | undefined,\n): string | undefined {\n if (!authHeader) return undefined;\n const match = /^Bearer\\s+(.+)$/i.exec(authHeader.trim());\n return match?.[1]?.trim() || undefined;\n}\n\nfunction addSecretCandidate(\n candidates: string[],\n secret: string | null | undefined,\n): void {\n const trimmed = secret?.trim();\n if (!trimmed || candidates.includes(trimmed)) return;\n candidates.push(trimmed);\n}\n\nasync function verifyA2AJwtForMcp(\n token: string,\n resourceUrl?: string | string[],\n): Promise<Record<string, unknown> | null> {\n const jose = await import(\"jose\");\n let unverifiedPayload: Record<string, unknown> | null = null;\n try {\n unverifiedPayload = jose.decodeJwt(token) as Record<string, unknown>;\n } catch {\n return null;\n }\n\n const candidateSecrets: string[] = [];\n addSecretCandidate(candidateSecrets, process.env.A2A_SECRET);\n\n const orgDomain =\n typeof unverifiedPayload.org_domain === \"string\"\n ? unverifiedPayload.org_domain\n : undefined;\n if (orgDomain) {\n try {\n const { getA2ASecretByDomain } = await import(\"../org/context.js\");\n addSecretCandidate(\n candidateSecrets,\n await getA2ASecretByDomain(orgDomain),\n );\n } catch {\n // DB not ready or org lookup unavailable — fall back to other candidates.\n }\n }\n\n const firstPartyMcp = unverifiedPayload.agent_native_first_party_mcp === true;\n const audiences = firstPartyMcp ? mcpAudienceList(resourceUrl) : null;\n if (firstPartyMcp && !audiences?.length) return null;\n\n for (const secret of candidateSecrets) {\n const encodedSecret = new TextEncoder().encode(secret);\n for (const audience of audiences ?? [undefined]) {\n try {\n const { payload } = await jose.jwtVerify(\n token,\n encodedSecret,\n audience ? { audience } : undefined,\n );\n return payload as Record<string, unknown>;\n } catch {\n // Try the next candidate without exposing which secret matched.\n }\n }\n }\n\n return null;\n}\n\nfunction mcpAudienceList(resource: string | string[] | undefined): string[] {\n const raw = Array.isArray(resource) ? resource : resource ? [resource] : [];\n const seen = new Set<string>();\n const out: string[] = [];\n for (const value of raw) {\n const normalized = value.replace(/\\/+$/, \"\");\n if (normalized && !seen.has(normalized)) {\n seen.add(normalized);\n out.push(normalized);\n }\n }\n return out;\n}\n\nasync function isConnectTokenAllowed(\n jti: string | undefined,\n): Promise<boolean> {\n if (!jti) return false;\n try {\n const { isJtiRevoked, touchTokenUsed } = await import(\"./connect-store.js\");\n if (await isJtiRevoked(jti)) return false;\n // Best-effort usage telemetry — never blocks / throws.\n void touchTokenUsed(jti);\n } catch {\n // Store import / lookup failed — fail open. Signature verification already\n // passed; this only gates explicit revokes.\n }\n return true;\n}\n\n/**\n * Verify the inbound auth header. Returns:\n * - { authed: true, identity } when verified — `identity` is derived from\n * the JWT (`sub` / `org_domain`) for JWT auth, or from the\n * `AGENT_NATIVE_OWNER_EMAIL` env / `X-Agent-Native-Owner-Email` header\n * for static-token auth (the `agent-native mcp install` flow). `identity`\n * is undefined only for true dev-open with no owner hint.\n * - { authed: false } on rejection.\n *\n * When A2A_SECRET is set we extract the JWT's `sub` (caller email) and\n * `org_domain` claims so the MCP endpoint can wrap tool runs in\n * `runWithRequestContext({ userEmail, orgId })`. Without that wrap, the\n * MCP endpoint loses tenant identity and downstream `accessFilter` /\n * `resolveCredential` calls fall back to platform-wide defaults.\n *\n * `ownerEmailHeader` is the forwarded `X-Agent-Native-Owner-Email` value; it\n * is consulted ONLY on the static-token / dev-open path (never to influence\n * verified JWT identity), so the install flow runs tools as the configured\n * owner instead of an unscoped anonymous caller.\n */\nexport async function verifyAuth(\n authHeader: string | undefined,\n ownerEmailHeader?: string | undefined,\n options: { allowDevOpen?: boolean; resourceUrl?: string | string[] } = {},\n): Promise<{\n authed: boolean;\n identity?: MCPCallerIdentity;\n /**\n * The caller presented a real credential — a verified A2A/connect JWT, a\n * matching ACCESS_TOKEN, or (on the no-auth-configured path) a forwarded\n * owner-email header from `agent-native mcp install`. Drives the full vs\n * sparse MCP tool surface in local dev. The pure unauthenticated dev-open\n * path (no secret, no token, no owner header) is `false`.\n */\n fullSurface?: boolean;\n /**\n * The caller explicitly opted up to the full connector catalog by minting\n * their token with `--full-catalog` (or equivalent). When `true`, the\n * compact/connector-catalog tier filter (active by default whenever a\n * `connectorCatalog` is declared) is bypassed for this caller. Derived from a\n * `catalog_scope: \"full\"` claim in the verified A2A/connect JWT.\n */\n fullCatalog?: boolean;\n}> {\n // No auth configured → allow only when the route caller has already\n // established that this is a loopback/local dev request. Still honour an\n // owner hint there so the local install/connect flow stays tenant-scoped.\n const accessTokens = getAccessTokens();\n const hasA2ASecret = !!process.env.A2A_SECRET?.trim();\n const token = getBearerToken(authHeader);\n if (token) {\n const oauthIdentity = await verifyMcpOAuthAccessToken(\n token,\n options.resourceUrl,\n );\n if (oauthIdentity) {\n if (\n oauthIdentity.clientId === MCP_CONNECT_OAUTH_CLIENT_ID &&\n !(await isConnectTokenAllowed(oauthIdentity.jti))\n ) {\n return { authed: false };\n }\n return {\n authed: true,\n identity: {\n userEmail: oauthIdentity.userEmail,\n ...(oauthIdentity.orgId ? { orgId: oauthIdentity.orgId } : {}),\n orgDomain: oauthIdentity.orgDomain,\n oauthScopes: oauthIdentity.scopes,\n oauthClientId: oauthIdentity.clientId,\n },\n fullSurface: true,\n // Per-token opt-up: `catalog_scope: \"full\"` in the OAuth token\n // bypasses the connector-catalog tier filter on hosted deployments.\n fullCatalog: oauthIdentity.catalogScope === \"full\",\n };\n }\n }\n if (accessTokens.length === 0 && !hasA2ASecret && !token) {\n if (options.allowDevOpen === false) {\n return { authed: false };\n }\n return {\n authed: true,\n identity: deriveStaticTokenIdentity(ownerEmailHeader),\n // `mcp install`'s stdio proxy forwards an owner-email header even when\n // the local app has no secret configured — that is a real, identified\n // caller and gets the full surface. A bare browser/curl dev probe with\n // no owner hint stays on the sparse dev surface.\n fullSurface: !!(ownerEmailHeader && ownerEmailHeader.trim()),\n };\n }\n\n if (!token) return { authed: false };\n\n // Try an A2A JWT via the shared A2A_SECRET first, then the caller org's\n // synced A2A secret when the token carries org_domain.\n const payload = await verifyA2AJwtForMcp(token, options.resourceUrl);\n if (payload) {\n const tokenScope =\n typeof payload.scope === \"string\" ? payload.scope : undefined;\n if (tokenScope && tokenScope !== MCP_CONNECT_SCOPE) {\n return { authed: false };\n }\n\n // Connect-minted tokens (scope === \"mcp-connect\") carry a random `jti`\n // and are individually revocable. Only these tokens hit the revoke\n // store — ordinary A2A delegation JWTs skip the DB lookup entirely so\n // the hot path is unchanged. The signature was already\n // cryptographically verified, so failing open here only widens the\n // explicit-revoke gate, never the trust boundary.\n if (tokenScope === MCP_CONNECT_SCOPE) {\n if (!(await isConnectTokenAllowed(payload.jti as string | undefined))) {\n return { authed: false };\n }\n }\n\n return {\n authed: true,\n identity: {\n userEmail: typeof payload.sub === \"string\" ? payload.sub : undefined,\n // Org SERVICE tokens (connect-minted, synthetic `svc-*@service.<org>`\n // subject) carry the org id directly as an `org_id` claim so the\n // resolved identity is org-scoped even when the org has no domain\n // mapping. Personal/delegation JWTs don't set the claim — unchanged.\n ...(typeof payload.org_id === \"string\" && payload.org_id\n ? { orgId: payload.org_id as string }\n : {}),\n orgDomain:\n typeof payload.org_domain === \"string\"\n ? (payload.org_domain as string)\n : undefined,\n ...(payload.agent_native_first_party_mcp === true\n ? { firstPartyMcp: true }\n : {}),\n },\n // Verified JWT (connect-minted or A2A delegation) — a real caller.\n fullSurface: true,\n // Per-token opt-up: `catalog_scope: \"full\"` embedded at mint time via\n // `agent-native connect --full-catalog` bypasses the connector-catalog\n // tier filter on hosted multi-tenant deployments.\n fullCatalog: payload.catalog_scope === \"full\",\n };\n }\n\n if (accessTokens.length === 0 && !hasA2ASecret) {\n if (options.allowDevOpen === false) {\n return { authed: false };\n }\n return {\n authed: true,\n identity: deriveStaticTokenIdentity(ownerEmailHeader),\n fullSurface: !!(ownerEmailHeader && ownerEmailHeader.trim()),\n };\n }\n\n // Try ACCESS_TOKEN / ACCESS_TOKENS exact match. Static tokens carry no\n // per-caller claims, so derive identity from the forwarded owner-email\n // hint (install flow) — otherwise tools would run unscoped. Compare in\n // constant time (matching the rest of this subsystem's secret-comparison\n // discipline); node:crypto is imported dynamically because this module is\n // bundled into the serverless function and avoids static Node-only imports.\n if (accessTokens.length > 0) {\n const { timingSafeEqual } = await import(\"node:crypto\");\n const candidate = Buffer.from(token, \"utf8\");\n const matched = accessTokens.some((configured) => {\n const expected = Buffer.from(configured, \"utf8\");\n return (\n expected.length === candidate.length &&\n timingSafeEqual(expected, candidate)\n );\n });\n if (matched) {\n return {\n authed: true,\n identity: deriveStaticTokenIdentity(ownerEmailHeader),\n // Matched a configured ACCESS_TOKEN — a real caller.\n fullSurface: true,\n };\n }\n }\n\n return { authed: false };\n}\n\nexport async function resolveOrgIdFromDomain(\n orgDomain: string | undefined,\n): Promise<string | undefined> {\n if (!orgDomain) return undefined;\n try {\n const { resolveOrgByDomain } = await import(\"../org/context.js\");\n const org = await resolveOrgByDomain(orgDomain);\n return org?.orgId ?? undefined;\n } catch {\n return undefined;\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"embed-app.d.ts","sourceRoot":"","sources":["../../src/mcp/embed-app.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAM/D,eAAO,MAAM,iCAAiC,mBAAmB,CAAC;AAElE,eAAO,MAAM,4BAA4B,MAAM,CAAC;AAChD,eAAO,MAAM,+BAA+B,QACkB,CAAC;AAE/D,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAUD,wBAAgB,QAAQ,CACtB,OAAO,GAAE,eAAoB,GAC5B,0BAA0B,
|
|
1
|
+
{"version":3,"file":"embed-app.d.ts","sourceRoot":"","sources":["../../src/mcp/embed-app.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAM/D,eAAO,MAAM,iCAAiC,mBAAmB,CAAC;AAElE,eAAO,MAAM,4BAA4B,MAAM,CAAC;AAChD,eAAO,MAAM,+BAA+B,QACkB,CAAC;AAE/D,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAUD,wBAAgB,QAAQ,CACtB,OAAO,GAAE,eAAoB,GAC5B,0BAA0B,CAm6D5B"}
|
package/dist/mcp/embed-app.js
CHANGED
|
@@ -1202,9 +1202,11 @@ export function embedApp(options = {}) {
|
|
|
1202
1202
|
if (mode === "iframe" || mode === "nested" || render.frame === "iframe" || render.nested) {
|
|
1203
1203
|
return false;
|
|
1204
1204
|
}
|
|
1205
|
+
// ChatGPT is excluded so it uses the controlled nested frame instead:
|
|
1206
|
+
// transplant would cross-origin import() app chunks in its opaque-origin
|
|
1207
|
+
// sandbox, which it blocks (blank embed). embedMode "transplant" still forces it.
|
|
1205
1208
|
return (
|
|
1206
1209
|
isClaudeMcpContentHost() ||
|
|
1207
|
-
isChatGptSandboxHost() ||
|
|
1208
1210
|
mode === "transplant" ||
|
|
1209
1211
|
render.frame === "transplant"
|
|
1210
1212
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"embed-app.js","sourceRoot":"","sources":["../../src/mcp/embed-app.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ActionMcpAppResourceConfig } from \"../action.js\";\nimport { MCP_APP_CHAT_BRIDGE_QUERY_PARAM } from \"../shared/embed-auth.js\";\n\nconst MCP_APP_IMPORT =\n \"https://esm.sh/@modelcontextprotocol/ext-apps@1.7.2/app-with-deps\";\n\nexport const MCP_APP_REQUEST_ORIGIN_CSP_SOURCE = \"$requestOrigin\";\nconst MCP_APP_WRAPPER_CHROME_HEIGHT = 44;\nexport const DEFAULT_MCP_APP_SHELL_HEIGHT = 560;\nexport const DEFAULT_MCP_APP_VIEWPORT_HEIGHT =\n DEFAULT_MCP_APP_SHELL_HEIGHT - MCP_APP_WRAPPER_CHROME_HEIGHT;\n\nexport interface EmbedAppOptions {\n title?: string;\n description?: string;\n iframeTitle?: string;\n openLabel?: string;\n embedByDefault?: boolean;\n startToolName?: string;\n connectDomains?: string[];\n resourceDomains?: string[];\n baseUriDomains?: string[];\n frameDomains?: string[];\n height?: number;\n}\n\nfunction attr(value: string | undefined): string {\n return String(value ?? \"\")\n .replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n}\n\nexport function embedApp(\n options: EmbedAppOptions = {},\n): ActionMcpAppResourceConfig {\n const title = options.title ?? \"Open app\";\n const iframeTitle = options.iframeTitle ?? \"Agent Native app\";\n const openLabel = options.openLabel ?? \"Open in app\";\n const startToolName = options.startToolName ?? \"create_embed_session\";\n const embedByDefault = options.embedByDefault !== false;\n const height = Math.max(\n 320,\n Math.min(900, options.height ?? DEFAULT_MCP_APP_SHELL_HEIGHT),\n );\n const viewportHeight = height - MCP_APP_WRAPPER_CHROME_HEIGHT;\n const frameDomains = [\n MCP_APP_REQUEST_ORIGIN_CSP_SOURCE,\n ...(options.frameDomains ?? []),\n ];\n\n return {\n title,\n ...(options.description ? { description: options.description } : {}),\n html: () => `<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <style>\n :root { color-scheme: light dark; font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif; background: Canvas; color: CanvasText; --agent-native-shell-height: ${height}px; --agent-native-viewport-height: ${viewportHeight}px; }\n * { box-sizing: border-box; }\n body { margin: 0; }\n .shell { display: grid; gap: 8px; min-height: var(--agent-native-shell-height); padding: 0; }\n .bar { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 36px; padding: 6px 8px; border-bottom: 1px solid color-mix(in srgb, CanvasText 12%, Canvas); }\n .title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; font-weight: 700; color: color-mix(in srgb, CanvasText 72%, Canvas); }\n .actions { display: flex; align-items: center; gap: 6px; }\n button { min-height: 28px; border: 1px solid color-mix(in srgb, CanvasText 14%, Canvas); border-radius: 7px; background: Canvas; color: CanvasText; cursor: pointer; font: inherit; font-size: 12px; font-weight: 700; padding: 0 9px; }\n button.primary { min-height: 32px; padding: 0 14px; background: CanvasText; color: Canvas; border-color: CanvasText; }\n button.primary:hover:not(:disabled) { background: color-mix(in srgb, CanvasText 86%, Canvas); }\n button:disabled { opacity: .55; cursor: default; }\n .stage { position: relative; min-height: var(--agent-native-viewport-height); }\n iframe { display: block; width: 100%; height: var(--agent-native-viewport-height); border: 0; background: Canvas; }\n .message { display: grid; place-items: center; min-height: var(--agent-native-viewport-height); padding: 18px; color: color-mix(in srgb, CanvasText 62%, Canvas); font-size: 13px; line-height: 1.45; text-align: center; }\n .fallback { display: grid; align-content: center; justify-items: center; gap: 12px; min-height: var(--agent-native-viewport-height); padding: 24px; background: Canvas; color: CanvasText; text-align: center; }\n .fallback-title { max-width: 440px; font-size: 14px; font-weight: 700; }\n .fallback-copy { max-width: 520px; color: color-mix(in srgb, CanvasText 64%, Canvas); font-size: 13px; line-height: 1.45; }\n .fallback-actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 8px; }\n .fallback-url { max-width: min(560px, 100%); overflow-wrap: anywhere; color: color-mix(in srgb, CanvasText 76%, Canvas); font-size: 12px; }\n </style>\n</head>\n<body\n data-app-title=\"${attr(title)}\"\n data-iframe-title=\"${attr(iframeTitle)}\"\n data-open-label=\"${attr(openLabel)}\"\n data-start-tool=\"${attr(startToolName)}\"\n data-embed-default=\"${embedByDefault ? \"1\" : \"0\"}\"\n>\n <main class=\"shell\">\n <div class=\"bar\">\n <div class=\"title\" data-title-label>${attr(title)}</div>\n <div class=\"actions\">\n <button type=\"button\" data-display hidden disabled>Fullscreen</button>\n <button type=\"button\" data-open disabled>${attr(openLabel)}</button>\n </div>\n </div>\n <section class=\"stage\" data-stage>\n <div class=\"message\">Preparing app</div>\n </section>\n </main>\n <script>\n (async () => {\n const body = document.body;\n const stage = document.querySelector(\"[data-stage]\");\n const titleEl = document.querySelector(\"[data-title-label]\");\n const openButton = document.querySelector(\"[data-open]\");\n const displayButton = document.querySelector(\"[data-display]\");\n const startTool = body.dataset.startTool || \"create_embed_session\";\n const embedByDefault = body.dataset.embedDefault !== \"0\";\n const chatBridgeParam = ${JSON.stringify(MCP_APP_CHAT_BRIDGE_QUERY_PARAM)};\n const defaultIntrinsicHeight = ${height};\n const chromeHeight = ${MCP_APP_WRAPPER_CHROME_HEIGHT};\n const frameReadyMessageDelays = [0, 200, 500, 1500, 3000, 7000, 15000, 30000];\n const frameReadyTimeoutMs = 45000;\n const frameLoadTimeoutMs = 45000;\n const maxEmbedSessionRefreshAttempts = 2;\n const defaultOpenAiBridgeWaitMs = 200;\n const chatGptOpenAiBridgeWaitMs = 5000;\n const openAiBridgePollMs = 50;\n const nativeBridgeInitializeTimeoutMs = 5000;\n const nativeBridgeRequestTimeoutMs = 30000;\n const wrapperRequestTimeoutMs = 5000;\n let app = null;\n let appConnectPromise = null;\n let openAiBridge = null;\n let wrapperRequestId = 0;\n const wrapperRequests = new Map();\n let toolInput = {};\n let toolResultData = {};\n let openUrl = \"\";\n let openStartUrl = \"\";\n let startedFor = \"\";\n let appFrame = null;\n let appFrameReady = false;\n let appFrameReadyTimer = null;\n let appFrameLoadTimer = null;\n let lastFrameSrc = \"\";\n let embedSessionRefreshAttempts = 0;\n\n function esc(value) {\n return String(value ?? \"\")\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\");\n }\n\n function parseJson(value, fallback) {\n if (value && typeof value === \"object\") return value;\n if (typeof value !== \"string\" || !value.trim()) return fallback;\n try { return JSON.parse(value); } catch { return fallback; }\n }\n\n function objectValue(value) {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? value\n : {};\n }\n\n function finiteNumber(value) {\n return typeof value === \"number\" && Number.isFinite(value) && value > 0\n ? value\n : null;\n }\n\n function contextMaxHeight(context) {\n if (!context || typeof context !== \"object\") return null;\n return finiteNumber(context.maxHeight) ||\n finiteNumber(context.containerDimensions && context.containerDimensions.maxHeight);\n }\n\n function visibleIntrinsicHeight() {\n const context = hostState().context || {};\n const hostMaxHeight = contextMaxHeight(context);\n if (hostMaxHeight) return Math.floor(hostMaxHeight);\n const viewportHeight = finiteNumber(window.visualViewport && window.visualViewport.height) ||\n finiteNumber(window.innerHeight);\n return Math.floor(viewportHeight || defaultIntrinsicHeight);\n }\n\n function applyIntrinsicHeight(nextHeight) {\n const boundedHeight = Math.min(\n defaultIntrinsicHeight,\n Math.floor(nextHeight || defaultIntrinsicHeight)\n );\n const height = Math.max(320, boundedHeight);\n const viewportHeight = Math.max(0, height - chromeHeight);\n document.documentElement.style.setProperty(\"--agent-native-shell-height\", height + \"px\");\n document.documentElement.style.setProperty(\"--agent-native-viewport-height\", viewportHeight + \"px\");\n if (appFrame) appFrame.style.height = viewportHeight + \"px\";\n return height;\n }\n\n function parseToolResult(params) {\n if (!params) return {};\n if (params.result && typeof params.result === \"object\") {\n return parseToolResult(params.result);\n }\n if (params.toolResult && typeof params.toolResult === \"object\") {\n return parseToolResult(params.toolResult);\n }\n if (params.structuredContent && typeof params.structuredContent === \"object\") {\n return params.structuredContent;\n }\n const parts = Array.isArray(params.content) ? params.content : [];\n const textPart = parts.find((part) => part && part.type === \"text\" && typeof part.text === \"string\");\n const text = textPart ? textPart.text : \"\";\n if (params.isError && typeof text === \"string\" && text.trim()) {\n return { error: text.trim() };\n }\n return parseJson(text, {});\n }\n\n function metadataRecord(value) {\n const meta = value && typeof value === \"object\" && !Array.isArray(value)\n ? value._meta\n : null;\n return meta && typeof meta === \"object\" && !Array.isArray(meta)\n ? meta\n : null;\n }\n\n function toolResultMeta(params) {\n if (!params || typeof params !== \"object\") return {};\n const direct = metadataRecord(params);\n if (direct) return direct;\n if (params.result && typeof params.result === \"object\") {\n return toolResultMeta(params.result);\n }\n if (params.toolResult && typeof params.toolResult === \"object\") {\n return toolResultMeta(params.toolResult);\n }\n return {};\n }\n\n function openLinkRecordFrom(value) {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? value\n : {};\n }\n\n function openLinkWebUrlFrom(value) {\n const record = openLinkRecordFrom(value);\n return typeof record.webUrl === \"string\" ? record.webUrl : \"\";\n }\n\n function firstNonEmbedStartUrl(values) {\n for (const value of values) {\n if (typeof value === \"string\" && value && !isEmbedStartUrl(value)) return value;\n }\n return \"\";\n }\n\n function firstEmbedStartUrl(values) {\n for (const value of values) {\n if (typeof value === \"string\" && value && isEmbedStartUrl(value)) {\n return withChatBridgeParam(value);\n }\n }\n return \"\";\n }\n\n function openLinkFrom(params, data) {\n const meta = toolResultMeta(params);\n const openLink = meta[\"agent-native/openLink\"];\n const metaUrl = openLinkWebUrlFrom(openLink);\n const record = data && typeof data === \"object\" ? data : {};\n const structuredOpenLinkUrl = openLinkWebUrlFrom(record.openLink);\n return firstNonEmbedStartUrl([\n record.embedTargetPath,\n record.deepLinkUrl,\n record.deepLink,\n record.openUrl,\n structuredOpenLinkUrl,\n metaUrl,\n record.url\n ]);\n }\n\n function embedStartUrlFrom(params, data) {\n const meta = toolResultMeta(params);\n const embedStart = meta[\"agent-native/embedStart\"];\n const embedStartRecord =\n embedStart && typeof embedStart === \"object\" && !Array.isArray(embedStart)\n ? embedStart\n : {};\n const openLink = meta[\"agent-native/openLink\"];\n const metaUrl = openLinkWebUrlFrom(openLink);\n const record = data && typeof data === \"object\" ? data : {};\n return firstEmbedStartUrl([\n embedStartRecord.startUrl,\n record.embedStartUrl,\n record.startUrl,\n record.url,\n openLinkWebUrlFrom(record.openLink),\n metaUrl\n ]);\n }\n\n function hostState() {\n if (openAiBridge) {\n return {\n context: {\n displayMode: openAiBridge.displayMode,\n availableDisplayModes: typeof openAiBridge.requestDisplayMode === \"function\"\n ? [\"inline\", \"fullscreen\", \"pip\"]\n : [],\n maxHeight: openAiBridge.maxHeight,\n locale: openAiBridge.locale,\n theme: openAiBridge.theme,\n view: openAiBridge.view\n },\n capabilities: { openai: true },\n version: openAiBridge.userAgent\n };\n }\n return {\n context: app && app.getHostContext ? app.getHostContext() : undefined,\n capabilities: app && app.getHostCapabilities ? app.getHostCapabilities() : undefined,\n version: app && app.getHostVersion ? app.getHostVersion() : undefined\n };\n }\n\n function sendToAppFrame(message) {\n if (!appFrame || !appFrame.contentWindow) return;\n try { appFrame.contentWindow.postMessage(message, \"*\"); } catch {}\n }\n\n function notifyOuterMcpAppReady() {\n try {\n window.parent.postMessage({ type: \"agentNative.embeddedAppReady\" }, \"*\");\n } catch {}\n }\n\n function nextWrapperRequestId() {\n wrapperRequestId += 1;\n return \"mcp-wrapper-\" + Date.now() + \"-\" + wrapperRequestId;\n }\n\n function respondToWrapperRequest(requestId, result) {\n if (!requestId) return;\n sendToAppFrame({\n type: \"agentNative.mcpHost.response\",\n data: {\n requestId,\n ok: !!(result && result.ok),\n result: result || {}\n }\n });\n }\n\n function wrapperRpcRequest(method, params, timeoutMs) {\n return new Promise((resolve) => {\n const id = nextWrapperRequestId();\n const timer = window.setTimeout(() => {\n wrapperRequests.delete(id);\n resolve({ ok: false, error: \"MCP host bridge request timed out.\" });\n }, timeoutMs || wrapperRequestTimeoutMs);\n wrapperRequests.set(id, { resolve, timer });\n try {\n window.parent.postMessage(\n { jsonrpc: \"2.0\", id, method, params: params || {} },\n \"*\"\n );\n } catch (err) {\n wrapperRequests.delete(id);\n clearTimeout(timer);\n resolve({ ok: false, error: err && err.message ? err.message : String(err) });\n }\n });\n }\n\n function settleWrapperRpcResponse(message) {\n const id = typeof (message && message.id) === \"string\" ? message.id : \"\";\n if (!id) return false;\n const pending = wrapperRequests.get(id);\n if (!pending) return false;\n wrapperRequests.delete(id);\n clearTimeout(pending.timer);\n if (message.error) {\n pending.resolve({ ok: false, error: message.error });\n } else {\n pending.resolve({ ok: true, result: message.result });\n }\n return true;\n }\n\n function sendHostContext() {\n sendToAppFrame({ type: \"agentNative.mcpHostContext\", data: hostState() });\n }\n\n function sendFrameReadyMessages(frame) {\n const originPayload = { type: \"agentNative.frameOrigin\", origin: window.location.origin };\n frameReadyMessageDelays.forEach((delay) => {\n setTimeout(() => {\n try { frame.contentWindow && frame.contentWindow.postMessage(originPayload, \"*\"); } catch {}\n sendHostContext();\n }, delay);\n });\n }\n\n function withChatBridgeParam(value) {\n if (typeof value !== \"string\" || !value) return value;\n try {\n const base = \"http://agent-native.invalid\";\n const url = value.startsWith(\"/\") ? new URL(value, base) : new URL(value);\n url.searchParams.set(chatBridgeParam, \"1\");\n return value.startsWith(\"/\")\n ? url.pathname + url.search + url.hash\n : url.toString();\n } catch {\n return value;\n }\n }\n\n function embedSessionArgsFor(value) {\n const chrome = typeof toolInput.chrome === \"string\" ? toolInput.chrome : \"full\";\n return typeof value === \"string\" && value.startsWith(\"/\")\n ? { path: value, chrome }\n : { url: value, chrome };\n }\n\n function isEmbedStartUrl(value) {\n if (typeof value !== \"string\" || !value) return false;\n try {\n const url = new URL(value, window.location.href);\n return url.pathname.endsWith(\"/_agent-native/embed/start\");\n } catch {\n return false;\n }\n }\n\n function localPathFromUrl(url, includeToken) {\n const next = new URL(url.href);\n if (!includeToken) next.searchParams.delete(\"__an_embed_token\");\n return next.pathname + next.search + next.hash;\n }\n\n function rewriteRootRelativeHtmlUrls(html, appOrigin) {\n return String(html).replace(\n /\\\\b(src|href|poster|action)\\\\s*=\\\\s*([\"'])\\\\/(?!\\\\/)/gi,\n (_match, name, quote) => String(name) + \"=\" + quote + appOrigin + \"/\"\n );\n }\n\n function removeHtmlCspMeta(html) {\n return String(html).replace(\n /<meta\\\\s+[^>]*http-equiv\\\\s*=\\\\s*([\"'])?content-security-policy\\\\1?[^>]*>/gi,\n \"\"\n );\n }\n\n function embedConfigForAppUrl(appUrl) {\n const sanitizedTarget = localPathFromUrl(appUrl, false);\n return {\n origin: appUrl.origin,\n href: appUrl.href,\n baseHref: appUrl.origin + appUrl.pathname,\n target: sanitizedTarget,\n token: appUrl.searchParams.get(\"__an_embed_token\") || \"\",\n chatBridgeActive: appUrl.searchParams.get(chatBridgeParam) === \"1\",\n chatBridgeParam,\n embedTokenParam: \"__an_embed_token\",\n embedTargetHeader: \"x-agent-native-embed-target\"\n };\n }\n\n function externalOpenUrlForAppUrl(appUrl) {\n if (openUrl) return openUrl;\n try {\n const url = new URL(appUrl.href);\n url.searchParams.delete(\"embedded\");\n url.searchParams.delete(\"__an_embed_token\");\n url.searchParams.delete(chatBridgeParam);\n return url.toString();\n } catch (_err) {\n return \"\";\n }\n }\n\n function installExternalOpenControl(appUrl) {\n const href = externalOpenUrlForAppUrl(appUrl);\n if (!href || !document.body || document.getElementById(\"agent-native-external-open-control\")) {\n return;\n }\n const host = document.createElement(\"div\");\n host.id = \"agent-native-external-open-control\";\n host.style.position = \"fixed\";\n host.style.top = \"10px\";\n host.style.right = \"10px\";\n host.style.zIndex = \"2147483647\";\n host.style.pointerEvents = \"auto\";\n const root = host.attachShadow ? host.attachShadow({ mode: \"open\" }) : host;\n root.innerHTML =\n '<style>' +\n ':host{all:initial;}' +\n 'button{box-sizing:border-box;min-height:30px;border:1px solid color-mix(in srgb, CanvasText 18%, Canvas);border-radius:7px;background:Canvas;color:CanvasText;box-shadow:0 6px 22px color-mix(in srgb, CanvasText 14%, transparent);cursor:pointer;font:700 12px ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif;padding:0 10px;white-space:nowrap;}' +\n 'button:hover{background:color-mix(in srgb, CanvasText 6%, Canvas);}' +\n '</style>' +\n '<button type=\"button\">Open in new tab</button>';\n const button = root.querySelector(\"button\");\n if (button) {\n button.addEventListener(\"click\", (event) => {\n event.preventDefault();\n void openHostLink({ url: href });\n });\n }\n document.body.appendChild(host);\n }\n\n function installReactRefreshPreambleFallback() {\n window.__vite_plugin_react_preamble_installed__ = true;\n if (typeof window.$RefreshReg$ !== \"function\") {\n window.$RefreshReg$ = function() {};\n }\n if (typeof window.$RefreshSig$ !== \"function\") {\n window.$RefreshSig$ = function() {\n return function(type) {\n return type;\n };\n };\n }\n }\n\n function installExternalEmbedRuntime(config) {\n window.__AGENT_NATIVE_EXTERNAL_EMBED = config;\n installReactRefreshPreambleFallback();\n try {\n if (config.target) {\n window.history.replaceState(window.history.state, \"\", config.target);\n }\n } catch (_err) {}\n try {\n if (config.token) {\n sessionStorage.setItem(\"agent-native:embed-auth-token\", config.token);\n }\n if (config.chatBridgeActive && config.token) {\n sessionStorage.setItem(\"agent-native:mcp-chat-bridge\", config.token);\n }\n } catch (_err) {}\n if (window.__agentNativeExternalEmbedRuntimeInstalled) return;\n window.__agentNativeExternalEmbedRuntimeInstalled = true;\n function appOrigin() {\n try {\n return new URL(config.origin).origin;\n } catch (_err) {\n return \"\";\n }\n }\n function targetPath() {\n return config.target || location.pathname + location.search;\n }\n function rewrittenUrl(value, appendToken) {\n const origin = appOrigin();\n if (!origin) return null;\n let url;\n try {\n url = new URL(value, location.href);\n } catch (_err) {\n return null;\n }\n if (url.origin !== location.origin && url.origin !== origin) return null;\n if (url.origin !== origin) {\n const app = new URL(origin);\n url.protocol = app.protocol;\n url.host = app.host;\n }\n if (appendToken && config.token && url.pathname === \"/_agent-native/events\") {\n url.searchParams.set(config.embedTokenParam, config.token);\n }\n return url.toString();\n }\n function authHeaders(input, init) {\n const headers = new Headers(\n init && init.headers ? init.headers : input instanceof Request ? input.headers : undefined\n );\n if (config.token && !headers.has(\"Authorization\")) {\n headers.set(\"Authorization\", \"Bearer \" + config.token);\n }\n if (!headers.has(config.embedTargetHeader)) {\n headers.set(config.embedTargetHeader, targetPath());\n }\n return headers;\n }\n if (typeof fetch === \"function\") {\n const originalFetch = fetch.bind(window);\n window.fetch = function(input, init) {\n const raw = input instanceof Request ? input.url : String(input);\n const url = rewrittenUrl(raw, false);\n if (!url) return originalFetch(input, init);\n const nextInit = Object.assign({}, init || {}, {\n headers: authHeaders(input, init),\n credentials: \"omit\"\n });\n if (input instanceof Request) {\n return originalFetch(new Request(url, input), nextInit);\n }\n return originalFetch(url, nextInit);\n };\n }\n if (typeof XMLHttpRequest !== \"undefined\") {\n const originalOpen = XMLHttpRequest.prototype.open;\n const originalSend = XMLHttpRequest.prototype.send;\n XMLHttpRequest.prototype.open = function(method, url) {\n const rewritten = rewrittenUrl(url, false);\n this.__agentNativeExternalEmbed = !!rewritten;\n return originalOpen.call(\n this,\n method,\n rewritten || url,\n arguments.length > 2 ? arguments[2] : true,\n arguments[3],\n arguments[4]\n );\n };\n XMLHttpRequest.prototype.send = function(body) {\n if (this.__agentNativeExternalEmbed) {\n try {\n if (config.token) this.setRequestHeader(\"Authorization\", \"Bearer \" + config.token);\n this.setRequestHeader(config.embedTargetHeader, targetPath());\n } catch (_err) {}\n }\n return originalSend.call(this, body);\n };\n }\n if (typeof EventSource !== \"undefined\") {\n const OriginalEventSource = EventSource;\n window.EventSource = function(url, options) {\n return new OriginalEventSource(rewrittenUrl(url, true) || url, options);\n };\n window.EventSource.prototype = OriginalEventSource.prototype;\n }\n }\n\n function copyDocumentElementAttributes(source) {\n const target = document.documentElement;\n for (const attr of Array.from(target.attributes)) {\n target.removeAttribute(attr.name);\n }\n for (const attr of Array.from(source.attributes)) {\n target.setAttribute(attr.name, attr.value);\n }\n }\n\n function importChildren(source, target) {\n target.replaceChildren(\n ...Array.from(source.childNodes).map((node) => document.importNode(node, true))\n );\n }\n\n function importHeadChildrenWithBase(source, baseHref) {\n const base = document.createElement(\"base\");\n base.href = baseHref;\n const nodes = Array.from(source.childNodes).filter((node) => {\n return !(\n node.nodeType === 1 &&\n String(node.nodeName || \"\").toLowerCase() === \"base\"\n );\n });\n document.head.replaceChildren(\n base,\n ...nodes.map((node) => document.importNode(node, true))\n );\n }\n\n function isModuleScript(script) {\n return (script.getAttribute(\"type\") || \"\").trim().toLowerCase() === \"module\";\n }\n\n function isRunnableClassicScript(script) {\n const type = (script.getAttribute(\"type\") || \"\").trim().toLowerCase();\n return !type || type === \"text/javascript\" || type === \"application/javascript\";\n }\n\n function runClassicScript(script) {\n const next = document.createElement(\"script\");\n for (const attr of Array.from(script.attributes)) {\n if (attr.name === \"type\") continue;\n next.setAttribute(attr.name, attr.value);\n }\n if (script.src) {\n next.src = script.src;\n } else {\n next.textContent = script.textContent || \"\";\n }\n document.body.appendChild(next);\n next.remove();\n }\n\n function isEmbedRuntimeModulePath(pathname) {\n if (typeof pathname !== \"string\" || !pathname) return false;\n return /(?:^|\\\\/)(?:@(?:id|vite|fs|react-refresh)|app|node_modules|packages|src)(?:\\\\/|$)/.test(pathname) ||\n /(?:^|\\\\/)__x00__virtual:/.test(pathname) ||\n pathname.includes(\"virtual:react-router\");\n }\n\n function appendEmbedParamsToAppUrl(url, config) {\n if (isEmbedRuntimeModulePath(url.pathname)) return url;\n if (config.token) url.searchParams.set(config.embedTokenParam, config.token);\n if (config.chatBridgeActive) url.searchParams.set(config.chatBridgeParam, \"1\");\n return url;\n }\n\n function rootRelativeSpecifierToAppUrl(specifier, config) {\n if (typeof specifier !== \"string\" || !specifier.startsWith(\"/\") || specifier.startsWith(\"//\")) {\n return specifier;\n }\n try {\n const url = new URL(specifier, config.origin);\n return appendEmbedParamsToAppUrl(url, config).toString();\n } catch (_err) {\n return specifier;\n }\n }\n\n function rootRelativeSpecifiersToAbsolute(code, config) {\n return String(code).replace(/([\"'])\\\\/(?!\\\\/)([^\"']*)/g, (_match, quote, rest) => {\n return quote + rootRelativeSpecifierToAppUrl(\"/\" + rest, config);\n });\n }\n\n function relativeSpecifierToAppUrl(specifier, config, baseUrl) {\n if (typeof specifier !== \"string\" || !/^\\\\.\\\\.?\\\\//.test(specifier)) {\n return specifier;\n }\n try {\n const url = new URL(specifier, baseUrl || config.baseHref);\n if (url.origin === config.origin) {\n appendEmbedParamsToAppUrl(url, config);\n }\n return url.toString();\n } catch (_err) {\n return specifier;\n }\n }\n\n function relativeModuleSpecifiersToAbsolute(code, config, baseUrl) {\n return String(code)\n .replace(/(\\\\bimport\\\\s+(?:[^\"']+?\\\\s+from\\\\s+)?)([\"'])(\\\\.\\\\.?\\\\/[^\"']*)\\\\2/g, (_match, prefix, quote, specifier) => {\n return prefix + quote + relativeSpecifierToAppUrl(specifier, config, baseUrl) + quote;\n })\n .replace(/(\\\\bimport\\\\s*\\\\(\\\\s*)([\"'])(\\\\.\\\\.?\\\\/[^\"']*)\\\\2/g, (_match, prefix, quote, specifier) => {\n return prefix + quote + relativeSpecifierToAppUrl(specifier, config, baseUrl) + quote;\n })\n .replace(/(\\\\bexport\\\\s+[^\"']*?\\\\s+from\\\\s+)([\"'])(\\\\.\\\\.?\\\\/[^\"']*)\\\\2/g, (_match, prefix, quote, specifier) => {\n return prefix + quote + relativeSpecifierToAppUrl(specifier, config, baseUrl) + quote;\n });\n }\n\n function stripDevOnlyModuleImports(code) {\n return String(code).replace(\n /\\\\bimport\\\\s+(?:[^\"']+\\\\s+from\\\\s+)?[\"'][^\"']*(?:virtual:react-router\\\\/inject-hmr-runtime|__x00__virtual:react-router\\\\/inject-hmr-runtime)[^\"']*[\"']\\\\s*;?/g,\n \"\"\n );\n }\n\n function namedImportBindings(specifierList) {\n return String(specifierList)\n .split(\",\")\n .map((part) => {\n const trimmed = part.trim();\n if (!trimmed) return \"\";\n return trimmed.replace(\n /^([A-Za-z_$][\\\\w$]*)\\\\s+as\\\\s+([A-Za-z_$][\\\\w$]*)$/,\n \"$1: $2\"\n );\n })\n .filter(Boolean)\n .join(\", \");\n }\n\n function moduleCodeToClassicAsync(code, config, baseUrl) {\n return relativeModuleSpecifiersToAbsolute(\n rootRelativeSpecifiersToAbsolute(stripDevOnlyModuleImports(code), config),\n config,\n baseUrl\n )\n .replace(\n /\\\\bimport\\\\s+([A-Za-z_$][\\\\w$]*)\\\\s*,\\\\s*\\\\*\\\\s+as\\\\s+([A-Za-z_$][\\\\w$]*)\\\\s+from\\\\s+([\"'][^\"']+[\"'])\\\\s*;?/g,\n \"const $2 = await import($3); const $1 = $2.default;\"\n )\n .replace(\n /\\\\bimport\\\\s+([A-Za-z_$][\\\\w$]*)\\\\s*,\\\\s*\\\\{([\\\\s\\\\S]*?)\\\\}\\\\s*from\\\\s+([\"'][^\"']+[\"'])\\\\s*;?/g,\n (_match, defaultName, specifiers, source) =>\n \"const { default: \" +\n defaultName +\n (namedImportBindings(specifiers) ? \", \" + namedImportBindings(specifiers) : \"\") +\n \" } = await import(\" +\n source +\n \");\"\n )\n .replace(\n /\\\\bimport\\\\s+\\\\{([\\\\s\\\\S]*?)\\\\}\\\\s*from\\\\s+([\"'][^\"']+[\"'])\\\\s*;?/g,\n (_match, specifiers, source) =>\n \"const { \" + namedImportBindings(specifiers) + \" } = await import(\" + source + \");\"\n )\n .replace(\n /\\\\bimport\\\\s+\\\\*\\\\s+as\\\\s+([A-Za-z_$][\\\\w$]*)\\\\s+from\\\\s+([\"'][^\"']+[\"'])\\\\s*;?/g,\n \"const $1 = await import($2);\"\n )\n .replace(\n /\\\\bimport\\\\s+([A-Za-z_$][\\\\w$]*)\\\\s+from\\\\s+([\"'][^\"']+[\"'])\\\\s*;?/g,\n \"const { default: $1 } = await import($2);\"\n )\n .replace(/\\\\bimport\\\\s+([\"'][^\"']+[\"'])\\\\s*;?/g, \"await import($1);\")\n .replace(/\\\\bimport\\\\(([\"'][^\"']+[\"'])\\\\)\\\\s*;?/g, \"await import($1);\");\n }\n\n function scriptSourceUrl(script, config) {\n const raw = script.getAttribute(\"src\") || \"\";\n if (!raw) return \"\";\n try {\n const url = new URL(raw, config.baseHref);\n if (url.origin === config.origin) {\n appendEmbedParamsToAppUrl(url, config);\n }\n return url.toString();\n } catch (_err) {\n return raw;\n }\n }\n\n async function moduleScriptCode(script, config) {\n const src = scriptSourceUrl(script, config);\n if (!src) return script.textContent || \"\";\n const response = await fetch(src, {\n credentials: \"omit\",\n headers: { Accept: \"text/javascript, application/javascript, */*\" }\n });\n if (!response.ok) {\n throw new Error(\"Module script returned HTTP \" + response.status + \".\");\n }\n return await response.text();\n }\n\n async function runModuleScriptAsClassic(script, config) {\n const sourceUrl = scriptSourceUrl(script, config) || config.baseHref;\n const code = moduleCodeToClassicAsync(\n await moduleScriptCode(script, config),\n config,\n sourceUrl\n );\n const runner = document.createElement(\"script\");\n runner.textContent =\n \"(async()=>{\" +\n code +\n \"})().catch((err)=>{console.error('[agent-native] transplanted app module failed',err);document.body.setAttribute('data-agent-native-hydration-error',String(err&&err.message||err));});\";\n document.body.appendChild(runner);\n runner.remove();\n }\n\n async function mountTransplantedHtml(html, appUrl) {\n const config = embedConfigForAppUrl(appUrl);\n installExternalEmbedRuntime(config);\n const parsed = new DOMParser().parseFromString(\n rewriteRootRelativeHtmlUrls(removeHtmlCspMeta(html), appUrl.origin),\n \"text/html\"\n );\n const scripts = Array.from(parsed.querySelectorAll(\"script\"));\n copyDocumentElementAttributes(parsed.documentElement);\n importHeadChildrenWithBase(parsed.head, config.baseHref);\n importChildren(parsed.body, document.body);\n installExternalOpenControl(appUrl);\n for (const script of scripts) {\n if (isRunnableClassicScript(script)) runClassicScript(script);\n }\n for (const script of scripts) {\n if (isModuleScript(script)) await runModuleScriptAsClassic(script, config);\n }\n }\n\n function absoluteUrl(value, base) {\n try {\n return new URL(value, base).toString();\n } catch {\n return \"\";\n }\n }\n\n async function resolveTransplantAppDocumentSource(src) {\n if (!isEmbedStartUrl(src)) {\n return { url: new URL(src), response: null };\n }\n const response = await fetch(src, {\n credentials: \"omit\",\n redirect: \"follow\",\n headers: {\n Accept: \"application/json\",\n \"X-Agent-Native-Embed-Transplant\": \"1\"\n }\n });\n const contentType = response.headers.get(\"content-type\") || \"\";\n if (response.ok && /\\\\bapplication\\\\/json\\\\b/i.test(contentType)) {\n const data = await response.json();\n const location = typeof data.location === \"string\" ? data.location : \"\";\n const url = absoluteUrl(location, src);\n if (url) return { url: new URL(withChatBridgeParam(url)), response: null };\n throw new Error(\"Embedded app did not return a launch URL.\");\n }\n return {\n url: new URL(response.url || src),\n response\n };\n }\n\n async function transplantAppDocument(src) {\n clearFrameReadyTimer();\n clearFrameLoadTimer();\n appFrame = null;\n lastFrameSrc = src;\n setMessage(\"Loading app\");\n const source = await resolveTransplantAppDocumentSource(src);\n const response = source.response || await fetch(source.url.href, {\n credentials: \"omit\",\n redirect: \"follow\",\n headers: { Accept: \"text/html\" }\n });\n if (!response.ok) {\n if (response.status === 401 && isEmbedStartUrl(src)) {\n reportEmbedError(\n \"transplant-auth\",\n \"Embedded app session expired (HTTP 401).\",\n \"Opaque-origin sandbox could not authenticate the embed.\",\n 401\n );\n refreshExpiredEmbedSession();\n return;\n }\n reportEmbedError(\n \"transplant-http\",\n \"Embedded app returned HTTP \" + response.status + \".\",\n undefined,\n response.status\n );\n throw new Error(\"Embedded app returned HTTP \" + response.status + \".\");\n }\n const html = await response.text();\n const appUrl = source.url || new URL(response.url || src);\n try {\n window.history.replaceState(window.history.state, \"\", localPathFromUrl(appUrl, false));\n } catch {}\n await mountTransplantedHtml(html, appUrl);\n embedSessionRefreshAttempts = 0;\n notifyHostHeightRepeatedly();\n }\n\n function wantsEmbed() {\n if (toolInput.embed === false || toolInput.embed === \"false\") return false;\n if (embedByDefault) return true;\n return toolInput.embed === true || toolInput.embed === \"true\";\n }\n\n function renderModeSource() {\n const input = objectValue(toolInput);\n const result = objectValue(toolResultData);\n return {\n mode: typeof input.embedMode === \"string\"\n ? input.embedMode\n : typeof input.renderMode === \"string\"\n ? input.renderMode\n : typeof result.embedMode === \"string\"\n ? result.embedMode\n : typeof result.renderMode === \"string\"\n ? result.renderMode\n : \"\",\n frame: typeof input.frame === \"string\"\n ? input.frame\n : typeof result.frame === \"string\"\n ? result.frame\n : \"\",\n nested: input.nested === true || result.nested === true\n };\n }\n\n function supportedDisplayMode(mode) {\n if (openAiBridge && typeof openAiBridge.requestDisplayMode === \"function\") {\n return mode === \"inline\" || mode === \"fullscreen\" || mode === \"pip\";\n }\n const modes = hostState().context && hostState().context.availableDisplayModes;\n return Array.isArray(modes) && modes.includes(mode);\n }\n\n async function requestHostDisplayMode(mode) {\n let result;\n if (openAiBridge && typeof openAiBridge.requestDisplayMode === \"function\") {\n result = await openAiBridge.requestDisplayMode({ mode });\n } else {\n if (!app || typeof app.requestDisplayMode !== \"function\") {\n throw new Error(\"Display mode changes are not available in this host.\");\n }\n result = await app.requestDisplayMode({ mode });\n }\n updateDisplayButton();\n sendHostContext();\n return result;\n }\n\n function updateDisplayButton() {\n const context = hostState().context || {};\n const nextMode = context.displayMode === \"fullscreen\" ? \"inline\" : \"fullscreen\";\n const supported = supportedDisplayMode(nextMode);\n displayButton.hidden = !supported;\n displayButton.disabled = !supported;\n displayButton.textContent = nextMode === \"fullscreen\" ? \"Fullscreen\" : \"Inline\";\n displayButton.onclick = () => {\n if (!supportedDisplayMode(nextMode)) return;\n void requestHostDisplayMode(nextMode).catch((err) => {\n console.warn(\"[agent-native] MCP host rejected display mode request\", err);\n });\n };\n }\n\n function setMessage(message) {\n stage.innerHTML = '<div class=\"message\">' + esc(message) + '</div>';\n }\n\n function clearFrameReadyTimer() {\n if (!appFrameReadyTimer) return;\n clearTimeout(appFrameReadyTimer);\n appFrameReadyTimer = null;\n }\n\n function clearFrameLoadTimer() {\n if (!appFrameLoadTimer) return;\n clearTimeout(appFrameLoadTimer);\n appFrameLoadTimer = null;\n }\n\n function startFrameReadyTimer(frame) {\n clearFrameReadyTimer();\n appFrameReadyTimer = setTimeout(() => {\n if (!appFrameReady && appFrame === frame) renderFrameFallback();\n }, frameReadyTimeoutMs);\n }\n\n // Best-effort telemetry sink so inline-embed failures are visible in\n // Sentry (handshake timeout, transplant fetch status/CORS, auth, CSP).\n // The shell is a sandboxed opaque-origin iframe, so it POSTs to the app\n // origin's CORS-open /_agent-native/mcp/embed-error route, derived from the\n // known app URLs. Deduped per stage+message so a retry loop can't spam.\n const reportedEmbedErrorKeys = new Set();\n let embedErrorReportCount = 0;\n function embedReportOrigin() {\n for (const value of [openStartUrl, openUrl, lastFrameSrc]) {\n if (typeof value === \"string\" && value) {\n try { return new URL(value, window.location.href).origin; } catch {}\n }\n }\n return \"\";\n }\n function reportEmbedError(stage, message, detail, status) {\n try {\n const key = String(stage) + \"|\" + String(message || \"\");\n if (reportedEmbedErrorKeys.has(key) || embedErrorReportCount >= 8) return;\n reportedEmbedErrorKeys.add(key);\n embedErrorReportCount += 1;\n const origin = embedReportOrigin();\n if (!origin) return;\n let renderMode = \"\";\n try { renderMode = renderModeSource().mode || \"\"; } catch {}\n const body = JSON.stringify({\n stage: String(stage || \"\"),\n message: String(message || \"\").slice(0, 500),\n detail: detail ? String(detail).slice(0, 1200) : undefined,\n url: openStartUrl || openUrl || lastFrameSrc || \"\",\n status: typeof status === \"number\" ? status : undefined,\n host: window.location.hostname || \"\",\n renderMode: renderMode,\n bridge: openAiBridge ? \"openai\" : app ? \"native\" : \"none\",\n userAgent: navigator.userAgent || \"\"\n });\n fetch(origin + \"/_agent-native/mcp/embed-error\", {\n method: \"POST\",\n credentials: \"omit\",\n keepalive: true,\n headers: { \"Content-Type\": \"application/json\" },\n body: body\n }).catch(() => {});\n } catch {}\n }\n\n function renderFrameFallback() {\n clearFrameReadyTimer();\n clearFrameLoadTimer();\n appFrame = null;\n const fallbackCopy = openUrl\n ? \"This chat host did not allow the embedded app frame to load inline. You can still open the same app route through the host or use the URL below.\"\n : \"This chat host did not allow the embedded app frame to load inline.\";\n reportEmbedError(\"frame-fallback\", fallbackCopy);\n stage.innerHTML =\n '<div class=\"fallback\">' +\n '<div class=\"fallback-title\">Open this app in its own tab</div>' +\n '<div class=\"fallback-copy\">' + esc(fallbackCopy) + '</div>' +\n '<div class=\"fallback-actions\">' +\n '<button type=\"button\" class=\"primary\" data-fallback-open>Open in new tab</button>' +\n '<button type=\"button\" data-fallback-retry>Try inline again</button>' +\n '</div>' +\n (openUrl ? '<a class=\"fallback-url\" href=\"' + esc(openUrl) + '\" target=\"_blank\" rel=\"noreferrer\">' + esc(openUrl) + '</a>' : '') +\n '</div>';\n const fallbackOpen = stage.querySelector(\"[data-fallback-open]\");\n const fallbackRetry = stage.querySelector(\"[data-fallback-retry]\");\n if (fallbackOpen) {\n fallbackOpen.disabled = !openUrl;\n fallbackOpen.onclick = () => {\n if (openUrl) void openFallbackExternal();\n };\n }\n if (fallbackRetry) {\n fallbackRetry.disabled = !lastFrameSrc;\n fallbackRetry.onclick = () => {\n if (lastFrameSrc) renderFrame(lastFrameSrc);\n };\n }\n }\n\n function renderAppLaunchError(message) {\n clearFrameReadyTimer();\n clearFrameLoadTimer();\n appFrame = null;\n const fallbackCopy = openUrl\n ? \"The inline MCP app could not load in this chat host. You can open the same app route in a new tab or retry the inline load.\"\n : \"The inline MCP app could not load in this chat host.\";\n reportEmbedError(\"app-launch-error\", message || fallbackCopy, message);\n const copyHtml = message\n ? '<div>' + esc(message) + '</div><div>' + esc(fallbackCopy) + '</div>'\n : esc(fallbackCopy);\n stage.innerHTML =\n '<div class=\"fallback\">' +\n '<div class=\"fallback-title\">App did not load</div>' +\n '<div class=\"fallback-copy\">' + copyHtml + '</div>' +\n '<div class=\"fallback-actions\">' +\n '<button type=\"button\" class=\"primary\" data-fallback-open>Open in new tab</button>' +\n '<button type=\"button\" data-fallback-retry>Retry</button>' +\n '</div>' +\n (openUrl ? '<a class=\"fallback-url\" href=\"' + esc(openUrl) + '\" target=\"_blank\" rel=\"noreferrer\">' + esc(openUrl) + '</a>' : '') +\n '</div>';\n const fallbackOpen = stage.querySelector(\"[data-fallback-open]\");\n const fallbackRetry = stage.querySelector(\"[data-fallback-retry]\");\n if (fallbackOpen) {\n fallbackOpen.disabled = !openUrl;\n fallbackOpen.onclick = () => {\n if (openUrl) void openHostLink({ url: openUrl });\n };\n }\n if (fallbackRetry) {\n fallbackRetry.onclick = () => {\n startedFor = \"\";\n void launchEmbed();\n };\n }\n }\n\n async function openFallbackExternal() {\n if (!openUrl) return;\n let url = withChatBridgeParam(openUrl);\n try {\n if (url) {\n const result = await callEmbedSessionTool(embedSessionArgsFor(url));\n const data = parseToolResult(result);\n if (typeof data.startUrl === \"string\" && data.startUrl) {\n url = withChatBridgeParam(data.startUrl);\n }\n }\n } catch (err) {\n console.warn(\"[agent-native] MCP fallback could not mint a fresh app session\", err);\n }\n await openHostLink({ url });\n }\n\n function renderFrame(src) {\n clearFrameReadyTimer();\n clearFrameLoadTimer();\n const frame = document.createElement(\"iframe\");\n frame.title = body.dataset.iframeTitle || \"Agent Native app\";\n frame.src = src;\n frame.allow = \"clipboard-read; clipboard-write\";\n appFrame = frame;\n appFrameReady = false;\n lastFrameSrc = src;\n frame.addEventListener(\"load\", () => {\n if (appFrame !== frame) return;\n clearFrameLoadTimer();\n notifyOuterMcpAppReady();\n sendFrameReadyMessages(frame);\n startFrameReadyTimer(frame);\n });\n stage.replaceChildren(frame);\n notifyHostHeight();\n appFrameLoadTimer = setTimeout(() => {\n if (!appFrameReady && appFrame === frame) renderFrameFallback();\n }, frameLoadTimeoutMs);\n }\n\n function refreshExpiredEmbedSession() {\n clearFrameReadyTimer();\n clearFrameLoadTimer();\n appFrameReady = false;\n if (!openUrl) {\n renderFrameFallback();\n return;\n }\n if (embedSessionRefreshAttempts >= maxEmbedSessionRefreshAttempts) {\n renderAppLaunchError(\n \"Embedded app session expired. Reopen the app to mint a fresh session.\"\n );\n return;\n }\n embedSessionRefreshAttempts += 1;\n openStartUrl = \"\";\n startedFor = \"\";\n lastFrameSrc = \"\";\n setMessage(\"Refreshing app session\");\n void launchEmbed();\n }\n\n function shouldSelfNavigateToApp() {\n const render = renderModeSource();\n const mode = render.mode;\n if (isClaudeMcpContentHost()) return true;\n if (mode === \"iframe\" || mode === \"nested\") return false;\n if (render.nested || render.frame === \"iframe\") return false;\n return true;\n }\n\n function shouldTransplantAppDocument() {\n const render = renderModeSource();\n const mode = render.mode;\n if (mode === \"iframe\" || mode === \"nested\" || render.frame === \"iframe\" || render.nested) {\n return false;\n }\n return (\n isClaudeMcpContentHost() ||\n isChatGptSandboxHost() ||\n mode === \"transplant\" ||\n render.frame === \"transplant\"\n );\n }\n\n function isClaudeMcpContentHost() {\n try {\n return /(^|\\\\.)claudemcpcontent\\\\.com$/i.test(window.location.hostname || \"\");\n } catch {\n return false;\n }\n }\n\n function isChatGptSandboxHost() {\n try {\n const host = window.location.hostname || \"\";\n const appParam = new URL(window.location.href).searchParams.get(\"app\");\n return /^(?:[^.]+\\\\.)?web-sandbox\\\\.oaiusercontent\\\\.com$/i.test(host) || appParam === \"chatgpt\";\n } catch {\n return false;\n }\n }\n\n function shouldRenderControlledAppFrame() {\n return !!openAiBridge || !!app || isChatGptSandboxHost();\n }\n\n function shouldDirectRenderKnownAppRoute(src) {\n return !!app && !openAiBridge && !isEmbedStartUrl(src) && !shouldTransplantAppDocument();\n }\n\n function isCurrentFrameUrl(src) {\n try {\n return new URL(src, window.location.href).href === window.location.href;\n } catch {\n return false;\n }\n }\n\n function navigateToAppFrame(src) {\n if (isCurrentFrameUrl(src)) {\n clearFrameReadyTimer();\n clearFrameLoadTimer();\n setMessage(\"App opened\");\n notifyHostHeightRepeatedly();\n return;\n }\n clearFrameReadyTimer();\n clearFrameLoadTimer();\n appFrame = null;\n lastFrameSrc = src;\n setMessage(\"Opening app\");\n try {\n window.location.replace(src);\n } catch (err) {\n console.warn(\"[agent-native] MCP app self-navigation failed\", err);\n renderFrameFallback();\n }\n }\n\n async function ensureHostAppConnected() {\n if (!app || typeof app.connect !== \"function\") return;\n if (!appConnectPromise) {\n appConnectPromise = Promise.resolve(app.connect())\n .then(async (value) => {\n // Let the host process ui/notifications/initialized before follow-up calls.\n await new Promise((resolve) => window.setTimeout(resolve, 0));\n await new Promise((resolve) => window.setTimeout(resolve, 0));\n return value;\n })\n .catch((err) => {\n appConnectPromise = null;\n throw err;\n });\n }\n await appConnectPromise;\n }\n\n async function updateHostModelContext(data) {\n const params = {};\n if (Array.isArray(data && data.content)) params.content = data.content;\n if (data && data.structuredContent && typeof data.structuredContent === \"object\") {\n params.structuredContent = data.structuredContent;\n }\n if (openAiBridge && typeof openAiBridge.setWidgetState === \"function\") {\n openAiBridge.setWidgetState({\n ...objectValue(openAiBridge.widgetState),\n agentNativeModelContext: params\n });\n return { ok: true };\n }\n if (!app || typeof app.updateModelContext !== \"function\") return { ok: false };\n await ensureHostAppConnected();\n await app.updateModelContext(params);\n return { ok: true };\n }\n\n async function openHostLink(data) {\n const url = typeof (data && data.url) === \"string\" ? data.url : \"\";\n if (!url) return { isError: true };\n if (openAiBridge && typeof openAiBridge.openExternal === \"function\") {\n return await openAiBridge.openExternal({ href: url, redirectUrl: false });\n }\n if (app && typeof app.openLink === \"function\") {\n return await app.openLink({ url });\n }\n window.open(url, \"_blank\", \"noopener,noreferrer\");\n return { ok: true };\n }\n\n function notifyHostHeight() {\n const height = applyIntrinsicHeight(visibleIntrinsicHeight());\n if (!openAiBridge || typeof openAiBridge.notifyIntrinsicHeight !== \"function\") {\n if (app && typeof app.sendSizeChanged === \"function\") {\n try {\n app.sendSizeChanged({ height });\n } catch (err) {\n console.warn(\"[agent-native] MCP host rejected size update\", err);\n }\n }\n return;\n }\n try {\n openAiBridge.notifyIntrinsicHeight({ height });\n } catch (err) {\n console.warn(\"[agent-native] ChatGPT rejected intrinsic height update\", err);\n }\n }\n\n function respondToAppFrame(requestId, work) {\n if (!requestId) return;\n Promise.resolve(work)\n .then((result) => {\n sendToAppFrame({\n type: \"agentNative.mcpHost.response\",\n data: { requestId, ok: true, result }\n });\n })\n .catch((err) => {\n sendToAppFrame({\n type: \"agentNative.mcpHost.response\",\n data: {\n requestId,\n ok: false,\n error: err && err.message ? err.message : String(err)\n }\n });\n });\n }\n\n async function sendHostChat(chat) {\n const requestId = typeof (chat && chat.requestId) === \"string\" ? chat.requestId : \"\";\n if (!chat || chat.submit === false) return;\n const message = typeof chat.message === \"string\" ? chat.message : \"\";\n if (!message.trim()) return;\n const context = typeof chat.context === \"string\" ? chat.context.trim() : \"\";\n const content = Array.isArray(chat.content) && chat.content.length\n ? chat.content\n : [{ type: \"text\", text: message }];\n const structuredContent =\n chat && chat.structuredContent !== undefined\n ? chat.structuredContent\n : undefined;\n try {\n const contextContent = context\n ? [{ type: \"text\", text: context }, ...content.filter((part) => part && part.type !== \"text\")]\n : content.filter((part) => part && part.type !== \"text\");\n const modelContext = {\n content: contextContent,\n ...(structuredContent !== undefined ? { structuredContent } : {})\n };\n if (openAiBridge && typeof openAiBridge.setWidgetState === \"function\") {\n openAiBridge.setWidgetState({\n ...objectValue(openAiBridge.widgetState),\n agentNativeChatContext: context || null,\n agentNativeModelContext: modelContext\n });\n } else if (app && typeof app.updateModelContext === \"function\") {\n await ensureHostAppConnected();\n await app.updateModelContext(modelContext);\n }\n } catch (err) {\n console.warn(\"[agent-native] MCP host rejected model context update\", err);\n }\n try {\n if (openAiBridge && typeof openAiBridge.sendFollowUpMessage === \"function\") {\n await openAiBridge.sendFollowUpMessage({\n prompt: message,\n scrollToBottom: true\n });\n respondToWrapperRequest(requestId, { ok: true });\n return;\n }\n let result = null;\n if (app && typeof app.sendMessage === \"function\") {\n await ensureHostAppConnected();\n result = await app.sendMessage({\n role: \"user\",\n content\n });\n } else {\n result = await wrapperRpcRequest(\"ui/message\", {\n role: \"user\",\n content\n });\n }\n if (result && result.isError) {\n console.warn(\"[agent-native] MCP host rejected chat message\", result);\n respondToWrapperRequest(requestId, { ok: false, result });\n return;\n }\n if (result && result.ok === false) {\n console.warn(\"[agent-native] MCP host chat bridge failed\", result);\n respondToWrapperRequest(requestId, { ok: false, result });\n return;\n }\n respondToWrapperRequest(requestId, { ok: true, result });\n } catch (err) {\n console.warn(\"[agent-native] MCP host chat bridge failed\", err);\n respondToWrapperRequest(requestId, { ok: false, error: err && err.message ? err.message : String(err) });\n }\n }\n\n window.addEventListener(\"message\", (event) => {\n if (event.source !== window.parent) return;\n const message = event.data;\n if (!message || message.jsonrpc !== \"2.0\") return;\n settleWrapperRpcResponse(message);\n });\n\n window.addEventListener(\"message\", (event) => {\n if (!appFrame || event.source !== appFrame.contentWindow) return;\n if (!event.data) return;\n const data = event.data.data || {};\n if (event.data.type === \"agentNative.embeddedAppReady\") {\n appFrameReady = true;\n embedSessionRefreshAttempts = 0;\n clearFrameLoadTimer();\n clearFrameReadyTimer();\n notifyOuterMcpAppReady();\n return;\n }\n if (event.data.type === \"agentNative.embedSessionExpired\") {\n refreshExpiredEmbedSession();\n return;\n }\n if (event.data.type === \"agentNative.submitChat\") {\n void sendHostChat(data);\n return;\n }\n if (event.data.type === \"agentNative.mcpHost.updateModelContext\") {\n respondToAppFrame(data.requestId, updateHostModelContext(data));\n return;\n }\n if (event.data.type === \"agentNative.mcpHost.openLink\") {\n respondToAppFrame(data.requestId, openHostLink(data));\n return;\n }\n if (event.data.type === \"agentNative.mcpHost.requestDisplayMode\") {\n respondToAppFrame(data.requestId, requestHostDisplayMode(data.mode));\n }\n });\n\n function notifyHostHeightSoon() {\n requestAnimationFrame(() => notifyHostHeight());\n }\n\n function notifyHostHeightRepeatedly() {\n notifyHostHeight();\n [0, 250, 1000, 2500].forEach((delay) => {\n setTimeout(() => notifyHostHeight(), delay);\n });\n }\n\n window.addEventListener(\"resize\", notifyHostHeightSoon, { passive: true });\n if (window.visualViewport) {\n window.visualViewport.addEventListener(\"resize\", notifyHostHeightSoon, { passive: true });\n }\n\n async function launchEmbed() {\n let launchUrl = openStartUrl || openUrl;\n if (!launchUrl) {\n renderAppLaunchError(\"Open link was not available.\");\n return;\n }\n if (!wantsEmbed()) {\n setMessage(\"Ready to open.\");\n return;\n }\n setMessage(\"Loading app\");\n try {\n const selfNavigate = shouldSelfNavigateToApp();\n if (startedFor === launchUrl) return;\n startedFor = launchUrl;\n const embedUrl = withChatBridgeParam(launchUrl);\n if (selfNavigate && isEmbedStartUrl(embedUrl)) {\n if (shouldTransplantAppDocument()) {\n await transplantAppDocument(embedUrl);\n } else if (shouldRenderControlledAppFrame()) {\n renderFrame(embedUrl);\n } else {\n navigateToAppFrame(embedUrl);\n }\n return;\n }\n if (!selfNavigate && isEmbedStartUrl(embedUrl)) {\n renderFrame(embedUrl);\n return;\n }\n if (shouldDirectRenderKnownAppRoute(embedUrl)) {\n renderFrame(embedUrl);\n return;\n }\n const result = await callEmbedSessionTool(embedSessionArgsFor(embedUrl));\n const data = parseToolResult(result);\n if (typeof data.startUrl !== \"string\" || !data.startUrl) {\n startedFor = \"\";\n renderAppLaunchError(data.error || \"This app can be opened, but not embedded from this MCP server.\");\n return;\n }\n const startUrl = withChatBridgeParam(data.startUrl);\n if (selfNavigate) {\n if (shouldTransplantAppDocument()) {\n await transplantAppDocument(startUrl);\n } else if (shouldRenderControlledAppFrame()) {\n renderFrame(startUrl);\n } else {\n navigateToAppFrame(startUrl);\n }\n } else {\n renderFrame(startUrl);\n }\n } catch (err) {\n startedFor = \"\";\n renderAppLaunchError(err && err.message ? err.message : \"Could not launch embedded app.\");\n }\n }\n\n async function callEmbedSessionTool(args) {\n if (openAiBridge && typeof openAiBridge.callTool === \"function\") {\n return await openAiBridge.callTool(startTool, args);\n }\n if (!app || typeof app.callServerTool !== \"function\") {\n throw new Error(\"Host tool calls are not available.\");\n }\n return await app.callServerTool({ name: startTool, arguments: args });\n }\n\n function updateHostOpenInAppUrl() {\n if (!openAiBridge || !openUrl || typeof openAiBridge.setOpenInAppUrl !== \"function\") {\n return;\n }\n try {\n openAiBridge.setOpenInAppUrl({ href: openUrl });\n } catch (err) {\n console.warn(\"[agent-native] ChatGPT rejected open-in-app URL\", err);\n }\n }\n\n function updateOpenButton() {\n const buttonUrl = openUrl;\n openButton.disabled = !buttonUrl;\n openButton.onclick = () => {\n if (buttonUrl) void openHostLink({ url: buttonUrl });\n };\n updateHostOpenInAppUrl();\n }\n\n function updateTitle(data) {\n const record = objectValue(data);\n const label = record.label || record.app || record.view || body.dataset.appTitle || \"App\";\n titleEl.textContent = String(label);\n }\n\n function readOpenAiBridge() {\n return window.openai && typeof window.openai === \"object\"\n ? window.openai\n : null;\n }\n\n function isChatGptHostHint() {\n try {\n if (new URLSearchParams(window.location.search).get(\"app\") === \"chatgpt\") return true;\n } catch (_err) {}\n try {\n if (/^(?:[^.]+\\\\.)?web-sandbox\\\\.oaiusercontent\\\\.com$/i.test(window.location.hostname || \"\")) return true;\n } catch (_err) {}\n try {\n return /chatgpt/i.test(String(navigator.userAgent || \"\"));\n } catch (_err) {\n return false;\n }\n }\n\n function openAiToolResultParams(bridge) {\n const params = {};\n if (bridge && bridge.toolOutput !== undefined) {\n if (bridge.toolOutput && typeof bridge.toolOutput === \"object\") {\n params.structuredContent = bridge.toolOutput;\n } else {\n params.content = [{ type: \"text\", text: String(bridge.toolOutput) }];\n }\n }\n if (bridge && bridge.toolResponseMetadata && typeof bridge.toolResponseMetadata === \"object\") {\n params._meta = bridge.toolResponseMetadata;\n }\n return params;\n }\n\n function syncOpenAiBridge(bridge) {\n if (!bridge) return false;\n openAiBridge = bridge;\n toolInput = objectValue(bridge.toolInput);\n const params = openAiToolResultParams(bridge);\n const data = parseToolResult(params);\n toolResultData = objectValue(data);\n openUrl = openLinkFrom(params, data);\n openStartUrl = embedStartUrlFrom(params, data);\n updateTitle(data);\n updateOpenButton();\n updateDisplayButton();\n notifyHostHeight();\n sendHostContext();\n if (openUrl || openStartUrl) {\n void launchEmbed();\n } else if (!appFrame) {\n setMessage(\"Waiting for app result\");\n }\n return true;\n }\n\n function waitForOpenAiBridge() {\n const existing = readOpenAiBridge();\n if (existing) return Promise.resolve(existing);\n return new Promise((resolve) => {\n let settled = false;\n let pollTimer = 0;\n const finish = (bridge) => {\n if (settled) return;\n settled = true;\n window.removeEventListener(\"openai:set_globals\", onGlobals);\n clearTimeout(timer);\n clearTimeout(pollTimer);\n resolve(bridge || readOpenAiBridge());\n };\n const poll = () => {\n const bridge = readOpenAiBridge();\n if (bridge) {\n finish(bridge);\n return;\n }\n pollTimer = window.setTimeout(poll, openAiBridgePollMs);\n };\n const onGlobals = () => finish(readOpenAiBridge());\n const timer = window.setTimeout(\n () => finish(null),\n isChatGptHostHint() ? chatGptOpenAiBridgeWaitMs : defaultOpenAiBridgeWaitMs\n );\n window.addEventListener(\"openai:set_globals\", onGlobals, { passive: true });\n pollTimer = window.setTimeout(poll, openAiBridgePollMs);\n });\n }\n\n window.addEventListener(\"openai:set_globals\", () => {\n const bridge = readOpenAiBridge();\n if (bridge && (!appFrame || openAiBridge)) syncOpenAiBridge(bridge);\n }, { passive: true });\n\n function createNativeMcpAppsBridge() {\n let rpcId = 0;\n let connectPromise = null;\n let hostContext = {};\n const pendingRequests = new Map();\n\n function rpcNotify(method, params) {\n window.parent.postMessage({ jsonrpc: \"2.0\", method, params: params || {} }, \"*\");\n }\n\n function rpcRequest(method, params, timeoutMs) {\n return new Promise((resolve, reject) => {\n const id = ++rpcId;\n const timer = window.setTimeout(() => {\n pendingRequests.delete(id);\n reject(new Error(\"MCP Apps bridge request timed out: \" + method));\n }, timeoutMs || nativeBridgeRequestTimeoutMs);\n pendingRequests.set(id, { resolve, reject, timer });\n window.parent.postMessage(\n { jsonrpc: \"2.0\", id, method, params: params || {} },\n \"*\"\n );\n });\n }\n\n function settleRpcResponse(message) {\n const pending = pendingRequests.get(message.id);\n if (!pending) return true;\n pendingRequests.delete(message.id);\n clearTimeout(pending.timer);\n if (message.error) {\n const error = new Error(message.error.message || \"MCP Apps bridge request failed.\");\n error.data = message.error.data;\n pending.reject(error);\n return true;\n }\n pending.resolve(message.result);\n return true;\n }\n\n function notificationParams(message) {\n return message && typeof message.params === \"object\" && message.params\n ? message.params\n : {};\n }\n\n function toolInputNotificationParams(params) {\n if (params && typeof params.arguments === \"object\" && params.arguments) {\n return params;\n }\n if (params && typeof params.input === \"object\" && params.input) {\n return { arguments: params.input };\n }\n return { arguments: objectValue(params) };\n }\n\n const nativeApp = {\n ontoolinput: null,\n ontoolresult: null,\n onhostcontextchanged: null,\n getHostContext() {\n return hostContext.context || hostContext;\n },\n getHostCapabilities() {\n return hostContext.capabilities || { tools: true, messaging: true };\n },\n getHostVersion() {\n return hostContext.protocolVersion || \"mcp-apps-postmessage\";\n },\n async connect() {\n if (connectPromise) return await connectPromise;\n connectPromise = (async () => {\n window.addEventListener(\"message\", onMessage, { passive: true });\n const result = await rpcRequest(\n \"ui/initialize\",\n {\n appInfo: { name: \"Agent Native Embed\", version: \"1.0.0\" },\n appCapabilities: {},\n protocolVersion: \"2026-01-26\"\n },\n nativeBridgeInitializeTimeoutMs\n );\n hostContext = objectValue(result);\n rpcNotify(\"ui/notifications/initialized\", {});\n if (typeof nativeApp.onhostcontextchanged === \"function\") {\n nativeApp.onhostcontextchanged(hostContext);\n }\n return hostContext;\n })().catch((err) => {\n connectPromise = null;\n throw err;\n });\n return await connectPromise;\n },\n async callServerTool(request) {\n await nativeApp.connect();\n const record = objectValue(request);\n return await rpcRequest(\"tools/call\", {\n name: record.name,\n arguments: objectValue(record.arguments)\n });\n },\n async updateModelContext(params) {\n await nativeApp.connect();\n return await rpcRequest(\"ui/update-model-context\", objectValue(params));\n },\n async openLink(params) {\n const url = typeof (params && params.url) === \"string\" ? params.url : \"\";\n if (!url) return { isError: true };\n try {\n return await rpcRequest(\"ui/open-link\", { url }, wrapperRequestTimeoutMs);\n } catch (err) {\n console.warn(\"[agent-native] MCP host open-link request failed\", err);\n }\n const opened = window.open(url, \"_blank\", \"noopener,noreferrer\");\n return opened ? { ok: true } : { isError: true };\n },\n async requestDisplayMode(params) {\n await nativeApp.connect();\n return await rpcRequest(\"ui/request-display-mode\", objectValue(params));\n },\n sendSizeChanged(params) {\n rpcNotify(\"ui/notifications/size-changed\", objectValue(params));\n },\n async sendMessage(params) {\n await nativeApp.connect();\n return await rpcRequest(\"ui/message\", objectValue(params));\n }\n };\n\n function onMessage(event) {\n if (event.source !== window.parent) return;\n const message = event.data;\n if (!message || message.jsonrpc !== \"2.0\") return;\n if (typeof message.id === \"number\" || typeof message.id === \"string\") {\n settleRpcResponse(message);\n return;\n }\n if (typeof message.method !== \"string\") return;\n const params = notificationParams(message);\n if (message.method === \"ui/notifications/tool-input\") {\n if (typeof nativeApp.ontoolinput === \"function\") {\n nativeApp.ontoolinput(toolInputNotificationParams(params));\n }\n return;\n }\n if (message.method === \"ui/notifications/tool-result\") {\n if (typeof nativeApp.ontoolresult === \"function\") {\n nativeApp.ontoolresult(params);\n }\n return;\n }\n if (\n message.method === \"ui/notifications/host-context-changed\" ||\n message.method === \"ui/notifications/host-context\" ||\n message.method === \"ui/notifications/context\"\n ) {\n hostContext = objectValue(params);\n if (typeof nativeApp.onhostcontextchanged === \"function\") {\n nativeApp.onhostcontextchanged(hostContext);\n }\n }\n }\n\n return nativeApp;\n }\n\n async function startNativeMcpAppsBridge() {\n app = createNativeMcpAppsBridge();\n appConnectPromise = null;\n app.ontoolinput = (params) => {\n toolInput = params.arguments || {};\n };\n app.ontoolresult = (params) => {\n const data = parseToolResult(params);\n toolResultData = objectValue(data);\n openUrl = openLinkFrom(params, data);\n openStartUrl = embedStartUrlFrom(params, data);\n updateTitle(data);\n updateOpenButton();\n void launchEmbed();\n };\n app.onhostcontextchanged = () => {\n updateDisplayButton();\n notifyHostHeight();\n sendHostContext();\n };\n await ensureHostAppConnected();\n notifyOuterMcpAppReady();\n updateDisplayButton();\n notifyHostHeight();\n sendHostContext();\n }\n\n async function startMcpAppsBridge() {\n const { App } = await import(\"${MCP_APP_IMPORT}\");\n app = new App(\n { name: \"Agent Native Embed\", version: \"1.0.0\" },\n {},\n { autoResize: false }\n );\n appConnectPromise = null;\n app.ontoolinput = (params) => {\n toolInput = params.arguments || {};\n };\n app.ontoolresult = (params) => {\n const data = parseToolResult(params);\n toolResultData = objectValue(data);\n openUrl = openLinkFrom(params, data);\n openStartUrl = embedStartUrlFrom(params, data);\n updateTitle(data);\n updateOpenButton();\n void launchEmbed();\n };\n app.onhostcontextchanged = () => {\n updateDisplayButton();\n notifyHostHeight();\n sendHostContext();\n };\n await ensureHostAppConnected();\n notifyOuterMcpAppReady();\n updateDisplayButton();\n notifyHostHeight();\n sendHostContext();\n }\n\n try {\n const initialOpenAiBridge = await waitForOpenAiBridge();\n if (!syncOpenAiBridge(initialOpenAiBridge)) {\n try {\n await startNativeMcpAppsBridge();\n } catch (nativeErr) {\n console.warn(\"[agent-native] native MCP Apps bridge failed\", nativeErr);\n await startMcpAppsBridge();\n }\n }\n } catch (err) {\n console.error(\"[agent-native] MCP app shell failed\", err);\n reportEmbedError(\n \"bridge-init\",\n err && err.message ? err.message : \"Could not initialize app.\",\n err && err.stack ? String(err.stack) : undefined\n );\n setMessage(err && err.message ? err.message : \"Could not initialize app.\");\n }\n\n window.addEventListener(\"error\", (event) => {\n const err = event && event.error;\n reportEmbedError(\n \"window-error\",\n (err && err.message) || (event && event.message) || \"Uncaught error in MCP app embed.\",\n err && err.stack ? String(err.stack) : undefined\n );\n });\n window.addEventListener(\"unhandledrejection\", (event) => {\n const reason = event && event.reason;\n reportEmbedError(\n \"unhandled-rejection\",\n (reason && reason.message) || String(reason || \"Unhandled promise rejection in MCP app embed.\"),\n reason && reason.stack ? String(reason.stack) : undefined\n );\n });\n })();\n </script>\n</body>\n</html>`,\n csp: {\n connectDomains: [\n \"https://esm.sh\",\n MCP_APP_REQUEST_ORIGIN_CSP_SOURCE,\n ...(options.connectDomains ?? []),\n ...(options.frameDomains ?? []),\n ],\n resourceDomains: [\n \"https://esm.sh\",\n MCP_APP_REQUEST_ORIGIN_CSP_SOURCE,\n ...(options.resourceDomains ?? []),\n ...(options.frameDomains ?? []),\n ],\n baseUriDomains: [\n MCP_APP_REQUEST_ORIGIN_CSP_SOURCE,\n ...(options.baseUriDomains ?? []),\n ],\n frameDomains,\n },\n prefersBorder: false,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"embed-app.js","sourceRoot":"","sources":["../../src/mcp/embed-app.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ActionMcpAppResourceConfig } from \"../action.js\";\nimport { MCP_APP_CHAT_BRIDGE_QUERY_PARAM } from \"../shared/embed-auth.js\";\n\nconst MCP_APP_IMPORT =\n \"https://esm.sh/@modelcontextprotocol/ext-apps@1.7.2/app-with-deps\";\n\nexport const MCP_APP_REQUEST_ORIGIN_CSP_SOURCE = \"$requestOrigin\";\nconst MCP_APP_WRAPPER_CHROME_HEIGHT = 44;\nexport const DEFAULT_MCP_APP_SHELL_HEIGHT = 560;\nexport const DEFAULT_MCP_APP_VIEWPORT_HEIGHT =\n DEFAULT_MCP_APP_SHELL_HEIGHT - MCP_APP_WRAPPER_CHROME_HEIGHT;\n\nexport interface EmbedAppOptions {\n title?: string;\n description?: string;\n iframeTitle?: string;\n openLabel?: string;\n embedByDefault?: boolean;\n startToolName?: string;\n connectDomains?: string[];\n resourceDomains?: string[];\n baseUriDomains?: string[];\n frameDomains?: string[];\n height?: number;\n}\n\nfunction attr(value: string | undefined): string {\n return String(value ?? \"\")\n .replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n}\n\nexport function embedApp(\n options: EmbedAppOptions = {},\n): ActionMcpAppResourceConfig {\n const title = options.title ?? \"Open app\";\n const iframeTitle = options.iframeTitle ?? \"Agent Native app\";\n const openLabel = options.openLabel ?? \"Open in app\";\n const startToolName = options.startToolName ?? \"create_embed_session\";\n const embedByDefault = options.embedByDefault !== false;\n const height = Math.max(\n 320,\n Math.min(900, options.height ?? DEFAULT_MCP_APP_SHELL_HEIGHT),\n );\n const viewportHeight = height - MCP_APP_WRAPPER_CHROME_HEIGHT;\n const frameDomains = [\n MCP_APP_REQUEST_ORIGIN_CSP_SOURCE,\n ...(options.frameDomains ?? []),\n ];\n\n return {\n title,\n ...(options.description ? { description: options.description } : {}),\n html: () => `<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <style>\n :root { color-scheme: light dark; font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif; background: Canvas; color: CanvasText; --agent-native-shell-height: ${height}px; --agent-native-viewport-height: ${viewportHeight}px; }\n * { box-sizing: border-box; }\n body { margin: 0; }\n .shell { display: grid; gap: 8px; min-height: var(--agent-native-shell-height); padding: 0; }\n .bar { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 36px; padding: 6px 8px; border-bottom: 1px solid color-mix(in srgb, CanvasText 12%, Canvas); }\n .title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; font-weight: 700; color: color-mix(in srgb, CanvasText 72%, Canvas); }\n .actions { display: flex; align-items: center; gap: 6px; }\n button { min-height: 28px; border: 1px solid color-mix(in srgb, CanvasText 14%, Canvas); border-radius: 7px; background: Canvas; color: CanvasText; cursor: pointer; font: inherit; font-size: 12px; font-weight: 700; padding: 0 9px; }\n button.primary { min-height: 32px; padding: 0 14px; background: CanvasText; color: Canvas; border-color: CanvasText; }\n button.primary:hover:not(:disabled) { background: color-mix(in srgb, CanvasText 86%, Canvas); }\n button:disabled { opacity: .55; cursor: default; }\n .stage { position: relative; min-height: var(--agent-native-viewport-height); }\n iframe { display: block; width: 100%; height: var(--agent-native-viewport-height); border: 0; background: Canvas; }\n .message { display: grid; place-items: center; min-height: var(--agent-native-viewport-height); padding: 18px; color: color-mix(in srgb, CanvasText 62%, Canvas); font-size: 13px; line-height: 1.45; text-align: center; }\n .fallback { display: grid; align-content: center; justify-items: center; gap: 12px; min-height: var(--agent-native-viewport-height); padding: 24px; background: Canvas; color: CanvasText; text-align: center; }\n .fallback-title { max-width: 440px; font-size: 14px; font-weight: 700; }\n .fallback-copy { max-width: 520px; color: color-mix(in srgb, CanvasText 64%, Canvas); font-size: 13px; line-height: 1.45; }\n .fallback-actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 8px; }\n .fallback-url { max-width: min(560px, 100%); overflow-wrap: anywhere; color: color-mix(in srgb, CanvasText 76%, Canvas); font-size: 12px; }\n </style>\n</head>\n<body\n data-app-title=\"${attr(title)}\"\n data-iframe-title=\"${attr(iframeTitle)}\"\n data-open-label=\"${attr(openLabel)}\"\n data-start-tool=\"${attr(startToolName)}\"\n data-embed-default=\"${embedByDefault ? \"1\" : \"0\"}\"\n>\n <main class=\"shell\">\n <div class=\"bar\">\n <div class=\"title\" data-title-label>${attr(title)}</div>\n <div class=\"actions\">\n <button type=\"button\" data-display hidden disabled>Fullscreen</button>\n <button type=\"button\" data-open disabled>${attr(openLabel)}</button>\n </div>\n </div>\n <section class=\"stage\" data-stage>\n <div class=\"message\">Preparing app</div>\n </section>\n </main>\n <script>\n (async () => {\n const body = document.body;\n const stage = document.querySelector(\"[data-stage]\");\n const titleEl = document.querySelector(\"[data-title-label]\");\n const openButton = document.querySelector(\"[data-open]\");\n const displayButton = document.querySelector(\"[data-display]\");\n const startTool = body.dataset.startTool || \"create_embed_session\";\n const embedByDefault = body.dataset.embedDefault !== \"0\";\n const chatBridgeParam = ${JSON.stringify(MCP_APP_CHAT_BRIDGE_QUERY_PARAM)};\n const defaultIntrinsicHeight = ${height};\n const chromeHeight = ${MCP_APP_WRAPPER_CHROME_HEIGHT};\n const frameReadyMessageDelays = [0, 200, 500, 1500, 3000, 7000, 15000, 30000];\n const frameReadyTimeoutMs = 45000;\n const frameLoadTimeoutMs = 45000;\n const maxEmbedSessionRefreshAttempts = 2;\n const defaultOpenAiBridgeWaitMs = 200;\n const chatGptOpenAiBridgeWaitMs = 5000;\n const openAiBridgePollMs = 50;\n const nativeBridgeInitializeTimeoutMs = 5000;\n const nativeBridgeRequestTimeoutMs = 30000;\n const wrapperRequestTimeoutMs = 5000;\n let app = null;\n let appConnectPromise = null;\n let openAiBridge = null;\n let wrapperRequestId = 0;\n const wrapperRequests = new Map();\n let toolInput = {};\n let toolResultData = {};\n let openUrl = \"\";\n let openStartUrl = \"\";\n let startedFor = \"\";\n let appFrame = null;\n let appFrameReady = false;\n let appFrameReadyTimer = null;\n let appFrameLoadTimer = null;\n let lastFrameSrc = \"\";\n let embedSessionRefreshAttempts = 0;\n\n function esc(value) {\n return String(value ?? \"\")\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\");\n }\n\n function parseJson(value, fallback) {\n if (value && typeof value === \"object\") return value;\n if (typeof value !== \"string\" || !value.trim()) return fallback;\n try { return JSON.parse(value); } catch { return fallback; }\n }\n\n function objectValue(value) {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? value\n : {};\n }\n\n function finiteNumber(value) {\n return typeof value === \"number\" && Number.isFinite(value) && value > 0\n ? value\n : null;\n }\n\n function contextMaxHeight(context) {\n if (!context || typeof context !== \"object\") return null;\n return finiteNumber(context.maxHeight) ||\n finiteNumber(context.containerDimensions && context.containerDimensions.maxHeight);\n }\n\n function visibleIntrinsicHeight() {\n const context = hostState().context || {};\n const hostMaxHeight = contextMaxHeight(context);\n if (hostMaxHeight) return Math.floor(hostMaxHeight);\n const viewportHeight = finiteNumber(window.visualViewport && window.visualViewport.height) ||\n finiteNumber(window.innerHeight);\n return Math.floor(viewportHeight || defaultIntrinsicHeight);\n }\n\n function applyIntrinsicHeight(nextHeight) {\n const boundedHeight = Math.min(\n defaultIntrinsicHeight,\n Math.floor(nextHeight || defaultIntrinsicHeight)\n );\n const height = Math.max(320, boundedHeight);\n const viewportHeight = Math.max(0, height - chromeHeight);\n document.documentElement.style.setProperty(\"--agent-native-shell-height\", height + \"px\");\n document.documentElement.style.setProperty(\"--agent-native-viewport-height\", viewportHeight + \"px\");\n if (appFrame) appFrame.style.height = viewportHeight + \"px\";\n return height;\n }\n\n function parseToolResult(params) {\n if (!params) return {};\n if (params.result && typeof params.result === \"object\") {\n return parseToolResult(params.result);\n }\n if (params.toolResult && typeof params.toolResult === \"object\") {\n return parseToolResult(params.toolResult);\n }\n if (params.structuredContent && typeof params.structuredContent === \"object\") {\n return params.structuredContent;\n }\n const parts = Array.isArray(params.content) ? params.content : [];\n const textPart = parts.find((part) => part && part.type === \"text\" && typeof part.text === \"string\");\n const text = textPart ? textPart.text : \"\";\n if (params.isError && typeof text === \"string\" && text.trim()) {\n return { error: text.trim() };\n }\n return parseJson(text, {});\n }\n\n function metadataRecord(value) {\n const meta = value && typeof value === \"object\" && !Array.isArray(value)\n ? value._meta\n : null;\n return meta && typeof meta === \"object\" && !Array.isArray(meta)\n ? meta\n : null;\n }\n\n function toolResultMeta(params) {\n if (!params || typeof params !== \"object\") return {};\n const direct = metadataRecord(params);\n if (direct) return direct;\n if (params.result && typeof params.result === \"object\") {\n return toolResultMeta(params.result);\n }\n if (params.toolResult && typeof params.toolResult === \"object\") {\n return toolResultMeta(params.toolResult);\n }\n return {};\n }\n\n function openLinkRecordFrom(value) {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? value\n : {};\n }\n\n function openLinkWebUrlFrom(value) {\n const record = openLinkRecordFrom(value);\n return typeof record.webUrl === \"string\" ? record.webUrl : \"\";\n }\n\n function firstNonEmbedStartUrl(values) {\n for (const value of values) {\n if (typeof value === \"string\" && value && !isEmbedStartUrl(value)) return value;\n }\n return \"\";\n }\n\n function firstEmbedStartUrl(values) {\n for (const value of values) {\n if (typeof value === \"string\" && value && isEmbedStartUrl(value)) {\n return withChatBridgeParam(value);\n }\n }\n return \"\";\n }\n\n function openLinkFrom(params, data) {\n const meta = toolResultMeta(params);\n const openLink = meta[\"agent-native/openLink\"];\n const metaUrl = openLinkWebUrlFrom(openLink);\n const record = data && typeof data === \"object\" ? data : {};\n const structuredOpenLinkUrl = openLinkWebUrlFrom(record.openLink);\n return firstNonEmbedStartUrl([\n record.embedTargetPath,\n record.deepLinkUrl,\n record.deepLink,\n record.openUrl,\n structuredOpenLinkUrl,\n metaUrl,\n record.url\n ]);\n }\n\n function embedStartUrlFrom(params, data) {\n const meta = toolResultMeta(params);\n const embedStart = meta[\"agent-native/embedStart\"];\n const embedStartRecord =\n embedStart && typeof embedStart === \"object\" && !Array.isArray(embedStart)\n ? embedStart\n : {};\n const openLink = meta[\"agent-native/openLink\"];\n const metaUrl = openLinkWebUrlFrom(openLink);\n const record = data && typeof data === \"object\" ? data : {};\n return firstEmbedStartUrl([\n embedStartRecord.startUrl,\n record.embedStartUrl,\n record.startUrl,\n record.url,\n openLinkWebUrlFrom(record.openLink),\n metaUrl\n ]);\n }\n\n function hostState() {\n if (openAiBridge) {\n return {\n context: {\n displayMode: openAiBridge.displayMode,\n availableDisplayModes: typeof openAiBridge.requestDisplayMode === \"function\"\n ? [\"inline\", \"fullscreen\", \"pip\"]\n : [],\n maxHeight: openAiBridge.maxHeight,\n locale: openAiBridge.locale,\n theme: openAiBridge.theme,\n view: openAiBridge.view\n },\n capabilities: { openai: true },\n version: openAiBridge.userAgent\n };\n }\n return {\n context: app && app.getHostContext ? app.getHostContext() : undefined,\n capabilities: app && app.getHostCapabilities ? app.getHostCapabilities() : undefined,\n version: app && app.getHostVersion ? app.getHostVersion() : undefined\n };\n }\n\n function sendToAppFrame(message) {\n if (!appFrame || !appFrame.contentWindow) return;\n try { appFrame.contentWindow.postMessage(message, \"*\"); } catch {}\n }\n\n function notifyOuterMcpAppReady() {\n try {\n window.parent.postMessage({ type: \"agentNative.embeddedAppReady\" }, \"*\");\n } catch {}\n }\n\n function nextWrapperRequestId() {\n wrapperRequestId += 1;\n return \"mcp-wrapper-\" + Date.now() + \"-\" + wrapperRequestId;\n }\n\n function respondToWrapperRequest(requestId, result) {\n if (!requestId) return;\n sendToAppFrame({\n type: \"agentNative.mcpHost.response\",\n data: {\n requestId,\n ok: !!(result && result.ok),\n result: result || {}\n }\n });\n }\n\n function wrapperRpcRequest(method, params, timeoutMs) {\n return new Promise((resolve) => {\n const id = nextWrapperRequestId();\n const timer = window.setTimeout(() => {\n wrapperRequests.delete(id);\n resolve({ ok: false, error: \"MCP host bridge request timed out.\" });\n }, timeoutMs || wrapperRequestTimeoutMs);\n wrapperRequests.set(id, { resolve, timer });\n try {\n window.parent.postMessage(\n { jsonrpc: \"2.0\", id, method, params: params || {} },\n \"*\"\n );\n } catch (err) {\n wrapperRequests.delete(id);\n clearTimeout(timer);\n resolve({ ok: false, error: err && err.message ? err.message : String(err) });\n }\n });\n }\n\n function settleWrapperRpcResponse(message) {\n const id = typeof (message && message.id) === \"string\" ? message.id : \"\";\n if (!id) return false;\n const pending = wrapperRequests.get(id);\n if (!pending) return false;\n wrapperRequests.delete(id);\n clearTimeout(pending.timer);\n if (message.error) {\n pending.resolve({ ok: false, error: message.error });\n } else {\n pending.resolve({ ok: true, result: message.result });\n }\n return true;\n }\n\n function sendHostContext() {\n sendToAppFrame({ type: \"agentNative.mcpHostContext\", data: hostState() });\n }\n\n function sendFrameReadyMessages(frame) {\n const originPayload = { type: \"agentNative.frameOrigin\", origin: window.location.origin };\n frameReadyMessageDelays.forEach((delay) => {\n setTimeout(() => {\n try { frame.contentWindow && frame.contentWindow.postMessage(originPayload, \"*\"); } catch {}\n sendHostContext();\n }, delay);\n });\n }\n\n function withChatBridgeParam(value) {\n if (typeof value !== \"string\" || !value) return value;\n try {\n const base = \"http://agent-native.invalid\";\n const url = value.startsWith(\"/\") ? new URL(value, base) : new URL(value);\n url.searchParams.set(chatBridgeParam, \"1\");\n return value.startsWith(\"/\")\n ? url.pathname + url.search + url.hash\n : url.toString();\n } catch {\n return value;\n }\n }\n\n function embedSessionArgsFor(value) {\n const chrome = typeof toolInput.chrome === \"string\" ? toolInput.chrome : \"full\";\n return typeof value === \"string\" && value.startsWith(\"/\")\n ? { path: value, chrome }\n : { url: value, chrome };\n }\n\n function isEmbedStartUrl(value) {\n if (typeof value !== \"string\" || !value) return false;\n try {\n const url = new URL(value, window.location.href);\n return url.pathname.endsWith(\"/_agent-native/embed/start\");\n } catch {\n return false;\n }\n }\n\n function localPathFromUrl(url, includeToken) {\n const next = new URL(url.href);\n if (!includeToken) next.searchParams.delete(\"__an_embed_token\");\n return next.pathname + next.search + next.hash;\n }\n\n function rewriteRootRelativeHtmlUrls(html, appOrigin) {\n return String(html).replace(\n /\\\\b(src|href|poster|action)\\\\s*=\\\\s*([\"'])\\\\/(?!\\\\/)/gi,\n (_match, name, quote) => String(name) + \"=\" + quote + appOrigin + \"/\"\n );\n }\n\n function removeHtmlCspMeta(html) {\n return String(html).replace(\n /<meta\\\\s+[^>]*http-equiv\\\\s*=\\\\s*([\"'])?content-security-policy\\\\1?[^>]*>/gi,\n \"\"\n );\n }\n\n function embedConfigForAppUrl(appUrl) {\n const sanitizedTarget = localPathFromUrl(appUrl, false);\n return {\n origin: appUrl.origin,\n href: appUrl.href,\n baseHref: appUrl.origin + appUrl.pathname,\n target: sanitizedTarget,\n token: appUrl.searchParams.get(\"__an_embed_token\") || \"\",\n chatBridgeActive: appUrl.searchParams.get(chatBridgeParam) === \"1\",\n chatBridgeParam,\n embedTokenParam: \"__an_embed_token\",\n embedTargetHeader: \"x-agent-native-embed-target\"\n };\n }\n\n function externalOpenUrlForAppUrl(appUrl) {\n if (openUrl) return openUrl;\n try {\n const url = new URL(appUrl.href);\n url.searchParams.delete(\"embedded\");\n url.searchParams.delete(\"__an_embed_token\");\n url.searchParams.delete(chatBridgeParam);\n return url.toString();\n } catch (_err) {\n return \"\";\n }\n }\n\n function installExternalOpenControl(appUrl) {\n const href = externalOpenUrlForAppUrl(appUrl);\n if (!href || !document.body || document.getElementById(\"agent-native-external-open-control\")) {\n return;\n }\n const host = document.createElement(\"div\");\n host.id = \"agent-native-external-open-control\";\n host.style.position = \"fixed\";\n host.style.top = \"10px\";\n host.style.right = \"10px\";\n host.style.zIndex = \"2147483647\";\n host.style.pointerEvents = \"auto\";\n const root = host.attachShadow ? host.attachShadow({ mode: \"open\" }) : host;\n root.innerHTML =\n '<style>' +\n ':host{all:initial;}' +\n 'button{box-sizing:border-box;min-height:30px;border:1px solid color-mix(in srgb, CanvasText 18%, Canvas);border-radius:7px;background:Canvas;color:CanvasText;box-shadow:0 6px 22px color-mix(in srgb, CanvasText 14%, transparent);cursor:pointer;font:700 12px ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif;padding:0 10px;white-space:nowrap;}' +\n 'button:hover{background:color-mix(in srgb, CanvasText 6%, Canvas);}' +\n '</style>' +\n '<button type=\"button\">Open in new tab</button>';\n const button = root.querySelector(\"button\");\n if (button) {\n button.addEventListener(\"click\", (event) => {\n event.preventDefault();\n void openHostLink({ url: href });\n });\n }\n document.body.appendChild(host);\n }\n\n function installReactRefreshPreambleFallback() {\n window.__vite_plugin_react_preamble_installed__ = true;\n if (typeof window.$RefreshReg$ !== \"function\") {\n window.$RefreshReg$ = function() {};\n }\n if (typeof window.$RefreshSig$ !== \"function\") {\n window.$RefreshSig$ = function() {\n return function(type) {\n return type;\n };\n };\n }\n }\n\n function installExternalEmbedRuntime(config) {\n window.__AGENT_NATIVE_EXTERNAL_EMBED = config;\n installReactRefreshPreambleFallback();\n try {\n if (config.target) {\n window.history.replaceState(window.history.state, \"\", config.target);\n }\n } catch (_err) {}\n try {\n if (config.token) {\n sessionStorage.setItem(\"agent-native:embed-auth-token\", config.token);\n }\n if (config.chatBridgeActive && config.token) {\n sessionStorage.setItem(\"agent-native:mcp-chat-bridge\", config.token);\n }\n } catch (_err) {}\n if (window.__agentNativeExternalEmbedRuntimeInstalled) return;\n window.__agentNativeExternalEmbedRuntimeInstalled = true;\n function appOrigin() {\n try {\n return new URL(config.origin).origin;\n } catch (_err) {\n return \"\";\n }\n }\n function targetPath() {\n return config.target || location.pathname + location.search;\n }\n function rewrittenUrl(value, appendToken) {\n const origin = appOrigin();\n if (!origin) return null;\n let url;\n try {\n url = new URL(value, location.href);\n } catch (_err) {\n return null;\n }\n if (url.origin !== location.origin && url.origin !== origin) return null;\n if (url.origin !== origin) {\n const app = new URL(origin);\n url.protocol = app.protocol;\n url.host = app.host;\n }\n if (appendToken && config.token && url.pathname === \"/_agent-native/events\") {\n url.searchParams.set(config.embedTokenParam, config.token);\n }\n return url.toString();\n }\n function authHeaders(input, init) {\n const headers = new Headers(\n init && init.headers ? init.headers : input instanceof Request ? input.headers : undefined\n );\n if (config.token && !headers.has(\"Authorization\")) {\n headers.set(\"Authorization\", \"Bearer \" + config.token);\n }\n if (!headers.has(config.embedTargetHeader)) {\n headers.set(config.embedTargetHeader, targetPath());\n }\n return headers;\n }\n if (typeof fetch === \"function\") {\n const originalFetch = fetch.bind(window);\n window.fetch = function(input, init) {\n const raw = input instanceof Request ? input.url : String(input);\n const url = rewrittenUrl(raw, false);\n if (!url) return originalFetch(input, init);\n const nextInit = Object.assign({}, init || {}, {\n headers: authHeaders(input, init),\n credentials: \"omit\"\n });\n if (input instanceof Request) {\n return originalFetch(new Request(url, input), nextInit);\n }\n return originalFetch(url, nextInit);\n };\n }\n if (typeof XMLHttpRequest !== \"undefined\") {\n const originalOpen = XMLHttpRequest.prototype.open;\n const originalSend = XMLHttpRequest.prototype.send;\n XMLHttpRequest.prototype.open = function(method, url) {\n const rewritten = rewrittenUrl(url, false);\n this.__agentNativeExternalEmbed = !!rewritten;\n return originalOpen.call(\n this,\n method,\n rewritten || url,\n arguments.length > 2 ? arguments[2] : true,\n arguments[3],\n arguments[4]\n );\n };\n XMLHttpRequest.prototype.send = function(body) {\n if (this.__agentNativeExternalEmbed) {\n try {\n if (config.token) this.setRequestHeader(\"Authorization\", \"Bearer \" + config.token);\n this.setRequestHeader(config.embedTargetHeader, targetPath());\n } catch (_err) {}\n }\n return originalSend.call(this, body);\n };\n }\n if (typeof EventSource !== \"undefined\") {\n const OriginalEventSource = EventSource;\n window.EventSource = function(url, options) {\n return new OriginalEventSource(rewrittenUrl(url, true) || url, options);\n };\n window.EventSource.prototype = OriginalEventSource.prototype;\n }\n }\n\n function copyDocumentElementAttributes(source) {\n const target = document.documentElement;\n for (const attr of Array.from(target.attributes)) {\n target.removeAttribute(attr.name);\n }\n for (const attr of Array.from(source.attributes)) {\n target.setAttribute(attr.name, attr.value);\n }\n }\n\n function importChildren(source, target) {\n target.replaceChildren(\n ...Array.from(source.childNodes).map((node) => document.importNode(node, true))\n );\n }\n\n function importHeadChildrenWithBase(source, baseHref) {\n const base = document.createElement(\"base\");\n base.href = baseHref;\n const nodes = Array.from(source.childNodes).filter((node) => {\n return !(\n node.nodeType === 1 &&\n String(node.nodeName || \"\").toLowerCase() === \"base\"\n );\n });\n document.head.replaceChildren(\n base,\n ...nodes.map((node) => document.importNode(node, true))\n );\n }\n\n function isModuleScript(script) {\n return (script.getAttribute(\"type\") || \"\").trim().toLowerCase() === \"module\";\n }\n\n function isRunnableClassicScript(script) {\n const type = (script.getAttribute(\"type\") || \"\").trim().toLowerCase();\n return !type || type === \"text/javascript\" || type === \"application/javascript\";\n }\n\n function runClassicScript(script) {\n const next = document.createElement(\"script\");\n for (const attr of Array.from(script.attributes)) {\n if (attr.name === \"type\") continue;\n next.setAttribute(attr.name, attr.value);\n }\n if (script.src) {\n next.src = script.src;\n } else {\n next.textContent = script.textContent || \"\";\n }\n document.body.appendChild(next);\n next.remove();\n }\n\n function isEmbedRuntimeModulePath(pathname) {\n if (typeof pathname !== \"string\" || !pathname) return false;\n return /(?:^|\\\\/)(?:@(?:id|vite|fs|react-refresh)|app|node_modules|packages|src)(?:\\\\/|$)/.test(pathname) ||\n /(?:^|\\\\/)__x00__virtual:/.test(pathname) ||\n pathname.includes(\"virtual:react-router\");\n }\n\n function appendEmbedParamsToAppUrl(url, config) {\n if (isEmbedRuntimeModulePath(url.pathname)) return url;\n if (config.token) url.searchParams.set(config.embedTokenParam, config.token);\n if (config.chatBridgeActive) url.searchParams.set(config.chatBridgeParam, \"1\");\n return url;\n }\n\n function rootRelativeSpecifierToAppUrl(specifier, config) {\n if (typeof specifier !== \"string\" || !specifier.startsWith(\"/\") || specifier.startsWith(\"//\")) {\n return specifier;\n }\n try {\n const url = new URL(specifier, config.origin);\n return appendEmbedParamsToAppUrl(url, config).toString();\n } catch (_err) {\n return specifier;\n }\n }\n\n function rootRelativeSpecifiersToAbsolute(code, config) {\n return String(code).replace(/([\"'])\\\\/(?!\\\\/)([^\"']*)/g, (_match, quote, rest) => {\n return quote + rootRelativeSpecifierToAppUrl(\"/\" + rest, config);\n });\n }\n\n function relativeSpecifierToAppUrl(specifier, config, baseUrl) {\n if (typeof specifier !== \"string\" || !/^\\\\.\\\\.?\\\\//.test(specifier)) {\n return specifier;\n }\n try {\n const url = new URL(specifier, baseUrl || config.baseHref);\n if (url.origin === config.origin) {\n appendEmbedParamsToAppUrl(url, config);\n }\n return url.toString();\n } catch (_err) {\n return specifier;\n }\n }\n\n function relativeModuleSpecifiersToAbsolute(code, config, baseUrl) {\n return String(code)\n .replace(/(\\\\bimport\\\\s+(?:[^\"']+?\\\\s+from\\\\s+)?)([\"'])(\\\\.\\\\.?\\\\/[^\"']*)\\\\2/g, (_match, prefix, quote, specifier) => {\n return prefix + quote + relativeSpecifierToAppUrl(specifier, config, baseUrl) + quote;\n })\n .replace(/(\\\\bimport\\\\s*\\\\(\\\\s*)([\"'])(\\\\.\\\\.?\\\\/[^\"']*)\\\\2/g, (_match, prefix, quote, specifier) => {\n return prefix + quote + relativeSpecifierToAppUrl(specifier, config, baseUrl) + quote;\n })\n .replace(/(\\\\bexport\\\\s+[^\"']*?\\\\s+from\\\\s+)([\"'])(\\\\.\\\\.?\\\\/[^\"']*)\\\\2/g, (_match, prefix, quote, specifier) => {\n return prefix + quote + relativeSpecifierToAppUrl(specifier, config, baseUrl) + quote;\n });\n }\n\n function stripDevOnlyModuleImports(code) {\n return String(code).replace(\n /\\\\bimport\\\\s+(?:[^\"']+\\\\s+from\\\\s+)?[\"'][^\"']*(?:virtual:react-router\\\\/inject-hmr-runtime|__x00__virtual:react-router\\\\/inject-hmr-runtime)[^\"']*[\"']\\\\s*;?/g,\n \"\"\n );\n }\n\n function namedImportBindings(specifierList) {\n return String(specifierList)\n .split(\",\")\n .map((part) => {\n const trimmed = part.trim();\n if (!trimmed) return \"\";\n return trimmed.replace(\n /^([A-Za-z_$][\\\\w$]*)\\\\s+as\\\\s+([A-Za-z_$][\\\\w$]*)$/,\n \"$1: $2\"\n );\n })\n .filter(Boolean)\n .join(\", \");\n }\n\n function moduleCodeToClassicAsync(code, config, baseUrl) {\n return relativeModuleSpecifiersToAbsolute(\n rootRelativeSpecifiersToAbsolute(stripDevOnlyModuleImports(code), config),\n config,\n baseUrl\n )\n .replace(\n /\\\\bimport\\\\s+([A-Za-z_$][\\\\w$]*)\\\\s*,\\\\s*\\\\*\\\\s+as\\\\s+([A-Za-z_$][\\\\w$]*)\\\\s+from\\\\s+([\"'][^\"']+[\"'])\\\\s*;?/g,\n \"const $2 = await import($3); const $1 = $2.default;\"\n )\n .replace(\n /\\\\bimport\\\\s+([A-Za-z_$][\\\\w$]*)\\\\s*,\\\\s*\\\\{([\\\\s\\\\S]*?)\\\\}\\\\s*from\\\\s+([\"'][^\"']+[\"'])\\\\s*;?/g,\n (_match, defaultName, specifiers, source) =>\n \"const { default: \" +\n defaultName +\n (namedImportBindings(specifiers) ? \", \" + namedImportBindings(specifiers) : \"\") +\n \" } = await import(\" +\n source +\n \");\"\n )\n .replace(\n /\\\\bimport\\\\s+\\\\{([\\\\s\\\\S]*?)\\\\}\\\\s*from\\\\s+([\"'][^\"']+[\"'])\\\\s*;?/g,\n (_match, specifiers, source) =>\n \"const { \" + namedImportBindings(specifiers) + \" } = await import(\" + source + \");\"\n )\n .replace(\n /\\\\bimport\\\\s+\\\\*\\\\s+as\\\\s+([A-Za-z_$][\\\\w$]*)\\\\s+from\\\\s+([\"'][^\"']+[\"'])\\\\s*;?/g,\n \"const $1 = await import($2);\"\n )\n .replace(\n /\\\\bimport\\\\s+([A-Za-z_$][\\\\w$]*)\\\\s+from\\\\s+([\"'][^\"']+[\"'])\\\\s*;?/g,\n \"const { default: $1 } = await import($2);\"\n )\n .replace(/\\\\bimport\\\\s+([\"'][^\"']+[\"'])\\\\s*;?/g, \"await import($1);\")\n .replace(/\\\\bimport\\\\(([\"'][^\"']+[\"'])\\\\)\\\\s*;?/g, \"await import($1);\");\n }\n\n function scriptSourceUrl(script, config) {\n const raw = script.getAttribute(\"src\") || \"\";\n if (!raw) return \"\";\n try {\n const url = new URL(raw, config.baseHref);\n if (url.origin === config.origin) {\n appendEmbedParamsToAppUrl(url, config);\n }\n return url.toString();\n } catch (_err) {\n return raw;\n }\n }\n\n async function moduleScriptCode(script, config) {\n const src = scriptSourceUrl(script, config);\n if (!src) return script.textContent || \"\";\n const response = await fetch(src, {\n credentials: \"omit\",\n headers: { Accept: \"text/javascript, application/javascript, */*\" }\n });\n if (!response.ok) {\n throw new Error(\"Module script returned HTTP \" + response.status + \".\");\n }\n return await response.text();\n }\n\n async function runModuleScriptAsClassic(script, config) {\n const sourceUrl = scriptSourceUrl(script, config) || config.baseHref;\n const code = moduleCodeToClassicAsync(\n await moduleScriptCode(script, config),\n config,\n sourceUrl\n );\n const runner = document.createElement(\"script\");\n runner.textContent =\n \"(async()=>{\" +\n code +\n \"})().catch((err)=>{console.error('[agent-native] transplanted app module failed',err);document.body.setAttribute('data-agent-native-hydration-error',String(err&&err.message||err));});\";\n document.body.appendChild(runner);\n runner.remove();\n }\n\n async function mountTransplantedHtml(html, appUrl) {\n const config = embedConfigForAppUrl(appUrl);\n installExternalEmbedRuntime(config);\n const parsed = new DOMParser().parseFromString(\n rewriteRootRelativeHtmlUrls(removeHtmlCspMeta(html), appUrl.origin),\n \"text/html\"\n );\n const scripts = Array.from(parsed.querySelectorAll(\"script\"));\n copyDocumentElementAttributes(parsed.documentElement);\n importHeadChildrenWithBase(parsed.head, config.baseHref);\n importChildren(parsed.body, document.body);\n installExternalOpenControl(appUrl);\n for (const script of scripts) {\n if (isRunnableClassicScript(script)) runClassicScript(script);\n }\n for (const script of scripts) {\n if (isModuleScript(script)) await runModuleScriptAsClassic(script, config);\n }\n }\n\n function absoluteUrl(value, base) {\n try {\n return new URL(value, base).toString();\n } catch {\n return \"\";\n }\n }\n\n async function resolveTransplantAppDocumentSource(src) {\n if (!isEmbedStartUrl(src)) {\n return { url: new URL(src), response: null };\n }\n const response = await fetch(src, {\n credentials: \"omit\",\n redirect: \"follow\",\n headers: {\n Accept: \"application/json\",\n \"X-Agent-Native-Embed-Transplant\": \"1\"\n }\n });\n const contentType = response.headers.get(\"content-type\") || \"\";\n if (response.ok && /\\\\bapplication\\\\/json\\\\b/i.test(contentType)) {\n const data = await response.json();\n const location = typeof data.location === \"string\" ? data.location : \"\";\n const url = absoluteUrl(location, src);\n if (url) return { url: new URL(withChatBridgeParam(url)), response: null };\n throw new Error(\"Embedded app did not return a launch URL.\");\n }\n return {\n url: new URL(response.url || src),\n response\n };\n }\n\n async function transplantAppDocument(src) {\n clearFrameReadyTimer();\n clearFrameLoadTimer();\n appFrame = null;\n lastFrameSrc = src;\n setMessage(\"Loading app\");\n const source = await resolveTransplantAppDocumentSource(src);\n const response = source.response || await fetch(source.url.href, {\n credentials: \"omit\",\n redirect: \"follow\",\n headers: { Accept: \"text/html\" }\n });\n if (!response.ok) {\n if (response.status === 401 && isEmbedStartUrl(src)) {\n reportEmbedError(\n \"transplant-auth\",\n \"Embedded app session expired (HTTP 401).\",\n \"Opaque-origin sandbox could not authenticate the embed.\",\n 401\n );\n refreshExpiredEmbedSession();\n return;\n }\n reportEmbedError(\n \"transplant-http\",\n \"Embedded app returned HTTP \" + response.status + \".\",\n undefined,\n response.status\n );\n throw new Error(\"Embedded app returned HTTP \" + response.status + \".\");\n }\n const html = await response.text();\n const appUrl = source.url || new URL(response.url || src);\n try {\n window.history.replaceState(window.history.state, \"\", localPathFromUrl(appUrl, false));\n } catch {}\n await mountTransplantedHtml(html, appUrl);\n embedSessionRefreshAttempts = 0;\n notifyHostHeightRepeatedly();\n }\n\n function wantsEmbed() {\n if (toolInput.embed === false || toolInput.embed === \"false\") return false;\n if (embedByDefault) return true;\n return toolInput.embed === true || toolInput.embed === \"true\";\n }\n\n function renderModeSource() {\n const input = objectValue(toolInput);\n const result = objectValue(toolResultData);\n return {\n mode: typeof input.embedMode === \"string\"\n ? input.embedMode\n : typeof input.renderMode === \"string\"\n ? input.renderMode\n : typeof result.embedMode === \"string\"\n ? result.embedMode\n : typeof result.renderMode === \"string\"\n ? result.renderMode\n : \"\",\n frame: typeof input.frame === \"string\"\n ? input.frame\n : typeof result.frame === \"string\"\n ? result.frame\n : \"\",\n nested: input.nested === true || result.nested === true\n };\n }\n\n function supportedDisplayMode(mode) {\n if (openAiBridge && typeof openAiBridge.requestDisplayMode === \"function\") {\n return mode === \"inline\" || mode === \"fullscreen\" || mode === \"pip\";\n }\n const modes = hostState().context && hostState().context.availableDisplayModes;\n return Array.isArray(modes) && modes.includes(mode);\n }\n\n async function requestHostDisplayMode(mode) {\n let result;\n if (openAiBridge && typeof openAiBridge.requestDisplayMode === \"function\") {\n result = await openAiBridge.requestDisplayMode({ mode });\n } else {\n if (!app || typeof app.requestDisplayMode !== \"function\") {\n throw new Error(\"Display mode changes are not available in this host.\");\n }\n result = await app.requestDisplayMode({ mode });\n }\n updateDisplayButton();\n sendHostContext();\n return result;\n }\n\n function updateDisplayButton() {\n const context = hostState().context || {};\n const nextMode = context.displayMode === \"fullscreen\" ? \"inline\" : \"fullscreen\";\n const supported = supportedDisplayMode(nextMode);\n displayButton.hidden = !supported;\n displayButton.disabled = !supported;\n displayButton.textContent = nextMode === \"fullscreen\" ? \"Fullscreen\" : \"Inline\";\n displayButton.onclick = () => {\n if (!supportedDisplayMode(nextMode)) return;\n void requestHostDisplayMode(nextMode).catch((err) => {\n console.warn(\"[agent-native] MCP host rejected display mode request\", err);\n });\n };\n }\n\n function setMessage(message) {\n stage.innerHTML = '<div class=\"message\">' + esc(message) + '</div>';\n }\n\n function clearFrameReadyTimer() {\n if (!appFrameReadyTimer) return;\n clearTimeout(appFrameReadyTimer);\n appFrameReadyTimer = null;\n }\n\n function clearFrameLoadTimer() {\n if (!appFrameLoadTimer) return;\n clearTimeout(appFrameLoadTimer);\n appFrameLoadTimer = null;\n }\n\n function startFrameReadyTimer(frame) {\n clearFrameReadyTimer();\n appFrameReadyTimer = setTimeout(() => {\n if (!appFrameReady && appFrame === frame) renderFrameFallback();\n }, frameReadyTimeoutMs);\n }\n\n // Best-effort telemetry sink so inline-embed failures are visible in\n // Sentry (handshake timeout, transplant fetch status/CORS, auth, CSP).\n // The shell is a sandboxed opaque-origin iframe, so it POSTs to the app\n // origin's CORS-open /_agent-native/mcp/embed-error route, derived from the\n // known app URLs. Deduped per stage+message so a retry loop can't spam.\n const reportedEmbedErrorKeys = new Set();\n let embedErrorReportCount = 0;\n function embedReportOrigin() {\n for (const value of [openStartUrl, openUrl, lastFrameSrc]) {\n if (typeof value === \"string\" && value) {\n try { return new URL(value, window.location.href).origin; } catch {}\n }\n }\n return \"\";\n }\n function reportEmbedError(stage, message, detail, status) {\n try {\n const key = String(stage) + \"|\" + String(message || \"\");\n if (reportedEmbedErrorKeys.has(key) || embedErrorReportCount >= 8) return;\n reportedEmbedErrorKeys.add(key);\n embedErrorReportCount += 1;\n const origin = embedReportOrigin();\n if (!origin) return;\n let renderMode = \"\";\n try { renderMode = renderModeSource().mode || \"\"; } catch {}\n const body = JSON.stringify({\n stage: String(stage || \"\"),\n message: String(message || \"\").slice(0, 500),\n detail: detail ? String(detail).slice(0, 1200) : undefined,\n url: openStartUrl || openUrl || lastFrameSrc || \"\",\n status: typeof status === \"number\" ? status : undefined,\n host: window.location.hostname || \"\",\n renderMode: renderMode,\n bridge: openAiBridge ? \"openai\" : app ? \"native\" : \"none\",\n userAgent: navigator.userAgent || \"\"\n });\n fetch(origin + \"/_agent-native/mcp/embed-error\", {\n method: \"POST\",\n credentials: \"omit\",\n keepalive: true,\n headers: { \"Content-Type\": \"application/json\" },\n body: body\n }).catch(() => {});\n } catch {}\n }\n\n function renderFrameFallback() {\n clearFrameReadyTimer();\n clearFrameLoadTimer();\n appFrame = null;\n const fallbackCopy = openUrl\n ? \"This chat host did not allow the embedded app frame to load inline. You can still open the same app route through the host or use the URL below.\"\n : \"This chat host did not allow the embedded app frame to load inline.\";\n reportEmbedError(\"frame-fallback\", fallbackCopy);\n stage.innerHTML =\n '<div class=\"fallback\">' +\n '<div class=\"fallback-title\">Open this app in its own tab</div>' +\n '<div class=\"fallback-copy\">' + esc(fallbackCopy) + '</div>' +\n '<div class=\"fallback-actions\">' +\n '<button type=\"button\" class=\"primary\" data-fallback-open>Open in new tab</button>' +\n '<button type=\"button\" data-fallback-retry>Try inline again</button>' +\n '</div>' +\n (openUrl ? '<a class=\"fallback-url\" href=\"' + esc(openUrl) + '\" target=\"_blank\" rel=\"noreferrer\">' + esc(openUrl) + '</a>' : '') +\n '</div>';\n const fallbackOpen = stage.querySelector(\"[data-fallback-open]\");\n const fallbackRetry = stage.querySelector(\"[data-fallback-retry]\");\n if (fallbackOpen) {\n fallbackOpen.disabled = !openUrl;\n fallbackOpen.onclick = () => {\n if (openUrl) void openFallbackExternal();\n };\n }\n if (fallbackRetry) {\n fallbackRetry.disabled = !lastFrameSrc;\n fallbackRetry.onclick = () => {\n if (lastFrameSrc) renderFrame(lastFrameSrc);\n };\n }\n }\n\n function renderAppLaunchError(message) {\n clearFrameReadyTimer();\n clearFrameLoadTimer();\n appFrame = null;\n const fallbackCopy = openUrl\n ? \"The inline MCP app could not load in this chat host. You can open the same app route in a new tab or retry the inline load.\"\n : \"The inline MCP app could not load in this chat host.\";\n reportEmbedError(\"app-launch-error\", message || fallbackCopy, message);\n const copyHtml = message\n ? '<div>' + esc(message) + '</div><div>' + esc(fallbackCopy) + '</div>'\n : esc(fallbackCopy);\n stage.innerHTML =\n '<div class=\"fallback\">' +\n '<div class=\"fallback-title\">App did not load</div>' +\n '<div class=\"fallback-copy\">' + copyHtml + '</div>' +\n '<div class=\"fallback-actions\">' +\n '<button type=\"button\" class=\"primary\" data-fallback-open>Open in new tab</button>' +\n '<button type=\"button\" data-fallback-retry>Retry</button>' +\n '</div>' +\n (openUrl ? '<a class=\"fallback-url\" href=\"' + esc(openUrl) + '\" target=\"_blank\" rel=\"noreferrer\">' + esc(openUrl) + '</a>' : '') +\n '</div>';\n const fallbackOpen = stage.querySelector(\"[data-fallback-open]\");\n const fallbackRetry = stage.querySelector(\"[data-fallback-retry]\");\n if (fallbackOpen) {\n fallbackOpen.disabled = !openUrl;\n fallbackOpen.onclick = () => {\n if (openUrl) void openHostLink({ url: openUrl });\n };\n }\n if (fallbackRetry) {\n fallbackRetry.onclick = () => {\n startedFor = \"\";\n void launchEmbed();\n };\n }\n }\n\n async function openFallbackExternal() {\n if (!openUrl) return;\n let url = withChatBridgeParam(openUrl);\n try {\n if (url) {\n const result = await callEmbedSessionTool(embedSessionArgsFor(url));\n const data = parseToolResult(result);\n if (typeof data.startUrl === \"string\" && data.startUrl) {\n url = withChatBridgeParam(data.startUrl);\n }\n }\n } catch (err) {\n console.warn(\"[agent-native] MCP fallback could not mint a fresh app session\", err);\n }\n await openHostLink({ url });\n }\n\n function renderFrame(src) {\n clearFrameReadyTimer();\n clearFrameLoadTimer();\n const frame = document.createElement(\"iframe\");\n frame.title = body.dataset.iframeTitle || \"Agent Native app\";\n frame.src = src;\n frame.allow = \"clipboard-read; clipboard-write\";\n appFrame = frame;\n appFrameReady = false;\n lastFrameSrc = src;\n frame.addEventListener(\"load\", () => {\n if (appFrame !== frame) return;\n clearFrameLoadTimer();\n notifyOuterMcpAppReady();\n sendFrameReadyMessages(frame);\n startFrameReadyTimer(frame);\n });\n stage.replaceChildren(frame);\n notifyHostHeight();\n appFrameLoadTimer = setTimeout(() => {\n if (!appFrameReady && appFrame === frame) renderFrameFallback();\n }, frameLoadTimeoutMs);\n }\n\n function refreshExpiredEmbedSession() {\n clearFrameReadyTimer();\n clearFrameLoadTimer();\n appFrameReady = false;\n if (!openUrl) {\n renderFrameFallback();\n return;\n }\n if (embedSessionRefreshAttempts >= maxEmbedSessionRefreshAttempts) {\n renderAppLaunchError(\n \"Embedded app session expired. Reopen the app to mint a fresh session.\"\n );\n return;\n }\n embedSessionRefreshAttempts += 1;\n openStartUrl = \"\";\n startedFor = \"\";\n lastFrameSrc = \"\";\n setMessage(\"Refreshing app session\");\n void launchEmbed();\n }\n\n function shouldSelfNavigateToApp() {\n const render = renderModeSource();\n const mode = render.mode;\n if (isClaudeMcpContentHost()) return true;\n if (mode === \"iframe\" || mode === \"nested\") return false;\n if (render.nested || render.frame === \"iframe\") return false;\n return true;\n }\n\n function shouldTransplantAppDocument() {\n const render = renderModeSource();\n const mode = render.mode;\n if (mode === \"iframe\" || mode === \"nested\" || render.frame === \"iframe\" || render.nested) {\n return false;\n }\n // ChatGPT is excluded so it uses the controlled nested frame instead:\n // transplant would cross-origin import() app chunks in its opaque-origin\n // sandbox, which it blocks (blank embed). embedMode \"transplant\" still forces it.\n return (\n isClaudeMcpContentHost() ||\n mode === \"transplant\" ||\n render.frame === \"transplant\"\n );\n }\n\n function isClaudeMcpContentHost() {\n try {\n return /(^|\\\\.)claudemcpcontent\\\\.com$/i.test(window.location.hostname || \"\");\n } catch {\n return false;\n }\n }\n\n function isChatGptSandboxHost() {\n try {\n const host = window.location.hostname || \"\";\n const appParam = new URL(window.location.href).searchParams.get(\"app\");\n return /^(?:[^.]+\\\\.)?web-sandbox\\\\.oaiusercontent\\\\.com$/i.test(host) || appParam === \"chatgpt\";\n } catch {\n return false;\n }\n }\n\n function shouldRenderControlledAppFrame() {\n return !!openAiBridge || !!app || isChatGptSandboxHost();\n }\n\n function shouldDirectRenderKnownAppRoute(src) {\n return !!app && !openAiBridge && !isEmbedStartUrl(src) && !shouldTransplantAppDocument();\n }\n\n function isCurrentFrameUrl(src) {\n try {\n return new URL(src, window.location.href).href === window.location.href;\n } catch {\n return false;\n }\n }\n\n function navigateToAppFrame(src) {\n if (isCurrentFrameUrl(src)) {\n clearFrameReadyTimer();\n clearFrameLoadTimer();\n setMessage(\"App opened\");\n notifyHostHeightRepeatedly();\n return;\n }\n clearFrameReadyTimer();\n clearFrameLoadTimer();\n appFrame = null;\n lastFrameSrc = src;\n setMessage(\"Opening app\");\n try {\n window.location.replace(src);\n } catch (err) {\n console.warn(\"[agent-native] MCP app self-navigation failed\", err);\n renderFrameFallback();\n }\n }\n\n async function ensureHostAppConnected() {\n if (!app || typeof app.connect !== \"function\") return;\n if (!appConnectPromise) {\n appConnectPromise = Promise.resolve(app.connect())\n .then(async (value) => {\n // Let the host process ui/notifications/initialized before follow-up calls.\n await new Promise((resolve) => window.setTimeout(resolve, 0));\n await new Promise((resolve) => window.setTimeout(resolve, 0));\n return value;\n })\n .catch((err) => {\n appConnectPromise = null;\n throw err;\n });\n }\n await appConnectPromise;\n }\n\n async function updateHostModelContext(data) {\n const params = {};\n if (Array.isArray(data && data.content)) params.content = data.content;\n if (data && data.structuredContent && typeof data.structuredContent === \"object\") {\n params.structuredContent = data.structuredContent;\n }\n if (openAiBridge && typeof openAiBridge.setWidgetState === \"function\") {\n openAiBridge.setWidgetState({\n ...objectValue(openAiBridge.widgetState),\n agentNativeModelContext: params\n });\n return { ok: true };\n }\n if (!app || typeof app.updateModelContext !== \"function\") return { ok: false };\n await ensureHostAppConnected();\n await app.updateModelContext(params);\n return { ok: true };\n }\n\n async function openHostLink(data) {\n const url = typeof (data && data.url) === \"string\" ? data.url : \"\";\n if (!url) return { isError: true };\n if (openAiBridge && typeof openAiBridge.openExternal === \"function\") {\n return await openAiBridge.openExternal({ href: url, redirectUrl: false });\n }\n if (app && typeof app.openLink === \"function\") {\n return await app.openLink({ url });\n }\n window.open(url, \"_blank\", \"noopener,noreferrer\");\n return { ok: true };\n }\n\n function notifyHostHeight() {\n const height = applyIntrinsicHeight(visibleIntrinsicHeight());\n if (!openAiBridge || typeof openAiBridge.notifyIntrinsicHeight !== \"function\") {\n if (app && typeof app.sendSizeChanged === \"function\") {\n try {\n app.sendSizeChanged({ height });\n } catch (err) {\n console.warn(\"[agent-native] MCP host rejected size update\", err);\n }\n }\n return;\n }\n try {\n openAiBridge.notifyIntrinsicHeight({ height });\n } catch (err) {\n console.warn(\"[agent-native] ChatGPT rejected intrinsic height update\", err);\n }\n }\n\n function respondToAppFrame(requestId, work) {\n if (!requestId) return;\n Promise.resolve(work)\n .then((result) => {\n sendToAppFrame({\n type: \"agentNative.mcpHost.response\",\n data: { requestId, ok: true, result }\n });\n })\n .catch((err) => {\n sendToAppFrame({\n type: \"agentNative.mcpHost.response\",\n data: {\n requestId,\n ok: false,\n error: err && err.message ? err.message : String(err)\n }\n });\n });\n }\n\n async function sendHostChat(chat) {\n const requestId = typeof (chat && chat.requestId) === \"string\" ? chat.requestId : \"\";\n if (!chat || chat.submit === false) return;\n const message = typeof chat.message === \"string\" ? chat.message : \"\";\n if (!message.trim()) return;\n const context = typeof chat.context === \"string\" ? chat.context.trim() : \"\";\n const content = Array.isArray(chat.content) && chat.content.length\n ? chat.content\n : [{ type: \"text\", text: message }];\n const structuredContent =\n chat && chat.structuredContent !== undefined\n ? chat.structuredContent\n : undefined;\n try {\n const contextContent = context\n ? [{ type: \"text\", text: context }, ...content.filter((part) => part && part.type !== \"text\")]\n : content.filter((part) => part && part.type !== \"text\");\n const modelContext = {\n content: contextContent,\n ...(structuredContent !== undefined ? { structuredContent } : {})\n };\n if (openAiBridge && typeof openAiBridge.setWidgetState === \"function\") {\n openAiBridge.setWidgetState({\n ...objectValue(openAiBridge.widgetState),\n agentNativeChatContext: context || null,\n agentNativeModelContext: modelContext\n });\n } else if (app && typeof app.updateModelContext === \"function\") {\n await ensureHostAppConnected();\n await app.updateModelContext(modelContext);\n }\n } catch (err) {\n console.warn(\"[agent-native] MCP host rejected model context update\", err);\n }\n try {\n if (openAiBridge && typeof openAiBridge.sendFollowUpMessage === \"function\") {\n await openAiBridge.sendFollowUpMessage({\n prompt: message,\n scrollToBottom: true\n });\n respondToWrapperRequest(requestId, { ok: true });\n return;\n }\n let result = null;\n if (app && typeof app.sendMessage === \"function\") {\n await ensureHostAppConnected();\n result = await app.sendMessage({\n role: \"user\",\n content\n });\n } else {\n result = await wrapperRpcRequest(\"ui/message\", {\n role: \"user\",\n content\n });\n }\n if (result && result.isError) {\n console.warn(\"[agent-native] MCP host rejected chat message\", result);\n respondToWrapperRequest(requestId, { ok: false, result });\n return;\n }\n if (result && result.ok === false) {\n console.warn(\"[agent-native] MCP host chat bridge failed\", result);\n respondToWrapperRequest(requestId, { ok: false, result });\n return;\n }\n respondToWrapperRequest(requestId, { ok: true, result });\n } catch (err) {\n console.warn(\"[agent-native] MCP host chat bridge failed\", err);\n respondToWrapperRequest(requestId, { ok: false, error: err && err.message ? err.message : String(err) });\n }\n }\n\n window.addEventListener(\"message\", (event) => {\n if (event.source !== window.parent) return;\n const message = event.data;\n if (!message || message.jsonrpc !== \"2.0\") return;\n settleWrapperRpcResponse(message);\n });\n\n window.addEventListener(\"message\", (event) => {\n if (!appFrame || event.source !== appFrame.contentWindow) return;\n if (!event.data) return;\n const data = event.data.data || {};\n if (event.data.type === \"agentNative.embeddedAppReady\") {\n appFrameReady = true;\n embedSessionRefreshAttempts = 0;\n clearFrameLoadTimer();\n clearFrameReadyTimer();\n notifyOuterMcpAppReady();\n return;\n }\n if (event.data.type === \"agentNative.embedSessionExpired\") {\n refreshExpiredEmbedSession();\n return;\n }\n if (event.data.type === \"agentNative.submitChat\") {\n void sendHostChat(data);\n return;\n }\n if (event.data.type === \"agentNative.mcpHost.updateModelContext\") {\n respondToAppFrame(data.requestId, updateHostModelContext(data));\n return;\n }\n if (event.data.type === \"agentNative.mcpHost.openLink\") {\n respondToAppFrame(data.requestId, openHostLink(data));\n return;\n }\n if (event.data.type === \"agentNative.mcpHost.requestDisplayMode\") {\n respondToAppFrame(data.requestId, requestHostDisplayMode(data.mode));\n }\n });\n\n function notifyHostHeightSoon() {\n requestAnimationFrame(() => notifyHostHeight());\n }\n\n function notifyHostHeightRepeatedly() {\n notifyHostHeight();\n [0, 250, 1000, 2500].forEach((delay) => {\n setTimeout(() => notifyHostHeight(), delay);\n });\n }\n\n window.addEventListener(\"resize\", notifyHostHeightSoon, { passive: true });\n if (window.visualViewport) {\n window.visualViewport.addEventListener(\"resize\", notifyHostHeightSoon, { passive: true });\n }\n\n async function launchEmbed() {\n let launchUrl = openStartUrl || openUrl;\n if (!launchUrl) {\n renderAppLaunchError(\"Open link was not available.\");\n return;\n }\n if (!wantsEmbed()) {\n setMessage(\"Ready to open.\");\n return;\n }\n setMessage(\"Loading app\");\n try {\n const selfNavigate = shouldSelfNavigateToApp();\n if (startedFor === launchUrl) return;\n startedFor = launchUrl;\n const embedUrl = withChatBridgeParam(launchUrl);\n if (selfNavigate && isEmbedStartUrl(embedUrl)) {\n if (shouldTransplantAppDocument()) {\n await transplantAppDocument(embedUrl);\n } else if (shouldRenderControlledAppFrame()) {\n renderFrame(embedUrl);\n } else {\n navigateToAppFrame(embedUrl);\n }\n return;\n }\n if (!selfNavigate && isEmbedStartUrl(embedUrl)) {\n renderFrame(embedUrl);\n return;\n }\n if (shouldDirectRenderKnownAppRoute(embedUrl)) {\n renderFrame(embedUrl);\n return;\n }\n const result = await callEmbedSessionTool(embedSessionArgsFor(embedUrl));\n const data = parseToolResult(result);\n if (typeof data.startUrl !== \"string\" || !data.startUrl) {\n startedFor = \"\";\n renderAppLaunchError(data.error || \"This app can be opened, but not embedded from this MCP server.\");\n return;\n }\n const startUrl = withChatBridgeParam(data.startUrl);\n if (selfNavigate) {\n if (shouldTransplantAppDocument()) {\n await transplantAppDocument(startUrl);\n } else if (shouldRenderControlledAppFrame()) {\n renderFrame(startUrl);\n } else {\n navigateToAppFrame(startUrl);\n }\n } else {\n renderFrame(startUrl);\n }\n } catch (err) {\n startedFor = \"\";\n renderAppLaunchError(err && err.message ? err.message : \"Could not launch embedded app.\");\n }\n }\n\n async function callEmbedSessionTool(args) {\n if (openAiBridge && typeof openAiBridge.callTool === \"function\") {\n return await openAiBridge.callTool(startTool, args);\n }\n if (!app || typeof app.callServerTool !== \"function\") {\n throw new Error(\"Host tool calls are not available.\");\n }\n return await app.callServerTool({ name: startTool, arguments: args });\n }\n\n function updateHostOpenInAppUrl() {\n if (!openAiBridge || !openUrl || typeof openAiBridge.setOpenInAppUrl !== \"function\") {\n return;\n }\n try {\n openAiBridge.setOpenInAppUrl({ href: openUrl });\n } catch (err) {\n console.warn(\"[agent-native] ChatGPT rejected open-in-app URL\", err);\n }\n }\n\n function updateOpenButton() {\n const buttonUrl = openUrl;\n openButton.disabled = !buttonUrl;\n openButton.onclick = () => {\n if (buttonUrl) void openHostLink({ url: buttonUrl });\n };\n updateHostOpenInAppUrl();\n }\n\n function updateTitle(data) {\n const record = objectValue(data);\n const label = record.label || record.app || record.view || body.dataset.appTitle || \"App\";\n titleEl.textContent = String(label);\n }\n\n function readOpenAiBridge() {\n return window.openai && typeof window.openai === \"object\"\n ? window.openai\n : null;\n }\n\n function isChatGptHostHint() {\n try {\n if (new URLSearchParams(window.location.search).get(\"app\") === \"chatgpt\") return true;\n } catch (_err) {}\n try {\n if (/^(?:[^.]+\\\\.)?web-sandbox\\\\.oaiusercontent\\\\.com$/i.test(window.location.hostname || \"\")) return true;\n } catch (_err) {}\n try {\n return /chatgpt/i.test(String(navigator.userAgent || \"\"));\n } catch (_err) {\n return false;\n }\n }\n\n function openAiToolResultParams(bridge) {\n const params = {};\n if (bridge && bridge.toolOutput !== undefined) {\n if (bridge.toolOutput && typeof bridge.toolOutput === \"object\") {\n params.structuredContent = bridge.toolOutput;\n } else {\n params.content = [{ type: \"text\", text: String(bridge.toolOutput) }];\n }\n }\n if (bridge && bridge.toolResponseMetadata && typeof bridge.toolResponseMetadata === \"object\") {\n params._meta = bridge.toolResponseMetadata;\n }\n return params;\n }\n\n function syncOpenAiBridge(bridge) {\n if (!bridge) return false;\n openAiBridge = bridge;\n toolInput = objectValue(bridge.toolInput);\n const params = openAiToolResultParams(bridge);\n const data = parseToolResult(params);\n toolResultData = objectValue(data);\n openUrl = openLinkFrom(params, data);\n openStartUrl = embedStartUrlFrom(params, data);\n updateTitle(data);\n updateOpenButton();\n updateDisplayButton();\n notifyHostHeight();\n sendHostContext();\n if (openUrl || openStartUrl) {\n void launchEmbed();\n } else if (!appFrame) {\n setMessage(\"Waiting for app result\");\n }\n return true;\n }\n\n function waitForOpenAiBridge() {\n const existing = readOpenAiBridge();\n if (existing) return Promise.resolve(existing);\n return new Promise((resolve) => {\n let settled = false;\n let pollTimer = 0;\n const finish = (bridge) => {\n if (settled) return;\n settled = true;\n window.removeEventListener(\"openai:set_globals\", onGlobals);\n clearTimeout(timer);\n clearTimeout(pollTimer);\n resolve(bridge || readOpenAiBridge());\n };\n const poll = () => {\n const bridge = readOpenAiBridge();\n if (bridge) {\n finish(bridge);\n return;\n }\n pollTimer = window.setTimeout(poll, openAiBridgePollMs);\n };\n const onGlobals = () => finish(readOpenAiBridge());\n const timer = window.setTimeout(\n () => finish(null),\n isChatGptHostHint() ? chatGptOpenAiBridgeWaitMs : defaultOpenAiBridgeWaitMs\n );\n window.addEventListener(\"openai:set_globals\", onGlobals, { passive: true });\n pollTimer = window.setTimeout(poll, openAiBridgePollMs);\n });\n }\n\n window.addEventListener(\"openai:set_globals\", () => {\n const bridge = readOpenAiBridge();\n if (bridge && (!appFrame || openAiBridge)) syncOpenAiBridge(bridge);\n }, { passive: true });\n\n function createNativeMcpAppsBridge() {\n let rpcId = 0;\n let connectPromise = null;\n let hostContext = {};\n const pendingRequests = new Map();\n\n function rpcNotify(method, params) {\n window.parent.postMessage({ jsonrpc: \"2.0\", method, params: params || {} }, \"*\");\n }\n\n function rpcRequest(method, params, timeoutMs) {\n return new Promise((resolve, reject) => {\n const id = ++rpcId;\n const timer = window.setTimeout(() => {\n pendingRequests.delete(id);\n reject(new Error(\"MCP Apps bridge request timed out: \" + method));\n }, timeoutMs || nativeBridgeRequestTimeoutMs);\n pendingRequests.set(id, { resolve, reject, timer });\n window.parent.postMessage(\n { jsonrpc: \"2.0\", id, method, params: params || {} },\n \"*\"\n );\n });\n }\n\n function settleRpcResponse(message) {\n const pending = pendingRequests.get(message.id);\n if (!pending) return true;\n pendingRequests.delete(message.id);\n clearTimeout(pending.timer);\n if (message.error) {\n const error = new Error(message.error.message || \"MCP Apps bridge request failed.\");\n error.data = message.error.data;\n pending.reject(error);\n return true;\n }\n pending.resolve(message.result);\n return true;\n }\n\n function notificationParams(message) {\n return message && typeof message.params === \"object\" && message.params\n ? message.params\n : {};\n }\n\n function toolInputNotificationParams(params) {\n if (params && typeof params.arguments === \"object\" && params.arguments) {\n return params;\n }\n if (params && typeof params.input === \"object\" && params.input) {\n return { arguments: params.input };\n }\n return { arguments: objectValue(params) };\n }\n\n const nativeApp = {\n ontoolinput: null,\n ontoolresult: null,\n onhostcontextchanged: null,\n getHostContext() {\n return hostContext.context || hostContext;\n },\n getHostCapabilities() {\n return hostContext.capabilities || { tools: true, messaging: true };\n },\n getHostVersion() {\n return hostContext.protocolVersion || \"mcp-apps-postmessage\";\n },\n async connect() {\n if (connectPromise) return await connectPromise;\n connectPromise = (async () => {\n window.addEventListener(\"message\", onMessage, { passive: true });\n const result = await rpcRequest(\n \"ui/initialize\",\n {\n appInfo: { name: \"Agent Native Embed\", version: \"1.0.0\" },\n appCapabilities: {},\n protocolVersion: \"2026-01-26\"\n },\n nativeBridgeInitializeTimeoutMs\n );\n hostContext = objectValue(result);\n rpcNotify(\"ui/notifications/initialized\", {});\n if (typeof nativeApp.onhostcontextchanged === \"function\") {\n nativeApp.onhostcontextchanged(hostContext);\n }\n return hostContext;\n })().catch((err) => {\n connectPromise = null;\n throw err;\n });\n return await connectPromise;\n },\n async callServerTool(request) {\n await nativeApp.connect();\n const record = objectValue(request);\n return await rpcRequest(\"tools/call\", {\n name: record.name,\n arguments: objectValue(record.arguments)\n });\n },\n async updateModelContext(params) {\n await nativeApp.connect();\n return await rpcRequest(\"ui/update-model-context\", objectValue(params));\n },\n async openLink(params) {\n const url = typeof (params && params.url) === \"string\" ? params.url : \"\";\n if (!url) return { isError: true };\n try {\n return await rpcRequest(\"ui/open-link\", { url }, wrapperRequestTimeoutMs);\n } catch (err) {\n console.warn(\"[agent-native] MCP host open-link request failed\", err);\n }\n const opened = window.open(url, \"_blank\", \"noopener,noreferrer\");\n return opened ? { ok: true } : { isError: true };\n },\n async requestDisplayMode(params) {\n await nativeApp.connect();\n return await rpcRequest(\"ui/request-display-mode\", objectValue(params));\n },\n sendSizeChanged(params) {\n rpcNotify(\"ui/notifications/size-changed\", objectValue(params));\n },\n async sendMessage(params) {\n await nativeApp.connect();\n return await rpcRequest(\"ui/message\", objectValue(params));\n }\n };\n\n function onMessage(event) {\n if (event.source !== window.parent) return;\n const message = event.data;\n if (!message || message.jsonrpc !== \"2.0\") return;\n if (typeof message.id === \"number\" || typeof message.id === \"string\") {\n settleRpcResponse(message);\n return;\n }\n if (typeof message.method !== \"string\") return;\n const params = notificationParams(message);\n if (message.method === \"ui/notifications/tool-input\") {\n if (typeof nativeApp.ontoolinput === \"function\") {\n nativeApp.ontoolinput(toolInputNotificationParams(params));\n }\n return;\n }\n if (message.method === \"ui/notifications/tool-result\") {\n if (typeof nativeApp.ontoolresult === \"function\") {\n nativeApp.ontoolresult(params);\n }\n return;\n }\n if (\n message.method === \"ui/notifications/host-context-changed\" ||\n message.method === \"ui/notifications/host-context\" ||\n message.method === \"ui/notifications/context\"\n ) {\n hostContext = objectValue(params);\n if (typeof nativeApp.onhostcontextchanged === \"function\") {\n nativeApp.onhostcontextchanged(hostContext);\n }\n }\n }\n\n return nativeApp;\n }\n\n async function startNativeMcpAppsBridge() {\n app = createNativeMcpAppsBridge();\n appConnectPromise = null;\n app.ontoolinput = (params) => {\n toolInput = params.arguments || {};\n };\n app.ontoolresult = (params) => {\n const data = parseToolResult(params);\n toolResultData = objectValue(data);\n openUrl = openLinkFrom(params, data);\n openStartUrl = embedStartUrlFrom(params, data);\n updateTitle(data);\n updateOpenButton();\n void launchEmbed();\n };\n app.onhostcontextchanged = () => {\n updateDisplayButton();\n notifyHostHeight();\n sendHostContext();\n };\n await ensureHostAppConnected();\n notifyOuterMcpAppReady();\n updateDisplayButton();\n notifyHostHeight();\n sendHostContext();\n }\n\n async function startMcpAppsBridge() {\n const { App } = await import(\"${MCP_APP_IMPORT}\");\n app = new App(\n { name: \"Agent Native Embed\", version: \"1.0.0\" },\n {},\n { autoResize: false }\n );\n appConnectPromise = null;\n app.ontoolinput = (params) => {\n toolInput = params.arguments || {};\n };\n app.ontoolresult = (params) => {\n const data = parseToolResult(params);\n toolResultData = objectValue(data);\n openUrl = openLinkFrom(params, data);\n openStartUrl = embedStartUrlFrom(params, data);\n updateTitle(data);\n updateOpenButton();\n void launchEmbed();\n };\n app.onhostcontextchanged = () => {\n updateDisplayButton();\n notifyHostHeight();\n sendHostContext();\n };\n await ensureHostAppConnected();\n notifyOuterMcpAppReady();\n updateDisplayButton();\n notifyHostHeight();\n sendHostContext();\n }\n\n try {\n const initialOpenAiBridge = await waitForOpenAiBridge();\n if (!syncOpenAiBridge(initialOpenAiBridge)) {\n try {\n await startNativeMcpAppsBridge();\n } catch (nativeErr) {\n console.warn(\"[agent-native] native MCP Apps bridge failed\", nativeErr);\n await startMcpAppsBridge();\n }\n }\n } catch (err) {\n console.error(\"[agent-native] MCP app shell failed\", err);\n reportEmbedError(\n \"bridge-init\",\n err && err.message ? err.message : \"Could not initialize app.\",\n err && err.stack ? String(err.stack) : undefined\n );\n setMessage(err && err.message ? err.message : \"Could not initialize app.\");\n }\n\n window.addEventListener(\"error\", (event) => {\n const err = event && event.error;\n reportEmbedError(\n \"window-error\",\n (err && err.message) || (event && event.message) || \"Uncaught error in MCP app embed.\",\n err && err.stack ? String(err.stack) : undefined\n );\n });\n window.addEventListener(\"unhandledrejection\", (event) => {\n const reason = event && event.reason;\n reportEmbedError(\n \"unhandled-rejection\",\n (reason && reason.message) || String(reason || \"Unhandled promise rejection in MCP app embed.\"),\n reason && reason.stack ? String(reason.stack) : undefined\n );\n });\n })();\n </script>\n</body>\n</html>`,\n csp: {\n connectDomains: [\n \"https://esm.sh\",\n MCP_APP_REQUEST_ORIGIN_CSP_SOURCE,\n ...(options.connectDomains ?? []),\n ...(options.frameDomains ?? []),\n ],\n resourceDomains: [\n \"https://esm.sh\",\n MCP_APP_REQUEST_ORIGIN_CSP_SOURCE,\n ...(options.resourceDomains ?? []),\n ...(options.frameDomains ?? []),\n ],\n baseUriDomains: [\n MCP_APP_REQUEST_ORIGIN_CSP_SOURCE,\n ...(options.baseUriDomains ?? []),\n ],\n frameDomains,\n },\n prefersBorder: false,\n };\n}\n"]}
|
|
@@ -23,8 +23,8 @@ export declare function resolveAgentEngineApiKeyWriteTarget(event: H3Event, scop
|
|
|
23
23
|
error: string;
|
|
24
24
|
}>;
|
|
25
25
|
export declare function createAgentEngineApiKeyHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
26
|
-
ok?: undefined;
|
|
27
26
|
error: any;
|
|
27
|
+
ok?: undefined;
|
|
28
28
|
key?: undefined;
|
|
29
29
|
scope?: undefined;
|
|
30
30
|
} | {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.77.
|
|
3
|
+
"version": "0.77.2",
|
|
4
4
|
"description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|