MCP Apps quick start
Scaffold when you can:
npx mountly-mcp create my-app --framework vuecd my-app && pnpm install && pnpm dev--framework: react | vue | svelte | vanilla. Vanilla has no framework
runtime. Call publishMcpView with mount / update / unmount.
Or install Agent Skills and ask an agent to create the App. The steps below match what the scaffold emits.
This walkthrough uses Vue. Swap /vue and the Vite plugin for React or Svelte.
Artifact and server APIs stay the same.
# React (default)npm install mountly-mcp react react-dom @modelcontextprotocol/sdknpm install -D vite @vitejs/plugin-react
# Vue (this page)npm install mountly-mcp mountly-vue @modelcontextprotocol/sdknpm install -D vite @vitejs/plugin-vue1. Publish the View
Section titled “1. Publish the View”import { createMcpView } from "mountly-mcp/vue";import QuoteCard from "./QuoteCard.vue";
createMcpView(QuoteCard);Read tool data without changing the component’s public props:
<script setup lang="ts">import { useHostContext, useToolResult } from "mountly-mcp/vue";
const result = useToolResult<{ structuredContent?: { total: number; currency: string };}>();const host = useHostContext();</script>
<template> <section :data-theme="host?.theme"> <h1>Total due</h1> <p> {{ result?.structuredContent?.total }} {{ result?.structuredContent?.currency }} </p> </section></template>
<style>section { background: var(--color-background-primary, #fff); color: var(--color-text-primary, #171717); font-family: var(--font-sans, system-ui, sans-serif);}</style>Vue composables return computed refs. React has matching hooks. Svelte gets
mcp, toolInput, toolInputPartial, toolResult, and hostContext as
props.
2. Vite config
Section titled “2. Vite config”import vue from "@vitejs/plugin-vue";import { defineConfig } from "vite";import { mountlyMcpViews } from "mountly-mcp/vite";
export default defineConfig({ plugins: [ vue(), mountlyMcpViews({ apps: [ { entry: "src/quote-view.ts", uri: "ui://payments/quote", name: "payment_quote", displayModes: ["inline", "fullscreen"], prefersBorder: true, csp: { connectDomains: ["https://api.example.com"] }, }, ], }), ],});npx mountly-mcp buildYou get dist/payment_quote.html, its metadata sidecar, and
dist/mountly-mcp.manifest.json. Hosts block origins missing from csp.
3. Register on your server
Section titled “3. Register on your server”import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";import { readMcpAppManifest } from "mountly-mcp/artifact";import { registerMcpApps } from "mountly-mcp/server";
export default async function createServer() { const server = new McpServer( { name: "payments", version: "1.0.0" }, { capabilities: { tools: {}, resources: {} } }, ); const { artifacts } = await readMcpAppManifest("dist/mountly-mcp.manifest.json");
await registerMcpApps(server, { views: artifacts.map((artifact) => ({ artifact })), tools: [ { name: "quote_payment", resourceUri: "ui://payments/quote", config: { description: "Quote a payment plan", inputSchema: { type: "object", properties: { plan: { type: "string" } }, required: ["plan"], }, }, handler: async ({ plan }: { plan: string }) => ({ structuredContent: { plan, total: 99, currency: "USD" }, }), }, ], });
return server;}Call registerMcpApps() before connect. If the handler returns only
structuredContent, Mountly adds a JSON text content block for models and
text-only clients.
Stdio:
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";import createServer from "./create-server.js";
const server = await createServer();await server.connect(new StdioServerTransport());Log to stderr. stdout is JSON-RPC.
4. Develop and verify
Section titled “4. Develop and verify”mcp.fixtures.json without --server delivers each value as
structuredContent:
{ "annual": { "plan": "annual", "total": 99, "currency": "USD" }, "monthly": { "plan": "monthly", "total": 12, "currency": "USD" }}npx mountly-mcp doctornpx mountly-mcp devnpx mountly-mcp dev --server ./dist/create-server.jsnpx mountly-mcp verify --render --strictMulti-View: pass --app payment_quote. CI: verify --render --strict fails
warnings and blank mounts.