Skip to content

Build and artifacts

The recommended build declares an apps collection and runs mountly-mcp build. Each View gets an isolated Vite environment, while all Views share one versioned App manifest.

vite.config.ts
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";
import { mountlyMcpViews } from "mountly-mcp/vite";
export default defineConfig({
plugins: [
react(),
mountlyMcpViews({
apps: [
{
entry: "src/dashboard.tsx",
uri: "ui://weather/dashboard",
name: "weather_dashboard",
displayModes: ["inline", "fullscreen"],
},
{
entry: "src/settings.tsx",
uri: "ui://weather/settings",
name: "weather_settings",
},
],
// Optional. Defaults to dist/mountly-mcp.manifest.json.
manifest: "dist/mountly-mcp.manifest.json",
}),
],
});
Terminal window
npx mountly-mcp build

Use --config <path> when Vite cannot discover the config automatically.

The default output is:

dist/
├── mountly-mcp.manifest.json
├── weather_dashboard.html
├── weather_dashboard.html.meta.json
├── weather_settings.html
└── weather_settings.html.meta.json

Each App artifact contains self-contained HTML plus its resource declaration. The per-View .meta.json file is transitional compatibility output. The App manifest is canonical: build, development, registration, and verification all consume the same identities and paths.

App manifest paths are relative to the manifest, so the complete dist directory can move as one deployable unit. Do not edit generated declarations independently; rebuild them from the Vite configuration.

Every View requires:

  • entry: source file that calls createMcpView(...) (or publishMcpView);
  • name: unique developer key and default output filename;
  • uri: unique protocol identity beginning with ui://.

Resource options include description, displayModes, prefersBorder, csp, permissions, awaitToolResult, and streamToolInput. Declare external network, resource, frame, and base origins in csp; undeclared origins are blocked by a conforming host.

Set an individual output to override a View’s HTML path. Set manifest: false only when another system owns the artifact collection; it disables the canonical contract used by the Mountly CLI.

Existing projects can keep the original options and vite build:

mountlyMcpViews({
entry: "src/view.tsx",
uri: "ui://example/view",
name: "example_view",
});

This still emits the View HTML, metadata, and default App manifest. Prefer the collection shape for new code so adding a second View is configuration-only.

mountly-mcp/build exposes buildMcpResource() and buildMcpResourceFromSource() for build systems that cannot use the Vite plugin. mountly-mcp/artifact exposes readMcpAppArtifact(), readMcpAppManifest(), and writeMcpAppManifest() so custom pipelines can produce and consume the same contract.

Use these lower-level interfaces only when the Vite adapter is not suitable; the adapter earns its depth by handling dependency bundling, CSS inlining, bridge injection, metadata, isolated environments, and cleanup together.