@ggui-ai/mcp-server 0.1.0-rc.3 → 0.2.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +1 -1
  2. package/dist/build-mcp.d.ts +8 -8
  3. package/dist/build-mcp.d.ts.map +1 -1
  4. package/dist/build-mcp.js +53 -12
  5. package/dist/console-auth.d.ts +7 -7
  6. package/dist/console-auth.d.ts.map +1 -1
  7. package/dist/console-auth.js +4 -4
  8. package/dist/console-cache.d.ts +2 -2
  9. package/dist/console-cache.d.ts.map +1 -1
  10. package/dist/console-cache.js +10 -10
  11. package/dist/console-headers.d.ts +2 -2
  12. package/dist/console-headers.js +2 -2
  13. package/dist/console-payloads.d.ts +3 -3
  14. package/dist/console-payloads.d.ts.map +1 -1
  15. package/dist/console-payloads.js +10 -10
  16. package/dist/console-timeline.d.ts +12 -30
  17. package/dist/console-timeline.d.ts.map +1 -1
  18. package/dist/console-timeline.js +44 -45
  19. package/dist/index.d.ts +7 -7
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +5 -5
  22. package/dist/instructions-presets.d.ts +1 -1
  23. package/dist/instructions-presets.d.ts.map +1 -1
  24. package/dist/instructions-presets.js +40 -22
  25. package/dist/llm-backed-negotiator.d.ts +6 -6
  26. package/dist/llm-backed-negotiator.d.ts.map +1 -1
  27. package/dist/llm-backed-negotiator.js +92 -91
  28. package/dist/mcp-apps-inbound.d.ts +3 -3
  29. package/dist/mcp-apps-inbound.d.ts.map +1 -1
  30. package/dist/mcp-apps-inbound.js +28 -23
  31. package/dist/mcp-apps-outbound.d.ts +136 -121
  32. package/dist/mcp-apps-outbound.d.ts.map +1 -1
  33. package/dist/mcp-apps-outbound.js +384 -414
  34. package/dist/mcp-mounts.d.ts +21 -20
  35. package/dist/mcp-mounts.d.ts.map +1 -1
  36. package/dist/mcp-mounts.js +25 -29
  37. package/dist/{session-channel.d.ts → render-channel.d.ts} +145 -102
  38. package/dist/render-channel.d.ts.map +1 -0
  39. package/dist/{session-channel.js → render-channel.js} +481 -462
  40. package/dist/schema-compat.d.ts +11 -11
  41. package/dist/schema-compat.d.ts.map +1 -1
  42. package/dist/schema-compat.js +6 -6
  43. package/dist/server.d.ts +224 -219
  44. package/dist/server.d.ts.map +1 -1
  45. package/dist/server.js +1498 -1963
  46. package/dist/storage.d.ts +7 -7
  47. package/dist/storage.d.ts.map +1 -1
  48. package/dist/storage.js +12 -12
  49. package/package.json +12 -11
  50. package/dist/render-gate.d.ts +0 -87
  51. package/dist/render-gate.d.ts.map +0 -1
  52. package/dist/render-gate.js +0 -77
  53. package/dist/render-rate-limit.d.ts +0 -59
  54. package/dist/render-rate-limit.d.ts.map +0 -1
  55. package/dist/render-rate-limit.js +0 -73
  56. package/dist/render-signing.d.ts +0 -98
  57. package/dist/render-signing.d.ts.map +0 -1
  58. package/dist/render-signing.js +0 -113
  59. package/dist/session-channel.d.ts.map +0 -1
package/dist/server.d.ts CHANGED
@@ -37,32 +37,32 @@
37
37
  * handlers wired up. The `Logger.warn('dev_mode_auth_enabled')` fires
38
38
  * once at boot so operators see the shape they're running.
39
39
  */
40
- import { type Express, type Request } from 'express';
41
- import { Server as NodeHttpServer } from 'node:http';
42
- import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
43
- import { type ThemeWriter, type ThemeFileUploader } from './console-theme-routes.js';
44
- import { type ZodRawShape } from 'zod';
45
- import type { AppMetadataStore, AuditSink, AuthAdapter, AuthResult, BlueprintProvider, BlueprintSearch, BlueprintSelector, BlueprintStore, ConnectorRegistry, CodeStore, EmbeddingProvider, GeneratorRegistry, KeyValueStore, PairingService, PendingEventConsumer, ProviderKeyStore, RateLimiter, SessionStore, SessionStreamBuffer, ShortCodeIndex, TelemetrySink, ThreadStore, VectorStore } from '@ggui-ai/mcp-server-core';
46
- import type { Blueprint } from '@ggui-ai/protocol';
47
- import type { DiscoveredPrimitiveCatalog, LoadedTheme } from '@ggui-ai/project-config/node';
48
- import type { OperatorConfig } from '@ggui-ai/project-config';
49
- import type { SharedHandler } from '@ggui-ai/mcp-server-handlers';
50
- import { type ThemeCatalogEntry } from '@ggui-ai/mcp-server-handlers/app-discovery';
51
- import { type AppsSource, type UserDefaultAppSource } from '@ggui-ai/mcp-server-handlers/ops-apps';
52
- import { type OrgsSource, type OrgInvitesSource } from '@ggui-ai/mcp-server-handlers/ops-orgs';
53
- import { type ConnectorKeysSource } from '@ggui-ai/mcp-server-handlers/ops-connector-keys';
54
- import { type CouponRedeemSource } from '@ggui-ai/mcp-server-handlers/ops-coupon';
55
- import type { UiRegistry } from '@ggui-ai/ui-registry';
56
- import { type ChannelNotifier, type GenerationCredentials, type GenerationDeps, type HandshakeNegotiator, type PropsUpdateNotifier, type ProvisionalPreviewDeps, type ProvisionalPreviewEmitter, type ProvisionalPreviewConfig, type ProvisionalPreviewOutcome } from '@ggui-ai/mcp-server-handlers/session-mutations';
57
- import { type ServerInfo } from './build-mcp.js';
58
- import { type OAuthConfig } from './oauth.js';
59
- import { type Logger } from './logger.js';
60
- import { type EmailSender, type MagicLinkStore } from './email-login.js';
61
- import { type McpInstructionsValue } from './instructions-presets.js';
62
- import { type ThreadOwnerResolver } from './thread-transport.js';
63
- import { type SessionChannelServer, type WiredActionRouter } from './session-channel.js';
64
- import { type McpServerMount, type McpService } from './mcp-mounts.js';
65
- import { type SchemaCompatMode } from './schema-compat.js';
40
+ import type { AppMetadataStore, AuditSink, AuthAdapter, AuthResult, BlueprintProvider, BlueprintSearch, BlueprintSelector, BlueprintStore, CodeStore, ConnectorRegistry, EmbeddingProvider, GeneratorRegistry, KeyValueStore, PairingService, PendingEventConsumer, ProviderKeyStore, RateLimiter, RenderStore, SessionStreamBuffer, ShortCodeIndex, TelemetrySink, ThreadStore, VectorStore } from "@ggui-ai/mcp-server-core";
41
+ import type { SharedHandler } from "@ggui-ai/mcp-server-handlers";
42
+ import { type ThemeCatalogEntry } from "@ggui-ai/mcp-server-handlers/app-discovery";
43
+ import type { OperatorConfig } from "@ggui-ai/project-config";
44
+ import type { DiscoveredPrimitiveCatalog, LoadedTheme } from "@ggui-ai/project-config/node";
45
+ import type { Blueprint } from "@ggui-ai/protocol";
46
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
47
+ import { type Express, type Request } from "express";
48
+ import { Server as NodeHttpServer } from "node:http";
49
+ import { type ZodRawShape } from "zod";
50
+ import { type ThemeFileUploader, type ThemeWriter } from "./console-theme-routes.js";
51
+ import { type AppsSource, type UserDefaultAppSource } from "@ggui-ai/mcp-server-handlers/ops-apps";
52
+ import { type ConnectorKeysSource } from "@ggui-ai/mcp-server-handlers/ops-connector-keys";
53
+ import { type CouponRedeemSource } from "@ggui-ai/mcp-server-handlers/ops-coupon";
54
+ import { type OrgInvitesSource, type OrgsSource } from "@ggui-ai/mcp-server-handlers/ops-orgs";
55
+ import { type ChannelNotifier, type GenerationCredentials, type GenerationDeps, type HandshakeNegotiator, type PropsUpdateNotifier, type ProvisionalPreviewConfig, type ProvisionalPreviewDeps, type ProvisionalPreviewEmitter, type ProvisionalPreviewOutcome } from "@ggui-ai/mcp-server-handlers/renders";
56
+ import type { UiRegistry } from "@ggui-ai/ui-registry";
57
+ import { type ServerInfo } from "./build-mcp.js";
58
+ import { type EmailSender, type MagicLinkStore } from "./email-login.js";
59
+ import { type McpInstructionsValue } from "./instructions-presets.js";
60
+ import { type Logger } from "./logger.js";
61
+ import { type McpServerMount, type McpService } from "./mcp-mounts.js";
62
+ import { type OAuthConfig } from "./oauth.js";
63
+ import { type RenderChannelServer, type WiredActionRouter } from "./render-channel.js";
64
+ import { type SchemaCompatMode } from "./schema-compat.js";
65
+ import { type ThreadOwnerResolver } from "./thread-transport.js";
66
66
  export declare function defaultHandlers(deps: {
67
67
  readonly embedding: EmbeddingProvider;
68
68
  readonly vectors: VectorStore;
@@ -93,24 +93,24 @@ export declare function defaultHandlers(deps: {
93
93
  readonly uiRegistry?: UiRegistry;
94
94
  /**
95
95
  * Handshake-state KV store. When bound, `ggui_handshake` is
96
- * registered and the paired `ggui_push({handshakeId})` consume
96
+ * registered and the paired `ggui_render({handshakeId})` consume
97
97
  * path is enabled. Both handlers share the same instance so the
98
98
  * write + read sit on one source of truth.
99
99
  *
100
100
  * Absent = handshake handler is NOT registered AND
101
- * `ggui_push({handshakeId})` falls back to a rejection shape.
101
+ * `ggui_render({handshakeId})` falls back to a rejection shape.
102
102
  */
103
103
  readonly handshake?: {
104
104
  readonly kvStore: KeyValueStore;
105
105
  /**
106
- * Optional session store. When bound, `ggui_handshake` validates
107
- * the wire `sessionId` against this store (existence + tenant
106
+ * Optional render store. When bound, `ggui_handshake` validates
107
+ * the wire render id against this store (existence + tenant
108
108
  * ownership) before negotiating. OSS sets this to the same store
109
- * push uses so the handshake catches unknown / cross-tenant ids
110
- * at the earliest boundary; cloud pods omit and validate at push
111
- * time via their own DDB-backed path.
109
+ * the render-commit handler uses so the handshake catches unknown
110
+ * / cross-tenant ids at the earliest boundary; cloud pods omit and
111
+ * validate at render-commit time via their own DDB-backed path.
112
112
  */
113
- readonly sessionStore?: SessionStore;
113
+ readonly renderStore?: RenderStore;
114
114
  /**
115
115
  * Optional negotiator binding. Absent = `ggui_handshake` stamps
116
116
  * `action: 'create'` + honest no-negotiator reason on the record
@@ -133,25 +133,18 @@ export declare function defaultHandlers(deps: {
133
133
  * subscribe-for vs. must iframe-poll directly. Returning
134
134
  * `undefined` omits the field (universal iframe-polling fallback).
135
135
  */
136
- readonly serverCapabilities?: () => import('@ggui-ai/protocol').ServerCapabilities | undefined;
136
+ readonly serverCapabilities?: () => import("@ggui-ai/protocol").ServerCapabilities | undefined;
137
137
  };
138
138
  readonly push?: {
139
- readonly sessionStore: SessionStore;
140
- readonly renderBaseUrl: string;
139
+ readonly renderStore: RenderStore;
141
140
  /**
142
- * Optional render-URL signer. Returns the query suffix to append
143
- * to a minted URL (`sig=...&exp=...`, no leading `?` or `&`).
144
- * Absent when `renderSigning: false` is set on boot.
145
- * Mirrors the handler-side dep with the same name.
141
+ * Optional bootstrap-credential minter. When present, `ggui_render`
142
+ * (the renamed render-commit tool) results carry the
143
+ * `ai.ggui/render` slice meta. When absent, they don't —
144
+ * non-MCP-Apps hosts read `{renderId}` off structuredContent and
145
+ * resolve the render-resource themselves.
146
146
  */
147
- readonly signRenderUrl?: (shortCode: string) => string;
148
- /**
149
- * Optional bootstrap-credential minter. When present, `ggui_push`
150
- * results carry `_meta.ggui.bootstrap`. When absent, they don't —
151
- * non-MCP-Apps hosts still get `structuredContent.url` as the
152
- * fallback link.
153
- */
154
- readonly mintBootstrap?: (sessionId: string, appId: string) => {
147
+ readonly mintBootstrap?: (renderId: string, appId: string) => {
155
148
  wsUrl: string;
156
149
  token: string;
157
150
  expiresAt: string;
@@ -159,7 +152,7 @@ export declare function defaultHandlers(deps: {
159
152
  /**
160
153
  * URL of the renderer bundle the thin-shell HTML should fetch
161
154
  * (C8 — plan §C8). Padded onto
162
- * {@link GguiBootstrapMeta.runtimeUrl} at `resultMeta` time.
155
+ * {@link McpAppAiGguiRenderMeta.runtimeUrl} at `resultMeta` time.
163
156
  * Same-origin default is `/_ggui/iframe-runtime.js`; hosted cloud
164
157
  * operators override to a CDN URL. Required when `mintBootstrap`
165
158
  * is set (the thin shell depends on it); otherwise ignored.
@@ -174,13 +167,13 @@ export declare function defaultHandlers(deps: {
174
167
  readonly runtimeUrl?: string | (() => string | undefined);
175
168
  /**
176
169
  * Theme preset id resolved from `ggui.json#theme`. Forwarded onto
177
- * `_meta.ggui.bootstrap.themeId` in the `ggui_push` resultMeta so
178
- * MCP Apps hosts (claude.ai, Claude Desktop) propagate the
179
- * operator's theme into the iframe.
170
+ * the `ai.ggui/render.themeId` slice field in the `ggui_render`
171
+ * resultMeta so MCP Apps hosts (claude.ai, Claude Desktop)
172
+ * propagate the operator's theme into the iframe.
180
173
  */
181
174
  readonly themeId?: string;
182
175
  /** Theme color mode resolved from `ggui.json#theme.mode`. */
183
- readonly themeMode?: 'light' | 'dark';
176
+ readonly themeMode?: "light" | "dark";
184
177
  /**
185
178
  * Live theme getter — resolved per-push. When set, supersedes
186
179
  * the static `themeId` / `themeMode` for every push's bootstrap.
@@ -192,7 +185,7 @@ export declare function defaultHandlers(deps: {
192
185
  */
193
186
  readonly themeProvider?: () => {
194
187
  readonly id?: string;
195
- readonly mode?: 'light' | 'dark';
188
+ readonly mode?: "light" | "dark";
196
189
  } | undefined;
197
190
  /**
198
191
  * Optional connector registry — required for accepting
@@ -201,16 +194,16 @@ export declare function defaultHandlers(deps: {
201
194
  */
202
195
  readonly connectors?: ConnectorRegistry;
203
196
  /**
204
- * Optional admission-control limiter. When present, `ggui_push`
197
+ * Optional admission-control limiter. When present, `ggui_render`
205
198
  * gates every call through `rateLimiter.check({key:
206
- * 'ggui_push:<appId>', cost:1})` before doing any work; denial
199
+ * 'ggui_render:<appId>', cost:1})` before doing any work; denial
207
200
  * surfaces as a `RateLimitedError`. Omitted = unlimited (the
208
201
  * `NoopRateLimiter` server default).
209
202
  */
210
203
  readonly rateLimiter?: RateLimiter;
211
204
  /**
212
205
  * Optional shortCode → session binding index. When present,
213
- * `ggui_push` records every minted `shortCode` so console's
206
+ * `ggui_render` records every minted `shortCode` so console's
214
207
  * `/s/<shortCode>` viewer (via the session-cookie endpoint) can
215
208
  * resolve it back to the right session. Absent = hosted cloud
216
209
  * flow (DynamoDB side-table owns lookups), or console not
@@ -218,83 +211,83 @@ export declare function defaultHandlers(deps: {
218
211
  */
219
212
  readonly shortCodeIndex?: ShortCodeIndex;
220
213
  /**
221
- * Optional provisional-preview wiring. When present, `ggui_push`
214
+ * Optional provisional-preview wiring. When present, `ggui_render`
222
215
  * kicks off the configured emitter on every qualifying push (the
223
216
  * `evaluateProvisionalPreviewGate` predicate filters MCP Apps
224
217
  * pushes + storyless calls automatically). Absent = no preview
225
218
  * channel traffic.
226
219
  *
227
220
  * Constructed by `createGguiServer` from `opts.provisionalPreview`
228
- * plus the late-bound `SessionChannelServer.sendToSession`
221
+ * plus the late-bound `RenderChannelServer.sendToSession`
229
222
  * closure; callers threading their own handler set can build
230
223
  * `ProvisionalPreviewDeps` directly.
231
224
  */
232
225
  readonly provisionalPreview?: ProvisionalPreviewDeps;
233
226
  /**
234
- * Optional generation wiring. When present, `ggui_push` invokes
227
+ * Optional generation wiring. When present, `ggui_render` invokes
235
228
  * the supplied {@link UiGenerator} on every story-path call and
236
- * appends the generated `StackItem` to the session before
237
- * returning `codeReady: true`. Absent = push stays in
238
- * placeholder mode (session + shortCode + preview still work,
239
- * but no componentCode is produced).
229
+ * commits the generated `Render` before returning `codeReady:
230
+ * true`. Absent = push stays in placeholder mode (render +
231
+ * shortCode + preview still work, but no componentCode is
232
+ * produced).
240
233
  *
241
234
  * Callers compose the `GenerationDeps` directly via the
242
235
  * `@ggui-ai/mcp-server-handlers` export — `defaultHandlers`
243
- * simply threads the bundle through to `createGguiPushHandler`.
236
+ * simply threads the bundle through to `createGguiRenderHandler`.
244
237
  */
245
238
  readonly generation?: GenerationDeps;
246
239
  /**
247
- * Optional live-subscriber stack-push notifier.
248
- * When present, every successful `appendStackItem` inside `ggui_push`
249
- * fan-outs a `{type:'push', payload:{stackItem}}` live-channel frame to
250
- * every live subscriber on the affected session. Forwarded as-is
251
- * to `createGguiPushHandler`.
240
+ * Optional live-subscriber render-commit notifier.
241
+ * When present, every successful `renderStore.commit` inside `ggui_render`
242
+ * fan-outs a `{type:'render', payload:{render}}` live-channel frame to
243
+ * every live subscriber on the affected render. Forwarded as-is
244
+ * to `createGguiRenderHandler`.
252
245
  *
253
- * Hosts without a session channel (programmatic embedding, Lambda
246
+ * Hosts without a render channel (programmatic embedding, Lambda
254
247
  * one-shot) leave this absent — there are no live subscribers to
255
- * notify, and the push handler's own no-op-on-absent posture
248
+ * notify, and the render handler's own no-op-on-absent posture
256
249
  * keeps the path intact.
257
250
  */
258
251
  readonly channelNotifier?: ChannelNotifier;
259
252
  /**
260
253
  * Optional F4 schema compat check hook. When present,
261
- * `ggui_push` invokes it immediately
262
- * before every `appendStackItem` — if the pending StackItem's
254
+ * `ggui_render` invokes it immediately
255
+ * before every `renderStore.commit` — if the pending Render's
263
256
  * `actionSpec` / `streamSpec` references a tool whose schemas
264
257
  * disagree, the hook throws `SchemaCompatError` and the handler
265
- * converts the rejection into an error stack-item + `codeReady:
266
- * false`. Forwarded as-is to `createGguiPushHandler`.
258
+ * converts the rejection into an error render + `codeReady:
259
+ * false`. Forwarded as-is to `createGguiRenderHandler`.
267
260
  *
268
261
  * `createGguiServer` binds this closure against the composed
269
262
  * `handlers` list + `opts.schemaCompatCheck` (default `'reject'`)
270
263
  * automatically; callers composing their own push handler via
271
264
  * `defaultHandlers` wire the hook themselves.
272
265
  */
273
- readonly checkStackItemContracts?: (shape: {
274
- readonly actionSpec?: import('@ggui-ai/protocol').ActionSpec;
275
- readonly streamSpec?: import('@ggui-ai/protocol').StreamSpec;
266
+ readonly checkRenderContracts?: (shape: {
267
+ readonly actionSpec?: import("@ggui-ai/protocol").ActionSpec;
268
+ readonly streamSpec?: import("@ggui-ai/protocol").StreamSpec;
276
269
  }) => void;
277
270
  /**
278
271
  * Optional content-addressable code store. When present together
279
- * with {@link codeBaseUrl}, `ggui_push` writes generated
272
+ * with {@link codeBaseUrl}, `ggui_render` writes generated
280
273
  * componentCode to the store and surfaces `codeUrl` + `codeHash`
281
274
  * on the response — the sole static-component delivery channel
282
275
  * post-T3-1 (2026-05-13).
283
276
  *
284
- * Absent: `ggui_push.resultMeta` omits `codeUrl`. The iframe boots
277
+ * Absent: `ggui_render.resultMeta` omits `codeUrl`. The iframe boots
285
278
  * via live-mode (wsUrl+token) and receives the stack item via the
286
- * live-channel WS subscribe. `/r/<shortCode>` + `/api/bootstrap/<shortCode>`
279
+ * live-channel WS subscribe. `/r/<shortCode>` (HTML default; JSON branch on `Accept: application/json`)
287
280
  * routes ALSO mint `codeUrl` when `codeStore` is set — they derive
288
281
  * the base URL from `req.protocol + req.host` when `codeBaseUrl`
289
282
  * isn't explicit (works for local dev + tunnel deployments).
290
- * Forwarded as-is to `createGguiPushHandler`.
283
+ * Forwarded as-is to `createGguiRenderHandler`.
291
284
  */
292
285
  readonly codeStore?: CodeStore;
293
286
  /**
294
287
  * Base URL the code-blob route resolves to. Required when
295
288
  * `codeStore` is present so the handler can compose
296
289
  * `<base>/code/<hash>.js`. Forwarded as-is to
297
- * `createGguiPushHandler`.
290
+ * `createGguiRenderHandler`.
298
291
  */
299
292
  readonly codeBaseUrl?: string;
300
293
  /**
@@ -330,53 +323,55 @@ export declare function defaultHandlers(deps: {
330
323
  * `channelBootstrap.refresh` so the OSS factory's behavior matches
331
324
  * the cloud pod's tool-side composition.
332
325
  */
333
- readonly bootstrapRefresh?: import('@ggui-ai/mcp-server-handlers/session-mutations').BootstrapRefreshSeam;
326
+ readonly bootstrapRefresh?: import("@ggui-ai/mcp-server-handlers/renders").WsTokenRefreshSeam;
334
327
  };
335
328
  /**
336
329
  * `ggui_update` wiring. When present, register the OSS update
337
- * handler against the supplied SessionStore + optional live-channel
338
- * props_update notifier. The handler reads sessionId / stackItemId
339
- * from wire input today, but a future in-process dispatcher can
340
- * populate them on the canonical context.
330
+ * handler against the supplied RenderStore + optional live-channel
331
+ * props_update notifier. The handler reads `renderId` from wire
332
+ * input today, but a future in-process dispatcher can populate it
333
+ * on the canonical context.
341
334
  *
342
335
  * Absent = `ggui_update` is NOT registered on this server. Hosts
343
336
  * that don't expose props mutation keep the smaller surface (e.g.,
344
337
  * static-blueprint demos, MCP-Apps-only deployments).
345
338
  */
346
339
  readonly update?: {
347
- readonly sessionStore: SessionStore;
340
+ readonly renderStore: RenderStore;
348
341
  /**
349
342
  * Optional live-subscriber `props_update` notifier — typically a
350
- * thin closure over `SessionChannelServer.sendPropsUpdate`.
343
+ * thin closure over `RenderChannelServer.sendPropsUpdate`.
351
344
  * Forwarded as-is to `createGguiUpdateHandler`. Hosts without a
352
- * session channel leave this absent; the handler still persists
353
- * via `sessionStore.appendStackItem` on every successful patch.
345
+ * render channel leave this absent; the handler still persists
346
+ * via `renderStore.commit` on every successful patch.
354
347
  */
355
348
  readonly propsUpdateNotifier?: PropsUpdateNotifier;
356
349
  /**
357
350
  * Bootstrap-credential minter (live trio). When wired, the
358
- * `ggui_update` resultMeta emits `_meta.ggui.bootstrap` so MCP Apps
359
- * hosts that re-post `ui/notifications/tool-result` via postMessage
360
- * can re-apply patched props on the live mount without re-subscribing.
361
- * Mirrors the same field on `push` deps; composing hosts wire both
362
- * from the same minter.
351
+ * `ggui_update` resultMeta emits the `ai.ggui/render` slice
352
+ * so MCP Apps hosts that re-post
353
+ * `ui/notifications/tool-result` via postMessage can re-apply
354
+ * patched props on the live mount without re-subscribing. Mirrors
355
+ * the same field on `render` deps; composing hosts wire both from
356
+ * the same minter.
363
357
  */
364
- readonly mintBootstrap?: (sessionId: string, appId: string) => {
358
+ readonly mintBootstrap?: (renderId: string, appId: string) => {
365
359
  wsUrl: string;
366
360
  token: string;
367
361
  expiresAt: string;
368
362
  };
369
- /** Iframe-runtime bundle URL forwarded onto bootstrap.runtimeUrl.
363
+ /** Iframe-runtime bundle URL forwarded onto the
364
+ * `ai.ggui/render.runtimeUrl` slice field.
370
365
  * Function form mirrors push deps — see {@link BuildMcpDeps.push}. */
371
366
  readonly runtimeUrl?: string | (() => string | undefined);
372
- /** Theme preset id forwarded onto bootstrap.themeId. */
367
+ /** Theme preset id forwarded onto the `ai.ggui/render.themeId` slice field. */
373
368
  readonly themeId?: string;
374
- /** Theme color mode forwarded onto bootstrap.themeMode. */
375
- readonly themeMode?: 'light' | 'dark';
369
+ /** Theme color mode forwarded onto the `ai.ggui/render.themeMode` slice field. */
370
+ readonly themeMode?: "light" | "dark";
376
371
  /** Live theme getter — overrides static themeId/themeMode per-update. */
377
372
  readonly themeProvider?: () => {
378
373
  readonly id?: string;
379
- readonly mode?: 'light' | 'dark';
374
+ readonly mode?: "light" | "dark";
380
375
  } | undefined;
381
376
  /** Returns names of app-visible tools for bootstrap.appCallableTools. */
382
377
  readonly appCallableTools?: () => readonly string[];
@@ -389,19 +384,19 @@ export declare function defaultHandlers(deps: {
389
384
  * default; pass `consume.pendingEventConsumer` to override (e.g.,
390
385
  * SQLite-backed for persistent dev or a Dynamo adapter on cloud).
391
386
  *
392
- * `defaultSessionTtlSeconds` controls the activity-bump TTL the
387
+ * `defaultRenderTtlSeconds` controls the activity-bump TTL the
393
388
  * handler forwards to `consumeAndClear` on every read. Falls back
394
389
  * to 1 day when omitted.
395
390
  */
396
391
  readonly consume?: {
397
392
  readonly pendingEventConsumer?: PendingEventConsumer;
398
- readonly defaultSessionTtlSeconds?: number;
393
+ readonly defaultRenderTtlSeconds?: number;
399
394
  };
400
395
  /**
401
396
  * Stream channel wiring for `ggui_emit`. When `push` is bound, the
402
397
  * handler registers automatically; its `sendEnvelope` closes over
403
398
  * `stream.channelProvider`, a lazy getter that resolves the
404
- * `SessionChannelServer` at emit time (the channel is constructed
399
+ * `RenderChannelServer` at emit time (the channel is constructed
405
400
  * AFTER `defaultHandlers` runs, so a static reference would always
406
401
  * be null on the OSS in-process boot).
407
402
  *
@@ -410,10 +405,10 @@ export declare function defaultHandlers(deps: {
410
405
  * cloud's `ggui_emit_accepted_no_receiver` posture.
411
406
  *
412
407
  * The getter pattern lets the OSS server bind once at boot, then
413
- * mutate the cell after `createSessionChannelServer` runs.
408
+ * mutate the cell after `createRenderChannelServer` runs.
414
409
  */
415
410
  readonly stream?: {
416
- readonly channelProvider?: () => SessionChannelServer | null;
411
+ readonly channelProvider?: () => RenderChannelServer | null;
417
412
  };
418
413
  /**
419
414
  * Structured-event logger threaded into handlers that emit
@@ -425,9 +420,10 @@ export declare function defaultHandlers(deps: {
425
420
  readonly logger?: Logger;
426
421
  /**
427
422
  * Operational-signal sink. Threaded into handlers that emit named
428
- * events (`ggui_new_session` emits `session.created` /
429
- * `session.create_failed`). Absent = NoopTelemetrySink semantic.
430
- * Lossy + non-throwing per the {@link TelemetrySink} contract.
423
+ * events (`ggui_render` emits `ui.created` / `ui.committed`;
424
+ * `ggui_handshake` emits `handshake.minted`). Absent =
425
+ * NoopTelemetrySink semantic. Lossy + non-throwing per the
426
+ * {@link TelemetrySink} contract.
431
427
  */
432
428
  readonly telemetry?: TelemetrySink;
433
429
  /**
@@ -445,7 +441,7 @@ export declare function defaultHandlers(deps: {
445
441
  readonly appMetadataStore?: AppMetadataStore;
446
442
  /**
447
443
  * Global theme-catalog resolver consumed by `ggui_list_themes` AND by
448
- * `ggui_new_session`'s opt-in `requestThemeList` projection. Returns
444
+ * `ggui_render`'s opt-in `requestThemeList` projection. Returns
449
445
  * the full registry every call (kept as a function so additions to
450
446
  * the catalog at runtime — e.g. operator-defined themes in a future
451
447
  * slice — surface without a server restart). When BOTH this and
@@ -503,7 +499,7 @@ export declare function defaultHandlers(deps: {
503
499
  * closure. When absent, the generate handler is NOT registered
504
500
  * (list/update/delete still register).
505
501
  */
506
- readonly resolveLlm?: (ctx: import('@ggui-ai/mcp-server-handlers').HandlerContext) => Promise<GenerationCredentials | null> | GenerationCredentials | null;
502
+ readonly resolveLlm?: (ctx: import("@ggui-ai/mcp-server-handlers").HandlerContext) => Promise<GenerationCredentials | null> | GenerationCredentials | null;
507
503
  /**
508
504
  * BlueprintProvider passed to the generator (same instance
509
505
  * `defaultHandlers`'s blueprint search reads). Required when
@@ -570,7 +566,7 @@ export interface CreateGguiServerOptions {
570
566
  * dev, anything else including unset → prod). Pass an explicit
571
567
  * value to override the env in test fixtures and embedders.
572
568
  */
573
- readonly mode?: 'dev' | 'prod';
569
+ readonly mode?: "dev" | "prod";
574
570
  /**
575
571
  * Shared handler set to expose. Defaults to the blueprint-read family
576
572
  * (search + list_featured + render). Pass your own list to add / remove
@@ -596,7 +592,7 @@ export interface CreateGguiServerOptions {
596
592
  * See `packages/mcp-server-handlers/src/types.ts`
597
593
  * (`SharedHandler.allowedFor`).
598
594
  */
599
- readonly allowedKinds?: ReadonlyArray<'app' | 'user' | 'builder'>;
595
+ readonly allowedKinds?: ReadonlyArray<"app" | "user" | "builder">;
600
596
  /**
601
597
  * Auth adapter. Defaults to `InMemoryAuthAdapter({devAllowAll: true})`
602
598
  * — accepts any non-empty bearer token as the `builder` identity.
@@ -618,7 +614,7 @@ export interface CreateGguiServerOptions {
618
614
  /**
619
615
  * Per-app metadata source. When bound, threaded into
620
616
  * `defaultHandlers` so `ggui_list_gadgets`,
621
- * `ggui_list_themes`, `ggui_new_session({themeId?})`, and the
617
+ * `ggui_list_themes`, `ggui_render({themeId?})`, and the
622
618
  * handshake's `app.gadgets` lookup all read from the same
623
619
  * store. The CLI binds an `InMemoryAppMetadataStore` seeded from
624
620
  * `ggui.json#theme.preset` (so every appId picks up the operator's
@@ -633,7 +629,7 @@ export interface CreateGguiServerOptions {
633
629
  /**
634
630
  * Global theme-catalog resolver. When bound alongside
635
631
  * `appMetadataStore`, registers `ggui_list_themes` and projects the
636
- * same catalog into `ggui_new_session({requestThemeList: true})`
632
+ * same catalog into `ggui_render({requestThemeList: true})`
637
633
  * outputs. Read each call so additions to the registry at runtime
638
634
  * (operator-defined themes in a future slice) surface without a
639
635
  * restart.
@@ -767,9 +763,9 @@ export interface CreateGguiServerOptions {
767
763
  */
768
764
  readonly themeFileUploader?: ThemeFileUploader;
769
765
  /**
770
- * Live-theme getter. When set, the `ggui_push` handler reads this
766
+ * Live-theme getter. When set, the `ggui_render` handler reads this
771
767
  * on every result-meta computation and embeds the returned `id` /
772
- * `mode` into `_meta.ggui.bootstrap`. Pair with
768
+ * `mode` into the `ai.ggui/render` slice meta. Pair with
773
769
  * {@link onThemeConfigChange} so a console save updates the
774
770
  * shared state cell the closure reads from. The cell pattern
775
771
  * closes the parallel-state-stores bug where the push handler
@@ -782,7 +778,7 @@ export interface CreateGguiServerOptions {
782
778
  */
783
779
  readonly themeProvider?: () => {
784
780
  readonly id?: string;
785
- readonly mode?: 'light' | 'dark';
781
+ readonly mode?: "light" | "dark";
786
782
  } | undefined;
787
783
  /**
788
784
  * Optional change notifier — fires when the operator's theme
@@ -800,11 +796,11 @@ export interface CreateGguiServerOptions {
800
796
  */
801
797
  readonly onThemeConfigChange?: (next: string | {
802
798
  preset: string;
803
- mode?: 'light' | 'dark';
799
+ mode?: "light" | "dark";
804
800
  overrides?: Record<string, string>;
805
801
  } | {
806
802
  file: string;
807
- mode?: 'light' | 'dark';
803
+ mode?: "light" | "dark";
808
804
  } | null) => void;
809
805
  /**
810
806
  * Map a resolved identity to the `appId` used by handlers for tenant
@@ -962,17 +958,17 @@ export interface CreateGguiServerOptions {
962
958
  * `'auth-adapter'`, the admin token is irrelevant — the route is
963
959
  * mounted whenever `providerKeys` is set.
964
960
  */
965
- readonly providerKeysGate?: 'admin-token' | 'auth-adapter';
961
+ readonly providerKeysGate?: "admin-token" | "auth-adapter";
966
962
  /** Express body size limit. Defaults to `'4mb'`. */
967
963
  readonly bodyLimit?: string;
968
964
  /**
969
- * Session store — backing plane for the live-channel session endpoint
970
- * (and future OSS session-reading MCP tools). Defaults to
971
- * `InMemorySessionStore`, which is fine for OSS zero-config / dev.
965
+ * Render store — backing plane for the live-channel render endpoint
966
+ * (and OSS render-reading MCP tools). Defaults to
967
+ * `InMemoryRenderStore`, which is fine for OSS zero-config / dev.
972
968
  * SQLite / Postgres / Redis adapters bind via the same interface
973
969
  * when they land.
974
970
  */
975
- readonly sessionStore?: SessionStore;
971
+ readonly renderStore?: RenderStore;
976
972
  /**
977
973
  * Outbound stream replay buffer for the live-channel endpoint. Defaults
978
974
  * to a fresh `InMemorySessionStreamBuffer` — fine for OSS zero-config
@@ -994,7 +990,7 @@ export interface CreateGguiServerOptions {
994
990
  *
995
991
  * The live channel is where the live-contract enforcement point
996
992
  * lives. Enabling this makes the OSS server a second real consumer
997
- * of the shared `@ggui-ai/mcp-server-handlers/session-mutations`
993
+ * of the shared `@ggui-ai/mcp-server-handlers/renders`
998
994
  * helpers.
999
995
  */
1000
996
  readonly sessionChannel?: boolean | {
@@ -1012,7 +1008,7 @@ export interface CreateGguiServerOptions {
1012
1008
  *
1013
1009
  * Absent = agent-mediated behavior (canonical for MCP Apps hosts and
1014
1010
  * Claude Agent SDK consumers). Inbound actions land on the
1015
- * stackItemId-keyed pending-events pipe via `ggui_runtime_submit_action`
1011
+ * renderId-keyed pending-events pipe via `ggui_runtime_submit_action`
1016
1012
  * and the agent's `ggui_consume` long-poll drains them. CLI
1017
1013
  * composition in `ggui serve` wires a router by default over the
1018
1014
  * same handler bundle `/mcp` uses, since that command runs WITHOUT
@@ -1025,7 +1021,7 @@ export interface CreateGguiServerOptions {
1025
1021
  /**
1026
1022
  * Per-call timeout for wired-tool invocations, in ms. Defaults to
1027
1023
  * `DEFAULT_WIRED_TOOL_TIMEOUT_MS` (30 s) when omitted. Forwarded
1028
- * verbatim to `createSessionChannelServer`.
1024
+ * verbatim to `createRenderChannelServer`.
1029
1025
  */
1030
1026
  readonly wiredActionTimeoutMs?: number;
1031
1027
  /**
@@ -1043,20 +1039,39 @@ export interface CreateGguiServerOptions {
1043
1039
  * agrees with the server on which channels use WS fan-out.
1044
1040
  *
1045
1041
  * Only consulted when `sessionChannel` is enabled. Forwarded
1046
- * verbatim to `createSessionChannelServer` (see
1047
- * `SessionChannelOptions.streamWebSocketLocalTools`).
1042
+ * verbatim to `createRenderChannelServer` (see
1043
+ * `RenderChannelOptions.streamWebSocketLocalTools`).
1044
+ */
1045
+ readonly streamWebSocketLocalTools?: import("./render-channel.js").RenderChannelLocalToolsOptions;
1046
+ /**
1047
+ * Hook fired when the local subscriber count for `sessionId`
1048
+ * transitions 0 → 1 on the live channel. Forwarded verbatim to
1049
+ * `createRenderChannelServer`. Used by cloud adapters for per-session
1050
+ * cross-pod pubsub channel scoping; OSS callers leave this undefined.
1051
+ *
1052
+ * Only consulted when `sessionChannel` is enabled. See
1053
+ * `RenderChannelOptions.onFirstSubscriber` for the full contract.
1054
+ */
1055
+ readonly onFirstSubscriber?: (sessionId: string) => void;
1056
+ /**
1057
+ * Hook fired when the local subscriber count for `sessionId`
1058
+ * transitions 1 → 0 on the live channel. Forwarded verbatim to
1059
+ * `createRenderChannelServer`.
1060
+ *
1061
+ * Only consulted when `sessionChannel` is enabled. See
1062
+ * `RenderChannelOptions.onLastSubscriberGone` for the full contract.
1048
1063
  */
1049
- readonly streamWebSocketLocalTools?: import('./session-channel.js').SessionChannelLocalToolsOptions;
1064
+ readonly onLastSubscriberGone?: (sessionId: string) => void;
1050
1065
  /**
1051
1066
  * Override the sanitizer applied to the stringified original error
1052
1067
  * written into `ContractErrorPayload.error.causedBy`. Defaults to
1053
1068
  * `@ggui-ai/protocol::sanitizeCausedBy` when omitted — redacts
1054
1069
  * Bearer tokens, query-param secrets, common env-var dumps, and
1055
1070
  * truncates at 2 KB. Forwarded verbatim to
1056
- * `createSessionChannelServer`. See `SessionChannelOptions
1071
+ * `createRenderChannelServer`. See `RenderChannelOptions
1057
1072
  * .sanitizeCausedBy` for the contract.
1058
1073
  */
1059
- readonly sanitizeCausedBy?: import('@ggui-ai/protocol').SanitizeCausedBy;
1074
+ readonly sanitizeCausedBy?: import("@ggui-ai/protocol").SanitizeCausedBy;
1060
1075
  /**
1061
1076
  * Extra reserved-channel payload validators merged with the
1062
1077
  * server's default A2UI preview validator before being passed to
@@ -1073,11 +1088,11 @@ export interface CreateGguiServerOptions {
1073
1088
  * fall-through behavior on `_ggui:preview` without the adapter
1074
1089
  * running.
1075
1090
  */
1076
- readonly extraReservedValidators?: ReadonlyMap<string, import('@ggui-ai/protocol').ReservedChannelValidator>;
1091
+ readonly extraReservedValidators?: ReadonlyMap<string, import("@ggui-ai/protocol").ReservedChannelValidator>;
1077
1092
  /**
1078
1093
  * Protocol-version handshake policy for the session channel. Forwarded
1079
- * verbatim to `createSessionChannelServer` (see
1080
- * `SessionChannelOptions.versionPolicy`). Defaults to `'reject'` —
1094
+ * verbatim to `createRenderChannelServer` (see
1095
+ * `RenderChannelOptions.versionPolicy`). Defaults to `'reject'` —
1081
1096
  * mismatched `SubscribePayload.supportedVersions` emits
1082
1097
  * UPGRADE_REQUIRED and closes the connection. Legacy opt-out
1083
1098
  * `'advisory'` keeps the connection open after the error frame for
@@ -1085,7 +1100,7 @@ export interface CreateGguiServerOptions {
1085
1100
  *
1086
1101
  * Only consulted when `sessionChannel` is enabled.
1087
1102
  */
1088
- readonly versionPolicy?: 'advisory' | 'reject';
1103
+ readonly versionPolicy?: "advisory" | "reject";
1089
1104
  /**
1090
1105
  * Policy for the schema compat check. Checks that every
1091
1106
  * `actionSpec[name]` tool ref points at a tool whose
@@ -1110,7 +1125,7 @@ export interface CreateGguiServerOptions {
1110
1125
  * endpoint (blueprint registration — fires when a manifest
1111
1126
  * blueprint's pre-declared `actionSpec` / `streamSpec`
1112
1127
  * references a tool mounted on this server).
1113
- * 2. The `ggui_push` generation path (push-time — defensive
1128
+ * 2. The `ggui_render` generation path (render-time — defensive
1114
1129
  * wiring for when the generator starts emitting
1115
1130
  * actionSpec / streamSpec on its `UIGenerationResponse`;
1116
1131
  * current generators emit only componentCode, but the
@@ -1158,32 +1173,29 @@ export interface CreateGguiServerOptions {
1158
1173
  /**
1159
1174
  * Enable the MCP Apps outbound delivery path on this server.
1160
1175
  *
1161
- * - `false` / omitted (default): `ggui_push` is NOT registered;
1162
- * `ui://ggui/session` is NOT served; `io.modelcontextprotocol/ui`
1176
+ * - `false` / omitted (default): `ggui_render` is NOT registered;
1177
+ * `ui://ggui/render` is NOT served; `io.modelcontextprotocol/ui`
1163
1178
  * is NOT advertised. Server looks identical to the pre-MCP-Apps
1164
1179
  * surface.
1165
1180
  * - `true`: enable with sensible defaults. Requires
1166
1181
  * `sessionChannel: true` so the iframe has a WebSocket to open;
1167
- * throws at construction otherwise. `renderBaseUrl` defaults to
1168
- * `"http://localhost/r/"` (dev-sensible; production operators
1169
- * override).
1170
- * - `{ renderBaseUrl?, shellHtml?, wsUrl? }`: explicit config.
1182
+ * throws at construction otherwise.
1183
+ * - `{ shellHtml?, wsUrl? }`: explicit config.
1171
1184
  *
1172
1185
  * When enabled, FOUR things happen on every fresh per-request
1173
1186
  * `McpServer`:
1174
- * 1. `ggui_push` tool is registered, carrying `_meta.ui.resourceUri:
1175
- * "ui://ggui/session"` and `_meta.ui.visibility: ["model"]` on
1187
+ * 1. `ggui_render` tool is registered, carrying `_meta.ui.resourceUri:
1188
+ * "ui://ggui/render"` and `_meta.ui.visibility: ["model"]` on
1176
1189
  * its declaration.
1177
- * 2. `ui://ggui/session` is served via `resources/read`.
1190
+ * 2. `ui://ggui/render` is served via `resources/read`.
1178
1191
  * 3. `io.modelcontextprotocol/ui` is advertised in the server's
1179
1192
  * `initialize` capabilities (under `experimental`).
1180
- * 4. Each `ggui_push` result carries `_meta.ggui.bootstrap` (wsUrl
1181
- * + short-TTL token + expiresAt). The session-channel server
1182
- * accepts that token on `subscribe` and issues a longer-TTL
1183
- * `sessionToken` in the ack for iframe reconnects.
1193
+ * 4. Each `ggui_render` result carries the `ai.ggui/render` slice
1194
+ * with wsUrl + short-TTL token + expiresAt. The session-channel
1195
+ * server accepts that token on `subscribe` and issues a
1196
+ * longer-TTL `renderToken` in the ack for iframe reconnects.
1184
1197
  */
1185
1198
  readonly mcpApps?: boolean | {
1186
- readonly renderBaseUrl?: string;
1187
1199
  readonly shellHtml?: string;
1188
1200
  /**
1189
1201
  * External WebSocket URL the iframe should open, visible to
@@ -1196,11 +1208,11 @@ export interface CreateGguiServerOptions {
1196
1208
  /**
1197
1209
  * Iframe-runtime bundle mount (C8 — plan §C8).
1198
1210
  *
1199
- * The thin-shell HTML served from `ui://ggui/session` dynamic-
1211
+ * The thin-shell HTML served from `ui://ggui/render` dynamic-
1200
1212
  * script-loads the renderer bundle from this URL. The server needs
1201
1213
  * to either (a) serve the bundle itself (default), or (b) publish
1202
- * the operator-owned URL on `_meta.ggui.bootstrap.runtimeUrl`
1203
- * so the shell knows where to look.
1214
+ * the operator-owned URL on the `ai.ggui/render.runtimeUrl` slice
1215
+ * field so the shell knows where to look.
1204
1216
  *
1205
1217
  * - `true` / omitted (default when `mcpApps` is on): serve the
1206
1218
  * bundle via `express.static` at `/_ggui/iframe-runtime.js` from the
@@ -1242,7 +1254,7 @@ export interface CreateGguiServerOptions {
1242
1254
  *
1243
1255
  * Ignored entirely when MCP Apps is disabled.
1244
1256
  */
1245
- readonly bootstrapSecret?: string;
1257
+ readonly wsTokenSecret?: string;
1246
1258
  /**
1247
1259
  * Enable the pairing transport. Adds `POST /pair` (public, completes a
1248
1260
  * pairing handshake) and by default `POST /admin/pair/init` (builder-
@@ -1323,7 +1335,7 @@ export interface CreateGguiServerOptions {
1323
1335
  * right durability claim; the server doesn't inspect the store
1324
1336
  * instance to guess.
1325
1337
  */
1326
- readonly durability?: 'durable' | 'ephemeral';
1338
+ readonly durability?: "durable" | "ephemeral";
1327
1339
  };
1328
1340
  readonly pairing?: boolean | {
1329
1341
  /**
@@ -1399,7 +1411,7 @@ export interface CreateGguiServerOptions {
1399
1411
  readonly audit?: AuditSink;
1400
1412
  /**
1401
1413
  * Admission-control limiter applied at the highest-cost handler
1402
- * ingress — today just `ggui_push`. Defaults to
1414
+ * ingress — today just `ggui_render`. Defaults to
1403
1415
  * {@link NoopRateLimiter} (always allows). Per-handler wiring maps
1404
1416
  * denials from a `RateLimitedError` to HTTP 429 + `Retry-After` /
1405
1417
  * `X-RateLimit-*` headers at the transport boundary.
@@ -1441,44 +1453,6 @@ export interface CreateGguiServerOptions {
1441
1453
  * still mounts so operators can paste credentials in advance).
1442
1454
  */
1443
1455
  readonly publicBaseUrl?: string;
1444
- /**
1445
- * Render-URL signing config — capability-URL hardening.
1446
- *
1447
- * When set (default), every minted `/r/<code>` URL carries
1448
- * `?sig=<hmac>&exp=<unix>`. The gate on `/r/` + `/api/bootstrap/`
1449
- * verifies the sig + freshness before lookup; tampered or expired
1450
- * URLs return 410.
1451
- *
1452
- * - `secret`: 32-byte hex key. When omitted, a fresh random key
1453
- * is minted at boot — restart = every outstanding URL dies
1454
- * (good for incident response, bad if you don't want it).
1455
- * Pin a stable secret to survive restarts.
1456
- * - `ttlSeconds`: URL lifetime. Defaults to 24h (86400s).
1457
- * - Set `renderSigning: false` to disable the layer entirely
1458
- * (`--no-render-signing`). URLs revert to the plain unsigned
1459
- * form. Use for legacy hosts that strip query strings or
1460
- * tooling that pre-records URLs.
1461
- */
1462
- readonly renderSigning?: false | {
1463
- readonly secret?: string;
1464
- readonly ttlSeconds?: number;
1465
- };
1466
- /**
1467
- * Per-shortCode rate-limit config. Defends `/r/` and
1468
- * `/api/bootstrap/` against brute-force scans.
1469
- *
1470
- * - `windowSeconds` + `limit`: bucket size. Default 60s / 30 hits.
1471
- * - `false`: disable rate limiting entirely (CI/test convenience).
1472
- *
1473
- * Rate-limit decision is per-shortCode (not per-peer) — cross-origin
1474
- * iframe hosts NAT every user through one proxy; per-peer limits
1475
- * would either rate-limit the whole host or accept every peer.
1476
- * See render-rate-limit.ts for the rationale.
1477
- */
1478
- readonly renderRateLimit?: false | {
1479
- readonly windowSeconds?: number;
1480
- readonly limit?: number;
1481
- };
1482
1456
  /**
1483
1457
  * Override path for `~/.ggui/oauth-providers.json`. Mainly for
1484
1458
  * tests + per-deployment isolation. Defaults to the home-relative
@@ -1578,7 +1552,7 @@ export interface CreateGguiServerOptions {
1578
1552
  readonly distDir?: string;
1579
1553
  /**
1580
1554
  * Enable the Slice-2 same-origin session-cookie flow
1581
- * (`POST /ggui/console/session-cookie` + session-channel
1555
+ * (`POST /ggui/console/render-cookie` + session-channel
1582
1556
  * cookie-auth wiring). Defaults to OFF — the landing-page
1583
1557
  * static surface is useful on its own (pair-code display,
1584
1558
  * server identity); turning on the cookie flow is an
@@ -1593,7 +1567,7 @@ export interface CreateGguiServerOptions {
1593
1567
  * cookie endpoint resolves shortCode → sessionId by reading
1594
1568
  * it. Throws at construction if the index is absent.
1595
1569
  *
1596
- * The cookie signing secret is the same {@link bootstrapSecret}
1570
+ * The cookie signing secret is the same {@link wsTokenSecret}
1597
1571
  * used by the MCP Apps bootstrap/session tokens — different
1598
1572
  * token `kind` claims make cross-kind confusion impossible
1599
1573
  * (see `console-auth.ts` isolation comment).
@@ -1683,7 +1657,7 @@ export interface CreateGguiServerOptions {
1683
1657
  * when `console.sessionCookie` is enabled (the cookie endpoint
1684
1658
  * looks up the posted shortCode to find the session to bind).
1685
1659
  *
1686
- * Pair this with a `push` handler so the agent's `ggui_push` writes
1660
+ * Pair this with a `push` handler so the agent's `ggui_render` writes
1687
1661
  * the shortCode into the same index that console later reads.
1688
1662
  * See `defaultHandlers` for the wiring seam.
1689
1663
  */
@@ -1692,11 +1666,12 @@ export interface CreateGguiServerOptions {
1692
1666
  * Content-addressable code blob storage. When wired, this server
1693
1667
  * mounts `GET /code/<hash>.js` for the iframe runtime to fetch
1694
1668
  * compiled componentCode by content hash. The push handler writes
1695
- * to the store before emitting `_meta.ggui.bootstrap.codeUrl`.
1669
+ * to the store before emitting `codeUrl` on the `ai.ggui/render`
1670
+ * slice.
1696
1671
  *
1697
1672
  * Defaults: when omitted the route is NOT mounted; the push
1698
- * handler falls back to inline base64 `componentCode` on
1699
- * `_meta.ggui.bootstrap` (legacy delivery channel).
1673
+ * handler falls back to inline base64 `componentCode` on the
1674
+ * `ai.ggui/render` slice (legacy delivery channel).
1700
1675
  *
1701
1676
  * OSS dev wires `FileSystemCodeStore` (rooted at `~/.ggui/code-cache/`)
1702
1677
  * via `ggui-cli/buildMcpServerBackend`. Tests wire
@@ -1707,7 +1682,7 @@ export interface CreateGguiServerOptions {
1707
1682
  */
1708
1683
  readonly codeStore?: CodeStore;
1709
1684
  /**
1710
- * Provisional A2UI preview wiring for `ggui_push`. When the config
1685
+ * Provisional A2UI preview wiring for `ggui_render`. When the config
1711
1686
  * flag is on, every qualifying component push kicks off the
1712
1687
  * supplied emitter; frames land on the reserved `_ggui:preview`
1713
1688
  * channel of the push's session.
@@ -1735,7 +1710,7 @@ export interface CreateGguiServerOptions {
1735
1710
  */
1736
1711
  readonly emitter: ProvisionalPreviewEmitter;
1737
1712
  /** Per-push predicate. See {@link ProvisionalPreviewConfig}. */
1738
- readonly isEnabledFor?: ProvisionalPreviewConfig['isEnabledFor'];
1713
+ readonly isEnabledFor?: ProvisionalPreviewConfig["isEnabledFor"];
1739
1714
  /** Lifecycle observer. Fires sync — must not throw. */
1740
1715
  readonly onOutcome?: (outcome: ProvisionalPreviewOutcome) => void;
1741
1716
  /** Clock override for tests. Defaults to `Date.now`. */
@@ -1744,7 +1719,7 @@ export interface CreateGguiServerOptions {
1744
1719
  /**
1745
1720
  * Handshake preflight wiring. When `mcpApps` is enabled, the
1746
1721
  * server defaults to an `InMemoryKeyValueStore` + no negotiator:
1747
- * `ggui_handshake` is registered, `ggui_push({handshakeId})` is
1722
+ * `ggui_handshake` is registered, `ggui_render({handshakeId})` is
1748
1723
  * consumable, and handshake records persist for 10 minutes before
1749
1724
  * single-use consumption.
1750
1725
  *
@@ -1757,16 +1732,16 @@ export interface CreateGguiServerOptions {
1757
1732
  * in a hosted closed runtime) so handshake records carry a
1758
1733
  * decision the paired push echoes as `structuredContent.decision`.
1759
1734
  * - `false` — explicitly disable: `ggui_handshake` is NOT
1760
- * registered and `ggui_push({handshakeId})` falls back to
1735
+ * registered and `ggui_render({handshakeId})` falls back to
1761
1736
  * the rejection shape.
1762
1737
  *
1763
1738
  * Omitted entirely means "use the default in-memory store when
1764
- * `mcpApps` is on". That matches how `sessionStore` and
1739
+ * `mcpApps` is on". That matches how `renderStore` and
1765
1740
  * `streamBuffer` default — no opt-in required for the OSS
1766
1741
  * first-run path.
1767
1742
  *
1768
1743
  * Requires `mcpApps` to be enabled — handshake is paired with
1769
- * `ggui_push`, which is only registered under MCP Apps. Throws
1744
+ * `ggui_render`, which is only registered under MCP Apps. Throws
1770
1745
  * at construction when handshake is explicitly enabled without
1771
1746
  * MCP Apps.
1772
1747
  */
@@ -1783,14 +1758,14 @@ export interface CreateGguiServerOptions {
1783
1758
  readonly negotiator?: HandshakeNegotiator;
1784
1759
  };
1785
1760
  /**
1786
- * Generation wiring for the `ggui_push` story path. When present,
1787
- * every component push invokes the bound `UiGenerator` and
1788
- * appends the result as a real `StackItem` on the session.
1789
- * Absent = placeholder mode: `ggui_push` on the story path
1790
- * returns `codeReady: false` without writing componentCode.
1761
+ * Generation wiring for the `ggui_render` story path. When present,
1762
+ * every component push invokes the bound `UiGenerator` and commits
1763
+ * the result as a real `Render`. Absent = placeholder mode:
1764
+ * `ggui_render` on the story path returns `codeReady: false`
1765
+ * without writing componentCode.
1791
1766
  *
1792
1767
  * Requires `mcpApps` to be enabled — generation attaches to
1793
- * `ggui_push`, which is only registered when MCP Apps is on.
1768
+ * `ggui_render`, which is only registered when MCP Apps is on.
1794
1769
  * Throws at construction otherwise so a misconfigured server
1795
1770
  * doesn't silently drop the generator binding.
1796
1771
  *
@@ -1937,6 +1912,36 @@ export interface CreateGguiServerOptions {
1937
1912
  readonly opsCoupon?: {
1938
1913
  readonly coupons: CouponRedeemSource;
1939
1914
  };
1915
+ /**
1916
+ * Extra readiness checks merged into `GET /ggui/health`. Each check
1917
+ * is a `{name, check}` pair; `check()` returns a boolean (or a
1918
+ * Promise<boolean>) — `true` means "this dependency is ready".
1919
+ *
1920
+ * When ANY check returns `false` (or throws), `/ggui/health` answers
1921
+ * `503 Service Unavailable` with `status: 'degraded'` + a `checks`
1922
+ * map naming each failing dependency. The default `200 ok` shape is
1923
+ * preserved when every check passes (and when the option is unset).
1924
+ *
1925
+ * Use this when an embedder wires a stateful external dependency
1926
+ * (e.g. a pubsub subscriber connection, a vector-store reachability
1927
+ * probe, a worker-pool health view) and wants its K8s readinessProbe
1928
+ * to take the pod OUT OF SERVICE when that dependency fails. The
1929
+ * sibling `/ggui/live` endpoint is unaffected — that is the K8s
1930
+ * livenessProbe target and stays 200 regardless of readiness, so a
1931
+ * transient upstream blip removes the pod from rotation without
1932
+ * restarting the process. Wire the two probes separately:
1933
+ *
1934
+ * livenessProbe: { httpGet: { path: '/ggui/live', port } }
1935
+ * readinessProbe: { httpGet: { path: '/ggui/health', port } }
1936
+ *
1937
+ * Each check MUST complete within ~1s; the server enforces a 1s
1938
+ * per-check timeout so a hung dependency cannot block the probe.
1939
+ * A timeout is treated as a failed check.
1940
+ */
1941
+ readonly readinessChecks?: ReadonlyArray<{
1942
+ readonly name: string;
1943
+ readonly check: () => boolean | Promise<boolean>;
1944
+ }>;
1940
1945
  }
1941
1946
  export interface GguiServer {
1942
1947
  /**
@@ -1965,7 +1970,7 @@ export interface GguiServer {
1965
1970
  * composition with future mutation handlers that want to fan out
1966
1971
  * via `sessionChannel.sendToSession(sessionId, data)`.
1967
1972
  */
1968
- readonly sessionChannel: SessionChannelServer | null;
1973
+ readonly sessionChannel: RenderChannelServer | null;
1969
1974
  /**
1970
1975
  * The pairing service bound to this server, when the `pairing` option
1971
1976
  * was enabled. `null` when pairing is disabled. In-process hosts