mountly-mcp 4.0.1 → 4.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -17
- package/dist/bridge/iframe-entry.js +3 -1
- package/dist/bridge/index.js +1 -1
- package/dist/{chunk-JVQZGKBL.js → chunk-2HNXL5A4.js} +4 -2
- package/dist/chunk-2HNXL5A4.js.map +1 -0
- package/dist/{chunk-SADNMGP6.js → chunk-5L3QHYWK.js} +1 -1
- package/dist/{chunk-SADNMGP6.js.map → chunk-5L3QHYWK.js.map} +1 -1
- package/dist/{chunk-AEVQKFXX.js → chunk-SXF23BZD.js} +2 -2
- package/dist/index.js +2 -2
- package/dist/json-render/index.js +2 -2
- package/dist/react/index.js +2 -2
- package/dist/svelte/index.js +1 -1
- package/dist/vue/index.js +1 -1
- package/package.json +9 -9
- package/dist/chunk-JVQZGKBL.js.map +0 -1
- /package/dist/{chunk-AEVQKFXX.js.map → chunk-SXF23BZD.js.map} +0 -0
package/README.md
CHANGED
|
@@ -30,12 +30,12 @@ way it drives the others.
|
|
|
30
30
|
|
|
31
31
|
## Build with Agent Skills
|
|
32
32
|
|
|
33
|
-
| Skill
|
|
34
|
-
|
|
|
35
|
-
| [`create-mcp-app`](../../plugins/mountly-mcp/skills/create-mcp-app/SKILL.md)
|
|
36
|
-
| [`add-app-to-server`](../../plugins/mountly-mcp/skills/add-app-to-server/SKILL.md) | _"Add UI to my MCP server"_
|
|
37
|
-
| [`convert-web-app`](../../plugins/mountly-mcp/skills/convert-web-app/SKILL.md)
|
|
38
|
-
| [`migrate-ext-apps`](../../plugins/mountly-mcp/skills/migrate-ext-apps/SKILL.md)
|
|
33
|
+
| Skill | Try it |
|
|
34
|
+
| ---------------------------------------------------------------------------------- | ------------------------------------- |
|
|
35
|
+
| [`create-mcp-app`](../../plugins/mountly-mcp/skills/create-mcp-app/SKILL.md) | _"Create an MCP App"_ |
|
|
36
|
+
| [`add-app-to-server`](../../plugins/mountly-mcp/skills/add-app-to-server/SKILL.md) | _"Add UI to my MCP server"_ |
|
|
37
|
+
| [`convert-web-app`](../../plugins/mountly-mcp/skills/convert-web-app/SKILL.md) | _"Turn my component into an MCP App"_ |
|
|
38
|
+
| [`migrate-ext-apps`](../../plugins/mountly-mcp/skills/migrate-ext-apps/SKILL.md) | _"Migrate from ext-apps"_ |
|
|
39
39
|
|
|
40
40
|
```
|
|
41
41
|
/plugin marketplace add jagreehal/mountly
|
|
@@ -271,18 +271,18 @@ renders what it can. Drop the loose branch once core relaxes those fields.
|
|
|
271
271
|
|
|
272
272
|
## Exports
|
|
273
273
|
|
|
274
|
-
| Entry | What's in it
|
|
275
|
-
| ---------------------- |
|
|
276
|
-
| `mountly-mcp` | `runBridge`, spec types re-exported from ext-apps
|
|
277
|
-
| `mountly-mcp/react` | `createMcpView` + hooks
|
|
278
|
-
| `mountly-mcp/vue` | `createMcpView` + composables
|
|
279
|
-
| `mountly-mcp/svelte` | `createMcpView` (props-based)
|
|
274
|
+
| Entry | What's in it |
|
|
275
|
+
| ---------------------- | ------------------------------------------------------- |
|
|
276
|
+
| `mountly-mcp` | `runBridge`, spec types re-exported from ext-apps |
|
|
277
|
+
| `mountly-mcp/react` | `createMcpView` + hooks |
|
|
278
|
+
| `mountly-mcp/vue` | `createMcpView` + composables |
|
|
279
|
+
| `mountly-mcp/svelte` | `createMcpView` (props-based) |
|
|
280
280
|
| `mountly-mcp/vite` | single- and multi-View `mountlyMcpViews()` build plugin |
|
|
281
|
-
| `mountly-mcp/artifact` | versioned manifest and App artifact APIs
|
|
282
|
-
| `mountly-mcp/dev` | `startDevHost()` and in-process server connectivity
|
|
283
|
-
| `mountly-mcp/build` | `buildMcpResource` for other bundlers
|
|
284
|
-
| `mountly-mcp/server` | `registerMcpApps` plus convenience server adapters
|
|
285
|
-
| `mountly-mcp/testing` | static/browser conformance and report formatting
|
|
281
|
+
| `mountly-mcp/artifact` | versioned manifest and App artifact APIs |
|
|
282
|
+
| `mountly-mcp/dev` | `startDevHost()` and in-process server connectivity |
|
|
283
|
+
| `mountly-mcp/build` | `buildMcpResource` for other bundlers |
|
|
284
|
+
| `mountly-mcp/server` | `registerMcpApps` plus convenience server adapters |
|
|
285
|
+
| `mountly-mcp/testing` | static/browser conformance and report formatting |
|
|
286
286
|
|
|
287
287
|
Types use the spec's own names (`McpUiHostContext`, `McpUiDisplayMode`, …) —
|
|
288
288
|
one vocabulary, no translation layer.
|
|
@@ -18589,6 +18589,7 @@ container holding the app. Specify either width or maxWidth, and either height o
|
|
|
18589
18589
|
let toolResult;
|
|
18590
18590
|
let mounted = false;
|
|
18591
18591
|
let stopped = false;
|
|
18592
|
+
let failed = false;
|
|
18592
18593
|
let pending = Promise.resolve();
|
|
18593
18594
|
function currentProps() {
|
|
18594
18595
|
return {
|
|
@@ -18600,6 +18601,7 @@ container holding the app. Specify either width or maxWidth, and either height o
|
|
|
18600
18601
|
};
|
|
18601
18602
|
}
|
|
18602
18603
|
function notifyError(code, error51) {
|
|
18604
|
+
failed = true;
|
|
18603
18605
|
const message = error51 instanceof Error ? error51.message : String(error51);
|
|
18604
18606
|
try {
|
|
18605
18607
|
void app.sendLog({ level: "error", data: { code, message } }).catch(() => void 0);
|
|
@@ -18615,7 +18617,7 @@ container holding the app. Specify either width or maxWidth, and either height o
|
|
|
18615
18617
|
const r2 = view2.mount(container2, props);
|
|
18616
18618
|
if (r2 instanceof Promise) await r2;
|
|
18617
18619
|
mounted = true;
|
|
18618
|
-
container2.setAttribute("data-mountly-mcp-state", "mounted");
|
|
18620
|
+
if (!failed) container2.setAttribute("data-mountly-mcp-state", "mounted");
|
|
18619
18621
|
} else if (view2.update) {
|
|
18620
18622
|
const r2 = view2.update(container2, props);
|
|
18621
18623
|
if (r2 instanceof Promise) await r2;
|
package/dist/bridge/index.js
CHANGED
|
@@ -35,6 +35,7 @@ function runBridge(options) {
|
|
|
35
35
|
let toolResult;
|
|
36
36
|
let mounted = false;
|
|
37
37
|
let stopped = false;
|
|
38
|
+
let failed = false;
|
|
38
39
|
let pending = Promise.resolve();
|
|
39
40
|
function currentProps() {
|
|
40
41
|
return {
|
|
@@ -46,6 +47,7 @@ function runBridge(options) {
|
|
|
46
47
|
};
|
|
47
48
|
}
|
|
48
49
|
function notifyError(code, error) {
|
|
50
|
+
failed = true;
|
|
49
51
|
const message = error instanceof Error ? error.message : String(error);
|
|
50
52
|
try {
|
|
51
53
|
void app.sendLog({ level: "error", data: { code, message } }).catch(() => void 0);
|
|
@@ -61,7 +63,7 @@ function runBridge(options) {
|
|
|
61
63
|
const r = view.mount(container, props);
|
|
62
64
|
if (r instanceof Promise) await r;
|
|
63
65
|
mounted = true;
|
|
64
|
-
container.setAttribute("data-mountly-mcp-state", "mounted");
|
|
66
|
+
if (!failed) container.setAttribute("data-mountly-mcp-state", "mounted");
|
|
65
67
|
} else if (view.update) {
|
|
66
68
|
const r = view.update(container, props);
|
|
67
69
|
if (r instanceof Promise) await r;
|
|
@@ -168,4 +170,4 @@ export {
|
|
|
168
170
|
PostMessageTransport,
|
|
169
171
|
runBridge
|
|
170
172
|
};
|
|
171
|
-
//# sourceMappingURL=chunk-
|
|
173
|
+
//# sourceMappingURL=chunk-2HNXL5A4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/bridge/index.ts"],"sourcesContent":["/**\n * View-side bridge that turns an MCP Apps `App` into a mountly view module\n * lifecycle. The full spec handshake — `ui/initialize`,\n * `ui/notifications/initialized`, `ui/notifications/tool-input(-partial)`,\n * `ui/notifications/tool-result`, `ui/notifications/tool-cancelled`,\n * `ui/notifications/host-context-changed`, `ui/resource-teardown`,\n * `ui/notifications/size-changed` — is delegated to ext-apps's `App`.\n */\nimport {\n App,\n PostMessageTransport,\n type McpUiAppCapabilities,\n type McpUiDisplayMode,\n type McpUiToolInputNotification,\n type McpUiToolInputPartialNotification,\n type McpUiToolResultNotification,\n} from \"@modelcontextprotocol/ext-apps\";\n\nimport { MCP_ERROR_CODES } from \"../schema.js\";\nimport type { McpView, McpViewProps } from \"../types.js\";\n\nexport interface RunBridgeOptions {\n /** Pre-constructed App (used by jsdom tests); otherwise one is created here. */\n app?: App;\n view: McpView;\n container: Element;\n /**\n * If true (default), mount is deferred until the first tool-result arrives;\n * the View renders against `{ toolInput, toolResult, hostContext, mcp }`\n * props on each notification.\n *\n * If false, mount fires immediately after `ui/initialize` with `{ mcp }`\n * only — for \"stateless\" views that drive themselves via `mcp.callServerTool`.\n */\n awaitToolResult?: boolean;\n /**\n * Render progressive states from `ui/notifications/tool-input-partial`.\n *\n * Off by default — the spec lets views ignore partials, and they carry\n * best-effort recovered JSON that MUST NOT drive critical operations. When\n * on, partials arrive as `toolInputPartial` (mounting the View early if\n * needed) and are cleared once the complete `tool-input` lands.\n */\n streamToolInput?: boolean;\n /** Display modes this view supports. Declared to the host during `ui/initialize`. */\n availableDisplayModes?: ReadonlyArray<McpUiDisplayMode>;\n /** App identity sent during `ui/initialize`. */\n appInfo?: { name: string; version: string };\n /** Override for tests; defaults to `window.addEventListener('beforeunload', ...)`. */\n onTeardown?: (handler: () => void) => () => void;\n}\n\nexport interface RunningBridge {\n /** Resolves once `ui/initialize` handshake completes and the first mount (or deferred mount) is wired. */\n ready: Promise<void>;\n /** The underlying App; exposed for hosts that want to drive the view directly. */\n app: App;\n /** Synchronously triggers teardown. */\n stop(): void;\n}\n\n/**\n * `data-mountly-mcp-state` is the View's machine-readable outcome, read by\n * `verify --render`. Once the boundary writes `error` the state latches:\n * a View that threw is a defect worth reporting even if a later notification\n * happens to render it successfully. The UI still recovers — only the recorded\n * outcome is sticky. See the `failed` flag in `runBridge`.\n */\nfunction renderErrorBoundary(container: Element, code: string, message?: string): void {\n container.setAttribute(\"data-mountly-mcp-state\", \"error\");\n const doc = container.ownerDocument;\n if (!doc) return;\n const errorDiv = doc.createElement(\"div\");\n errorDiv.setAttribute(\"data-mountly-mcp-error\", code);\n if (message !== undefined) errorDiv.textContent = message;\n container.innerHTML = \"\";\n container.appendChild(errorDiv);\n}\n\nexport function runBridge(options: RunBridgeOptions): RunningBridge {\n const {\n view,\n container,\n awaitToolResult = true,\n streamToolInput = false,\n availableDisplayModes = [\"inline\"],\n appInfo = { name: \"mountly-mcp\", version: \"0.0.0\" },\n } = options;\n\n const appCapabilities: McpUiAppCapabilities = {\n availableDisplayModes: [...availableDisplayModes],\n };\n\n const app = options.app ?? new App(appInfo, appCapabilities);\n\n let toolInput: McpUiToolInputNotification[\"params\"] | undefined;\n let toolInputPartial: McpUiToolInputPartialNotification[\"params\"] | undefined;\n let toolResult: McpUiToolResultNotification[\"params\"] | undefined;\n let mounted = false;\n let stopped = false;\n /** Latches once the error boundary has fired; see `renderErrorBoundary`. */\n let failed = false;\n let pending: Promise<void> = Promise.resolve();\n\n function currentProps(): McpViewProps {\n return {\n mcp: app,\n toolInput,\n toolInputPartial,\n toolResult,\n hostContext: app.getHostContext(),\n };\n }\n\n function notifyError(code: string, error: unknown): void {\n failed = true;\n const message = error instanceof Error ? error.message : String(error);\n try {\n void app.sendLog({ level: \"error\", data: { code, message } }).catch(() => undefined);\n } catch {\n // ignore — log channel may not be ready\n }\n renderErrorBoundary(container, code, message);\n }\n\n function renderWith(props: McpViewProps): Promise<void> {\n pending = pending.then(async () => {\n if (stopped) return;\n try {\n if (!mounted) {\n const r = view.mount(container, props);\n if (r instanceof Promise) await r;\n mounted = true;\n // Recovering the UI is good; pretending the earlier throw did not\n // happen is not. The attribute stays `error` once it has been set.\n if (!failed) container.setAttribute(\"data-mountly-mcp-state\", \"mounted\");\n } else if (view.update) {\n const r = view.update(container, props);\n if (r instanceof Promise) await r;\n } else {\n await view.unmount(container);\n mounted = false;\n const r = view.mount(container, props);\n if (r instanceof Promise) await r;\n mounted = true;\n }\n } catch (error) {\n notifyError(MCP_ERROR_CODES.VIEW_MOUNT_THREW, error);\n }\n });\n return pending;\n }\n\n async function unmountView(): Promise<void> {\n await pending;\n if (!mounted) return;\n mounted = false;\n await view.unmount(container);\n }\n\n // Event handlers MUST be registered before connect() — ext-apps will refuse\n // to attach handlers retroactively after the initialize handshake completes.\n const handleToolInput = (params: McpUiToolInputNotification[\"params\"]) => {\n toolInput = params;\n toolInputPartial = undefined;\n if (!awaitToolResult) return;\n if (mounted || toolResult !== undefined) void renderWith(currentProps());\n };\n\n const handleToolInputPartial = (params: McpUiToolInputPartialNotification[\"params\"]) => {\n // Views MAY ignore partial input per spec; opt in with `streamToolInput`.\n // Consumers wanting finer control can subscribe via app.addEventListener.\n if (!streamToolInput) return;\n toolInputPartial = params;\n void renderWith(currentProps());\n };\n\n const handleToolResult = (params: McpUiToolResultNotification[\"params\"]) => {\n toolResult = params;\n void renderWith(currentProps());\n };\n\n const handleToolCancelled = () => {\n void renderWith(currentProps());\n };\n\n const handleHostContextChanged = () => {\n if (mounted) void renderWith(currentProps());\n };\n\n app.addEventListener(\"toolinput\", handleToolInput);\n app.addEventListener(\"toolinputpartial\", handleToolInputPartial);\n app.addEventListener(\"toolresult\", handleToolResult);\n app.addEventListener(\"toolcancelled\", handleToolCancelled);\n app.addEventListener(\"hostcontextchanged\", handleHostContextChanged);\n\n const previousTeardown = app.onteardown;\n const bridgeTeardown: NonNullable<typeof app.onteardown> = async (params, extra) => {\n stopped = true;\n detachTeardown();\n detachAppHandlers();\n await unmountView();\n return (await previousTeardown?.(params, extra)) ?? {};\n };\n app.onteardown = bridgeTeardown;\n\n function detachAppHandlers(): void {\n app.removeEventListener(\"toolinput\", handleToolInput);\n app.removeEventListener(\"toolinputpartial\", handleToolInputPartial);\n app.removeEventListener(\"toolresult\", handleToolResult);\n app.removeEventListener(\"toolcancelled\", handleToolCancelled);\n app.removeEventListener(\"hostcontextchanged\", handleHostContextChanged);\n if (app.onteardown === bridgeTeardown) app.onteardown = previousTeardown;\n }\n\n const ready = (async () => {\n try {\n if (!options.app) {\n // App.connect() defaults to PostMessageTransport(window.parent, window.parent)\n // and owns automatic resize setup.\n await app.connect();\n }\n\n if (!awaitToolResult) {\n await renderWith(currentProps());\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n const code = /timeout/i.test(message)\n ? MCP_ERROR_CODES.INITIALIZE_TIMEOUT\n : MCP_ERROR_CODES.INITIALIZE_FAILED;\n notifyError(code, error);\n throw error;\n }\n })();\n\n let detachTeardown: () => void = () => undefined;\n\n function stopBridge(): void {\n if (stopped) return;\n stopped = true;\n detachTeardown();\n detachAppHandlers();\n void unmountView();\n if (!options.app) void app.close().catch(() => undefined);\n }\n\n detachTeardown =\n options.onTeardown?.(stopBridge) ??\n (typeof window !== \"undefined\"\n ? (() => {\n const h = () => stopBridge();\n window.addEventListener(\"beforeunload\", h);\n return () => window.removeEventListener(\"beforeunload\", h);\n })()\n : () => undefined);\n\n return {\n ready,\n app,\n stop: stopBridge,\n };\n}\n\nexport { App, PostMessageTransport };\nexport type {\n McpUiAppCapabilities,\n McpUiHostCapabilities,\n McpUiHostContext,\n McpUiToolInputNotification,\n McpUiToolInputPartialNotification,\n McpUiToolResultNotification,\n McpUiToolCancelledNotification,\n McpUiHostContextChangedNotification,\n} from \"@modelcontextprotocol/ext-apps\";\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/publish.ts"],"sourcesContent":["import type { McpView } from \"./types.js\";\n\n/** Internal bridge key — prefer {@link publishMcpView} / `createMcpView`. */\nexport const MCP_VIEW_GLOBAL_KEY = \"__mountlyMcpView__\" as const;\n\n/**\n * Publish a View module for the iframe bridge. Call once from your View entry\n * (or rely on `createMcpView`, which does this for you).\n */\nexport function publishMcpView(view: McpView): McpView {\n (globalThis as Record<string, unknown>)[MCP_VIEW_GLOBAL_KEY] = view;\n return view;\n}\n\n/** Read the published View module, if any. */\nexport function getPublishedMcpView(): McpView | undefined {\n return (globalThis as Record<string, unknown>)[MCP_VIEW_GLOBAL_KEY] as
|
|
1
|
+
{"version":3,"sources":["../src/publish.ts"],"sourcesContent":["import type { McpView } from \"./types.js\";\n\n/** Internal bridge key — prefer {@link publishMcpView} / `createMcpView`. */\nexport const MCP_VIEW_GLOBAL_KEY = \"__mountlyMcpView__\" as const;\n\n/**\n * Publish a View module for the iframe bridge. Call once from your View entry\n * (or rely on `createMcpView`, which does this for you).\n */\nexport function publishMcpView(view: McpView): McpView {\n (globalThis as Record<string, unknown>)[MCP_VIEW_GLOBAL_KEY] = view;\n return view;\n}\n\n/** Read the published View module, if any. */\nexport function getPublishedMcpView(): McpView | undefined {\n return (globalThis as Record<string, unknown>)[MCP_VIEW_GLOBAL_KEY] as McpView | undefined;\n}\n"],"mappings":";AAGO,IAAM,sBAAsB;AAM5B,SAAS,eAAe,MAAwB;AACrD,EAAC,WAAuC,mBAAmB,IAAI;AAC/D,SAAO;AACT;AAGO,SAAS,sBAA2C;AACzD,SAAQ,WAAuC,mBAAmB;AACpE;","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
publishMcpView
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-5L3QHYWK.js";
|
|
4
4
|
|
|
5
5
|
// src/react/context.ts
|
|
6
6
|
import { createContext } from "react";
|
|
@@ -116,4 +116,4 @@ export {
|
|
|
116
116
|
useAutoResize,
|
|
117
117
|
createMcpView
|
|
118
118
|
};
|
|
119
|
-
//# sourceMappingURL=chunk-
|
|
119
|
+
//# sourceMappingURL=chunk-SXF23BZD.js.map
|
package/dist/index.js
CHANGED
|
@@ -5,12 +5,12 @@ import {
|
|
|
5
5
|
MCP_VIEW_GLOBAL_KEY,
|
|
6
6
|
getPublishedMcpView,
|
|
7
7
|
publishMcpView
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-5L3QHYWK.js";
|
|
9
9
|
import {
|
|
10
10
|
App,
|
|
11
11
|
PostMessageTransport,
|
|
12
12
|
runBridge
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-2HNXL5A4.js";
|
|
14
14
|
import {
|
|
15
15
|
EXTENSION_ID,
|
|
16
16
|
LATEST_PROTOCOL_VERSION,
|
package/dist/react/index.js
CHANGED
|
@@ -14,8 +14,8 @@ import {
|
|
|
14
14
|
useToolInputPartial,
|
|
15
15
|
useToolResult,
|
|
16
16
|
useUpdateModelContext
|
|
17
|
-
} from "../chunk-
|
|
18
|
-
import "../chunk-
|
|
17
|
+
} from "../chunk-SXF23BZD.js";
|
|
18
|
+
import "../chunk-5L3QHYWK.js";
|
|
19
19
|
export {
|
|
20
20
|
McpContext,
|
|
21
21
|
createMcpView,
|
package/dist/svelte/index.js
CHANGED
package/dist/vue/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mountly-mcp",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.2",
|
|
4
4
|
"description": "Build MCP Apps (SEP-1865) views from React, Vue or Svelte components — new or existing. One build emits the ui:// resource, its sidecar, and the MCP server wiring.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"chatgpt",
|
|
@@ -8,13 +8,13 @@
|
|
|
8
8
|
"mcp",
|
|
9
9
|
"mcp-apps",
|
|
10
10
|
"mcp-ui",
|
|
11
|
+
"mcp-view",
|
|
11
12
|
"model-context-protocol",
|
|
12
13
|
"react",
|
|
13
14
|
"sep-1865",
|
|
14
15
|
"svelte",
|
|
15
16
|
"vite-plugin",
|
|
16
|
-
"vue"
|
|
17
|
-
"mcp-view"
|
|
17
|
+
"vue"
|
|
18
18
|
],
|
|
19
19
|
"license": "Apache-2.0",
|
|
20
20
|
"repository": {
|
|
@@ -107,8 +107,8 @@
|
|
|
107
107
|
"dependencies": {
|
|
108
108
|
"@modelcontextprotocol/ext-apps": "^1.7.5",
|
|
109
109
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
110
|
-
"mountly": "^0.
|
|
111
|
-
"mountly-react": "^2.0
|
|
110
|
+
"mountly": "^1.0.0",
|
|
111
|
+
"mountly-react": "^2.1.0",
|
|
112
112
|
"zod": "^4.4.3"
|
|
113
113
|
},
|
|
114
114
|
"devDependencies": {
|
|
@@ -125,16 +125,16 @@
|
|
|
125
125
|
"tsup": "^8.5.1",
|
|
126
126
|
"typescript": "^7.0.2",
|
|
127
127
|
"vite": "^8.1.5",
|
|
128
|
-
"mountly-svelte": "^2.0
|
|
129
|
-
"mountly-vue": "^2.0
|
|
128
|
+
"mountly-svelte": "^2.1.0",
|
|
129
|
+
"mountly-vue": "^2.1.0"
|
|
130
130
|
},
|
|
131
131
|
"peerDependencies": {
|
|
132
132
|
"@json-render/core": "^0.20.0",
|
|
133
133
|
"@json-render/react": "^0.20.0",
|
|
134
134
|
"ai": "^7.0.65",
|
|
135
135
|
"axe-core": ">=4.10.0",
|
|
136
|
-
"mountly-svelte": "^2.0
|
|
137
|
-
"mountly-vue": "^2.0
|
|
136
|
+
"mountly-svelte": "^2.1.0",
|
|
137
|
+
"mountly-vue": "^2.1.0",
|
|
138
138
|
"playwright": ">=1.62.1",
|
|
139
139
|
"react": "^19",
|
|
140
140
|
"react-dom": "^19",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/bridge/index.ts"],"sourcesContent":["/**\n * View-side bridge that turns an MCP Apps `App` into a mountly view module\n * lifecycle. The full spec handshake — `ui/initialize`,\n * `ui/notifications/initialized`, `ui/notifications/tool-input(-partial)`,\n * `ui/notifications/tool-result`, `ui/notifications/tool-cancelled`,\n * `ui/notifications/host-context-changed`, `ui/resource-teardown`,\n * `ui/notifications/size-changed` — is delegated to ext-apps's `App`.\n */\nimport {\n App,\n PostMessageTransport,\n type McpUiAppCapabilities,\n type McpUiDisplayMode,\n type McpUiToolInputNotification,\n type McpUiToolInputPartialNotification,\n type McpUiToolResultNotification,\n} from \"@modelcontextprotocol/ext-apps\";\n\nimport { MCP_ERROR_CODES } from \"../schema.js\";\nimport type { McpView, McpViewProps } from \"../types.js\";\n\nexport interface RunBridgeOptions {\n /** Pre-constructed App (used by jsdom tests); otherwise one is created here. */\n app?: App;\n view: McpView;\n container: Element;\n /**\n * If true (default), mount is deferred until the first tool-result arrives;\n * the View renders against `{ toolInput, toolResult, hostContext, mcp }`\n * props on each notification.\n *\n * If false, mount fires immediately after `ui/initialize` with `{ mcp }`\n * only — for \"stateless\" views that drive themselves via `mcp.callServerTool`.\n */\n awaitToolResult?: boolean;\n /**\n * Render progressive states from `ui/notifications/tool-input-partial`.\n *\n * Off by default — the spec lets views ignore partials, and they carry\n * best-effort recovered JSON that MUST NOT drive critical operations. When\n * on, partials arrive as `toolInputPartial` (mounting the View early if\n * needed) and are cleared once the complete `tool-input` lands.\n */\n streamToolInput?: boolean;\n /** Display modes this view supports. Declared to the host during `ui/initialize`. */\n availableDisplayModes?: ReadonlyArray<McpUiDisplayMode>;\n /** App identity sent during `ui/initialize`. */\n appInfo?: { name: string; version: string };\n /** Override for tests; defaults to `window.addEventListener('beforeunload', ...)`. */\n onTeardown?: (handler: () => void) => () => void;\n}\n\nexport interface RunningBridge {\n /** Resolves once `ui/initialize` handshake completes and the first mount (or deferred mount) is wired. */\n ready: Promise<void>;\n /** The underlying App; exposed for hosts that want to drive the view directly. */\n app: App;\n /** Synchronously triggers teardown. */\n stop(): void;\n}\n\n/**\n * `data-mountly-mcp-state` is the View's machine-readable outcome, read by\n * `verify --render`. It only ever moves forward — `mounted` once the View\n * has mounted, `error` if the boundary replaced it — so a state written here\n * can never be clobbered by a later lifecycle step.\n */\nfunction renderErrorBoundary(container: Element, code: string, message?: string): void {\n container.setAttribute(\"data-mountly-mcp-state\", \"error\");\n const doc = container.ownerDocument;\n if (!doc) return;\n const errorDiv = doc.createElement(\"div\");\n errorDiv.setAttribute(\"data-mountly-mcp-error\", code);\n if (message !== undefined) errorDiv.textContent = message;\n container.innerHTML = \"\";\n container.appendChild(errorDiv);\n}\n\nexport function runBridge(options: RunBridgeOptions): RunningBridge {\n const {\n view,\n container,\n awaitToolResult = true,\n streamToolInput = false,\n availableDisplayModes = [\"inline\"],\n appInfo = { name: \"mountly-mcp\", version: \"0.0.0\" },\n } = options;\n\n const appCapabilities: McpUiAppCapabilities = {\n availableDisplayModes: [...availableDisplayModes],\n };\n\n const app = options.app ?? new App(appInfo, appCapabilities);\n\n let toolInput: McpUiToolInputNotification[\"params\"] | undefined;\n let toolInputPartial: McpUiToolInputPartialNotification[\"params\"] | undefined;\n let toolResult: McpUiToolResultNotification[\"params\"] | undefined;\n let mounted = false;\n let stopped = false;\n let pending: Promise<void> = Promise.resolve();\n\n function currentProps(): McpViewProps {\n return {\n mcp: app,\n toolInput,\n toolInputPartial,\n toolResult,\n hostContext: app.getHostContext(),\n };\n }\n\n function notifyError(code: string, error: unknown): void {\n const message = error instanceof Error ? error.message : String(error);\n try {\n void app.sendLog({ level: \"error\", data: { code, message } }).catch(() => undefined);\n } catch {\n // ignore — log channel may not be ready\n }\n renderErrorBoundary(container, code, message);\n }\n\n function renderWith(props: McpViewProps): Promise<void> {\n pending = pending.then(async () => {\n if (stopped) return;\n try {\n if (!mounted) {\n const r = view.mount(container, props);\n if (r instanceof Promise) await r;\n mounted = true;\n container.setAttribute(\"data-mountly-mcp-state\", \"mounted\");\n } else if (view.update) {\n const r = view.update(container, props);\n if (r instanceof Promise) await r;\n } else {\n await view.unmount(container);\n mounted = false;\n const r = view.mount(container, props);\n if (r instanceof Promise) await r;\n mounted = true;\n }\n } catch (error) {\n notifyError(MCP_ERROR_CODES.VIEW_MOUNT_THREW, error);\n }\n });\n return pending;\n }\n\n async function unmountView(): Promise<void> {\n await pending;\n if (!mounted) return;\n mounted = false;\n await view.unmount(container);\n }\n\n // Event handlers MUST be registered before connect() — ext-apps will refuse\n // to attach handlers retroactively after the initialize handshake completes.\n const handleToolInput = (params: McpUiToolInputNotification[\"params\"]) => {\n toolInput = params;\n toolInputPartial = undefined;\n if (!awaitToolResult) return;\n if (mounted || toolResult !== undefined) void renderWith(currentProps());\n };\n\n const handleToolInputPartial = (params: McpUiToolInputPartialNotification[\"params\"]) => {\n // Views MAY ignore partial input per spec; opt in with `streamToolInput`.\n // Consumers wanting finer control can subscribe via app.addEventListener.\n if (!streamToolInput) return;\n toolInputPartial = params;\n void renderWith(currentProps());\n };\n\n const handleToolResult = (params: McpUiToolResultNotification[\"params\"]) => {\n toolResult = params;\n void renderWith(currentProps());\n };\n\n const handleToolCancelled = () => {\n void renderWith(currentProps());\n };\n\n const handleHostContextChanged = () => {\n if (mounted) void renderWith(currentProps());\n };\n\n app.addEventListener(\"toolinput\", handleToolInput);\n app.addEventListener(\"toolinputpartial\", handleToolInputPartial);\n app.addEventListener(\"toolresult\", handleToolResult);\n app.addEventListener(\"toolcancelled\", handleToolCancelled);\n app.addEventListener(\"hostcontextchanged\", handleHostContextChanged);\n\n const previousTeardown = app.onteardown;\n const bridgeTeardown: NonNullable<typeof app.onteardown> = async (params, extra) => {\n stopped = true;\n detachTeardown();\n detachAppHandlers();\n await unmountView();\n return (await previousTeardown?.(params, extra)) ?? {};\n };\n app.onteardown = bridgeTeardown;\n\n function detachAppHandlers(): void {\n app.removeEventListener(\"toolinput\", handleToolInput);\n app.removeEventListener(\"toolinputpartial\", handleToolInputPartial);\n app.removeEventListener(\"toolresult\", handleToolResult);\n app.removeEventListener(\"toolcancelled\", handleToolCancelled);\n app.removeEventListener(\"hostcontextchanged\", handleHostContextChanged);\n if (app.onteardown === bridgeTeardown) app.onteardown = previousTeardown;\n }\n\n const ready = (async () => {\n try {\n if (!options.app) {\n // App.connect() defaults to PostMessageTransport(window.parent, window.parent)\n // and owns automatic resize setup.\n await app.connect();\n }\n\n if (!awaitToolResult) {\n await renderWith(currentProps());\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n const code = /timeout/i.test(message)\n ? MCP_ERROR_CODES.INITIALIZE_TIMEOUT\n : MCP_ERROR_CODES.INITIALIZE_FAILED;\n notifyError(code, error);\n throw error;\n }\n })();\n\n let detachTeardown: () => void = () => undefined;\n\n function stopBridge(): void {\n if (stopped) return;\n stopped = true;\n detachTeardown();\n detachAppHandlers();\n void unmountView();\n if (!options.app) void app.close().catch(() => undefined);\n }\n\n detachTeardown =\n options.onTeardown?.(stopBridge) ??\n (typeof window !== \"undefined\"\n ? (() => {\n const h = () => stopBridge();\n window.addEventListener(\"beforeunload\", h);\n return () => window.removeEventListener(\"beforeunload\", h);\n })()\n : () => undefined);\n\n return {\n ready,\n app,\n stop: stopBridge,\n };\n}\n\nexport { App, PostMessageTransport };\nexport type {\n McpUiAppCapabilities,\n McpUiHostCapabilities,\n McpUiHostContext,\n McpUiToolInputNotification,\n McpUiToolInputPartialNotification,\n McpUiToolResultNotification,\n McpUiToolCancelledNotification,\n McpUiHostContextChangedNotification,\n} from \"@modelcontextprotocol/ext-apps\";\n"],"mappings":"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","names":[]}
|
|
File without changes
|