@happyvertical/smrt-mcp-apps 0.0.0-stage → 0.51.38

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/AGENTS.md ADDED
@@ -0,0 +1,16 @@
1
+ # @happyvertical/smrt-mcp-apps
2
+
3
+ Browser-only view-side portable MCP Apps bridge. `src/index.ts` owns lifecycle,
4
+ correlated transport and capability gates; `src/validation.ts` owns bounded JSON
5
+ and the deliberately text/structured subset. No server credentials, Svelte,
6
+ OpenAI symbols or browser authorization/REST engine belong here.
7
+
8
+ The pinned upstream protocol/schema and known prose discrepancy are documented in
9
+ [README.md](README.md). Never change the protocol or widen a modality silently.
10
+ Host window and exact origin are immutable. Disposal rejects pending work.
11
+ Public registries remain in smrt-ui; Svelte bindings use the smrt-web intent
12
+ compiler through the explicit `smrt-svelte/mcp-apps` subpath.
13
+
14
+ Run package build/typecheck/test/test:e2e/verify:pack plus the Svelte browser gate
15
+ listed in README. `e2e/` is a synthetic host, not external-host compatibility
16
+ proof. Keep the generated reference resource under 100 KiB and CSP no-network.
package/CLAUDE.md ADDED
@@ -0,0 +1 @@
1
+ @AGENTS.md
package/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright <2025> <Happy Vertical Corporation>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,168 @@
1
- # Temporary Holding Version
1
+ # @happyvertical/smrt-mcp-apps
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Framework-neutral, browser-only **view-side** bridge for portable MCP Apps.
4
+ It is not a server adapter, host/sandbox implementation, authorization layer or
5
+ WebMCP tool registrar. Importing it does not require a browser until construction.
6
+
7
+ ## Usage
8
+
9
+ ```ts
10
+ import { McpAppBridge } from '@happyvertical/smrt-mcp-apps';
11
+
12
+ const bridge = new McpAppBridge({
13
+ hostWindow: window.parent,
14
+ hostOrigin: 'https://trusted-host.example',
15
+ appInfo: { name: 'Opportunity viewer', version: '1.0.0' },
16
+ });
17
+ await bridge.connect();
18
+ if (bridge.snapshot.hostCapabilities.serverTools) {
19
+ const result = await bridge.callTool('opportunity_list', {});
20
+ // Render text with textContent and validate domain-shaped structuredContent.
21
+ }
22
+ // Owning component unmount:
23
+ bridge.dispose();
24
+ ```
25
+
26
+ Supply the immediate parent window and its exact origin from trusted deployment
27
+ configuration. Do not learn them from the first message, URL query, untrusted
28
+ referrer or tool arguments. The same window and origin remain bound for the
29
+ instance lifetime. HTTPS is required except explicit loopback HTTP development.
30
+ Opaque (`null`) parent origins and wildcard targets are intentionally unsupported;
31
+ a host with an opaque immediate sandbox proxy needs a reviewed transport design.
32
+ The view itself may have an opaque origin. Host authentication stays outside it.
33
+
34
+ ## Supported contract
35
+
36
+ Pinned upstream revision: `82221c0c8ce7661efa6771c9d461511b1650495f`.
37
+ The [runtime schema](https://github.com/modelcontextprotocol/ext-apps/blob/82221c0c8ce7661efa6771c9d461511b1650495f/src/generated/schema.ts)
38
+ is authoritative for implemented fields; its
39
+ [protocol constant](https://github.com/modelcontextprotocol/ext-apps/blob/82221c0c8ce7661efa6771c9d461511b1650495f/src/spec.types.ts)
40
+ is `2026-01-26`, independent of server MCP `2026-07-28`.
41
+ The same revision's
42
+ [prose examples](https://github.com/modelcontextprotocol/ext-apps/blob/82221c0c8ce7661efa6771c9d461511b1650495f/specification/2026-01-26/apps.mdx)
43
+ differ: `ui/message` shows singleton content and omits message/context modality
44
+ capabilities, whereas the runtime schema uses a content array, capability modality
45
+ objects, required `hostContext`, optional tool-input arguments and optional
46
+ cancellation reason. Contract tests pin these runtime shapes explicitly.
47
+
48
+ Implemented methods: initialize/initialized, server `tools/call`, `ui/open-link`,
49
+ text `ui/message`, text/structured `ui/update-model-context`, display-mode requests,
50
+ size notifications, ping and resource teardown. Tool input/result/cancellation
51
+ and host-context notifications are accepted only after initialization. Exactly one
52
+ complete initial input and terminal result/cancellation are accepted; late or
53
+ out-of-order updates are ignored. Partial input is ignored. No app-tools capability
54
+ is advertised; inbound `tools/call` receives method-not-found. Resource proxying, sampling and downloads have no built-in typed adapter; an
55
+ opt-in extension adapter may register a bounded contract below. Binary content
56
+ in built-in tool results and executable host CSS remain unsupported.
57
+ Unknown capabilities never grant a supported feature. Unsupported tool content
58
+ modalities reject explicitly. Text and structured results remain available without
59
+ interactive capabilities; consumers must retain a normal app/review URL fallback.
60
+
61
+ Host context exposes only theme, display mode(s), platform, locale and timezone.
62
+ Unknown context fields are ignored by the typed projection; executable CSS/tool
63
+ definitions are never applied. `snapshot.rawHostContext` and
64
+ `snapshot.rawHostCapabilities` retain bounded JSON for opt-in extension adapters.
65
+ Context notifications merge into the raw context; capabilities remain fixed at
66
+ handshake. Every snapshot/observer receives an isolated clone. Extension adapters
67
+ must validate their own fields and treat raw data as untrusted; raw capabilities
68
+ cannot enable typed methods or bypass their gates. There is no global arbitrary RPC method. Optional adapters must explicitly
69
+ register the capability-gated contract described below. Unknown supported-field enum values fail closed. A missing display-mode
70
+ list permits only inline. Host rejection (`isError: true`) and RPC errors propagate.
71
+
72
+ Payload limits: 24 nested levels, 4096 array items, 1024 object keys, conservative
73
+ 128 KiB character/node budget; text blocks 32 KiB, 128 blocks; 32 pending requests;
74
+ 15-second default timeout (configurable 1–120000 ms). Arrays must be dense own data properties with no named/symbol properties; their iterators are never invoked. Cycles/non-JSON/accessors and
75
+ prototype keys are rejected. Requests use per-instance random correlated IDs.
76
+ Timeout, abort and disposal reject pending calls and send best-effort cancellation.
77
+ Disposal removes the listener, aborts `signal`, and clears observers. Cancellation
78
+ is not a rollback guarantee: server workflows retain idempotency/transaction rules.
79
+
80
+ ## Svelte and mounted interactions
81
+
82
+ Explicitly import `useMcpApp` and `useMcpAppIntent` from
83
+ `@happyvertical/smrt-svelte/mcp-apps`. `useMcpApp(() => options)` constructs only on
84
+ mount and disposes on unmount; its state contains `bridge`, `snapshot` and `error`.
85
+ Use `bridge.signal` or an owned abort signal for associated asynchronous work.
86
+
87
+ `useMcpAppIntent(intent, binding)` binds an existing public view-intent declaration
88
+ to a mounted ControlInteractionRegistry or DataSurfaceRegistry. It uses the public
89
+ `compileViewIntentToolSpec` implementation and requires no `document.modelContext`.
90
+ It is a component-local callable, never forwarded or advertised as a remote tool.
91
+ Control proposals remain agent-sourced; existing trusted human staged review owns
92
+ application of values. The component owns registry registrations and their cleanup.
93
+ No new REST engine, browser permission engine or final-submission API is introduced.
94
+
95
+ ## Validation
96
+
97
+ After `pnpm install` and documented dependency builds:
98
+
99
+ - `pnpm --filter @happyvertical/smrt-mcp-apps build`
100
+ - `pnpm --filter @happyvertical/smrt-mcp-apps typecheck`
101
+ - `pnpm --filter @happyvertical/smrt-mcp-apps test`
102
+ - `pnpm --filter @happyvertical/smrt-mcp-apps test:e2e`
103
+ - `pnpm --filter @happyvertical/smrt-mcp-apps verify:pack`
104
+ - `pnpm --filter @happyvertical/smrt-svelte check`
105
+ - `pnpm --filter @happyvertical/smrt-svelte exec playwright test -c e2e/playwright.config.ts mcp-apps.spec.ts`
106
+
107
+ The Chromium host fixture bundles an Iolaus-shaped synthetic list/detail viewer,
108
+ prepares and reads it through the public M3 resource APIs, and routes host-proxied
109
+ calls through `createMcpAppServer` with a server-owned synthetic principal.
110
+ It checks resource digest/MIME/CSP metadata and revoked-resource/tool denial,
111
+ raw generated HTML below 100 KiB, and hash-only script/style CSP with no external
112
+ network/assets. Browser gates cover hostile messages, capability absence,
113
+ repeated teardown/reconnect, late superseded results, and keyboard navigation at
114
+ 320/390px without horizontal overflow. The visible review URL wraps and remains
115
+ copyable even where sandbox policy blocks opening a new window. The Svelte browser fixture uses real public registries and a genuine
116
+ Playwright click to apply a staged proposal; fabricated approval is denied.
117
+ These fixtures prove synthetic browser behavior only. No actual OpenAI or other
118
+ external host compatibility is claimed. M3 resource metadata still requires the
119
+ host to enforce CSP and sandbox permissions; the browser bridge cannot enforce a
120
+ host's policy on its behalf. The reference view only opens a human-review URL and
121
+ contains no candidate records or transmission/approval operation.
122
+
123
+
124
+ ## Optional extension contracts
125
+
126
+ `bridge.registerExtension(definition)` returns a `McpAppExtension` only after the
127
+ Apps handshake completes and the declaration's capability path selects a plain
128
+ object in the initialized host capabilities. Declarations are trusted local code;
129
+ never derive capability paths or method lists from host/model input. For example:
130
+
131
+ ```ts
132
+ const resources = bridge.registerExtension({
133
+ id: 'example.resources',
134
+ capability: { path: ['experimental', 'example/resources'] },
135
+ methods: ['resources/read', 'resources/subscribe', 'resources/unsubscribe'],
136
+ notifications: ['notifications/resources/updated'],
137
+ });
138
+ const unsubscribe = resources.subscribe((method, params) => {
139
+ // Adapter validates its exact URI/schema/ownership before acting.
140
+ });
141
+ const result = await resources.request('resources/read', { uri: 'test://fixture' });
142
+ // Validate the extension's exact result schema before consuming it.
143
+ unsubscribe();
144
+ resources.dispose();
145
+ ```
146
+
147
+ If a wire capability declares a version, specify
148
+ `capability.version: { key: 'version', supported: ['1'] }`; mismatches reject.
149
+ Omit this field for capabilities without wire versions rather than inventing one.
150
+ The bridge copies declarations and permits at most 16 registrations, 16 request
151
+ methods and 16 notification names per registration, and 32 listeners per handle.
152
+ Duplicate IDs/method ownership, unlisted requests, reserved lifecycle/tool methods
153
+ and malformed JSON reject. Unknown notifications are ignored; host requests never
154
+ invoke notification callbacks. Every observer receives isolated bounded data.
155
+
156
+ Native `ui/message` and `ui/update-model-context` are narrow allowlist exceptions
157
+ for extension metadata: the core capability and text/structured modality gates,
158
+ user role, text-content shape/limits and failure-result checks still apply in
159
+ addition to the extension capability. No image modality or tool-call bypass is
160
+ introduced. Extension adapters own semantic metadata/result validation and any
161
+ additional application authorization, not this transport API.
162
+
163
+ The handle shares the existing bound host/origin, JSON budget, 32-pending limit,
164
+ correlated IDs and timeout behavior. `signal` aborts on handle or bridge disposal;
165
+ pending work rejects and later notifications/results cannot revive the handle.
166
+ A new registration has a new lifetime. Adapters should request remote unsubscribe
167
+ before disposal when practical; teardown aborts immediately and does not wait for
168
+ a host acknowledgement. This is cancellation, not a server rollback guarantee.
@@ -0,0 +1,30 @@
1
+ /** Trusted local declaration. Extension adapters own method-specific wire schemas. */
2
+ export interface McpAppExtensionDefinition {
3
+ id: string;
4
+ capability: {
5
+ /** Own-property path into the initialized host's capability object. */
6
+ path: readonly string[];
7
+ /** Only declare this when the extension's wire capability actually has a version field. */
8
+ version?: {
9
+ key: string;
10
+ supported: readonly string[];
11
+ };
12
+ };
13
+ methods: readonly string[];
14
+ notifications: readonly string[];
15
+ }
16
+ /** One owner, one initialized bridge lifetime; no independent transport or authority. */
17
+ export interface McpAppExtension {
18
+ readonly signal: AbortSignal;
19
+ request(method: string, params: Record<string, unknown>, signal?: AbortSignal): Promise<Record<string, unknown>>;
20
+ subscribe(listener: (method: string, params: Record<string, unknown>) => void): () => void;
21
+ dispose(): void;
22
+ }
23
+ export interface RegisteredExtension {
24
+ definition: McpAppExtensionDefinition;
25
+ lifetime: AbortController;
26
+ listeners: Set<(method: string, params: Record<string, unknown>) => void>;
27
+ }
28
+ /** Validate and copy the declaration before it can affect transport dispatch. */
29
+ export declare function extensionDefinition(value: McpAppExtensionDefinition, capabilities: Record<string, unknown>): McpAppExtensionDefinition;
30
+ //# sourceMappingURL=extensions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extensions.d.ts","sourceRoot":"","sources":["../src/extensions.ts"],"names":[],"mappings":"AAEA,sFAAsF;AACtF,MAAM,WAAW,yBAAyB;IACxC,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE;QACV,uEAAuE;QACvE,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;QACxB,2FAA2F;QAC3F,OAAO,CAAC,EAAE;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;SAAE,CAAC;KACzD,CAAC;IACF,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC;AACD,yFAAyF;AACzF,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,OAAO,CACL,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACpC,SAAS,CACP,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,GAClE,MAAM,IAAI,CAAC;IACd,OAAO,IAAI,IAAI,CAAC;CACjB;AACD,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,yBAAyB,CAAC;IACtC,QAAQ,EAAE,eAAe,CAAC;IAC1B,SAAS,EAAE,GAAG,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC;CAC3E;AAOD,iFAAiF;AACjF,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,yBAAyB,EAChC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACpC,yBAAyB,CA6D3B"}
@@ -0,0 +1,61 @@
1
+ import { json, object, string } from './validation.js';
2
+ function name(value) {
3
+ const result = string(value, 128);
4
+ if (!/^[a-zA-Z][a-zA-Z0-9_.-]*(\/[a-zA-Z][a-zA-Z0-9_.-]*){1,4}$/.test(result))
5
+ throw new Error('Invalid extension method name');
6
+ return result;
7
+ }
8
+ /** Validate and copy the declaration before it can affect transport dispatch. */
9
+ export function extensionDefinition(value, capabilities) {
10
+ json(value);
11
+ const input = object(value);
12
+ const extensionId = string(input.id, 64);
13
+ if (!/^[a-z][a-z0-9.-]{0,63}$/.test(extensionId))
14
+ throw new Error('Invalid extension id');
15
+ const capability = object(input.capability);
16
+ if (!Array.isArray(capability.path) ||
17
+ capability.path.length < 1 ||
18
+ capability.path.length > 4)
19
+ throw new Error('Invalid extension capability path');
20
+ let selected = capabilities;
21
+ for (const key of capability.path) {
22
+ string(key, 128);
23
+ const parent = object(selected);
24
+ if (!Object.hasOwn(parent, key))
25
+ throw new Error('Host extension capability unavailable');
26
+ selected = parent[key];
27
+ }
28
+ const supportedCapability = object(selected);
29
+ if (capability.version !== undefined) {
30
+ const version = object(capability.version);
31
+ const key = string(version.key, 128);
32
+ if (!Array.isArray(version.supported) ||
33
+ !version.supported.length ||
34
+ version.supported.length > 8)
35
+ throw new Error('Invalid extension versions');
36
+ for (const item of version.supported)
37
+ string(item, 64);
38
+ if (!Object.hasOwn(supportedCapability, key) ||
39
+ !version.supported.includes(supportedCapability[key]))
40
+ throw new Error('Unsupported host extension version');
41
+ }
42
+ for (const field of ['methods', 'notifications']) {
43
+ const names = input[field];
44
+ if (!Array.isArray(names) ||
45
+ names.length > 16 ||
46
+ new Set(names).size !== names.length)
47
+ throw new Error('Invalid extension allowlist');
48
+ for (const item of names) {
49
+ const method = name(item);
50
+ const nativeTextRequest = field === 'methods' &&
51
+ ['ui/message', 'ui/update-model-context'].includes(method);
52
+ if ((method.startsWith('ui/') && !nativeTextRequest) ||
53
+ method.startsWith('tools/') ||
54
+ method === 'notifications/cancelled' ||
55
+ (field === 'methods' && method.startsWith('notifications/')))
56
+ throw new Error('Reserved bridge method');
57
+ }
58
+ }
59
+ return structuredClone(value);
60
+ }
61
+ //# sourceMappingURL=extensions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extensions.js","sourceRoot":"","sources":["../src/extensions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ import type { McpAppExtension, McpAppExtensionDefinition } from './extensions.js';
2
+ export type { McpAppExtension, McpAppExtensionDefinition, } from './extensions.js';
3
+ import type { DisplayMode, HostCapabilities, HostContext, ToolResult } from './validation.js';
4
+ export type { DisplayMode, HostCapabilities, HostContext, TextContent, ToolResult, } from './validation.js';
5
+ /** Pinned independently from the server MCP protocol (2026-07-28). */
6
+ export declare const MCP_APPS_PROTOCOL_VERSION = "2026-01-26";
7
+ /** Exact upstream schema baseline, not a dependency on the SDK v1 helper. */
8
+ export declare const MCP_APPS_SCHEMA_REVISION = "82221c0c8ce7661efa6771c9d461511b1650495f";
9
+ export interface McpAppBridgeOptions {
10
+ /** The immediate parent (including a sandbox proxy), supplied by trusted app configuration. */
11
+ hostWindow: Window;
12
+ /** Exact parent origin. Opaque/null/wildcard origins are intentionally unsupported. */
13
+ hostOrigin: string;
14
+ appInfo: {
15
+ name: string;
16
+ version: string;
17
+ };
18
+ window?: Window;
19
+ timeoutMs?: number;
20
+ availableDisplayModes?: DisplayMode[];
21
+ }
22
+ export interface McpAppSnapshot {
23
+ state: 'idle' | 'connecting' | 'ready' | 'disposed';
24
+ hostCapabilities: HostCapabilities;
25
+ hostContext: HostContext;
26
+ /** Bounded JSON from the bound host, isolated on every snapshot. Extensions must validate their own fields. */
27
+ rawHostContext: Readonly<Record<string, unknown>>;
28
+ /** Informational extension negotiation only; never bypasses the bridge's typed capability gates. */
29
+ rawHostCapabilities: Readonly<Record<string, unknown>>;
30
+ toolInput?: Record<string, unknown>;
31
+ toolResult?: ToolResult;
32
+ cancelled?: boolean;
33
+ }
34
+ /** Portable view-side transport. It never registers browser closures as remote tools. */
35
+ export declare class McpAppBridge {
36
+ #private;
37
+ constructor(options: McpAppBridgeOptions);
38
+ /** Aborts component-owned asynchronous work on host teardown or local disposal. */
39
+ get signal(): AbortSignal;
40
+ get snapshot(): McpAppSnapshot;
41
+ subscribe(listener: (snapshot: McpAppSnapshot) => void): () => void;
42
+ /** Negotiate once. Failed or timed-out negotiation closes this instance permanently. */
43
+ connect(): Promise<void>;
44
+ /**
45
+ * Opt in to a finite extension contract after initialization. The adapter must
46
+ * validate its method-specific schemas; this handle never bypasses transport,
47
+ * lifecycle, or native text-method capability checks.
48
+ */
49
+ registerExtension(declaration: McpAppExtensionDefinition): McpAppExtension;
50
+ /** Calls the server through the host. No credentials, tenant overrides or approval metadata. */
51
+ callTool(name: string, args?: Record<string, unknown>, signal?: AbortSignal): Promise<ToolResult>;
52
+ /** Human review destination only; applications own their approved URL allowlist. */
53
+ openLink(url: string, signal?: AbortSignal): Promise<void>;
54
+ sendMessage(text: string, signal?: AbortSignal): Promise<void>;
55
+ updateModelContext(value: {
56
+ text?: string;
57
+ structuredContent?: Record<string, unknown>;
58
+ }, signal?: AbortSignal): Promise<void>;
59
+ requestDisplayMode(value: DisplayMode, signal?: AbortSignal): Promise<DisplayMode>;
60
+ reportSize(width: number, height: number): void;
61
+ /** Idempotent. Pending requests reject; late responses and notifications have no owner. */
62
+ dispose(): void;
63
+ }
64
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,495 @@
1
+ import { extensionDefinition } from './extensions.js';
2
+ import { capabilities, context, id, json, mode, object, string, success, toolResult, } from './validation.js';
3
+ /** Pinned independently from the server MCP protocol (2026-07-28). */
4
+ export const MCP_APPS_PROTOCOL_VERSION = '2026-01-26';
5
+ /** Exact upstream schema baseline, not a dependency on the SDK v1 helper. */
6
+ export const MCP_APPS_SCHEMA_REVISION = '82221c0c8ce7661efa6771c9d461511b1650495f';
7
+ /** Portable view-side transport. It never registers browser closures as remote tools. */
8
+ export class McpAppBridge {
9
+ #host;
10
+ #window;
11
+ #origin;
12
+ #timeout;
13
+ #appInfo;
14
+ #modes;
15
+ #prefix;
16
+ #pending = new Map();
17
+ #extensions = new Map();
18
+ #subscribers = new Set();
19
+ #lifetime = new AbortController();
20
+ #sequence = 0;
21
+ #inputReceived = false;
22
+ #terminalReceived = false;
23
+ #connect;
24
+ #snapshot = {
25
+ state: 'idle',
26
+ hostCapabilities: {},
27
+ hostContext: {},
28
+ rawHostContext: {},
29
+ rawHostCapabilities: {},
30
+ };
31
+ constructor(options) {
32
+ const origin = new URL(options.hostOrigin);
33
+ if (origin.origin !== options.hostOrigin ||
34
+ !['https:', 'http:'].includes(origin.protocol))
35
+ throw new Error('Expected exact HTTP(S) host origin');
36
+ if (origin.protocol === 'http:' &&
37
+ !['localhost', '127.0.0.1', '[::1]'].includes(origin.hostname))
38
+ throw new Error('Host origin requires HTTPS');
39
+ this.#window = options.window ?? window;
40
+ this.#host = options.hostWindow;
41
+ if (this.#host === this.#window)
42
+ throw new Error('MCP Apps requires an embedded host window');
43
+ this.#origin = options.hostOrigin;
44
+ this.#timeout = options.timeoutMs ?? 15000;
45
+ if (!Number.isSafeInteger(this.#timeout) ||
46
+ this.#timeout < 1 ||
47
+ this.#timeout > 120000)
48
+ throw new Error('Invalid request timeout');
49
+ this.#appInfo = {
50
+ name: string(options.appInfo.name, 128),
51
+ version: string(options.appInfo.version, 128),
52
+ };
53
+ this.#modes = (options.availableDisplayModes ?? ['inline']).map(mode);
54
+ if (!this.#modes.length || this.#modes.length > 3)
55
+ throw new Error('Invalid app display modes');
56
+ this.#prefix = this.#window.crypto.randomUUID();
57
+ }
58
+ /** Aborts component-owned asynchronous work on host teardown or local disposal. */
59
+ get signal() {
60
+ return this.#lifetime.signal;
61
+ }
62
+ get snapshot() {
63
+ return structuredClone(this.#snapshot);
64
+ }
65
+ subscribe(listener) {
66
+ if (this.#snapshot.state === 'disposed')
67
+ return () => { };
68
+ this.#subscribers.add(listener);
69
+ try {
70
+ listener(this.snapshot);
71
+ }
72
+ catch {
73
+ /* Observer owns its error reporting, including initial delivery. */
74
+ }
75
+ return () => {
76
+ this.#subscribers.delete(listener);
77
+ };
78
+ }
79
+ #emit() {
80
+ for (const listener of this.#subscribers) {
81
+ // One component observer cannot prevent transport cleanup or other observers.
82
+ try {
83
+ listener(this.snapshot);
84
+ }
85
+ catch {
86
+ /* Observer owns its error reporting. */
87
+ }
88
+ }
89
+ }
90
+ #post(message) {
91
+ json(message);
92
+ this.#host.postMessage(message, this.#origin);
93
+ }
94
+ #request(method, params, signal) {
95
+ if (this.#snapshot.state === 'disposed' || signal?.aborted)
96
+ return Promise.reject(new Error('MCP Apps request cancelled'));
97
+ if (this.#pending.size >= 32)
98
+ return Promise.reject(new Error('Too many pending MCP Apps requests'));
99
+ const requestId = `${this.#prefix}:${++this.#sequence}`;
100
+ return new Promise((resolve, reject) => {
101
+ const cancel = () => {
102
+ const pending = this.#pending.get(requestId);
103
+ if (!pending)
104
+ return;
105
+ this.#pending.delete(requestId);
106
+ pending.cleanup();
107
+ reject(new Error('MCP Apps request cancelled or timed out'));
108
+ try {
109
+ this.#post({
110
+ jsonrpc: '2.0',
111
+ method: 'notifications/cancelled',
112
+ params: { requestId },
113
+ });
114
+ }
115
+ catch {
116
+ /* Local cancellation remains effective. */
117
+ }
118
+ };
119
+ const timer = setTimeout(cancel, this.#timeout);
120
+ const cleanup = () => {
121
+ clearTimeout(timer);
122
+ signal?.removeEventListener('abort', cancel);
123
+ };
124
+ this.#pending.set(requestId, { resolve, reject, cleanup });
125
+ signal?.addEventListener('abort', cancel, { once: true });
126
+ try {
127
+ this.#post({ jsonrpc: '2.0', id: requestId, method, params });
128
+ }
129
+ catch (error) {
130
+ this.#pending.delete(requestId);
131
+ cleanup();
132
+ reject(error);
133
+ }
134
+ });
135
+ }
136
+ /** Negotiate once. Failed or timed-out negotiation closes this instance permanently. */
137
+ connect() {
138
+ if (this.#connect)
139
+ return this.#connect;
140
+ if (this.#snapshot.state === 'disposed')
141
+ return Promise.reject(new Error('MCP Apps bridge disposed'));
142
+ this.#snapshot.state = 'connecting';
143
+ this.#window.addEventListener('message', this.#receive);
144
+ this.#connect = this.#request('ui/initialize', {
145
+ protocolVersion: MCP_APPS_PROTOCOL_VERSION,
146
+ appInfo: this.#appInfo,
147
+ appCapabilities: { availableDisplayModes: this.#modes },
148
+ })
149
+ .then((value) => {
150
+ if (this.#snapshot.state === 'disposed')
151
+ throw new Error('MCP Apps bridge disposed');
152
+ const result = object(value);
153
+ if (result.protocolVersion !== MCP_APPS_PROTOCOL_VERSION)
154
+ throw new Error('Unsupported MCP Apps protocol version');
155
+ const info = object(result.hostInfo);
156
+ string(info.name, 128);
157
+ string(info.version, 128);
158
+ this.#snapshot.hostCapabilities = capabilities(result.hostCapabilities);
159
+ this.#snapshot.hostContext = context(result.hostContext);
160
+ this.#snapshot.rawHostContext = structuredClone(object(result.hostContext));
161
+ this.#snapshot.rawHostCapabilities = structuredClone(object(result.hostCapabilities));
162
+ this.#post({ jsonrpc: '2.0', method: 'ui/notifications/initialized' });
163
+ this.#snapshot.state = 'ready';
164
+ this.#emit();
165
+ })
166
+ .catch((error) => {
167
+ this.dispose();
168
+ throw error;
169
+ });
170
+ // Publish only after reentrant observers can reuse the same negotiation.
171
+ this.#emit();
172
+ return this.#connect;
173
+ }
174
+ #ready() {
175
+ if (this.#snapshot.state !== 'ready')
176
+ throw new Error('MCP Apps bridge is not ready');
177
+ }
178
+ #require(capability) {
179
+ this.#ready();
180
+ if (!this.#snapshot.hostCapabilities[capability])
181
+ throw new Error(`Host capability unavailable: ${capability}`);
182
+ }
183
+ /**
184
+ * Opt in to a finite extension contract after initialization. The adapter must
185
+ * validate its method-specific schemas; this handle never bypasses transport,
186
+ * lifecycle, or native text-method capability checks.
187
+ */
188
+ registerExtension(declaration) {
189
+ this.#ready();
190
+ const definition = extensionDefinition(declaration, this.#snapshot.rawHostCapabilities);
191
+ if (this.#extensions.size >= 16 || this.#extensions.has(definition.id))
192
+ throw new Error('Extension already registered or registration limit reached');
193
+ const names = [...definition.methods, ...definition.notifications];
194
+ if (new Set(names).size !== names.length)
195
+ throw new Error('Extension request/notification collision');
196
+ for (const registered of this.#extensions.values()) {
197
+ const existing = [
198
+ ...registered.definition.methods,
199
+ ...registered.definition.notifications,
200
+ ];
201
+ if (names.some((name) => existing.includes(name)))
202
+ throw new Error('Extension method already registered');
203
+ }
204
+ const state = {
205
+ definition,
206
+ lifetime: new AbortController(),
207
+ listeners: new Set(),
208
+ };
209
+ this.#extensions.set(definition.id, state);
210
+ const active = () => {
211
+ this.#ready();
212
+ if (this.#extensions.get(definition.id) !== state ||
213
+ state.lifetime.signal.aborted)
214
+ throw new Error('MCP Apps extension disposed');
215
+ };
216
+ const dispose = () => {
217
+ if (this.#extensions.get(definition.id) !== state)
218
+ return;
219
+ this.#extensions.delete(definition.id);
220
+ state.listeners.clear();
221
+ state.lifetime.abort();
222
+ };
223
+ return Object.freeze({
224
+ signal: state.lifetime.signal,
225
+ request: async (method, params, signal) => {
226
+ active();
227
+ if (!definition.methods.includes(method))
228
+ throw new Error('Extension method is not registered');
229
+ json(params);
230
+ object(params);
231
+ this.#validateNativeExtensionRequest(method, params);
232
+ const requestSignal = signal
233
+ ? AbortSignal.any([state.lifetime.signal, signal])
234
+ : state.lifetime.signal;
235
+ const result = await this.#request(method, structuredClone(params), requestSignal);
236
+ active();
237
+ if (requestSignal.aborted)
238
+ throw new Error('MCP Apps extension request cancelled');
239
+ object(result);
240
+ if (method === 'ui/message' || method === 'ui/update-model-context')
241
+ success(result);
242
+ return structuredClone(result);
243
+ },
244
+ subscribe: (listener) => {
245
+ active();
246
+ if (typeof listener !== 'function' || state.listeners.size >= 32)
247
+ throw new Error('Invalid extension listener or listener limit reached');
248
+ state.listeners.add(listener);
249
+ return () => {
250
+ state.listeners.delete(listener);
251
+ };
252
+ },
253
+ dispose,
254
+ });
255
+ }
256
+ #validateNativeExtensionRequest(method, params) {
257
+ if (method !== 'ui/message' && method !== 'ui/update-model-context')
258
+ return;
259
+ const capability = method === 'ui/message' ? 'message' : 'updateModelContext';
260
+ this.#require(capability);
261
+ const caps = this.#snapshot.hostCapabilities[capability];
262
+ if (method === 'ui/message' &&
263
+ (params.role !== 'user' || params.content === undefined))
264
+ throw new Error('Invalid native message shape');
265
+ if (params.content !== undefined) {
266
+ if (!caps?.text)
267
+ throw new Error('Host text modality unavailable');
268
+ const blocks = toolResult({ content: params.content }).content;
269
+ for (const block of blocks)
270
+ string(block.text, 16384);
271
+ }
272
+ if (method === 'ui/update-model-context' &&
273
+ params.structuredContent !== undefined) {
274
+ if (!this.#snapshot.hostCapabilities.updateModelContext?.structuredContent)
275
+ throw new Error('Host structured modality unavailable');
276
+ object(params.structuredContent);
277
+ }
278
+ }
279
+ #notifyExtensions(method, params) {
280
+ for (const state of [...this.#extensions.values()]) {
281
+ if (!state.definition.notifications.includes(method) ||
282
+ state.lifetime.signal.aborted)
283
+ continue;
284
+ for (const listener of [...state.listeners]) {
285
+ if (state.lifetime.signal.aborted || !state.listeners.has(listener))
286
+ continue;
287
+ try {
288
+ listener(method, structuredClone(params));
289
+ }
290
+ catch {
291
+ /* Adapter owns schema and observer errors. */
292
+ }
293
+ }
294
+ }
295
+ }
296
+ /** Calls the server through the host. No credentials, tenant overrides or approval metadata. */
297
+ async callTool(name, args = {}, signal) {
298
+ this.#require('serverTools');
299
+ if (!/^[A-Za-z0-9_.-]{1,128}$/.test(name))
300
+ throw new Error('Invalid tool name');
301
+ object(args);
302
+ return toolResult(await this.#request('tools/call', { name, arguments: args }, signal));
303
+ }
304
+ /** Human review destination only; applications own their approved URL allowlist. */
305
+ async openLink(url, signal) {
306
+ this.#require('openLinks');
307
+ const parsed = new URL(string(url));
308
+ if (parsed.protocol !== 'https:' || parsed.username || parsed.password)
309
+ throw new Error('Expected credential-free HTTPS link');
310
+ success(await this.#request('ui/open-link', { url: parsed.href }, signal));
311
+ }
312
+ async sendMessage(text, signal) {
313
+ this.#require('message');
314
+ if (!this.#snapshot.hostCapabilities.message?.text)
315
+ throw new Error('Host text modality unavailable');
316
+ success(await this.#request('ui/message', {
317
+ role: 'user',
318
+ content: [{ type: 'text', text: string(text, 16384) }],
319
+ }, signal));
320
+ }
321
+ async updateModelContext(value, signal) {
322
+ this.#require('updateModelContext');
323
+ const caps = this.#snapshot.hostCapabilities.updateModelContext;
324
+ const params = {};
325
+ if (value.text !== undefined) {
326
+ if (!caps?.text)
327
+ throw new Error('Host text modality unavailable');
328
+ params.content = [{ type: 'text', text: string(value.text, 16384) }];
329
+ }
330
+ if (value.structuredContent !== undefined) {
331
+ if (!caps?.structuredContent)
332
+ throw new Error('Host structured modality unavailable');
333
+ params.structuredContent = object(value.structuredContent);
334
+ }
335
+ success(await this.#request('ui/update-model-context', params, signal));
336
+ }
337
+ async requestDisplayMode(value, signal) {
338
+ this.#ready();
339
+ const requested = mode(value);
340
+ if (!this.#modes.includes(requested) ||
341
+ !(this.#snapshot.hostContext.availableDisplayModes ?? ['inline']).includes(requested))
342
+ throw new Error('Display mode unavailable');
343
+ return mode(object(await this.#request('ui/request-display-mode', { mode: requested }, signal)).mode);
344
+ }
345
+ reportSize(width, height) {
346
+ this.#ready();
347
+ if (![width, height].every((v) => Number.isFinite(v) && v >= 0 && v <= 100000))
348
+ throw new Error('Invalid view dimensions');
349
+ this.#post({
350
+ jsonrpc: '2.0',
351
+ method: 'ui/notifications/size-changed',
352
+ params: { width, height },
353
+ });
354
+ }
355
+ #receive = (event) => {
356
+ if (event.source !== this.#host ||
357
+ event.origin !== this.#origin ||
358
+ this.#snapshot.state === 'disposed')
359
+ return;
360
+ try {
361
+ json(event.data);
362
+ const message = object(event.data);
363
+ if (message.jsonrpc !== '2.0')
364
+ return;
365
+ if (typeof message.method === 'string') {
366
+ if ('result' in message ||
367
+ 'error' in message ||
368
+ this.#snapshot.state !== 'ready')
369
+ return;
370
+ this.#incoming(message);
371
+ return;
372
+ }
373
+ if (!id(message.id) ||
374
+ typeof message.id !== 'string' ||
375
+ 'result' in message === 'error' in message)
376
+ return;
377
+ const pending = this.#pending.get(message.id);
378
+ if (!pending)
379
+ return;
380
+ let error;
381
+ if ('error' in message) {
382
+ const failure = object(message.error);
383
+ if (!Number.isSafeInteger(failure.code))
384
+ return;
385
+ error = new Error(`Host error ${failure.code}: ${string(failure.message, 4096)}`);
386
+ }
387
+ this.#pending.delete(message.id);
388
+ pending.cleanup();
389
+ if (error)
390
+ pending.reject(error);
391
+ else
392
+ pending.resolve(message.result);
393
+ }
394
+ catch {
395
+ /* Malformed/untrusted messages cannot change lifecycle or settle a request. */
396
+ }
397
+ };
398
+ #incoming(message) {
399
+ if ('id' in message) {
400
+ if (!id(message.id))
401
+ return;
402
+ if (message.method === 'ping' ||
403
+ message.method === 'ui/resource-teardown') {
404
+ if (message.params !== undefined)
405
+ object(message.params);
406
+ try {
407
+ this.#post({ jsonrpc: '2.0', id: message.id, result: {} });
408
+ }
409
+ finally {
410
+ if (message.method === 'ui/resource-teardown')
411
+ this.dispose();
412
+ }
413
+ }
414
+ else {
415
+ this.#post({
416
+ jsonrpc: '2.0',
417
+ id: message.id,
418
+ error: { code: -32601, message: 'Method not found' },
419
+ });
420
+ }
421
+ return;
422
+ }
423
+ const params = object(message.params);
424
+ switch (message.method) {
425
+ case 'ui/notifications/host-context-changed': {
426
+ const projected = context(params);
427
+ const merged = { ...this.#snapshot.rawHostContext, ...params };
428
+ // Each notification is bounded, and accumulated extension state must be too.
429
+ json(merged);
430
+ this.#snapshot.hostContext = {
431
+ ...this.#snapshot.hostContext,
432
+ ...projected,
433
+ };
434
+ this.#snapshot.rawHostContext = structuredClone(merged);
435
+ break;
436
+ }
437
+ case 'ui/notifications/tool-input':
438
+ if (this.#inputReceived || this.#terminalReceived)
439
+ return;
440
+ this.#snapshot.toolInput =
441
+ params.arguments === undefined ? {} : object(params.arguments);
442
+ this.#inputReceived = true;
443
+ break;
444
+ case 'ui/notifications/tool-result':
445
+ if (!this.#inputReceived || this.#terminalReceived)
446
+ return;
447
+ this.#snapshot.toolResult = toolResult(params);
448
+ this.#terminalReceived = true;
449
+ break;
450
+ case 'ui/notifications/tool-cancelled':
451
+ if (this.#terminalReceived)
452
+ return;
453
+ if (params.reason !== undefined)
454
+ string(params.reason);
455
+ this.#snapshot.cancelled = true;
456
+ this.#terminalReceived = true;
457
+ break;
458
+ default:
459
+ this.#notifyExtensions(message.method, params);
460
+ return;
461
+ }
462
+ this.#emit();
463
+ }
464
+ /** Idempotent. Pending requests reject; late responses and notifications have no owner. */
465
+ dispose() {
466
+ if (this.#snapshot.state === 'disposed')
467
+ return;
468
+ this.#snapshot.state = 'disposed';
469
+ this.#window.removeEventListener('message', this.#receive);
470
+ this.#lifetime.abort();
471
+ for (const state of this.#extensions.values()) {
472
+ state.listeners.clear();
473
+ state.lifetime.abort();
474
+ }
475
+ this.#extensions.clear();
476
+ for (const [requestId, pending] of this.#pending) {
477
+ pending.cleanup();
478
+ pending.reject(new Error('MCP Apps bridge disposed'));
479
+ try {
480
+ this.#post({
481
+ jsonrpc: '2.0',
482
+ method: 'notifications/cancelled',
483
+ params: { requestId },
484
+ });
485
+ }
486
+ catch {
487
+ /* Best effort transport cancellation. */
488
+ }
489
+ }
490
+ this.#pending.clear();
491
+ this.#emit();
492
+ this.#subscribers.clear();
493
+ }
494
+ }
495
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ /** Bounded JSON only. Never stringify arbitrary incoming objects before checking depth. */
2
+ export declare function json(value: unknown): void;
3
+ export declare function record(v: unknown): v is Record<string, unknown>;
4
+ export declare function object(v: unknown): Record<string, unknown>;
5
+ export declare function string(v: unknown, max?: number): string;
6
+ export declare function boolean(v: unknown): void;
7
+ export declare function id(v: unknown): v is string | number;
8
+ export type DisplayMode = 'inline' | 'fullscreen' | 'pip';
9
+ export declare function mode(v: unknown): DisplayMode;
10
+ export interface TextContent {
11
+ type: 'text';
12
+ text: string;
13
+ }
14
+ export interface ToolResult {
15
+ content: TextContent[];
16
+ structuredContent?: Record<string, unknown>;
17
+ isError?: boolean;
18
+ }
19
+ /** This bridge intentionally supports text + structured data, not binary content. */
20
+ export declare function toolResult(v: unknown): ToolResult;
21
+ export interface HostCapabilities {
22
+ openLinks?: Record<string, never>;
23
+ serverTools?: {
24
+ listChanged?: boolean;
25
+ };
26
+ message?: {
27
+ text?: Record<string, never>;
28
+ };
29
+ updateModelContext?: {
30
+ text?: Record<string, never>;
31
+ structuredContent?: Record<string, never>;
32
+ };
33
+ }
34
+ /** Unknown capabilities never grant behavior; known malformed fields fail closed. */
35
+ export declare function capabilities(v: unknown): HostCapabilities;
36
+ /** Deliberately non-executable subset: host CSS, tool definitions and unknown keys are not applied. */
37
+ export interface HostContext {
38
+ theme?: 'light' | 'dark';
39
+ displayMode?: DisplayMode;
40
+ availableDisplayModes?: DisplayMode[];
41
+ platform?: 'web' | 'desktop' | 'mobile';
42
+ locale?: string;
43
+ timeZone?: string;
44
+ }
45
+ export declare function context(v: unknown): HostContext;
46
+ export declare function success(v: unknown): void;
47
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAC3F,wBAAgB,IAAI,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CA6CzC;AACD,wBAAgB,MAAM,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQ/D;AACD,wBAAgB,MAAM,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAG1D;AACD,wBAAgB,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,SAAO,GAAG,MAAM,CAIrD;AACD,wBAAgB,OAAO,CAAC,CAAC,EAAE,OAAO,GAAG,IAAI,CAExC;AACD,wBAAgB,EAAE,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,MAAM,GAAG,MAAM,CAKnD;AACD,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,YAAY,GAAG,KAAK,CAAC;AAC1D,wBAAgB,IAAI,CAAC,CAAC,EAAE,OAAO,GAAG,WAAW,CAI5C;AACD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AACD,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AACD,qFAAqF;AACrF,wBAAgB,UAAU,CAAC,CAAC,EAAE,OAAO,GAAG,UAAU,CAkBjD;AACD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAClC,WAAW,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IACxC,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;KAAE,CAAC;IAC3C,kBAAkB,CAAC,EAAE;QACnB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;KAC3C,CAAC;CACH;AACD,qFAAqF;AACrF,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,GAAG,gBAAgB,CA+BzD;AACD,uGAAuG;AACvG,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,qBAAqB,CAAC,EAAE,WAAW,EAAE,CAAC;IACtC,QAAQ,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,QAAQ,CAAC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AACD,wBAAgB,OAAO,CAAC,CAAC,EAAE,OAAO,GAAG,WAAW,CA0B/C;AACD,wBAAgB,OAAO,CAAC,CAAC,EAAE,OAAO,GAAG,IAAI,CAIxC"}
@@ -0,0 +1,169 @@
1
+ /** Bounded JSON only. Never stringify arbitrary incoming objects before checking depth. */
2
+ export function json(value) {
3
+ let budget = 131072;
4
+ const visit = (v, depth) => {
5
+ if (--budget < 0 || depth > 24)
6
+ throw new Error('MCP Apps payload exceeds limits');
7
+ if (v === null || typeof v === 'boolean')
8
+ return;
9
+ if (typeof v === 'number' && Number.isFinite(v))
10
+ return;
11
+ if (typeof v === 'string') {
12
+ budget -= v.length * 3;
13
+ if (budget < 0)
14
+ throw new Error('MCP Apps payload exceeds limits');
15
+ return;
16
+ }
17
+ if (Array.isArray(v)) {
18
+ const length = Object.getOwnPropertyDescriptor(v, 'length')?.value;
19
+ if (!Number.isSafeInteger(length) || length < 0 || length > 4096)
20
+ throw new Error('MCP Apps array exceeds limits');
21
+ // Structured clone preserves named array properties. JSON does not: reject
22
+ // them (including symbol iterators), holes and accessors before any reads.
23
+ if (Reflect.ownKeys(v).length !== length + 1)
24
+ throw new Error('Expected dense JSON array');
25
+ const values = [];
26
+ for (let index = 0; index < length; index++) {
27
+ const descriptor = Object.getOwnPropertyDescriptor(v, String(index));
28
+ if (!descriptor || !('value' in descriptor))
29
+ throw new Error('Expected JSON array data property');
30
+ values.push(descriptor.value);
31
+ }
32
+ for (let index = 0; index < length; index++)
33
+ visit(values[index], depth + 1);
34
+ return;
35
+ }
36
+ if (!record(v))
37
+ throw new Error('Expected JSON object');
38
+ const keys = Object.keys(v);
39
+ if (keys.length > 1024)
40
+ throw new Error('MCP Apps object exceeds limits');
41
+ for (const key of keys) {
42
+ if (['__proto__', 'constructor', 'prototype'].includes(key))
43
+ throw new Error('Unsafe JSON key');
44
+ budget -= key.length * 3;
45
+ const descriptor = Object.getOwnPropertyDescriptor(v, key);
46
+ if (!descriptor || !('value' in descriptor))
47
+ throw new Error('Expected JSON property');
48
+ visit(descriptor.value, depth + 1);
49
+ }
50
+ };
51
+ visit(value, 0);
52
+ }
53
+ export function record(v) {
54
+ return (typeof v === 'object' &&
55
+ v !== null &&
56
+ !Array.isArray(v) &&
57
+ (Object.getPrototypeOf(v) === Object.prototype ||
58
+ Object.getPrototypeOf(v) === null));
59
+ }
60
+ export function object(v) {
61
+ if (!record(v))
62
+ throw new Error('Expected object');
63
+ return v;
64
+ }
65
+ export function string(v, max = 4096) {
66
+ if (typeof v !== 'string' || v.length > max)
67
+ throw new Error('Expected bounded string');
68
+ return v;
69
+ }
70
+ export function boolean(v) {
71
+ if (typeof v !== 'boolean')
72
+ throw new Error('Expected boolean');
73
+ }
74
+ export function id(v) {
75
+ return ((typeof v === 'string' && v.length > 0 && v.length <= 128) ||
76
+ (typeof v === 'number' && Number.isSafeInteger(v)));
77
+ }
78
+ export function mode(v) {
79
+ if (v !== 'inline' && v !== 'fullscreen' && v !== 'pip')
80
+ throw new Error('Unsupported display mode');
81
+ return v;
82
+ }
83
+ /** This bridge intentionally supports text + structured data, not binary content. */
84
+ export function toolResult(v) {
85
+ const r = object(v);
86
+ if (!Array.isArray(r.content) || r.content.length > 128)
87
+ throw new Error('Invalid tool content');
88
+ const content = r.content.map((item) => {
89
+ const block = object(item);
90
+ if (block.type !== 'text')
91
+ throw new Error('Unsupported tool content modality');
92
+ return { type: 'text', text: string(block.text, 32768) };
93
+ });
94
+ if (r.isError !== undefined)
95
+ boolean(r.isError);
96
+ return {
97
+ content,
98
+ ...(r.structuredContent === undefined
99
+ ? {}
100
+ : { structuredContent: object(r.structuredContent) }),
101
+ ...(r.isError === undefined ? {} : { isError: r.isError }),
102
+ };
103
+ }
104
+ /** Unknown capabilities never grant behavior; known malformed fields fail closed. */
105
+ export function capabilities(v) {
106
+ const input = object(v);
107
+ const out = {};
108
+ if (input.openLinks !== undefined) {
109
+ object(input.openLinks);
110
+ out.openLinks = {};
111
+ }
112
+ if (input.serverTools !== undefined) {
113
+ const tools = object(input.serverTools);
114
+ if (tools.listChanged !== undefined)
115
+ boolean(tools.listChanged);
116
+ out.serverTools =
117
+ tools.listChanged === undefined
118
+ ? {}
119
+ : { listChanged: tools.listChanged };
120
+ }
121
+ for (const key of ['message', 'updateModelContext']) {
122
+ if (input[key] === undefined)
123
+ continue;
124
+ const modalities = object(input[key]);
125
+ const value = {};
126
+ for (const modality of ['text', 'structuredContent']) {
127
+ if (modalities[modality] !== undefined) {
128
+ object(modalities[modality]);
129
+ value[modality] = {};
130
+ }
131
+ }
132
+ out[key] = value;
133
+ }
134
+ return out;
135
+ }
136
+ export function context(v) {
137
+ const input = object(v);
138
+ const out = {};
139
+ if (input.theme !== undefined) {
140
+ if (input.theme !== 'light' && input.theme !== 'dark')
141
+ throw new Error('Unsupported theme');
142
+ out.theme = input.theme;
143
+ }
144
+ if (input.displayMode !== undefined)
145
+ out.displayMode = mode(input.displayMode);
146
+ if (input.availableDisplayModes !== undefined) {
147
+ if (!Array.isArray(input.availableDisplayModes) ||
148
+ input.availableDisplayModes.length > 3)
149
+ throw new Error('Invalid modes');
150
+ out.availableDisplayModes = input.availableDisplayModes.map(mode);
151
+ }
152
+ if (input.platform !== undefined) {
153
+ if (!['web', 'desktop', 'mobile'].includes(string(input.platform)))
154
+ throw new Error('Unsupported platform');
155
+ out.platform = input.platform;
156
+ }
157
+ for (const key of ['locale', 'timeZone'])
158
+ if (input[key] !== undefined)
159
+ out[key] = string(input[key], 128);
160
+ return out;
161
+ }
162
+ export function success(v) {
163
+ const r = object(v);
164
+ if (r.isError !== undefined)
165
+ boolean(r.isError);
166
+ if (r.isError === true)
167
+ throw new Error('Host rejected request');
168
+ }
169
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,45 @@
1
1
  {
2
2
  "name": "@happyvertical/smrt-mcp-apps",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.51.38",
4
+ "description": "Framework-neutral browser bridge for portable MCP Apps",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "browser": "./dist/index.js",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md",
18
+ "AGENTS.md",
19
+ "CLAUDE.md"
20
+ ],
21
+ "devDependencies": {
22
+ "@happyvertical/smrt-app-mcp": "0.51.38",
23
+ "@happyvertical/smrt-core": "0.51.38",
24
+ "@types/node": "24.13.6",
25
+ "typescript": "6.0.3",
26
+ "vitest": "4.1.10"
27
+ },
28
+ "author": "HappyVertical",
29
+ "license": "MIT",
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "https://github.com/happyvertical/smrt.git",
33
+ "directory": "packages/mcp-apps"
34
+ },
35
+ "publishConfig": {
36
+ "access": "public"
37
+ },
38
+ "scripts": {
39
+ "build": "tsc -p tsconfig.json",
40
+ "typecheck": "tsc --noEmit -p tsconfig.json",
41
+ "test": "vitest run",
42
+ "test:e2e": "playwright test -c e2e/playwright.config.ts",
43
+ "verify:pack": "node ../../scripts/verify-package-types-exports.js ."
44
+ }
6
45
  }