.memstack/skills/mcp-app-workflow/SKILL.md
Complete workflow for creating, building, and registering MCP Apps with interactive UIs. Use when the user wants to build a new MCP App from scratch, needs step-by-step guidance through the full development cycle (setup → code → build → register → test), or asks "how to create an MCP app end-to-end". For SDK-specific patterns and API details, see the create-mcp-app skill.
npx skillsauth add s1366560/agi-demos mcp-app-workflowInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Complete workflow for creating MCP Apps from project setup to server registration and testing.
1. Initialize Project → 2. Implement Server → 3. Build UI → 4. Bundle → 5. Register → 6. Test
Create a new project directory with proper dependencies:
mkdir my-mcp-app && cd my-mcp-app
npm init -y
npm install @modelcontextprotocol/sdk @modelcontextprotocol/ext-apps zod
npm install -D typescript tsx vite vite-plugin-singlefile
Create configuration files:
tsconfig.json:
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"esModuleInterop": true,
"strict": true,
"skipLibCheck": true,
"outDir": "./dist"
},
"include": ["*.ts", "src/**/*.ts", "src/**/*.tsx"]
}
vite.config.ts:
import { defineConfig } from 'vite';
import { vitePluginSinglefile } from 'vite-plugin-singlefile';
export default defineConfig({
plugins: [vitePluginSinglefile()],
build: {
outDir: 'dist',
rollupOptions: {
input: 'mcp-app.html',
output: { entryFileNames: 'mcp-app.html' }
}
}
});
package.json scripts:
{
"scripts": {
"build": "vite build",
"serve": "tsx server.ts"
}
}
Create server.ts with tool and resource registration:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { registerAppTool, registerAppResource } from "@modelcontextprotocol/ext-apps";
import { z } from "zod";
import { readFileSync } from "fs";
import { fileURLToPath } from "url";
import { dirname, join } from "path";
const __dirname = dirname(fileURLToPath(import.meta.url));
const server = new McpServer({ name: "my-app-server", version: "1.0.0" });
// Register tool
registerAppTool(server, "my_tool", {
title: "My Tool",
description: "Tool description",
argsSchema: { param1: z.string().optional() },
_meta: { ui: { resourceUri: "app://my-app/mcp-app.html" } },
}, async (args, context) => {
return {
content: [
{ type: "text", text: JSON.stringify({ result: "success", args }) },
{ type: "resource", resourceUri: "app://my-app/mcp-app.html" }
]
};
});
// Register resource (serves bundled HTML)
registerAppResource(server, "app://my-app/mcp-app.html", async () => {
const html = readFileSync(join(__dirname, "dist", "mcp-app.html"), "utf-8");
return { contents: [{ uri: "app://my-app/mcp-app.html", mimeType: "text/html", text: html }] };
});
// Start server
const transport = new StdioServerTransport();
await server.connect(transport);
Create mcp-app.html with vanilla JS (see asset template for complete example):
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script type="module">
import { App } from "@modelcontextprotocol/ext-apps";
const app = new App({ name: "My App", version: "1.0.0" });
// Register handlers BEFORE connect
app.ontoolinput = (params) => {
console.log("Tool input:", params.arguments);
render(params.arguments);
};
app.ontoolresult = (result) => {
console.log("Tool result:", result);
};
app.onhostcontextchanged = (ctx) => {
if (ctx.theme) document.documentElement.className = ctx.theme;
};
app.onteardown = async () => ({});
await app.connect();
function render(data) {
// Update UI with data
}
</script>
</head>
<body>
<!-- UI content -->
</body>
</html>
Build the UI to create a single bundled HTML file:
npm run build
This produces dist/mcp-app.html with all JS/CSS inlined.
Use the register_mcp_server tool to register the running server:
server_name: "my-app-server"
server_type: "stdio"
command: "npx"
args: ["tsx", "server.ts"]
The server must be running for registration to work.
Call the registered tool to verify the UI renders correctly:
Call my_tool with param1="test"
The Canvas panel should display the interactive UI.
| Issue | Solution |
|-------|----------|
| Cannot find module | Run npm install to install dependencies |
| dist/mcp-app.html not found | Run npm run build before starting server |
| UI not rendering | Check tool returns resourceUri matching resource |
| Handlers not firing | Register handlers BEFORE app.connect() |
| Styles not applying | Use host CSS variables: var(--color-text-primary) |
See assets/project_template/ for a complete working project structure.
tools
Sandbox MCP Server 是一个隔离的代码执行环境,提供完整的文件系统操作、命令执行、 代码分析、测试运行和远程桌面能力。当你需要执行代码、操作文件、运行测试、 分析代码结构、或需要图形界面操作时使用此技能。支持 Python、Node.js、Java 等多语言环境。
tools
Replace with description of the skill and when Claude should use it.
development
Generate high-quality images using ModelScope's Z-Image API. Use this skill when the user wants to generate images using the specific Z-Image model or ModelScope API they provided. Trigger words: 'Zimage', 'ModelScope', 'generate zimage'.
tools
No-code automation democratizes workflow building. Zapier and Make (formerly Integromat) let non-developers automate business processes without writing code. But no-code doesn't mean no-complexity ...