@guuey/mcp-apps-host 0.3.0
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/LICENSE +21 -0
- package/README.md +29 -0
- package/dist/block-ui.d.ts +114 -0
- package/dist/block-ui.d.ts.map +1 -0
- package/dist/block-ui.js +173 -0
- package/dist/card-mount.d.ts +92 -0
- package/dist/card-mount.d.ts.map +1 -0
- package/dist/card-mount.js +103 -0
- package/dist/ggui-render.d.ts +120 -0
- package/dist/ggui-render.d.ts.map +1 -0
- package/dist/ggui-render.js +85 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/narrowing.d.ts +9 -0
- package/dist/narrowing.d.ts.map +1 -0
- package/dist/narrowing.js +8 -0
- package/package.json +66 -0
- package/src/block-ui.ts +205 -0
- package/src/card-mount.ts +149 -0
- package/src/ggui-render.ts +168 -0
- package/src/index.ts +36 -0
- package/src/narrowing.ts +19 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The **ggui render** channel: narrowing + self-contained shell construction
|
|
3
|
+
* for a generative-UI card produced by the ggui MCP server (`ggui_render`).
|
|
4
|
+
*
|
|
5
|
+
* ## Where the pieces live (guuey#108 / ggui#427)
|
|
6
|
+
*
|
|
7
|
+
* The two halves of this channel have different owners, and the module is
|
|
8
|
+
* split along that line:
|
|
9
|
+
*
|
|
10
|
+
* - **ggui's wire contract** — what makes a `_meta` slice a mountable
|
|
11
|
+
* render bootstrap, and what the self-contained shell must contain — is
|
|
12
|
+
* OWNED by ggui and imported from
|
|
13
|
+
* `@ggui-ai/protocol/integrations/mcp-apps` ({@link asGguiRenderBootstrap},
|
|
14
|
+
* {@link gguiShellHtml}, the `ai.ggui/render` key). This package used to
|
|
15
|
+
* carry byte-compatible private copies (lifted upstream as ggui#427);
|
|
16
|
+
* re-exporting the originals means a shell-contract change lands here by
|
|
17
|
+
* bumping the pin, not by mirror-editing two repos.
|
|
18
|
+
* - **host/silverprotocol shapes** — the `uiData`-keyed RECOGNITION signal,
|
|
19
|
+
* the `AgBlock` tool-result narrowing, and the `McpUiResourcePayload`
|
|
20
|
+
* adapter onto the host's existing mcp-ui mount path — are guuey-side
|
|
21
|
+
* contracts and stay implemented here.
|
|
22
|
+
*
|
|
23
|
+
* ## Why recognition and mounting are separate
|
|
24
|
+
*
|
|
25
|
+
* A ggui render's `tool.done` carries two distinct signals:
|
|
26
|
+
*
|
|
27
|
+
* 1. **`uiData.resourceUri` is the RECOGNITION signal.** It is the only part
|
|
28
|
+
* of the render's identity that survives `@silverprotocol/core`'s fold
|
|
29
|
+
* (the reducer copies `uiData` — and, as of `@silverprotocol/core`
|
|
30
|
+
* 0.4.1 (workspace#9), `_meta` — onto the `tool-result` block).
|
|
31
|
+
* 2. **`_meta["ai.ggui/render"]` is the MOUNT MATERIAL.** Everything needed
|
|
32
|
+
* to boot the card — which runtime bundle to load, which live-channel to
|
|
33
|
+
* open, which props to seed — lives there and nowhere else.
|
|
34
|
+
*
|
|
35
|
+
* The shell {@link gguiShellHtml} builds is a string of HTML, so the ggui
|
|
36
|
+
* card rides the host's EXISTING mcp-ui mount path unchanged: it narrows to
|
|
37
|
+
* the same `McpUiResourcePayload` an inline resource does, so
|
|
38
|
+
* `@mcp-ui/client`'s `AppRenderer` posts it as `srcdoc` into the
|
|
39
|
+
* second-origin `mcp-app-sandbox.html` page — same double-iframe rule, same
|
|
40
|
+
* sandbox origin, same opaque inner frame. No second mount mechanism.
|
|
41
|
+
*
|
|
42
|
+
* NOT in scope here: rehydrating a ggui card from persisted history. The
|
|
43
|
+
* bootstrap's `wsToken` expires minutes after the render, so a stored
|
|
44
|
+
* bootstrap is dead on arrival — a history card resolves to the `locator`
|
|
45
|
+
* channel (`card-mount.ts`, guuey#122) and remounts by a fresh
|
|
46
|
+
* `resources/read`, never a bootstrap replay.
|
|
47
|
+
*/
|
|
48
|
+
import type { AgBlock, JsonValue } from "@silverprotocol/core";
|
|
49
|
+
import {
|
|
50
|
+
asGguiRenderBootstrap,
|
|
51
|
+
gguiShellHtml,
|
|
52
|
+
MCP_APP_AI_GGUI_RENDER_META_KEY,
|
|
53
|
+
type GguiRenderBootstrap,
|
|
54
|
+
} from "@ggui-ai/protocol/integrations/mcp-apps";
|
|
55
|
+
import { isJsonObject, type McpUiResourcePayload } from "./block-ui.js";
|
|
56
|
+
|
|
57
|
+
export {
|
|
58
|
+
asGguiRenderBootstrap,
|
|
59
|
+
gguiShellHtml,
|
|
60
|
+
} from "@ggui-ai/protocol/integrations/mcp-apps";
|
|
61
|
+
export type {
|
|
62
|
+
GguiRenderBootstrap,
|
|
63
|
+
GguiShellHtmlOptions,
|
|
64
|
+
} from "@ggui-ai/protocol/integrations/mcp-apps";
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* The `_meta` key the ggui render bootstrap rides on. Alias of the
|
|
68
|
+
* protocol package's own constant — one spelling, owned upstream.
|
|
69
|
+
*/
|
|
70
|
+
export const GGUI_RENDER_META_KEY = MCP_APP_AI_GGUI_RENDER_META_KEY;
|
|
71
|
+
|
|
72
|
+
/** The `ui://` scheme prefix every ggui render resource uri carries. */
|
|
73
|
+
const UI_SCHEME = "ui://";
|
|
74
|
+
|
|
75
|
+
/** A ggui render recognised on a tool result: its resource uri + mount material. */
|
|
76
|
+
export interface GguiRenderDescriptor {
|
|
77
|
+
/** `uiData.resourceUri` — `ui://ggui/render/<sessionId>/<contractHash>`. */
|
|
78
|
+
resourceUri: string;
|
|
79
|
+
/** `uiData.sessionId`, when present. */
|
|
80
|
+
sessionId?: string;
|
|
81
|
+
/**
|
|
82
|
+
* The `_meta["ai.ggui/render"]` slice, when it reached us. Absent for a
|
|
83
|
+
* persisted history card and for any consumer folding without `fold.ts`'s
|
|
84
|
+
* `_meta` carriage — such a descriptor is recognised but NOT mountable.
|
|
85
|
+
*/
|
|
86
|
+
bootstrap?: GguiRenderBootstrap;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* A tool result's `uiData` (+ its `_meta`, when carried) → a ggui render
|
|
91
|
+
* descriptor, or `undefined` for anything that is not one.
|
|
92
|
+
*
|
|
93
|
+
* The `ui://` scheme gate is deliberate: `uiData` is a general-purpose channel
|
|
94
|
+
* (every `structuredContent` of a `_meta.ui`-stamped tool lands there), so a
|
|
95
|
+
* bare `resourceUri` string is not on its own a claim of generative UI.
|
|
96
|
+
*/
|
|
97
|
+
export function asGguiRender(
|
|
98
|
+
uiData: JsonValue | undefined,
|
|
99
|
+
meta: JsonValue | undefined,
|
|
100
|
+
): GguiRenderDescriptor | undefined {
|
|
101
|
+
if (!isJsonObject(uiData)) return undefined;
|
|
102
|
+
const resourceUri = uiData.resourceUri;
|
|
103
|
+
if (typeof resourceUri !== "string" || !resourceUri.startsWith(UI_SCHEME)) return undefined;
|
|
104
|
+
const bootstrap = asGguiRenderBootstrap(meta);
|
|
105
|
+
return {
|
|
106
|
+
resourceUri,
|
|
107
|
+
...(typeof uiData.sessionId === "string" ? { sessionId: uiData.sessionId } : {}),
|
|
108
|
+
...(bootstrap ? { bootstrap } : {}),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* A live `tool-result` AgBlock → its ggui render descriptor, if it is one.
|
|
114
|
+
*
|
|
115
|
+
* NOTE: `@ggui-ai/protocol/integrations/mcp-apps` exports a helper of the
|
|
116
|
+
* same name that narrows a spec-canonical MCP `CallToolResult` instead. This
|
|
117
|
+
* one is the silverprotocol-side twin — the input is the FOLDED block, whose
|
|
118
|
+
* `uiData`/`_meta` carriage is `@silverprotocol/core`'s contract, not ggui's.
|
|
119
|
+
*/
|
|
120
|
+
export function toolResultGguiRender(
|
|
121
|
+
block: Extract<AgBlock, { type: "tool-result" }>,
|
|
122
|
+
): GguiRenderDescriptor | undefined {
|
|
123
|
+
return asGguiRender(block.uiData, block._meta);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** An untyped (persisted-snapshot) block → its ggui render descriptor, if it is one. */
|
|
127
|
+
export function blockGguiRender(block: JsonValue): GguiRenderDescriptor | undefined {
|
|
128
|
+
if (!isJsonObject(block)) return undefined;
|
|
129
|
+
if (block.type !== "tool-result") return undefined;
|
|
130
|
+
return asGguiRender(block.uiData, block._meta);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* A ggui render descriptor → the mountable resource the host's existing
|
|
135
|
+
* mcp-ui path already knows how to mount, or `undefined` when the descriptor
|
|
136
|
+
* carries no bootstrap (history cards, and any fold that dropped `_meta`).
|
|
137
|
+
*
|
|
138
|
+
* The `uri` is the render's REAL `resourceUri` — the shell is the payload, not
|
|
139
|
+
* a renaming of the resource.
|
|
140
|
+
*
|
|
141
|
+
* The shell is built `background: 'transparent'`: every guuey host that
|
|
142
|
+
* mounts through this adapter (widget, portal web, Studio) draws its own
|
|
143
|
+
* card chrome around the iframe, so the host page composits behind the card.
|
|
144
|
+
* The upstream default (`'surface'`) is for standalone served documents —
|
|
145
|
+
* see `GguiShellHtmlOptions` in `@ggui-ai/protocol/integrations/mcp-apps`.
|
|
146
|
+
*
|
|
147
|
+
* **On `_meta` being required to MOUNT (but never to RECOGNISE).** Recognition
|
|
148
|
+
* — "this tool result is a ggui card" — is keyed on `uiData.resourceUri` alone
|
|
149
|
+
* and never waits for anything (see {@link asGguiRender}); nothing in this
|
|
150
|
+
* package is blocked on an upstream change. Mounting is different, and the
|
|
151
|
+
* requirement is ggui's, not ours: its runtime rejects a slice without
|
|
152
|
+
* `runtimeUrl` AND without at least one mode discriminator (`wsUrl`+`wsToken`,
|
|
153
|
+
* `codeUrl`, or `kind`) as `MALFORMED_BOOTSTRAP` and renders nothing. `uiData`
|
|
154
|
+
* carries none of those fields, so a bootstrap-less descriptor could only ever
|
|
155
|
+
* produce a blank frame; returning `undefined` and letting the host show its
|
|
156
|
+
* own placeholder is the honest answer, not a deferral. `@silverprotocol/core`'s
|
|
157
|
+
* `Reducer` is what puts `_meta` on the block for a live turn, in-repo, today.
|
|
158
|
+
*/
|
|
159
|
+
export function gguiRenderResource(
|
|
160
|
+
render: GguiRenderDescriptor,
|
|
161
|
+
): McpUiResourcePayload | undefined {
|
|
162
|
+
if (!render.bootstrap) return undefined;
|
|
163
|
+
return {
|
|
164
|
+
uri: render.resourceUri,
|
|
165
|
+
mimeType: "text/html",
|
|
166
|
+
text: gguiShellHtml(render.bootstrap, { background: "transparent" }),
|
|
167
|
+
};
|
|
168
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @guuey/mcp-apps-host — the MCP Apps (SEP-1865) Host role: view-mount
|
|
3
|
+
* narrowing, ui:// locator rehydration, sandbox-trust channels. See README +
|
|
4
|
+
* the conformance map (guuey#123).
|
|
5
|
+
*/
|
|
6
|
+
export {
|
|
7
|
+
asResourcePayload,
|
|
8
|
+
asUiResource,
|
|
9
|
+
blockUiResource,
|
|
10
|
+
isJsonObject,
|
|
11
|
+
resourceHtml,
|
|
12
|
+
scanProviderRawForUiResource,
|
|
13
|
+
snapshotUiResource,
|
|
14
|
+
toolResultUiResource,
|
|
15
|
+
uiLocator,
|
|
16
|
+
type McpUiResourcePayload,
|
|
17
|
+
} from "./block-ui.js";
|
|
18
|
+
export {
|
|
19
|
+
asGguiRender,
|
|
20
|
+
asGguiRenderBootstrap,
|
|
21
|
+
blockGguiRender,
|
|
22
|
+
gguiRenderResource,
|
|
23
|
+
gguiShellHtml,
|
|
24
|
+
toolResultGguiRender,
|
|
25
|
+
GGUI_RENDER_META_KEY,
|
|
26
|
+
type GguiRenderBootstrap,
|
|
27
|
+
type GguiRenderDescriptor,
|
|
28
|
+
type GguiShellHtmlOptions,
|
|
29
|
+
} from "./ggui-render.js";
|
|
30
|
+
export {
|
|
31
|
+
snapshotViewMount,
|
|
32
|
+
toolResultViewMount,
|
|
33
|
+
type UiResourceReader,
|
|
34
|
+
type ViewMount,
|
|
35
|
+
type ViewMountChannel,
|
|
36
|
+
} from "./card-mount.js";
|
package/src/narrowing.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Protocol-free subpath (`@guuey/mcp-apps-host/narrowing`): ONLY the
|
|
3
|
+
* recognition/narrowing helpers, so lean consumers (e.g. `@guuey/threads`'
|
|
4
|
+
* persistence projection) never pull `@ggui-ai/protocol` into their runtime
|
|
5
|
+
* graph through the barrel (which re-exports the ggui render arm until its
|
|
6
|
+
* retirement — conformance-map step 4).
|
|
7
|
+
*/
|
|
8
|
+
export {
|
|
9
|
+
asResourcePayload,
|
|
10
|
+
asUiResource,
|
|
11
|
+
blockUiResource,
|
|
12
|
+
isJsonObject,
|
|
13
|
+
resourceHtml,
|
|
14
|
+
scanProviderRawForUiResource,
|
|
15
|
+
snapshotUiResource,
|
|
16
|
+
toolResultUiResource,
|
|
17
|
+
uiLocator,
|
|
18
|
+
type McpUiResourcePayload,
|
|
19
|
+
} from "./block-ui.js";
|