mountly-mcp 0.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +258 -20
  3. package/dist/artifact/index.d.ts +49 -0
  4. package/dist/artifact/index.js +21 -0
  5. package/dist/artifact/index.js.map +1 -0
  6. package/dist/bridge/iframe-entry.d.ts +1 -0
  7. package/dist/bridge/iframe-entry.js +251 -209
  8. package/dist/bridge/index.d.ts +17 -12
  9. package/dist/bridge/index.js +2 -2
  10. package/dist/build/emit-html.d.ts +30 -0
  11. package/dist/build/emit-meta.d.ts +17 -0
  12. package/dist/build/index.d.ts +32 -47
  13. package/dist/build/index.js +9 -135
  14. package/dist/build/index.js.map +1 -1
  15. package/dist/chunk-33DMFKKD.js +111 -0
  16. package/dist/chunk-33DMFKKD.js.map +1 -0
  17. package/dist/chunk-4HC3OWAQ.js +185 -0
  18. package/dist/chunk-4HC3OWAQ.js.map +1 -0
  19. package/dist/chunk-4WAKOYMK.js +196 -0
  20. package/dist/chunk-4WAKOYMK.js.map +1 -0
  21. package/dist/chunk-5EHNJCMF.js +58 -0
  22. package/dist/chunk-5EHNJCMF.js.map +1 -0
  23. package/dist/chunk-6QHKKFO3.js +30 -0
  24. package/dist/chunk-6QHKKFO3.js.map +1 -0
  25. package/dist/chunk-DKK26TRS.js +199 -0
  26. package/dist/chunk-DKK26TRS.js.map +1 -0
  27. package/dist/{chunk-A64ZILAS.js → chunk-DQLQOMDM.js} +2 -1
  28. package/dist/{chunk-A64ZILAS.js.map → chunk-DQLQOMDM.js.map} +1 -1
  29. package/dist/chunk-KRAS266U.js +260 -0
  30. package/dist/chunk-KRAS266U.js.map +1 -0
  31. package/dist/chunk-NLQDVNZP.js +115 -0
  32. package/dist/chunk-NLQDVNZP.js.map +1 -0
  33. package/dist/chunk-SNWNF2XI.js +171 -0
  34. package/dist/chunk-SNWNF2XI.js.map +1 -0
  35. package/dist/chunk-UECZA34Q.js +52 -0
  36. package/dist/chunk-UECZA34Q.js.map +1 -0
  37. package/dist/chunk-YJA4H6IB.js +13 -0
  38. package/dist/chunk-YJA4H6IB.js.map +1 -0
  39. package/dist/cli.d.ts +2 -0
  40. package/dist/cli.js +286 -0
  41. package/dist/cli.js.map +1 -0
  42. package/dist/connect-server-7L4HGKKL.js +7 -0
  43. package/dist/connect-server-7L4HGKKL.js.map +1 -0
  44. package/dist/dev/connect-server.d.ts +13 -0
  45. package/dist/dev/host-entry.d.ts +13 -0
  46. package/dist/dev/host-entry.js +18330 -0
  47. package/dist/dev/index.d.ts +45 -0
  48. package/dist/dev/index.js +14 -0
  49. package/dist/dev/index.js.map +1 -0
  50. package/dist/dev/sandbox-entry.d.ts +7 -0
  51. package/dist/dev/sandbox-entry.js +80 -0
  52. package/dist/html.d.ts +4 -0
  53. package/dist/index.d.ts +6 -26
  54. package/dist/index.js +8 -3
  55. package/dist/json-render/app.d.ts +22 -0
  56. package/dist/json-render/app.js +10 -0
  57. package/dist/json-render/app.js.map +1 -0
  58. package/dist/json-render/index.d.ts +10 -0
  59. package/dist/json-render/index.js +119 -0
  60. package/dist/json-render/index.js.map +1 -0
  61. package/dist/json-render/mcp.d.ts +49 -0
  62. package/dist/json-render/mcp.js +11 -0
  63. package/dist/json-render/mcp.js.map +1 -0
  64. package/dist/json-render/server.d.ts +72 -0
  65. package/dist/json-render/server.js +98 -0
  66. package/dist/json-render/server.js.map +1 -0
  67. package/dist/json-render/spec-stream.d.ts +26 -0
  68. package/dist/json-render/use-spec-stream.d.ts +26 -0
  69. package/dist/json-render/widget.d.ts +59 -0
  70. package/dist/react/context.d.ts +14 -0
  71. package/dist/react/create-widget.d.ts +11 -0
  72. package/dist/react/hooks.d.ts +46 -0
  73. package/dist/react/index.d.ts +3 -0
  74. package/dist/react/index.js +35 -0
  75. package/dist/react/index.js.map +1 -0
  76. package/dist/sandbox/index.d.ts +16 -0
  77. package/dist/sandbox/index.js +8 -0
  78. package/dist/sandbox/index.js.map +1 -0
  79. package/dist/schema.d.ts +20 -0
  80. package/dist/server/index.d.ts +73 -0
  81. package/dist/server/index.js +235 -0
  82. package/dist/server/index.js.map +1 -0
  83. package/dist/svelte/index.d.ts +35 -0
  84. package/dist/svelte/index.js +9 -0
  85. package/dist/svelte/index.js.map +1 -0
  86. package/dist/testing/index.d.ts +27 -0
  87. package/dist/testing/index.js +312 -0
  88. package/dist/testing/index.js.map +1 -0
  89. package/dist/testing/render-artifact.d.ts +35 -0
  90. package/dist/types.d.ts +55 -0
  91. package/dist/vite/index.d.ts +23 -0
  92. package/dist/vite/index.js +211 -0
  93. package/dist/vite/index.js.map +1 -0
  94. package/dist/vue/index.d.ts +56 -0
  95. package/dist/vue/index.js +89 -0
  96. package/dist/vue/index.js.map +1 -0
  97. package/package.json +166 -20
  98. package/dist/chunk-BUGGLMNA.js +0 -132
  99. package/dist/chunk-BUGGLMNA.js.map +0 -1
  100. package/dist/types-B9JAWm4W.d.ts +0 -62
package/dist/cli.js ADDED
@@ -0,0 +1,286 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ startDevHost
4
+ } from "./chunk-KRAS266U.js";
5
+ import "./chunk-UECZA34Q.js";
6
+ import "./chunk-YJA4H6IB.js";
7
+
8
+ // src/cli.ts
9
+ import { readFile } from "fs/promises";
10
+ import { resolve } from "path";
11
+ function parseArgs(argv) {
12
+ const args = { open: true };
13
+ for (let i = 0; i < argv.length; i += 1) {
14
+ const arg = argv[i];
15
+ const next = () => {
16
+ const value = argv[i + 1];
17
+ if (value === void 0) throw new Error(`mountly-mcp: ${arg} needs a value`);
18
+ i += 1;
19
+ return value;
20
+ };
21
+ if (arg === "--config" || arg === "-c") args.config = next();
22
+ else if (arg === "--fixtures" || arg === "-f") args.fixtures = next();
23
+ else if (arg === "--server" || arg === "-s") args.server = next();
24
+ else if (arg === "--app" || arg === "-a") args.app = next();
25
+ else if (arg === "--port" || arg === "-p") args.port = Number(next());
26
+ else if (arg === "--no-open") args.open = false;
27
+ else if (arg === "--help" || arg === "-h") {
28
+ printUsage();
29
+ process.exit(0);
30
+ } else throw new Error(`mountly-mcp: unknown option '${arg}'`);
31
+ }
32
+ return args;
33
+ }
34
+ function parseVerifyArgs(argv) {
35
+ const args = { html: [], strict: false, render: false, json: false };
36
+ for (let i = 0; i < argv.length; i += 1) {
37
+ const arg = argv[i];
38
+ const next = () => {
39
+ const value = argv[i + 1];
40
+ if (value === void 0) throw new Error(`mountly-mcp: ${arg} needs a value`);
41
+ i += 1;
42
+ return value;
43
+ };
44
+ if (arg === "--manifest" || arg === "-m") args.manifest = next();
45
+ else if (arg === "--html") args.html.push(next());
46
+ else if (arg === "--strict") args.strict = true;
47
+ else if (arg === "--render") args.render = true;
48
+ else if (arg === "--json") args.json = true;
49
+ else throw new Error(`mountly-mcp: unknown verify option '${arg}'`);
50
+ }
51
+ if (args.manifest && args.html.length > 0) {
52
+ throw new Error("mountly-mcp: verify accepts either --manifest or --html, not both");
53
+ }
54
+ return args;
55
+ }
56
+ function parseBuildArgs(argv) {
57
+ const args = {};
58
+ for (let i = 0; i < argv.length; i += 1) {
59
+ const arg = argv[i];
60
+ if (arg === "--config" || arg === "-c") {
61
+ const value = argv[i + 1];
62
+ if (value === void 0) throw new Error(`mountly-mcp: ${arg} needs a value`);
63
+ args.config = value;
64
+ i += 1;
65
+ } else throw new Error(`mountly-mcp: unknown build option '${arg}'`);
66
+ }
67
+ return args;
68
+ }
69
+ function printUsage() {
70
+ process.stdout.write(`mountly-mcp \u2014 build, develop, and verify MCP Apps
71
+
72
+ Usage:
73
+ mountly-mcp build [options]
74
+ mountly-mcp dev [options]
75
+ mountly-mcp verify [options]
76
+
77
+ Options:
78
+ -c, --config <path> vite config to read the widget from (default: auto)
79
+ -f, --fixtures <path> JSON of named samples (default: mcp.fixtures.json)
80
+ -s, --server <path> module default-exporting your MCP server, to call real tools
81
+ -a, --app <name> View to develop (required when the manifest has several)
82
+ -p, --port <number> host port (default: 5179; the sandbox takes the next one)
83
+ --no-open don't open a browser
84
+ -h, --help show this
85
+
86
+ Verify options:
87
+ -m, --manifest <path> manifest to verify (default: dist/mountly-mcp.manifest.json)
88
+ --html <path> transitional single-View HTML; repeat for several
89
+ --strict fail when warnings are present
90
+ --render require each View to mount with content in Chromium (needs playwright)
91
+ --json output the conformance report as JSON
92
+
93
+ The widget's entry, uri and name come from the mountlyMcpWidget() plugin in
94
+ your vite config, so there is nothing extra to configure.
95
+
96
+ Without --server each fixture value is delivered as structuredContent. With
97
+ --server it is the tool's arguments instead, the view receives what the real
98
+ tool returns, and tool calls the view makes itself are routed to your server.
99
+ `);
100
+ }
101
+ async function buildApps(args) {
102
+ const { createBuilder } = await import("vite");
103
+ const builder = await createBuilder({ configFile: args.config }, false);
104
+ await builder.buildApp();
105
+ }
106
+ async function verify(args) {
107
+ const { formatConformanceReport, verifyMcpApps } = await import("./testing/index.js");
108
+ const report = await verifyMcpApps({
109
+ manifestPath: args.manifest,
110
+ htmlPaths: args.html.length > 0 ? args.html : void 0,
111
+ render: args.render
112
+ });
113
+ process.stdout.write(
114
+ args.json ? JSON.stringify(report, null, 2) : formatConformanceReport(report)
115
+ );
116
+ if (!report.ok || args.strict && report.diagnostics.length > 0) process.exitCode = 1;
117
+ }
118
+ async function loadWidgetOptions(configFile, appName) {
119
+ const { loadConfigFromFile } = await import("vite");
120
+ const loaded = await loadConfigFromFile({ command: "build", mode: "development" }, configFile);
121
+ if (!loaded) {
122
+ throw new Error(
123
+ "mountly-mcp: no vite config found. Pass --config, or add mountlyMcpWidget() to vite.config.ts."
124
+ );
125
+ }
126
+ const plugins = (loaded.config.plugins ?? []).flat(
127
+ Number.POSITIVE_INFINITY
128
+ );
129
+ const plugin = plugins.find((p) => p?.api?.mountlyMcp);
130
+ if (!plugin?.api?.mountlyMcp) {
131
+ throw new Error(
132
+ `mountly-mcp: no mountlyMcpWidget() plugin in ${loaded.path}. Add it to the plugins array.`
133
+ );
134
+ }
135
+ const apps = plugin.api.mountlyMcp.apps;
136
+ if (apps.length > 1 && appName === void 0) {
137
+ throw new Error(
138
+ `mountly-mcp: this build contains several Views; pass --app <name>. Available: ${apps.map((app) => app.name).join(", ")}`
139
+ );
140
+ }
141
+ const selected = appName === void 0 ? apps[0] : apps.find((app) => app.name === appName);
142
+ if (!selected) {
143
+ throw new Error(
144
+ `mountly-mcp: no View named '${String(appName)}'. Available: ${apps.map((app) => app.name).join(", ")}`
145
+ );
146
+ }
147
+ return {
148
+ options: selected,
149
+ outDir: loaded.config.build?.outDir ?? "dist",
150
+ root: loaded.config.root ?? process.cwd()
151
+ };
152
+ }
153
+ async function waitForFile(path, timeoutMs = 15e3) {
154
+ const deadline = Date.now() + timeoutMs;
155
+ for (; ; ) {
156
+ try {
157
+ await readFile(path);
158
+ return;
159
+ } catch {
160
+ if (Date.now() > deadline) throw new Error(`mountly-mcp: timed out waiting for ${path}`);
161
+ await new Promise((done) => setTimeout(done, 50));
162
+ }
163
+ }
164
+ }
165
+ async function loadFixtures(path) {
166
+ const file = path ?? "mcp.fixtures.json";
167
+ try {
168
+ return JSON.parse(await readFile(resolve(file), "utf8"));
169
+ } catch (error) {
170
+ if (path) throw new Error(`mountly-mcp: could not read fixtures '${file}': ${String(error)}`);
171
+ return {};
172
+ }
173
+ }
174
+ async function dev(args) {
175
+ const { options, outDir, root } = await loadWidgetOptions(args.config, args.app);
176
+ const fixtures = await loadFixtures(args.fixtures);
177
+ let server;
178
+ let toolName;
179
+ const { build } = await import("vite");
180
+ const htmlPath = options.output ? resolve(root, options.output) : resolve(root, outDir, `${options.name}.html`);
181
+ let host;
182
+ let started = false;
183
+ const previousSelectedApp = process.env.MOUNTLY_MCP_SELECTED_APP;
184
+ process.env.MOUNTLY_MCP_SELECTED_APP = options.name;
185
+ const watcher = await build({
186
+ configFile: args.config ?? void 0,
187
+ build: { watch: {} },
188
+ logLevel: "warn"
189
+ }).finally(() => {
190
+ if (previousSelectedApp === void 0) delete process.env.MOUNTLY_MCP_SELECTED_APP;
191
+ else process.env.MOUNTLY_MCP_SELECTED_APP = previousSelectedApp;
192
+ });
193
+ const rollupWatcher = watcher;
194
+ rollupWatcher.on("event", (event) => {
195
+ if (event.code === "ERROR") {
196
+ process.stderr.write(`mountly-mcp: build failed \u2014 ${event.error?.message ?? "unknown"}
197
+ `);
198
+ return;
199
+ }
200
+ if (event.code !== "END") return;
201
+ if (started) {
202
+ void waitForFile(`${htmlPath}.meta.json`).then(
203
+ () => {
204
+ host?.reload();
205
+ process.stdout.write("mountly-mcp: rebuilt\n");
206
+ },
207
+ (error) => process.stderr.write(`${String(error)}
208
+ `)
209
+ );
210
+ return;
211
+ }
212
+ started = true;
213
+ void (async () => {
214
+ await waitForFile(`${htmlPath}.meta.json`);
215
+ if (args.server) {
216
+ const { connectMcpServer } = await import("./connect-server-7L4HGKKL.js");
217
+ server = await connectMcpServer(args.server);
218
+ toolName = await server.toolFor(options.uri);
219
+ if (!toolName) {
220
+ throw new Error(
221
+ `mountly-mcp: server '${args.server}' has no tool linked to View '${options.uri}'`
222
+ );
223
+ }
224
+ }
225
+ host = await startDevHost({
226
+ htmlPath,
227
+ fixtures,
228
+ toolInput: {},
229
+ toolName,
230
+ callTool: server?.callTool,
231
+ hostPort: args.port
232
+ });
233
+ process.stdout.write(
234
+ `
235
+ mountly-mcp dev
236
+ host ${host.hostUrl}
237
+ sandbox ${host.sandboxUrl}
238
+ widget ${htmlPath}
239
+ fixtures ${Object.keys(fixtures).length || "none \u2014 pass --fixtures"}
240
+ server ${server ? `${args.server} \u2192 ${toolName ?? "no tool bound to " + options.uri}` : "none \u2014 fixtures deliver directly"}
241
+
242
+ watching for changes; ctrl+c to stop
243
+
244
+ `
245
+ );
246
+ if (args.open) {
247
+ const { spawn } = await import("child_process");
248
+ const opener = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
249
+ spawn(opener, [host.hostUrl], { stdio: "ignore", detached: true, shell: true }).unref();
250
+ }
251
+ })().catch((error) => {
252
+ process.stderr.write(`${error instanceof Error ? error.message : String(error)}
253
+ `);
254
+ void Promise.all([rollupWatcher.close(), server?.close()]).finally(() => process.exit(1));
255
+ });
256
+ });
257
+ const shutdown = () => {
258
+ void (async () => {
259
+ await rollupWatcher.close();
260
+ await host?.close();
261
+ await server?.close();
262
+ process.exit(0);
263
+ })();
264
+ };
265
+ process.on("SIGINT", shutdown);
266
+ process.on("SIGTERM", shutdown);
267
+ }
268
+ async function main() {
269
+ const [command, ...rest] = process.argv.slice(2);
270
+ if (command === void 0 || command === "--help" || command === "-h") {
271
+ printUsage();
272
+ process.exit(command === void 0 ? 1 : 0);
273
+ }
274
+ if (command === "dev") return dev(parseArgs(rest));
275
+ if (command === "build") return buildApps(parseBuildArgs(rest));
276
+ if (command === "verify") return verify(parseVerifyArgs(rest));
277
+ process.stderr.write(`mountly-mcp: unknown command '${command}'. Try 'mountly-mcp --help'.
278
+ `);
279
+ process.exit(1);
280
+ }
281
+ main().catch((error) => {
282
+ process.stderr.write(`${error instanceof Error ? error.message : String(error)}
283
+ `);
284
+ process.exit(1);
285
+ });
286
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * `mountly-mcp dev` — build the widget, serve it in a real sandboxed MCP Apps\n * host, and rebuild on change.\n *\n * Config comes from the `mountlyMcpWidget()` plugin already in vite.config.ts,\n * so there is nothing new to configure.\n */\nimport { readFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport { startDevHost } from \"./dev/index.js\";\nimport type { ConnectedMcpServer } from \"./dev/connect-server.js\";\nimport type { MountlyMcpViteApi, MountlyMcpWidgetOptions } from \"./vite/index.js\";\n\ninterface Args {\n config?: string;\n fixtures?: string;\n server?: string;\n app?: string;\n port?: number;\n open: boolean;\n}\n\ninterface VerifyArgs {\n manifest?: string;\n html: string[];\n strict: boolean;\n render: boolean;\n json: boolean;\n}\n\ninterface BuildArgs {\n config?: string;\n}\n\nfunction parseArgs(argv: ReadonlyArray<string>): Args {\n const args: Args = { open: true };\n for (let i = 0; i < argv.length; i += 1) {\n const arg = argv[i];\n const next = (): string => {\n const value = argv[i + 1];\n if (value === undefined) throw new Error(`mountly-mcp: ${arg} needs a value`);\n i += 1;\n return value;\n };\n if (arg === \"--config\" || arg === \"-c\") args.config = next();\n else if (arg === \"--fixtures\" || arg === \"-f\") args.fixtures = next();\n else if (arg === \"--server\" || arg === \"-s\") args.server = next();\n else if (arg === \"--app\" || arg === \"-a\") args.app = next();\n else if (arg === \"--port\" || arg === \"-p\") args.port = Number(next());\n else if (arg === \"--no-open\") args.open = false;\n else if (arg === \"--help\" || arg === \"-h\") {\n printUsage();\n process.exit(0);\n } else throw new Error(`mountly-mcp: unknown option '${arg}'`);\n }\n return args;\n}\n\nfunction parseVerifyArgs(argv: ReadonlyArray<string>): VerifyArgs {\n const args: VerifyArgs = { html: [], strict: false, render: false, json: false };\n for (let i = 0; i < argv.length; i += 1) {\n const arg = argv[i];\n const next = (): string => {\n const value = argv[i + 1];\n if (value === undefined) throw new Error(`mountly-mcp: ${arg} needs a value`);\n i += 1;\n return value;\n };\n if (arg === \"--manifest\" || arg === \"-m\") args.manifest = next();\n else if (arg === \"--html\") args.html.push(next());\n else if (arg === \"--strict\") args.strict = true;\n else if (arg === \"--render\") args.render = true;\n else if (arg === \"--json\") args.json = true;\n else throw new Error(`mountly-mcp: unknown verify option '${arg}'`);\n }\n if (args.manifest && args.html.length > 0) {\n throw new Error(\"mountly-mcp: verify accepts either --manifest or --html, not both\");\n }\n return args;\n}\n\nfunction parseBuildArgs(argv: ReadonlyArray<string>): BuildArgs {\n const args: BuildArgs = {};\n for (let i = 0; i < argv.length; i += 1) {\n const arg = argv[i];\n if (arg === \"--config\" || arg === \"-c\") {\n const value = argv[i + 1];\n if (value === undefined) throw new Error(`mountly-mcp: ${arg} needs a value`);\n args.config = value;\n i += 1;\n } else throw new Error(`mountly-mcp: unknown build option '${arg}'`);\n }\n return args;\n}\n\nfunction printUsage(): void {\n process.stdout.write(`mountly-mcp — build, develop, and verify MCP Apps\n\nUsage:\n mountly-mcp build [options]\n mountly-mcp dev [options]\n mountly-mcp verify [options]\n\nOptions:\n -c, --config <path> vite config to read the widget from (default: auto)\n -f, --fixtures <path> JSON of named samples (default: mcp.fixtures.json)\n -s, --server <path> module default-exporting your MCP server, to call real tools\n -a, --app <name> View to develop (required when the manifest has several)\n -p, --port <number> host port (default: 5179; the sandbox takes the next one)\n --no-open don't open a browser\n -h, --help show this\n\nVerify options:\n -m, --manifest <path> manifest to verify (default: dist/mountly-mcp.manifest.json)\n --html <path> transitional single-View HTML; repeat for several\n --strict fail when warnings are present\n --render require each View to mount with content in Chromium (needs playwright)\n --json output the conformance report as JSON\n\nThe widget's entry, uri and name come from the mountlyMcpWidget() plugin in\nyour vite config, so there is nothing extra to configure.\n\nWithout --server each fixture value is delivered as structuredContent. With\n--server it is the tool's arguments instead, the view receives what the real\ntool returns, and tool calls the view makes itself are routed to your server.\n`);\n}\n\nasync function buildApps(args: BuildArgs): Promise<void> {\n const { createBuilder } = await import(\"vite\");\n const builder = await createBuilder({ configFile: args.config }, false);\n await builder.buildApp();\n}\n\nasync function verify(args: VerifyArgs): Promise<void> {\n const { formatConformanceReport, verifyMcpApps } = await import(\"./testing/index.js\");\n const report = await verifyMcpApps({\n manifestPath: args.manifest,\n htmlPaths: args.html.length > 0 ? args.html : undefined,\n render: args.render,\n });\n process.stdout.write(\n args.json ? JSON.stringify(report, null, 2) : formatConformanceReport(report),\n );\n if (!report.ok || (args.strict && report.diagnostics.length > 0)) process.exitCode = 1;\n}\n\n/**\n * Read the widget's options back out of the vite config. The plugin publishes\n * them on `api.mountlyMcp`, so this stays correct if its option shape changes.\n */\nasync function loadWidgetOptions(\n configFile: string | undefined,\n appName: string | undefined,\n): Promise<{ options: MountlyMcpWidgetOptions; outDir: string; root: string }> {\n const { loadConfigFromFile } = await import(\"vite\");\n const loaded = await loadConfigFromFile({ command: \"build\", mode: \"development\" }, configFile);\n if (!loaded) {\n throw new Error(\n \"mountly-mcp: no vite config found. Pass --config, or add mountlyMcpWidget() to vite.config.ts.\",\n );\n }\n // Flattened as unknown[]: vite's PluginOption is recursively nested, and\n // asking TS to flatten it by its own type sends the checker infinite.\n const plugins = ((loaded.config.plugins ?? []) as unknown[]).flat(\n Number.POSITIVE_INFINITY,\n ) as Array<{ name?: string; api?: { mountlyMcp?: MountlyMcpViteApi } } | null>;\n const plugin = plugins.find((p) => p?.api?.mountlyMcp);\n if (!plugin?.api?.mountlyMcp) {\n throw new Error(\n `mountly-mcp: no mountlyMcpWidget() plugin in ${loaded.path}. Add it to the plugins array.`,\n );\n }\n const apps = plugin.api.mountlyMcp.apps;\n if (apps.length > 1 && appName === undefined) {\n throw new Error(\n `mountly-mcp: this build contains several Views; pass --app <name>. Available: ${apps.map((app) => app.name).join(\", \")}`,\n );\n }\n const selected = appName === undefined ? apps[0] : apps.find((app) => app.name === appName);\n if (!selected) {\n throw new Error(\n `mountly-mcp: no View named '${String(appName)}'. Available: ${apps.map((app) => app.name).join(\", \")}`,\n );\n }\n return {\n options: selected,\n outDir: (loaded.config.build?.outDir as string | undefined) ?? \"dist\",\n root: (loaded.config.root as string | undefined) ?? process.cwd(),\n };\n}\n\n/**\n * Vite empties the out dir at the start of every build and the plugin writes\n * the resource in `closeBundle`, so the watcher's END event can arrive while\n * the files are still missing. Wait for the artifact rather than trusting the\n * event ordering — this also covers a build that failed and wrote nothing.\n */\nasync function waitForFile(path: string, timeoutMs = 15_000): Promise<void> {\n const deadline = Date.now() + timeoutMs;\n for (;;) {\n try {\n await readFile(path);\n return;\n } catch {\n if (Date.now() > deadline) throw new Error(`mountly-mcp: timed out waiting for ${path}`);\n await new Promise((done) => setTimeout(done, 50));\n }\n }\n}\n\nasync function loadFixtures(path: string | undefined): Promise<Record<string, unknown>> {\n const file = path ?? \"mcp.fixtures.json\";\n try {\n return JSON.parse(await readFile(resolve(file), \"utf8\")) as Record<string, unknown>;\n } catch (error) {\n // An explicit --fixtures that doesn't load is a mistake worth reporting;\n // the default one simply being absent is not.\n if (path) throw new Error(`mountly-mcp: could not read fixtures '${file}': ${String(error)}`);\n return {};\n }\n}\n\nasync function dev(args: Args): Promise<void> {\n const { options, outDir, root } = await loadWidgetOptions(args.config, args.app);\n const fixtures = await loadFixtures(args.fixtures);\n\n // Connected after the first build, not here: a server module typically reads\n // the View it serves, which does not exist yet on a cold checkout.\n let server: ConnectedMcpServer | undefined;\n let toolName: string | undefined;\n\n const { build } = await import(\"vite\");\n const htmlPath = options.output\n ? resolve(root, options.output)\n : resolve(root, outDir, `${options.name}.html`);\n\n // A watching build: vite rebuilds on change, and each rebuild bumps the\n // version the browser is polling, which reloads it.\n let host: Awaited<ReturnType<typeof startDevHost>> | undefined;\n let started = false;\n\n const previousSelectedApp = process.env.MOUNTLY_MCP_SELECTED_APP;\n process.env.MOUNTLY_MCP_SELECTED_APP = options.name;\n const watcher = await build({\n configFile: args.config ?? undefined,\n build: { watch: {} },\n logLevel: \"warn\",\n }).finally(() => {\n if (previousSelectedApp === undefined) delete process.env.MOUNTLY_MCP_SELECTED_APP;\n else process.env.MOUNTLY_MCP_SELECTED_APP = previousSelectedApp;\n });\n\n // `build({ watch })` returns a rollup watcher; the first BUNDLE_END means the\n // widget exists on disk and the host has something to serve.\n const rollupWatcher = watcher as unknown as {\n on(event: \"event\", cb: (e: { code: string; error?: Error }) => void): void;\n close(): Promise<void>;\n };\n\n rollupWatcher.on(\"event\", (event) => {\n if (event.code === \"ERROR\") {\n process.stderr.write(`mountly-mcp: build failed — ${event.error?.message ?? \"unknown\"}\\n`);\n return;\n }\n if (event.code !== \"END\") return;\n if (started) {\n void waitForFile(`${htmlPath}.meta.json`).then(\n () => {\n host?.reload();\n process.stdout.write(\"mountly-mcp: rebuilt\\n\");\n },\n (error: unknown) => process.stderr.write(`${String(error)}\\n`),\n );\n return;\n }\n started = true;\n void (async () => {\n await waitForFile(`${htmlPath}.meta.json`);\n if (args.server) {\n const { connectMcpServer } = await import(\"./dev/connect-server.js\");\n server = await connectMcpServer(args.server);\n toolName = await server.toolFor(options.uri);\n if (!toolName) {\n throw new Error(\n `mountly-mcp: server '${args.server}' has no tool linked to View '${options.uri}'`,\n );\n }\n }\n host = await startDevHost({\n htmlPath,\n fixtures,\n toolInput: {},\n toolName,\n callTool: server?.callTool,\n hostPort: args.port,\n });\n process.stdout.write(\n `\\n mountly-mcp dev\\n` +\n ` host ${host.hostUrl}\\n` +\n ` sandbox ${host.sandboxUrl}\\n` +\n ` widget ${htmlPath}\\n` +\n ` fixtures ${Object.keys(fixtures).length || \"none — pass --fixtures\"}\\n` +\n ` server ${server ? `${args.server} → ${toolName ?? \"no tool bound to \" + options.uri}` : \"none — fixtures deliver directly\"}\\n\\n` +\n ` watching for changes; ctrl+c to stop\\n\\n`,\n );\n if (args.open) {\n const { spawn } = await import(\"node:child_process\");\n const opener =\n process.platform === \"darwin\"\n ? \"open\"\n : process.platform === \"win32\"\n ? \"start\"\n : \"xdg-open\";\n spawn(opener, [host.hostUrl], { stdio: \"ignore\", detached: true, shell: true }).unref();\n }\n })().catch((error: unknown) => {\n // Startup runs inside a watcher callback, where a rejection would\n // otherwise be silent and leave the process alive with no host.\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`);\n void Promise.all([rollupWatcher.close(), server?.close()]).finally(() => process.exit(1));\n });\n });\n\n const shutdown = (): void => {\n void (async () => {\n await rollupWatcher.close();\n await host?.close();\n await server?.close();\n process.exit(0);\n })();\n };\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n}\n\nasync function main(): Promise<void> {\n const [command, ...rest] = process.argv.slice(2);\n if (command === undefined || command === \"--help\" || command === \"-h\") {\n printUsage();\n process.exit(command === undefined ? 1 : 0);\n }\n if (command === \"dev\") return dev(parseArgs(rest));\n if (command === \"build\") return buildApps(parseBuildArgs(rest));\n if (command === \"verify\") return verify(parseVerifyArgs(rest));\n process.stderr.write(`mountly-mcp: unknown command '${command}'. Try 'mountly-mcp --help'.\\n`);\n process.exit(1);\n}\n\nmain().catch((error: unknown) => {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`);\n process.exit(1);\n});\n"],"mappings":"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","names":[]}
@@ -0,0 +1,7 @@
1
+ import {
2
+ connectMcpServer
3
+ } from "./chunk-UECZA34Q.js";
4
+ export {
5
+ connectMcpServer
6
+ };
7
+ //# sourceMappingURL=connect-server-7L4HGKKL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,13 @@
1
+ export interface ConnectedMcpServer {
2
+ callTool: (name: string, args: unknown) => Promise<unknown>;
3
+ /** The model-visible tool bound to `uri` — the one a host would call. */
4
+ toolFor(uri: string): Promise<string | undefined>;
5
+ close(): Promise<void>;
6
+ }
7
+ /**
8
+ * Connect a server module in-process for a development session.
9
+ *
10
+ * The module default-exports either the server or a function returning it: a
11
+ * `RunningMcpAppServer` from `createMcpAppServer`, or a raw `McpServer`.
12
+ */
13
+ export declare function connectMcpServer(path: string): Promise<ConnectedMcpServer>;
@@ -0,0 +1,13 @@
1
+ interface DevHostConfig {
2
+ toolName: string;
3
+ sandboxOrigin: string;
4
+ fixtures: Record<string, unknown>;
5
+ toolInput: Record<string, unknown>;
6
+ uri: string;
7
+ hasServer: boolean;
8
+ sandboxPath: string;
9
+ }
10
+ declare global {
11
+ var __mountlyMcpDevHost__: DevHostConfig;
12
+ }
13
+ export {};